Просмотр исходного кода

sketching support for upgrade handling

Christian Grothoff 9 лет назад
Родитель
Сommit
e0a43cb194

+ 4 - 0
ChangeLog

@@ -1,3 +1,7 @@
+Sat Aug 27 20:07:53 CEST 2016
+	Adding completely *untested* logic for HTTP "Upgrade"
+	handling. -CG
+
 Sat Aug 27 18:20:38 CEST 2016
 	Releasing libmicrohttpd 0.9.51. -CG
 

+ 3 - 4
src/include/microhttpd.h

@@ -126,7 +126,7 @@ typedef intptr_t ssize_t;
  * Current version of the library.
  * 0x01093001 = 1.9.30-1.
  */
-#define MHD_VERSION 0x00095100
+#define MHD_VERSION 0x00095101
 
 /**
  * MHD-internal return code for "YES".
@@ -2221,7 +2221,6 @@ MHD_create_response_from_fd_at_offset64 (uint64_t size,
                                          uint64_t offset);
 
 
-#if 0
 /**
  * Enumeration for actions MHD should perform on the underlying socket
  * of the upgrade.  This API is not finalized, and in particular
@@ -2334,7 +2333,7 @@ typedef void
                       struct MHD_Connection *connection,
                       const char *extra_in,
                       size_t extra_in_size,
-                      MHD_SOCKET sock,
+                      MHD_socket sock,
                       struct MHD_UpgradeResponseHandle *urh);
 
 
@@ -2370,7 +2369,7 @@ typedef void
 _MHD_EXTERN struct MHD_Response *
 MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
 				 void *upgrade_handler_cls);
-#endif
+
 
 /**
  * Destroy a response object and associated resources.  Note that

+ 29 - 4
src/microhttpd/connection.c

@@ -736,7 +736,8 @@ keepalive_possible (struct MHD_Connection *connection)
     if (NULL == end)
       return MHD_YES;
     if ( (MHD_str_equal_caseless_ (end, "close")) ||
-         (MHD_str_equal_caseless_ (end, "upgrade")) )
+         ( (MHD_str_equal_caseless_ (end, "upgrade")) &&
+           (NULL == connection->response->upgrade_handler) ) )
       return MHD_NO;
    return MHD_YES;
   }
@@ -2222,6 +2223,9 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
           break;
         case MHD_CONNECTION_CLOSED:
           return MHD_YES;
+        case MHD_CONNECTION_UPGRADE:
+          EXTRA_CHECK (0);
+          break;
         default:
           /* shrink read buffer to how much is actually used */
           MHD_pool_reallocate (connection->pool,
@@ -2305,7 +2309,8 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
           do_write (connection);
 	  if (connection->state != MHD_CONNECTION_HEADERS_SENDING)
  	     break;
-          check_write_done (connection, MHD_CONNECTION_HEADERS_SENT);
+          check_write_done (connection,
+                            MHD_CONNECTION_HEADERS_SENT);
           break;
         case MHD_CONNECTION_HEADERS_SENT:
           EXTRA_CHECK (0);
@@ -2395,6 +2400,9 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
         case MHD_TLS_CONNECTION_INIT:
           EXTRA_CHECK (0);
           break;
+        case MHD_CONNECTION_UPGRADE:
+          EXTRA_CHECK (0);
+          break;
         default:
           EXTRA_CHECK (0);
 	  CONNECTION_CLOSE_ERROR (connection,
@@ -2586,9 +2594,9 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
             }
           if ( (NULL != connection->response) &&
 	       ( (MHD_str_equal_caseless_ (connection->method,
-				   MHD_HTTP_METHOD_POST)) ||
+                                           MHD_HTTP_METHOD_POST)) ||
 		 (MHD_str_equal_caseless_ (connection->method,
-				   MHD_HTTP_METHOD_PUT))) )
+                                           MHD_HTTP_METHOD_PUT))) )
             {
               /* we refused (no upload allowed!) */
               connection->remaining_upload_size = 0;
@@ -2722,6 +2730,21 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
             }
           else
             socket_start_normal_buffering (connection);
+          if (NULL != connection->response->upgrade_handler)
+            {
+              /* This connection is "upgraded".  Pass socket to application. */
+              if (MHD_YES !=
+                  MHD_response_execute_upgrade_ (connection->response,
+                                                 connection))
+                {
+                  /* upgrade failed, fail hard */
+                  CONNECTION_CLOSE_ERROR (connection,
+                                          NULL);
+                  continue;
+                }
+              connection->state = MHD_CONNECTION_UPGRADE;
+              continue;
+            }
 
           if (connection->have_chunked_upload)
             connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
@@ -2882,6 +2905,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
         case MHD_CONNECTION_CLOSED:
 	  cleanup_connection (connection);
 	  return MHD_NO;
+        case MHD_CONNECTION_UPGRADE:
+          return MHD_YES; /* keep open */
         default:
           EXTRA_CHECK (0);
           break;

+ 7 - 3
src/microhttpd/internal.h

@@ -274,7 +274,6 @@ struct MHD_Response
    */
   MHD_ContentReaderFreeCallback crfc;
 
-#if 0
   /**
    * Application function to call once we are done sending the headers
    * of the response; NULL unless this is a response created with
@@ -286,7 +285,6 @@ struct MHD_Response
    * Closure for @e uh.
    */
   void *upgrade_handler_cls;
-#endif
 
   /**
    * Mutex to synchronize access to @e data, @e size and
@@ -476,7 +474,13 @@ enum MHD_CONNECTION_STATE
    * Handshake messages will be processed in this state & while
    * in the #MHD_TLS_HELLO_REQUEST state
    */
-  MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_IN_CLEANUP + 1
+  MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_IN_CLEANUP + 1,
+
+  /**
+   * Connection was "upgraded" and socket is now under the
+   * control of the application.
+   */
+  MHD_CONNECTION_UPGRADE = MHD_TLS_CONNECTION_INIT + 1
 
 };
 

+ 14 - 17
src/microhttpd/response.c

@@ -1,6 +1,6 @@
 /*
      This file is part of libmicrohttpd
-     Copyright (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff
+     Copyright (C) 2007, 2009, 2010, 2016 Daniel Pittman and Christian Grothoff
 
      This library is free software; you can redistribute it and/or
      modify it under the terms of the GNU Lesser General Public
@@ -29,6 +29,9 @@
 #include "internal.h"
 #include "response.h"
 #include "mhd_limits.h"
+#include "mhd_sockets.h"
+#include "mhd_itc.h"
+#include "connection.h"
 
 #if defined(_WIN32) && defined(MHD_W32_MUTEX_)
 #ifndef WIN32_LEAN_AND_MEAN
@@ -577,7 +580,6 @@ MHD_create_response_from_buffer (size_t size,
 }
 
 
-#if 0
 /**
  * Handle given to the application to manage special
  * actions relating to MHD responses that "upgrade"
@@ -596,13 +598,13 @@ struct MHD_UpgradeResponseHandle
   /**
    * The socket we gave to the application (r/w).
    */
-  MHD_SOCKET app_sock;
+  MHD_socket app_socket;
 
   /**
    * If @a app_sock was a socketpair, our end of it, otherwise
    * #MHD_INVALID_SOCKET; (r/w).
    */
-  MHD_SOCKET mhd_sock;
+  MHD_socket mhd_socket;
 
 };
 
@@ -629,12 +631,12 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
   case MHD_UPGRADE_ACTION_CLOSE:
     /* Application is done with this connection, tear it down! */
     if ( (MHD_INVALID_SOCKET != urh->app_socket) &&
-         (0 != MHD_socket_close (urh->app_socket)) )
+         (0 != MHD_socket_close_ (urh->app_socket)) )
       MHD_PANIC ("close failed\n");
     if ( (MHD_INVALID_SOCKET != urh->mhd_socket) &&
-         (0 != MHD_socket_close (urh->mhd_socket)) )
+         (0 != MHD_socket_close_ (urh->mhd_socket)) )
       MHD_PANIC ("close failed\n");
-    MHD_connection_resume (urh->connection);
+    MHD_resume_connection (urh->connection);
     MHD_connection_close_ (urh->connection,
                            MHD_REQUEST_TERMINATED_COMPLETED_OK);
     free (urh);
@@ -659,9 +661,6 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
  * @return #MHD_YES on success, #MHD_NO on failure (will cause
  *        connection to be closed)
  */
-// FIXME: This function will need to be called at the right place(s)
-// in the connection processing (just after we are done sending the header)
-// (for responses that have the 'upgrade_header' callback set).
 int
 MHD_response_execute_upgrade_ (struct MHD_Response *response,
                                struct MHD_Connection *connection)
@@ -674,7 +673,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
   if (NULL == urh)
     return MHD_NO;
 #if HTTPS_SUPPORT
-  if (0 != (connection->daemon->flags & MHD_USE_SSL) )
+  if (0 != (connection->daemon->options & MHD_USE_SSL) )
   {
     /* FIXME: this is non-portable for now; W32 port pending... */
     if (0 != socketpair (AF_UNIX,
@@ -694,12 +693,12 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
                                connection,
                                connection->read_buffer,
                                rbo,
-                               urh->app_sock,
+                               urh->app_socket,
                                urh);
     /* As far as MHD is concerned, this connection is
        suspended; it will be resumed once we are done
        in the #MHD_upgrade_action() function */
-    MHD_connection_suspend (connection);
+    MHD_suspend_connection (connection);
     /* FIXME: also need to start some processing logic in _all_ MHD
        event loops for the sv traffic! (NOT IMPLEMENTED!!!) */
     return MHD_YES;
@@ -718,7 +717,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
   /* As far as MHD is concerned, this connection is
      suspended; it will be resumed once we are done
      in the #MHD_upgrade_action() function */
-  MHD_connection_suspend (connection);
+  MHD_suspend_connection (connection);
   return MHD_YES;
 }
 
@@ -758,7 +757,7 @@ MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
 {
   struct MHD_Response *response;
 
-  if (NULL == upgrade_header)
+  if (NULL == upgrade_handler)
     return NULL; /* invalid request */
   response = malloc (sizeof (struct MHD_Response));
   if (NULL == response)
@@ -769,14 +768,12 @@ MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
       free (response);
       return NULL;
     }
-  urh->response = response;
   response->upgrade_handler = upgrade_handler;
   response->upgrade_handler_cls = upgrade_handler_cls;
   response->total_size = MHD_SIZE_UNKNOWN;
   response->reference_count = 1;
   return response;
 }
-#endif
 
 
 /**

+ 18 - 0
src/microhttpd/response.h

@@ -36,4 +36,22 @@ void
 MHD_increment_response_rc (struct MHD_Response *response);
 
 
+/**
+ * We are done sending the header of a given response
+ * to the client.  Now it is time to perform the upgrade
+ * and hand over the connection to the application.
+ *
+ * @param response the response that was created for an upgrade
+ * @param connection the specific connection we are upgrading
+ * @return #MHD_YES on success, #MHD_NO on failure (will cause
+ *        connection to be closed)
+ */
+// FIXME: This function will need to be called at the right place(s)
+// in the connection processing (just after we are done sending the header)
+// (for responses that have the 'upgrade_header' callback set).
+int
+MHD_response_execute_upgrade_ (struct MHD_Response *response,
+                               struct MHD_Connection *connection);
+
+
 #endif