libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 602a14fb5d0e81e1f59bf8e1012cbb034d978fe4
parent bd05eb27037144c3058c30dc20640d4b1ffa68a3
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Wed, 25 Nov 2015 18:45:22 +0000

Reduce last packet response delay observable with keep-alive on BSD and Darwin platforms

Diffstat:
MChangeLog | 4++++
Mconfigure.ac | 3---
Msrc/include/microhttpd.h | 2+-
Msrc/microhttpd/connection.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mw32/VS2013/MHD_config.h | 8--------
5 files changed, 55 insertions(+), 20 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,7 @@ +Wed Nov 25 17:02:53 CET 2015 + Remove 200ms delay observable with keep-alive on Darwin + and *BSD platfroms. -EG + Tue Nov 10 15:25:48 CET 2015 Fix issue with shutdown if connection was resumed just before shutdown. -FC diff --git a/configure.ac b/configure.ac @@ -544,9 +544,6 @@ have_inet6=no ]) AC_MSG_RESULT($have_inet6) -# TCP_CORK and TCP_NOPUSH -AC_CHECK_DECLS([TCP_CORK, TCP_NOPUSH], [], [], [[#include <netinet/tcp.h>]]) - HIDDEN_VISIBILITY_CFLAGS="" case "$host" in *-*-mingw*) diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -130,7 +130,7 @@ typedef intptr_t ssize_t; * Current version of the library. * 0x01093001 = 1.9.30-1. */ -#define MHD_VERSION 0x00094602 +#define MHD_VERSION 0x00094603 /** * MHD-internal return code for "YES". diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c @@ -2422,14 +2422,29 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) } connection->state = MHD_CONNECTION_HEADERS_SENDING; -#if HAVE_DECL_TCP_CORK - /* starting header send, set TCP cork */ - { + /* starting send, prefer fill full buffer before sending */ +#if defined(TCP_CORK) + { /* Send only full packets */ const _MHD_SOCKOPT_BOOL_TYPE val = 1; setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val, sizeof (val)); } -#endif +#elif defined(TCP_NODELAY) || defined(TCP_NOPUSH) +#if defined(TCP_NOPUSH) + { /* Buffer data before sending */ + const _MHD_SOCKOPT_BOOL_TYPE on_val = 1; + setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&on_val, + sizeof (on_val)); + } +#endif /* TCP_NOPUSH */ +#if defined(TCP_NODELAY) + { /* Enable Nagle's algorithm, even if it was disabled somehow */ + const _MHD_SOCKOPT_BOOL_TYPE off_val = 0; + setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&off_val, + sizeof (off_val)); + } +#endif /* TCP_NODELAY */ +#endif /* TCP_NODELAY || TCP_NOPUSH */ break; case MHD_CONNECTION_HEADERS_SENDING: /* no default action */ @@ -2506,14 +2521,35 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) /* no default action */ break; case MHD_CONNECTION_FOOTERS_SENT: -#if HAVE_DECL_TCP_CORK - /* done sending, uncork */ - { + /* done sending, send last partial packet immediately if possible */ +#if defined(TCP_CORK) + { /* Flush buffered data, allow partial packets */ const _MHD_SOCKOPT_BOOL_TYPE val = 0; setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val, sizeof (val)); } -#endif +#elif defined(TCP_NODELAY) || defined(TCP_NOPUSH) +#if defined(TCP_NODELAY) + { /* Disable Nagle's algorithm to push partial packet */ + const _MHD_SOCKOPT_BOOL_TYPE on_val = 1; + setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&on_val, + sizeof (on_val)); + } +#endif /* TCP_NODELAY */ +#if defined(TCP_NOPUSH) + { /* Send data without extra buffering, may flush pending data on some platforms */ + const _MHD_SOCKOPT_BOOL_TYPE off_val = 0; + setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&off_val, + sizeof (off_val)); + } +#endif /* TCP_NOPUSH */ + { /* force flush data with zero send otherwise Darwin and some BSD systems + will add 5 seconds delay */ + const int dummy = 0; + (void)send (connection->socket_fd, (const void*)&dummy, 0, 0); + } +#endif /* TCP_NODELAY || TCP_NOPUSH */ + end = MHD_get_response_header (connection->response, MHD_HTTP_HEADER_CONNECTION); @@ -2557,6 +2593,12 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) else { /* can try to keep-alive */ +#if !defined(TCP_CORK) && defined(TCP_NODELAY) + /* Enable Nagle's algorithm */ + const _MHD_SOCKOPT_BOOL_TYPE off_val = 0; + setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&off_val, + sizeof (off_val)); +#endif /* !TCP_CORK && TCP_NODELAY */ connection->version = NULL; connection->state = MHD_CONNECTION_INIT; /* Reset the read buffer to the starting size, diff --git a/w32/VS2013/MHD_config.h b/w32/VS2013/MHD_config.h @@ -62,14 +62,6 @@ don't. */ #define HAVE_DECL_SOCK_NONBLOCK 0 -/* Define to 1 if you have the declaration of `TCP_CORK', and to 0 if you - don't. */ -#define HAVE_DECL_TCP_CORK 0 - -/* Define to 1 if you have the declaration of `TCP_NOPUSH', and to 0 if you - don't. */ -#define HAVE_DECL_TCP_NOPUSH 0 - /* Define to 1 if you have the `_lseeki64' function. */ #define HAVE___LSEEKI64 1