gnunet-svn
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]