gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] branch master updated: Track socket CORK/NO


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated: Track socket CORK/NODELAY states to avoid extra syscalls
Date: Mon, 10 Dec 2018 20:22:11 +0100

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

The following commit(s) were added to refs/heads/master by this push:
     new e13c79ee Track socket CORK/NODELAY states to avoid extra syscalls
e13c79ee is described below

commit e13c79ee3b5208c8b94538144abe58eab099b3f8
Author: Evgeny Grin (Karlson2k) <address@hidden>
AuthorDate: Mon Dec 10 22:14:59 2018 +0300

    Track socket CORK/NODELAY states to avoid extra syscalls
---
 src/microhttpd/connection.c  | 215 +++++++++++++++++++++----------------------
 src/microhttpd/daemon.c      |   9 ++
 src/microhttpd/internal.h    |  13 +++
 src/microhttpd/mhd_sockets.c |  35 +++++++
 src/microhttpd/mhd_sockets.h |  23 +++++
 5 files changed, 185 insertions(+), 110 deletions(-)

diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 4d2f49b5..d521c036 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -49,6 +49,10 @@
 #ifdef HTTPS_SUPPORT
 #include "connection_https.h"
 #endif /* HTTPS_SUPPORT */
+#ifdef HAVE_SYS_PARAM_H
+/* For FreeBSD version identification */
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
 
 
 /**
@@ -496,51 +500,46 @@ socket_flush_possible(struct MHD_Connection *connection)
 _MHD_static_inline bool
 socket_start_extra_buffering (struct MHD_Connection *connection)
 {
-  bool res = false;
-#if defined(TCP_CORK) || defined(TCP_NOPUSH)
-  const MHD_SCKT_OPT_BOOL_ on_val = 1;
-#if defined(TCP_NODELAY)
-  const MHD_SCKT_OPT_BOOL_ off_val = 0;
-#endif /* TCP_NODELAY */
-  (void) connection; /* mute compiler warning, assertion below
-                       may be compiled out! */
   mhd_assert(NULL != connection);
-#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
-  /* Buffer data before sending */
-  res = (0 == setsockopt (connection->socket_fd,
-                          IPPROTO_TCP,
-                          TCP_NOPUSH,
-                          (const void *) &on_val,
-                          sizeof (on_val)));
 #if defined(TCP_NODELAY)
-  /* Enable Nagle's algorithm */
-  /* TCP_NODELAY may interfere with TCP_NOPUSH */
-  res = (0 == setsockopt (connection->socket_fd,
+  if (connection->sk_tcp_nodelay_on)
+    {
+      const MHD_SCKT_OPT_BOOL_ off_val = 0;
+      /* Enable Nagle's algorithm */
+      /* TCP_NODELAY may interfere with TCP_NOPUSH */
+      if (0 == setsockopt (connection->socket_fd,
                            IPPROTO_TCP,
                            TCP_NODELAY,
                            (const void *) &off_val,
-                           sizeof (off_val))) && res;
+                           sizeof (off_val)))
+        {
+          connection->sk_tcp_nodelay_on = false;
+        }
+    }
 #endif /* TCP_NODELAY */
-#else /* TCP_CORK */
+
+#if defined(MHD_TCP_CORK_NOPUSH)
+  if (!connection->sk_tcp_cork_nopush_on)
+    {
+      const MHD_SCKT_OPT_BOOL_ on_val = 1;
+      /* Buffer data before sending (TCP_CORK) or
+       * Send only full frames (TCP_NOPUSH) */
+      if (0 == setsockopt (connection->socket_fd,
+                           IPPROTO_TCP,
+                           MHD_TCP_CORK_NOPUSH,
+                           (const void *) &on_val,
+                           sizeof (on_val)))
+        {
+          connection->sk_tcp_cork_nopush_on = true;
+        }
+    }
+#endif /* MHD_TCP_CORK_NOPUSH */
+
 #if defined(TCP_NODELAY)
-  /* Enable Nagle's algorithm */
-  /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode 
depends
-     solely on TCP_CORK result, so ignoring return code here. */
-  (void) setsockopt (connection->socket_fd,
-                     IPPROTO_TCP,
-                     TCP_NODELAY,
-                     (const void *) &off_val,
-                     sizeof (off_val));
-#endif /* TCP_NODELAY */
-  /* Send only full packets */
-  res = (0 == setsockopt (connection->socket_fd,
-                          IPPROTO_TCP,
-                          TCP_CORK,
-                          (const void *) &on_val,
-                          sizeof (on_val)));
-#endif /* TCP_CORK */
-#endif /* TCP_CORK || TCP_NOPUSH */
-  return res;
+   return connection->sk_tcp_cork_nopush_on && !connection->sk_tcp_nodelay_on;
+#else  /* ! TCP_NODELAY */
+   return connection->sk_tcp_cork_nopush_on;
+#endif /* ! TCP_NODELAY */
 }
 
 
@@ -553,43 +552,38 @@ socket_start_extra_buffering (struct MHD_Connection 
*connection)
 _MHD_static_inline bool
 socket_start_no_buffering (struct MHD_Connection *connection)
 {
-#if defined(TCP_NODELAY)
-  bool res = true;
-  const MHD_SCKT_OPT_BOOL_ on_val = 1;
-#if defined(TCP_CORK) || defined(TCP_NOPUSH)
-  const MHD_SCKT_OPT_BOOL_ off_val = 0;
-#endif /* TCP_CORK || TCP_NOPUSH */
-
-  (void)connection; /* Mute compiler warning. */
-  mhd_assert(NULL != connection);
-#if defined(TCP_CORK)
-  /* Allow partial packets */
-  res = (0 == setsockopt (connection->socket_fd,
+#if defined(MHD_TCP_CORK_NOPUSH)
+  if (connection->sk_tcp_cork_nopush_on)
+    {
+      const MHD_SCKT_OPT_BOOL_ off_val = 0;
+      /* Disable extra buffering */
+      if (0 == setsockopt (connection->socket_fd,
                            IPPROTO_TCP,
-                           TCP_CORK,
+                           MHD_TCP_CORK_NOPUSH,
                            (const void *) &off_val,
-                           sizeof (off_val))) && res;
-#endif /* TCP_CORK */
+                           sizeof (off_val)))
+        {
+          connection->sk_tcp_cork_nopush_on = false;
+        }
+    }
+#endif /* MHD_TCP_CORK_NOPUSH */
+
 #if defined(TCP_NODELAY)
-  /* Disable Nagle's algorithm for sending packets without delay */
-  res = (0 == setsockopt (connection->socket_fd,
+  if (!connection->sk_tcp_nodelay_on)
+    {
+      const MHD_SCKT_OPT_BOOL_ on_val = 1;
+      /* Enable sending without delay */
+      if (0 == setsockopt (connection->socket_fd,
                            IPPROTO_TCP,
                            TCP_NODELAY,
                            (const void *) &on_val,
-                           sizeof (on_val))) && res;
+                           sizeof (on_val)))
+        {
+          connection->sk_tcp_nodelay_on = true;
+        }
+    }
 #endif /* TCP_NODELAY */
-#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
-  /* Disable extra buffering */
-  res = (0 == setsockopt (connection->socket_fd,
-                           IPPROTO_TCP,
-                           TCP_NOPUSH,
-                           (const void *) &off_val,
-                           sizeof (off_val))) && res;
-#endif /* TCP_NOPUSH  && !TCP_CORK */
-  return res;
-#else  /* !TCP_NODELAY */
-  return false;
-#endif /* !TCP_NODELAY */
+  return connection->sk_tcp_nodelay_on && !connection->sk_tcp_cork_nopush_on;
 }
 
 
@@ -607,12 +601,24 @@ socket_start_no_buffering_flush (struct MHD_Connection 
*connection)
 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
   const int dummy = 0;
 #endif /* !TCP_CORK */
-
-  (void)connection; /* Mute compiler warning. */
-  mhd_assert(NULL != connection);
+#if defined(TCP_CORK) || (defined(__FreeBSD__) &&  __FreeBSD__+0 >= 9)
+  const MHD_SCKT_OPT_BOOL_ off_val = 0;
+  /* Switching off TCP_CORK flush buffer even
+   * if TCP_CORK was not enabled */
+  if (0 == setsockopt (connection->socket_fd,
+                       IPPROTO_TCP,
+                       MHD_TCP_CORK_NOPUSH,
+                       (const void *) &off_val,
+                       sizeof (off_val)))
+    {
+      connection->sk_tcp_cork_nopush_on = false;
+    }
+#endif /* MHD_TCP_CORK_NOPUSH */
 
   res = socket_start_no_buffering (connection);
-#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
+#if defined(__FreeBSD__) &&  __FreeBSD__+0 >= 9
+  /* FreeBSD do not need zero-send for flushing starting from version 9 */
+#elif defined(TCP_NOPUSH) && !defined(TCP_CORK)
   /* Force flush data with zero send otherwise Darwin and some BSD systems
      will add 5 seconds delay. Not required with TCP_CORK as switching off
      TCP_CORK always flushes socket buffer. */
@@ -633,50 +639,39 @@ socket_start_no_buffering_flush (struct MHD_Connection 
*connection)
 _MHD_static_inline bool
 socket_start_normal_buffering (struct MHD_Connection *connection)
 {
-#if defined(TCP_NODELAY)
-  bool res = true;
-  const MHD_SCKT_OPT_BOOL_ off_val = 0;
-#if defined(TCP_CORK)
-  MHD_SCKT_OPT_BOOL_ cork_val = 0;
-  socklen_t param_size = sizeof (cork_val);
-#endif /* TCP_CORK */
   mhd_assert(NULL != connection);
-#if defined(TCP_CORK)
-  /* Allow partial packets */
-  /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't 
enabled before
-     so try to check current value of TCP_CORK to prevent unrequested flushing 
*/
-  if ( (0 != getsockopt (connection->socket_fd,
-                         IPPROTO_TCP,
-                         TCP_CORK,
-                         (void*)&cork_val,
-                         &param_size)) ||
-       (0 != cork_val))
-    res = (0 == setsockopt (connection->socket_fd,
-                             IPPROTO_TCP,
-                             TCP_CORK,
-                             (const void *) &off_val,
-                             sizeof (off_val))) && res;
-#elif defined(TCP_NOPUSH)
-  /* Disable extra buffering */
-  /* No need to check current value as disabling TCP_NOPUSH will not flush 
partial
-     packet if TCP_NOPUSH wasn't enabled before */
-  res = (0 == setsockopt (connection->socket_fd,
+#if defined(MHD_TCP_CORK_NOPUSH)
+  if (connection->sk_tcp_cork_nopush_on)
+    {
+      const MHD_SCKT_OPT_BOOL_ off_val = 0;
+      /* Disable extra buffering */
+      if (0 == setsockopt (connection->socket_fd,
                            IPPROTO_TCP,
-                           TCP_NOPUSH,
+                           MHD_TCP_CORK_NOPUSH,
                            (const void *) &off_val,
-                           sizeof (off_val))) && res;
-#endif /* TCP_NOPUSH && !TCP_CORK */
-  /* Enable Nagle's algorithm for normal buffering */
-  res = (0 == setsockopt (connection->socket_fd,
+                           sizeof (off_val)))
+        {
+          connection->sk_tcp_cork_nopush_on = false;
+        }
+    }
+#endif /* MHD_TCP_CORK_NOPUSH */
+
+#if defined(TCP_NODELAY)
+  if (connection->sk_tcp_nodelay_on)
+    {
+      const MHD_SCKT_OPT_BOOL_ off_val = 0;
+      /* Enable Nagle's algorithm */
+      if (0 == setsockopt (connection->socket_fd,
                            IPPROTO_TCP,
                            TCP_NODELAY,
                            (const void *) &off_val,
-                           sizeof (off_val))) && res;
-  return res;
-#else  /* !TCP_NODELAY */
-  (void) connection;
-  return false;
-#endif /* !TCP_NODELAY */
+                           sizeof (off_val)))
+        {
+          connection->sk_tcp_nodelay_on = false;
+        }
+    }
+#endif /* TCP_NODELAY */
+  return !connection->sk_tcp_nodelay_on && !connection->sk_tcp_cork_nopush_on;
 }
 
 
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 2c162def..ea12a532 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -3020,6 +3020,15 @@ MHD_add_connection (struct MHD_Daemon *daemon,
                 _("Failed to set noninheritable mode on new client 
socket.\n"));
 #endif
     }
+
+  if ( (0 == (daemon->options & MHD_USE_TURBO)) &&
+       (! MHD_socket_buffering_reset_ (client_socket)) )
+    {
+#ifdef HAVE_MESSAGES
+      MHD_DLOG (daemon,
+                _("Failed to reset buffering mode on new client socket.\n"));
+#endif
+    }
   return internal_add_connection (daemon,
                                  client_socket,
                                  addr,
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index aa6af5e8..97db942f 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -601,6 +601,7 @@ enum MHD_ConnKeepAlive
   MHD_CONN_USE_KEEPALIVE = 1
 };
 
+
 /**
  * State kept for each HTTP request.
  */
@@ -863,6 +864,18 @@ struct MHD_Connection
   bool sk_nonblck;
 
   /**
+   * Indicate whether connection socket has TCP_NODELAY turned on / Nagle’s 
algorithm turned off.
+   * TCP_NODELAY should not be turned on when TCP_CORK/TCP_NOPUSH is turned 
off.
+   */
+  bool sk_tcp_nodelay_on;
+
+  /**
+   * Indicate whether connection socket has TCP_CORK/TCP_NOPUSH turned on.
+   * TCP_CORK/TCP_NOPUSH should not be turned on when TCP_NODELAY is turned 
off.
+   */
+  bool sk_tcp_cork_nopush_on;
+
+  /**
    * Has this socket been closed for reading (i.e.  other side closed
    * the connection)?  If so, we must completely close the connection
    * once we are done sending our response (and stop trying to read
diff --git a/src/microhttpd/mhd_sockets.c b/src/microhttpd/mhd_sockets.c
index 56a8a852..3504dc26 100644
--- a/src/microhttpd/mhd_sockets.c
+++ b/src/microhttpd/mhd_sockets.c
@@ -462,6 +462,41 @@ MHD_socket_noninheritable_ (MHD_socket sock)
 
 
 /**
+ * Change socket buffering mode to default.
+ *
+ * @param sock socket to manipulate
+ * @return non-zero if succeeded, zero otherwise
+ */
+int
+MHD_socket_buffering_reset_ (MHD_socket sock)
+{
+  int res = !0;
+#if defined(TCP_NODELAY) || defined(MHD_TCP_CORK_NOPUSH)
+  const MHD_SCKT_OPT_BOOL_ off_val = 0;
+#if defined(MHD_TCP_CORK_NOPUSH)
+  /* Disable extra buffering */
+  res = (0 == setsockopt (sock,
+                          IPPROTO_TCP,
+                          MHD_TCP_CORK_NOPUSH,
+                          (const void *) &off_val,
+                          sizeof (off_val))) && res;
+#endif /* MHD_TCP_CORK_NOPUSH */
+#if defined(TCP_NODELAY)
+  /* Enable Nagle's algorithm for normal buffering */
+  res = (0 == setsockopt (sock,
+                          IPPROTO_TCP,
+                          TCP_NODELAY,
+                          (const void *) &off_val,
+                          sizeof (off_val))) && res;
+#endif /* TCP_NODELAY */
+#else  /* !TCP_NODELAY && !MHD_TCP_CORK_NOPUSH */
+  (void) sock;
+#endif /* !TCP_NODELAY && !MHD_TCP_CORK_NOPUSH */
+  return res;
+}
+
+
+/**
  * Create a listen socket, with noninheritable flag if possible.
  *
  * @param pf protocol family to use
diff --git a/src/microhttpd/mhd_sockets.h b/src/microhttpd/mhd_sockets.h
index 9be34144..8663edd3 100644
--- a/src/microhttpd/mhd_sockets.h
+++ b/src/microhttpd/mhd_sockets.h
@@ -194,6 +194,19 @@
 #endif
 
 
+#if defined(TCP_CORK)
+/**
+ * Value of TCP_CORK or TCP_NOPUSH
+ */
+#define MHD_TCP_CORK_NOPUSH TCP_CORK
+#elif defined(TCP_NOPUSH)
+/**
+ * Value of TCP_CORK or TCP_NOPUSH
+ */
+#define MHD_TCP_CORK_NOPUSH TCP_NOPUSH
+#endif /* TCP_NOPUSH */
+
+
 /**
  * MHD_SCKT_OPT_BOOL_ is type for bool parameters for setsockopt()/getsockopt()
  */
@@ -736,6 +749,16 @@ int
 MHD_socket_noninheritable_ (MHD_socket sock);
 
 
+/**
+ * Change socket buffering mode to default.
+ *
+ * @param sock socket to manipulate
+ * @return non-zero if succeeded, zero otherwise
+ */
+int
+MHD_socket_buffering_reset_ (MHD_socket sock);
+
+
 #if defined(SOL_SOCKET) && defined(SO_NOSIGPIPE)
    static const int _MHD_socket_int_one = 1;
 /**

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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