[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,
- ¶m_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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] [libmicrohttpd] branch master updated: Track socket CORK/NODELAY states to avoid extra syscalls,
gnunet <=