Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add config option for enabling the TCP_NODELAY option on client sockets. #25

Open
wants to merge 1 commit into
base: ceph-jewel
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion src/civetweb.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ struct pollfd {
#include <sys/socket.h>
#include <sys/poll.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/utsname.h>
Expand Down Expand Up @@ -711,6 +712,7 @@ enum {
LUA_WEBSOCKET_EXTENSIONS,
#endif
ACCESS_CONTROL_ALLOW_ORIGIN, ERROR_PAGES,
CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the socket option typedef TCP_NODELAY */

NUM_OPTIONS
};
Expand Down Expand Up @@ -761,6 +763,7 @@ static struct mg_option config_options[] = {
#endif
{"access_control_allow_origin", CONFIG_TYPE_STRING, "*"},
{"error_pages", CONFIG_TYPE_DIRECTORY, NULL},
{"tcp_nodelay", CONFIG_TYPE_BOOLEAN, "no"},

{NULL, CONFIG_TYPE_UNKNOWN, NULL}
};
Expand Down Expand Up @@ -6350,6 +6353,23 @@ static void reset_per_request_attributes(struct mg_connection *conn)
conn->is_chunked = 0;
}

typedef const char *SOCK_OPT_TYPE;

static int
set_tcp_nodelay(SOCKET sock, int nodelay_on)
{
if (setsockopt(sock,
IPPROTO_TCP,
TCP_NODELAY,
(SOCK_OPT_TYPE)&nodelay_on,
sizeof(nodelay_on)) != 0) {
/* Error */
return 1;
}
/* OK */
return 0;
}

static void close_socket_gracefully(struct mg_connection *conn)
{
#if defined(_WIN32)
Expand Down Expand Up @@ -6813,7 +6833,25 @@ static void accept_new_connection(const struct socket *listener,
"%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
__func__, strerror(ERRNO));
}
set_sock_timeout(so.sock, atoi(ctx->config[REQUEST_TIMEOUT]));

/* Disable TCP Nagle's algorithm. Normally TCP packets are coalesced
* to effectively fill up the underlying IP packet payload and
* reduce the overhead of sending lots of small buffers. However
* this hurts the server's throughput (ie. operations per second)
* when HTTP 1.1 persistent connections are used and the responses
* are relatively small (eg. less than 1400 bytes).
*/
if ((ctx != NULL) && (ctx->config[CONFIG_TCP_NODELAY] != NULL)
&& (!strcmp(ctx->config[CONFIG_TCP_NODELAY], "1"))) {
if (set_tcp_nodelay(so.sock, 1) != 0) {
mg_cry(fc(ctx),
"%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s",
__func__,
strerror(ERRNO));
}
}

set_sock_timeout(so.sock, atoi(ctx->config[REQUEST_TIMEOUT]));
produce_socket(ctx, &so);
}
}
Expand Down