libmicrohttpd

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

commit bc1137bd60c3eeb2e7ed0e8a968674a4ae9b2a2a
parent c4c1456adf519c3b587d1e797f9b500d896fa3d2
Author: Sree Harsha Totakura <sreeharsha@totakura.in>
Date:   Mon, 24 Feb 2014 16:25:43 +0000

Add support for TCP FASTOPEN connections.


Diffstat:
MAUTHORS | 2+-
Mdoc/libmicrohttpd.texi | 16++++++++++++++++
Msrc/include/microhttpd.h | 20++++++++++++++++++--
Msrc/microhttpd/daemon.c | 35+++++++++++++++++++++++++++++++++++
Msrc/microhttpd/internal.h | 10++++++++++
5 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/AUTHORS b/AUTHORS @@ -46,8 +46,8 @@ Matthew Mundell <matthew.mundell@greenbone.net> Scott Goldman <scottjg@github.com> Jared Cantwell Luke-Jr <luke@dashjr.org> +Sree Harsha Totakura <sreeharsha@totakura.in> Documentation contributions also came from: Marco Maggi <marco.maggi-ipsu@poste.it> Sebastian Gerhardt <sebgerhardt@gmx.net> - diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi @@ -519,6 +519,12 @@ Enables using @code{MHD_suspend_connection} and additional pipes to be created, and code not using these calls should not pay the cost. +@item MHD_USE_TCP_FASTOPEN +@cindex listen +Enable TCP_FASTOPEN on the listen socket. TCP_FASTOPEN is currently +supported on Linux >= 3.6. On other systems using this option with +cause @code{MHD_start_daemon} to fail. + @end table @end deftp @@ -831,6 +837,16 @@ followed by a @code{size_t}). Not specifying this option or using a value of zero means using the system default (which is likely to differ based on your platform). +@item MHD_OPTION_TCP_FASTQUEUE_QUEUE_SIZE +@cindex listen +When the flag @code{MHD_USE_TCP_FASTOPEN} is used, this option sets the +connection handshake queue size for the TCP FASTOPEN connections. Note +that a TCP FASTOPEN connection handshake occupies more resources than a +TCP handshake as the SYN packets also contain DATA which is kept in the +associate state until handshake is completed. If this option is not +given the queue size is set to a default value of 10. This option must +be followed by a @code{unsigned int}. + @end table @end deftp diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -551,7 +551,14 @@ enum MHD_FLAG * Enable suspend/resume functions, which also implies setting up * pipes to signal resume. */ - MHD_USE_SUSPEND_RESUME = 8192 | MHD_USE_PIPE_FOR_SHUTDOWN + MHD_USE_SUSPEND_RESUME = 8192 | MHD_USE_PIPE_FOR_SHUTDOWN, + + /** + * Enable TCP_FASTOPEN option. This option is only available on Linux with a + * kernel >= 3.6. On other systems, using this option cases #MHD_start_daemon + * to fail. + */ + MHD_USE_TCP_FASTOPEN = 16384 }; @@ -817,7 +824,16 @@ enum MHD_OPTION * to access the SNI data using `gnutls_server_name_get()`. * Using this option requires GnuTLS 3.0 or higher. */ - MHD_OPTION_HTTPS_CERT_CALLBACK = 22 + MHD_OPTION_HTTPS_CERT_CALLBACK = 22, + + /** + * When using #MHD_USE_TCP_FASTOPEN, this option changes the default TCP + * fastopen queue length of 50. Note that having a larger queue size can + * cause resource exhaustion attack as the TCP stack has to now allocate + * resources for the SYN packet along with its DATA. This option should be + * followed by an `unsigned int` argument. + */ + MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE = 23 }; diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -75,6 +75,13 @@ */ #define MHD_POOL_SIZE_DEFAULT (32 * 1024) +#ifdef TCP_FASTOPEN +/** + * Default TCP fastopen queue size. + */ +#define MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT 10 +#endif + /** * Print extra messages with reasons for closing * sockets? (only adds non-error messages). @@ -2957,6 +2964,11 @@ parse_options_va (struct MHD_Daemon *daemon, case MHD_OPTION_THREAD_STACK_SIZE: daemon->thread_stack_size = va_arg (ap, size_t); break; +#ifdef TCP_FASTOPEN + case MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE: + daemon->fastopen_queue_size = va_arg (ap, unsigned int); + break; +#endif case MHD_OPTION_ARRAY: oa = va_arg (ap, struct MHD_OptionItem*); i = 0; @@ -2981,6 +2993,7 @@ parse_options_va (struct MHD_Daemon *daemon, case MHD_OPTION_CONNECTION_TIMEOUT: case MHD_OPTION_PER_IP_CONNECTION_LIMIT: case MHD_OPTION_THREAD_POOL_SIZE: + case MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE: if (MHD_YES != parse_options (daemon, servaddr, opt, @@ -3229,6 +3242,10 @@ MHD_start_daemon_va (unsigned int flags, if (0 != (flags & MHD_USE_SSL)) return NULL; #endif +#ifndef TCP_FASTOPEN + if (0 != (flags & MHD_USE_TCP_FASTSEND)) + return NULL; +#endif if (NULL == dh) return NULL; if (NULL == (daemon = malloc (sizeof (struct MHD_Daemon)))) @@ -3541,6 +3558,24 @@ MHD_start_daemon_va (unsigned int flags, MHD_PANIC ("close failed\n"); goto free_and_fail; } +#ifdef TCP_FASTOPEN + if (0 != (flags & MHD_USE_TCP_FASTOPEN)) + { + if (0 == daemon->fastopen_queue_size) + daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT; + if (0 != setsockopt (socket_fd, + IPPROTO_TCP, TCP_FASTOPEN, + &daemon->fastopen_queue_size, + sizeof (daemon->fastopen_queue_size))) + { +#if HAVE_MESSAGES + MHD_DLOG (daemon, + "setsockopt failed: %s\n", + MHD_socket_last_strerr_ ()); +#endif + } + } +#endif #if EPOLL_SUPPORT if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY)) { diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h @@ -39,6 +39,10 @@ #if EPOLL_SUPPORT #include <sys/epoll.h> #endif +#if HAVE_NETINET_TCP_H +/* for TCP_FASTOPEN */ +#include <netinet/tcp.h> +#endif /** @@ -1228,6 +1232,12 @@ struct MHD_Daemon #endif +#ifdef TCP_FASTOPEN + /** + * The queue size for incoming SYN + DATA packets. + */ + unsigned int fastopen_queue_size; +#endif };