Bladeren bron

Add support for TCP FASTOPEN connections.

Sree Harsha Totakura 12 jaren geleden
bovenliggende
commit
bc1137bd60
5 gewijzigde bestanden met toevoegingen van 80 en 3 verwijderingen
  1. 1 1
      AUTHORS
  2. 16 0
      doc/libmicrohttpd.texi
  3. 18 2
      src/include/microhttpd.h
  4. 35 0
      src/microhttpd/daemon.c
  5. 10 0
      src/microhttpd/internal.h

+ 1 - 1
AUTHORS

@@ -46,8 +46,8 @@ Matthew Mundell <[email protected]>
 Scott Goldman <[email protected]>
 Jared Cantwell
 Luke-Jr <[email protected]>
+Sree Harsha Totakura <[email protected]>
 
 Documentation contributions also came from:
 Marco Maggi <[email protected]>
 Sebastian Gerhardt <[email protected]>
-

+ 16 - 0
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
 

+ 18 - 2
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
 
 };
 

+ 35 - 0
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,
@@ -3228,6 +3241,10 @@ MHD_start_daemon_va (unsigned int flags,
 #if ! HTTPS_SUPPORT
   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;
@@ -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))
 	{

+ 10 - 0
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
 };