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:
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
};