ソースを参照

Deduplicated connection's closure code, improved TLS closure.

Evgeny Grin (Karlson2k) 9 年 前
コミット
384cb2ab65

+ 39 - 5
src/microhttpd/connection.c

@@ -36,6 +36,9 @@
 #include "mhd_sockets.h"
 #include "mhd_compat.h"
 #include "mhd_itc.h"
+#ifdef HTTPS_SUPPORT
+#include "connection_https.h"
+#endif /* HTTPS_SUPPORT */
 
 
 /**
@@ -490,6 +493,41 @@ need_100_continue (struct MHD_Connection *connection)
 }
 
 
+/**
+ * Mark connection as "closed".
+ * @remark To be called from any thread.
+ *
+ * @param connection connection to close
+ */
+void
+MHD_connection_mark_closed_ (struct MHD_Connection *connection)
+{
+  struct MHD_Daemon * const daemon = connection->daemon;
+
+  connection->state = MHD_CONNECTION_CLOSED;
+  connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
+  if (0 == (daemon->options & MHD_USE_EPOLL_TURBO))
+    {
+#ifdef HTTPS_SUPPORT
+      /* For TLS connection use shutdown of TLS layer
+       * and do not shutdown TCP socket. This give more
+       * chances to send TLS closure data to remote side.
+       * Closure of TLS layer will be interpreted by
+       * remote side as end of transmission. */
+      if (0 != (daemon->options & MHD_USE_TLS))
+        {
+          if (MHD_NO == MHD_tls_connection_shutdown(connection))
+            shutdown (connection->socket_fd,
+                      SHUT_WR);
+        }
+      else /* Combined with next 'shutdown()'. */
+#endif /* HTTPS_SUPPORT */
+      shutdown (connection->socket_fd,
+                SHUT_WR);
+    }
+}
+
+
 /**
  * Close the given connection and give the
  * specified termination code to the user.
@@ -507,11 +545,7 @@ MHD_connection_close_ (struct MHD_Connection *connection,
   struct MHD_Response * const resp = connection->response;
 
   daemon = connection->daemon;
-  if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
-    shutdown (connection->socket_fd,
-              SHUT_WR);
-  connection->state = MHD_CONNECTION_CLOSED;
-  connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
+  MHD_connection_mark_closed_ (connection);
   if (NULL != resp)
     {
       connection->response = NULL;

+ 10 - 0
src/microhttpd/connection.h

@@ -84,6 +84,16 @@ int
 MHD_connection_handle_idle (struct MHD_Connection *connection);
 
 
+/**
+ * Mark connection as "closed".
+ * @remark To be called from any thread.
+ *
+ * @param connection connection to close
+ */
+void
+MHD_connection_mark_closed_ (struct MHD_Connection *connection);
+
+
 /**
  * Close the given connection and give the
  * specified termination code to the user.

+ 18 - 2
src/microhttpd/connection_https.c

@@ -152,8 +152,6 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection)
       break;
       /* close connection if necessary */
     case MHD_CONNECTION_CLOSED:
-      gnutls_bye (connection->tls_session,
-                  GNUTLS_SHUT_RDWR);
       return MHD_connection_handle_idle (connection);
     default:
       if ( (0 != gnutls_record_check_pending (connection->tls_session)) &&
@@ -183,4 +181,22 @@ MHD_set_https_callbacks (struct MHD_Connection *connection)
   connection->idle_handler = &MHD_tls_connection_handle_idle;
 }
 
+
+/**
+ * Initiate shutdown of TLS layer of connection.
+ *
+ * @param connection to use
+ * @return #MHD_YES if succeed, #MHD_NO otherwise.
+ */
+int
+MHD_tls_connection_shutdown (struct MHD_Connection *connection)
+{
+  if (MHD_NO != connection->tls_closed)
+    return MHD_NO;
+
+  connection->tls_closed = MHD_YES;
+  return (GNUTLS_E_SUCCESS == gnutls_bye(connection->tls_session, GNUTLS_SHUT_WR)) ?
+      MHD_YES : MHD_NO;
+}
+
 /* end of connection_https.c */

+ 11 - 1
src/microhttpd/connection_https.h

@@ -37,6 +37,16 @@
  */
 void 
 MHD_set_https_callbacks (struct MHD_Connection *connection);
-#endif
+
+
+/**
+ * Initiate shutdown of TLS layer of connection.
+ *
+ * @param connection to use
+ * @return #MHD_YES if succeed, #MHD_NO otherwise.
+ */
+int
+MHD_tls_connection_shutdown (struct MHD_Connection *connection);
+#endif /* HTTPS_SUPPORT */
 
 #endif

+ 5 - 4
src/microhttpd/daemon.c

@@ -3569,7 +3569,7 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
           struct MHD_UpgradeResponseHandle * const urh = ueh->urh;
 
           /* Each MHD_UpgradeResponseHandle can be processed two times:
-           * one for TLS data and one for socketpair data.
+           * one time for TLS data and one time for socketpair data.
            * If forwarding was finished on first time, second time must
            * be skipped as urh must not be used anymore. */
           if (MHD_NO != urh->clean_ready)
@@ -3915,10 +3915,11 @@ close_connection (struct MHD_Connection *pos)
 {
   struct MHD_Daemon *daemon = pos->daemon;
 
-  pos->state = MHD_CONNECTION_CLOSED;
-  pos->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
-    return; /* must let thread to the rest */
+    {
+      MHD_connection_mark_closed_ (pos);
+      return; /* must let thread to do the rest */
+    }
   MHD_connection_close_ (pos,
                          MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
   if (pos->connection_timeout == pos->daemon->connection_timeout)

+ 5 - 0
src/microhttpd/internal.h

@@ -911,6 +911,11 @@ struct MHD_Connection
    * even though the socket is not?
    */
   int tls_read_ready;
+
+  /**
+   * TLS layer was shut down?
+   */
+  int tls_closed;
 #endif
 
   /**