[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [libmicrohttpd] 10/154: mhd_send: Restructure.
From: |
gnunet |
Subject: |
[GNUnet-SVN] [libmicrohttpd] 10/154: mhd_send: Restructure. |
Date: |
Mon, 19 Aug 2019 10:15:22 +0200 |
This is an automated email from the git hooks/post-receive script.
ng0 pushed a commit to branch master
in repository libmicrohttpd.
commit 43c21d59f2f7671e1888f3f2bd6169b99b755317
Author: ng0 <address@hidden>
AuthorDate: Thu Jun 20 19:16:55 2019 +0000
mhd_send: Restructure.
---
src/microhttpd/mhd_send.c | 352 +++++++++++++++++++---------------------------
1 file changed, 146 insertions(+), 206 deletions(-)
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c
index 252e5e86..beb7b60a 100644
--- a/src/microhttpd/mhd_send.c
+++ b/src/microhttpd/mhd_send.c
@@ -20,13 +20,14 @@
/**
* @file microhttpd/mhd_send.c
- * @brief Implementation of send() and sendfile() wrappers.
+ * @brief Implementation of send() wrappers.
* @author ng0 <address@hidden>
*/
// to be used in: send_param_adapter, MHD_send_
// and every place where sendfile(), sendfile64(), setsockopt()
// are used.
+// TODO: sendfile() wrappers.
#include "platform.h"
@@ -35,6 +36,9 @@
// TCP_CORK/TCP_NOPUSH: don't send out partial frames.
// TCP_NODELAY: disable Nagle (aggregate data based on
// buffer pressur).
+// TODO: It is possible that Solaris/SunOS depending on
+// the linked library needs a different setsockopt usage:
+//
https://stackoverflow.com/questions/48670299/setsockopt-usage-in-linux-and-solaris-invalid-argument-in-solaris
enum MHD_SendSocketOptions
{
@@ -61,11 +65,12 @@ enum MHD_SendSocketOptions
* (so far) only provide a FreeBSD compatibility here, for example).
* Since we only deal with IPPROTO_TCP flags in this file and nowhere
* else, we don't have to move this elsewhere for now.
- */
+*/
+/*
#if ! defined(TCP_CORK) && defined(TCP_NOPUSH)
#define TCP_CORK TCP_NOPUSH
#endif
-
+*/
/*
* -- OBJECTIVE:
* connection: use member 'socket', and remember the
@@ -87,187 +92,133 @@ MHD_send_on_connection_ (struct MHD_Connection
*connection,
size_t buffer_size,
enum MHD_SendSocketOptions options)
{
- size_t length, opt1, opt2;
- ssize_t num_bytes;
- int errno = 0;
- /* s: the socket. */
+ //size_t length, opt1, opt2;
+ // ssize_t num_bytes;
+ //int errno = 0;
+ bool want_cork, have_cork, have_more;
+ /* The socket. */
MHD_socket s = connection->socket_fd;
- bool want_cork;
- bool have_cork;
- bool have_more;
-
+ // new code...
+ /* Get socket options, change/set options if necessary. */
switch (options)
{
+ /* No corking */
case MHD_SSO_NO_CORK:
want_cork = false;
break;
+ /* Do corking, consider MSG_MORE instead if available */
case MHD_SSO_MAY_CORK:
want_cork = true;
break;
+ /* Cork the header */
case MHD_SSO_HDR_CORK:
want_cork = (buffer_size >= 1024) && (buffer_size <= 1220);
break;
}
+
+ // ! could be avoided by redefining the variable
have_cork = ! connection->sk_tcp_nodelay_on;
+
#ifdef MSG_MORE
have_more = true;
#else
have_more = false;
#endif
+ bool use_corknopush;
+#if HAVE_NODELAY
+ use_corknopush = false;
+#elif HAVE_CORK
+ use_corknopush = true;
+#elif HAVE_NOPUSH
+ use_corknopush = true;
+#endif
- /* Get socket options, change/set options if necessary. */
- switch (options)
+#if HAVE_CORK
+ if (use_corknopush)
{
- /* No corking */
- case MHD_SSO_NO_CORK:
- if (! connection->sk_tcp_nodelay_on)
+ if (have_cork && ! want_cork)
{
- opt1 = 1;
- opt2 = sizeof (int);
- /*
- * TODO: It is possible that Solaris/SunOS depending on
- * the linked library needs a different setsockopt usage:
- *
https://stackoverflow.com/questions/48670299/setsockopt-usage-in-linux-and-solaris-invalid-argument-in-solaris
- */
- if (0 == setsockopt (s, IPPROTO_TCP, TCP_NODELAY, &opt1, opt2))
- {
- connection->sk_tcp_nodelay_on = true;
- }
- else
- {
- /*
- * TODO: use last return from setsockopt
- * here, which for error is -1 when its
- * implementation is POSIX conform.
- */
- errno = -1;
- }
+ setsockopt (s, IPPROTO_TCP, TCP_CORK, 1, sizeof (int)) ||
+ (setsockopt (s, IPPROTO_TCP, TCP_NODELAY, 1, sizeof (int)) &&connection
+ ->sk_tcp_nodelay = true);
+ //setsockopt (cork-on); // or nodelay on // + update
connection->sk_tcp_nodelay_on
+ // When we have CORK, we can have NODELAY on the same system,
+ // at least since Linux 2.2 and both can be combined since
+ // Linux 2.5.71. See tcp(7). No other system in 2019-06 has TCP_CORK.
}
- /* Do corking, do MSG_MORE instead if available */
- case MHD_SSO_MAY_CORK:
-#if defined(TCP_CORK) && ! defined(MSG_MORE)
- /*
- * We have TCP_CORK and we don't have MSG_MORE.
- * This means we want to enable corking.
- * Check if our corking boolean is not already set.
- */
- if (! connection->sk_tcp_cork_nopush_on)
+ }
+#elif HAVE_NOPUSH
+ /*
+ * TCP_NOPUSH on FreeBSD is equal to cork on Linux, with the
+ * exception that we know that TCP_NOPUSH will definitely
+ * exist and we can disregard TCP_NODELAY unless requested.
+ */
+ if (use_corknopush)
+ {
+ if (have_cork && ! want_cork)
{
- /*
- * corking boolean is false. We want to enable
- * Corking then.
- */
- opt1 = 1;
- opt2 = sizeof (int);
- /*
- * If we succesfully set TCP_CORK, set the corking
- * boolean to true.
- */
- if (0 == setsockopt (s, IPPROTO_TCP, TCP_CORK, &opt1, opt2))
- {
- connection->sk_tcp_cork_nopush_on = true;
- }
- /* And if we don't, set errno to -1. */
- else
- {
- errno = -1;
- }
+ setsockopt (s, IPPROTO_TCP, TCP_NOPUSH, 1, sizeof (int));
+ // TODO: set corknopush to true here?
+ // connection->sk_tcp_cork_nopush_on = true;
}
+ }
#endif
-#ifdef MSG_MORE
- /*
- * We have MSG_MORE. This means we want to use MSG_MORE
- * for send() and keep the socket on NODELAY.
- * Check if our nodelay boolean is false.
- */
- if (! connection->sk_tcp_nodelay_on)
+#if HAVE_NODELAY
+ if (! use_corknopush)
+ {
+ if (! have_cork && want_cork)
{
- /*
- * If we have MSG_MORE, keep the
- * socket on NO_DELAY / NO_CORK.
- * Since MSG_MORE is an argument to
- * send(), in some cases we will be
- * using send() with MSG_MORE.
- */
- opt1 = 1;
- opt2 = sizeof (int);
- /*
- * If we successfully set TCP_NODELAY, set the nodelay
- * boolean to true.
- */
- if (0 == setsockopt (s, IPPROTO_TCP, TCP_NODELAY, &opt1, opt2))
- {
- connection->sk_tcp_nodelay_on = true;
- }
- else
- {
- errno = -1;
- }
+ // setsockopt (nodelay-off);
+ setsockopt (s, IPPROTO_TCP, TCP_NODELAY, 0, sizeof (int));
+ connection->sk_tcp_nodelay = false;
}
+ // ...
+ }
#endif
- /* Cork the header */
- case MHD_SSO_HDR_CORK:
- if (something_with_snd_mss > (sizeof (buffer - 10)))
- { // magic guessing?
- if ((! 100_Continue) && (sending_header))
- {
- // uncork
- if (connection->sk_tcp_cork_nopush_on)
- {
- opt1 = 0;
- opt2 = sizeof (int);
- if (0 == setsockopt (s, IPPROTO_TCP, TCP_CORK, &opt1, opt2))
- connection->sk_tcp_cork_nopush_on = false;
- }
- // setsockopt() uncork flag
- opt1 = 1;
- opt2 = sizeof (int);
- if (0 == setsockopt (s, IPPROTO_TCP, TCP_NODELAY, &opt1, opt2))
- connection->sk_tcp_nodelay_on = true;
- // -> if we now cork again, would that
- // be too much for this case? If we
- // want to cork, we use case 1.
- }
+
+
+ ret = send (s, buffer, buffer_size, want_cork ? MSG_MORE : 0);
+ eno = errno;
+#if HAVE_CORK
+ if (use_corknopush)
+ {
+ if (! have_cork && want_cork && ! have_more)
+ {
+ //setsockopt (cork-off); // or nodelay off // + update
connection->sk_tcp_nodelay_on
+ setsockopt (s, IPPROTO_TCP, TCP_CORK, 0, sizeof (int)) ||
+ (setsockopt (s, IPPROTO_TCP, TCP_NODELAY, 0, sizeof (int)) &&connection
+ ->sk_tcp_nodelay_on = false);
}
}
-}
-if (MHD_SendSocketOptions == 1)
-{
-#ifdef MSG_MORE
- num_bytes = send (s, buffer, buffer_size, MSG_MORE);
-#else
- num_bytes = send (s, buffer, buffer_size);
+#elif HAVE_NOPUSH
+ // We don't have MSG_MORE.
+ if (use_corknopush)
+ {
+ // ...
+ }
#endif
-}
-else
-{
- num_bytes = send (s, buffer, buffer_size);
-}
-// -- pseudo Start:
-// set socket := connect->MHD_socket
-// get stateof(socket)
-// in case 0,1,2 where case from MHD_SendSocketOptions do
-// $case:
-// setsockopt PLATFORM_ACCORDINGLY
-// "update socket state"
-// send(socket, buffer, buffer_size)
-// if socketError:
-// return -1
-// return numBytes
-// -- pseudo End
-// error
-/*
- * send() returns -1 on error, we might as well return num_bytes,
- * but we need to catch the errors before send().
- */
-if (0 != errno)
- return -1;
-if (0 == errno)
- return num_bytes;
-}
+
+#if HAVE_NODELAY
+ if (! use_corknopush)
+ {
+ if (have_cork && ! want_cork)
+ {
+ // setsockopt (nodelay - on);
+ setsockopt (s,
+ IPPROTO_TCP,
+ TCP_NODELAY,
+ 1,
+ sizeof (int)) &&connection->sk_tcp_nodelay_on = true;
+ }
+ // ...
+ }
+#endif
+ errno = eno;
+ return ret;
+
// * Send header followed by buffer on connection;
// * uses writev if possible to send both at once
@@ -285,55 +236,46 @@ MHD_send_on_connection2_ (struct MHD_Connection
*connection,
size_t buffer_size,
enum MHD_SendSocketOptions options)
{
- int errno = 0;
MHD_socket s = connection->socket_fd;
- // -- <pseudo>
- // set socket := connect->MHD_socket
- // in case 0,1,2 where case from MHD_SendSocketOptions do
- // $case:
- // setsockopt
- // update boolean
- // nbuffer = header + buffer
- // #if defined(WRITEV)
- // struct iovec vector[2];
- // vector[0].iov_base = header;
- // vector[0].iov_len = header_size;
- // vector[1].iov_base = buffer;
- // vector[1].iov_len = buffer_size;
- // i = writev(s, &vector[0], 2);
- // num_bytes = send(socket, i, WHATSIZE?)
- // #else
- // //not available, send a combination of header + buffer.
- // size_t nbuffersize = buffer_size + header_size
- // num_bytes = send(socket, nbuffer, nbuffersize)
- // #endif
- // if socketError:
- // return -1
- // return numBytes
- // -- </pseudo>
- struct tcp_info tcp_;
- size_t opt1, opt2, length;
-
- if (0 ==
- getsockopt (connection->socket,
- TCP_INFO,
- IPPROTO_TCP,
- &tcp_,
- sizeof (tcp_)))
- {
- // mss = tcp_.tcpi_snd_mss;
- }
+ bool want_cork, have_cork, have_more;
switch (options)
{
+ /* No corking */
case MHD_SSO_NO_CORK:
- /* No corking */
+ want_cork = false;
+ break;
+ /* Do corking, do MSG_MORE instead if available */
case MHD_SSO_MAY_CORK:
+ want_cork = true;
+ break;
+ /* Cork the header */
case MHD_SSO_HDR_CORK:
+ want_cork = (buffer_size >= 1024) && (buffer_size <= 1220);
+ break;
}
- if (MHD_SendSocketOptions == 1)
+ // ! could be avoided by redefining the variable
+ have_cork = ! connection->sk_tcp_nodelay_on;
+
+#ifdef MSG_MORE
+ have_more = true;
+#else
+ have_more = false;
+#endif
+
+ bool use_corknopush;
+
+#if HAVE_NODELAY
+ use_corknopush = false;
+#elif HAVE_CORK
+ use_corknopush = true;
+#elif HAVE_NOPUSH
+ use_corknopush = true;
+#endif
+
+#if HAVE_WRITEV
+ if ((options == MHD_SSO_HDR_CORK) && want_cork)
{
-#ifdef WRITEV
int iovcnt;
struct iovec vector[2];
vector[0].iov_base = header;
@@ -341,22 +283,20 @@ MHD_send_on_connection2_ (struct MHD_Connection
*connection,
vector[1].iov_base = buffer;
vector[1].iov_len = strlen (buffer);
iovcnt = sizeof (vector) / sizeof (struct iovec);
- int i = writev (s, vector, iovcnt);
- fprintf (stdout, "i=%d, errno=%d\n", i, errno);
-#else
- // not available, send a combination of header + buffer.
- //size_t concatsize = header_size + buffer_size;
- //const char *concatbuffer;
- //concatbuffer = header + buffer;
-#ifdef MSG_MORE
- num_bytes = send (s, header, header_size, MSG_MORE);
-#else
- num_bytes = send (s, header, header_size);
-#endif
-#endif
+ ret = writev (s, vector, iovcnt);
+ eno = errno;
+ if ((ret == header_len + buffer_len) && have_cork)
+ {
+ // response complete, definitely uncork!
+ // setsockopt (cork-off);
+ setsockopt (s, IPPROTO_TCP, TCP_CORK, 0, sizeof (int));
+ // connection->sk_tcp_cork_nopush_on = true;
+ }
+ errno = eno;
+ return ret;
}
- if (0 != errno)
- return -1;
- if (0 == errno)
- return num_bytes;
+#endif
+
+ errno = eno;
+ return ret;
}
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [GNUnet-SVN] [libmicrohttpd] 33/154: replace connection->send_cls(), (continued)
- [GNUnet-SVN] [libmicrohttpd] 33/154: replace connection->send_cls(), gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 13/154: mhd_send.c: fix compiler error about MSG_MORE when MSG_MORE is undefined., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 18/154: more from connection.c, without checks so far., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 16/154: mhd_send: Use MHD_SCKT_OPT_BOOL_ for setsockopt optval., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 28/154: fixes, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 43/154: move comment above function., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 25/154: inline TLS logic, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 15/154: iAdd headerfile for mhd_send., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 26/154: indentation, comments, issue, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 29/154: fix err logic, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 10/154: mhd_send: Restructure.,
gnunet <=
- [GNUnet-SVN] [libmicrohttpd] 27/154: fixes, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 32/154: setsockopt(): check return value., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 21/154: mhd_send.c: Use daemon from connection struct., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 45/154: fix compiler error., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 44/154: remove verbose comments in mhd_send.c, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 55/154: doxygen: MHD_SSO, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 30/154: comments, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 49/154: more OLDSOCK., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 59/154: sendfile and netbsd, comment., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 31/154: combine ifs, fix uninitialized var error, gnunet, 2019/08/19