Ver código fonte

Handler for websocket connection (Step 6/7)

Add an interface to register handler for websocket connections.
See enhancement #30 and question #101
bel 10 anos atrás
pai
commit
121ae6c7f6

+ 1 - 1
VS2012/civetweb/civetweb.vcxproj

@@ -39,7 +39,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v110_xp</PlatformToolset>
+    <PlatformToolset>v100</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   </PropertyGroup>

+ 1 - 1
VS2012/ex_embed_cpp/ex_embed_cpp.vcxproj

@@ -39,7 +39,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v110_xp</PlatformToolset>
+    <PlatformToolset>v100</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   </PropertyGroup>

+ 1 - 1
VS2012/ex_embedded_c/ex_embedded_c.vcxproj

@@ -46,7 +46,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v110_xp</PlatformToolset>
+    <PlatformToolset>v100</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   </PropertyGroup>

+ 2 - 1
VS2012/ex_websocket/ex_websocket.vcxproj

@@ -40,6 +40,7 @@
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
     <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v100</PlatformToolset>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
@@ -116,7 +117,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>USE_WEBSOCKET;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_WEBSOCKET;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     </ClCompile>
     <Link>
     <Link>

+ 2 - 1
VS2012/ex_websocket_client/ex_websocket_client.vcxproj

@@ -40,6 +40,7 @@
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
     <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v100</PlatformToolset>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
@@ -116,7 +117,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>USE_WEBSOCKET;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_WEBSOCKET;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     </ClCompile>
     <Link>
     <Link>

+ 1 - 0
VS2012/unit_test/unit_test.vcxproj

@@ -26,6 +26,7 @@
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
     <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v100</PlatformToolset>
   </PropertyGroup>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   <ImportGroup Label="ExtensionSettings">

+ 1 - 1
VS2012/upload/upload.vcxproj

@@ -46,7 +46,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v110_xp</PlatformToolset>
+    <PlatformToolset>v100</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   </PropertyGroup>

+ 4 - 5
examples/embedded_c/embedded_c.c

@@ -132,14 +132,13 @@ int WebSocketConnectHandler(const struct mg_connection * conn, void *cbdata)
     return reject;
     return reject;
 }
 }
 
 
-void WebSocketReadyHandler(const struct mg_connection * conn, void *cbdata)
+void WebSocketReadyHandler(struct mg_connection * conn, void *cbdata)
 {
 {
-    struct mg_context *ctx = mg_get_context((struct mg_connection *) /* TODO: check const_casts */ conn);
+    struct mg_context *ctx = mg_get_context(conn);
     int i;
     int i;
 
 
     const char * text = "Hello from the websocket ready handler";
     const char * text = "Hello from the websocket ready handler";
-    /* TODO: check "const struct mg_connection *" vs "struct mg_connection *" everywhere */
-    mg_websocket_write((struct mg_connection *)conn, WEBSOCKET_OPCODE_TEXT, text, strlen(text));
+    mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, text, strlen(text));
     fprintf(stdout, "Client added to the set of webserver connections\r\n\r\n");
     fprintf(stdout, "Client added to the set of webserver connections\r\n\r\n");
     mg_lock_context(ctx);
     mg_lock_context(ctx);
     for (i=0; i<MAX_WS_CLIENTS; i++) {
     for (i=0; i<MAX_WS_CLIENTS; i++) {
@@ -151,7 +150,7 @@ void WebSocketReadyHandler(const struct mg_connection * conn, void *cbdata)
     mg_unlock_context(ctx);
     mg_unlock_context(ctx);
 }
 }
 
 
-int WebsocketDataHandler(const struct mg_connection * conn, int bits, char * data, size_t len, void *cbdata)
+int WebsocketDataHandler(struct mg_connection * conn, int bits, char * data, size_t len, void *cbdata)
 {
 {
     fprintf(stdout, "Websocket got data:\r\n");
     fprintf(stdout, "Websocket got data:\r\n");
     fwrite(data, len, 1, stdout);
     fwrite(data, len, 1, stdout);

+ 3 - 3
examples/websocket_client/websocket_client.c

@@ -105,9 +105,9 @@ struct tclient_data {
     int closed;
     int closed;
 };
 };
 
 
-static int websocket_client_data_handler(const struct mg_connection *conn, int flags, char *data, size_t data_len, void * user_data)
+static int websocket_client_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len, void * user_data)
 {
 {
-    struct mg_context *ctx = mg_get_context(conn); /* TODO: const qualifier */
+    struct mg_context *ctx = mg_get_context(conn);
     struct tclient_data *pclient_data = (struct tclient_data *) mg_get_user_data(ctx);
     struct tclient_data *pclient_data = (struct tclient_data *) mg_get_user_data(ctx);
 
 
     printf("Client received data from server: ");
     printf("Client received data from server: ");
@@ -124,7 +124,7 @@ static int websocket_client_data_handler(const struct mg_connection *conn, int f
 
 
 static void websocket_client_close_handler(const struct mg_connection *conn, void * user_data)
 static void websocket_client_close_handler(const struct mg_connection *conn, void * user_data)
 {
 {
-    struct mg_context *ctx = mg_get_context(conn); /* TODO: const qualifier */
+    struct mg_context *ctx = mg_get_context(conn);
     struct tclient_data *pclient_data = (struct tclient_data *) mg_get_user_data(ctx);
     struct tclient_data *pclient_data = (struct tclient_data *) mg_get_user_data(ctx);
 
 
     printf("Client: Close handler\n");
     printf("Client: Close handler\n");

+ 3 - 3
include/civetweb.h

@@ -293,8 +293,8 @@ CIVETWEB_API void mg_set_request_handler(struct mg_context *ctx, const char *uri
    mg_connection_close_handler
    mg_connection_close_handler
        Is called, when the connection is closed.*/
        Is called, when the connection is closed.*/
 typedef int  (*mg_websocket_connect_handler)(const struct mg_connection *, void *);
 typedef int  (*mg_websocket_connect_handler)(const struct mg_connection *, void *);
-typedef void (*mg_websocket_ready_handler)(const struct mg_connection *, void *);
-typedef int  (*mg_websocket_data_handler)(const struct mg_connection *, int, char *, size_t, void *);
+typedef void (*mg_websocket_ready_handler)(struct mg_connection *, void *);
+typedef int  (*mg_websocket_data_handler)(struct mg_connection *, int, char *, size_t, void *);
 typedef void (*mg_websocket_close_handler)(const struct mg_connection *, void *);
 typedef void (*mg_websocket_close_handler)(const struct mg_connection *, void *);
 
 
 /* mg_set_websocket_handler
 /* mg_set_websocket_handler
@@ -320,7 +320,7 @@ CIVETWEB_API const char *mg_get_option(const struct mg_context *ctx, const char
 
 
 
 
 /* Get context from connection. */
 /* Get context from connection. */
-CIVETWEB_API struct mg_context *mg_get_context(struct mg_connection *conn);
+CIVETWEB_API struct mg_context *mg_get_context(const struct mg_connection *conn);
 
 
 
 
 /* Get user data passed to mg_start from context. */
 /* Get user data passed to mg_start from context. */

+ 15 - 7
src/civetweb.c

@@ -1220,7 +1220,7 @@ const char *mg_get_option(const struct mg_context *ctx, const char *name)
     }
     }
 }
 }
 
 
-struct mg_context *mg_get_context(struct mg_connection * conn)
+struct mg_context *mg_get_context(const struct mg_connection * conn)
 {
 {
     return (conn == NULL) ? (struct mg_context *)NULL : (conn->ctx);
     return (conn == NULL) ? (struct mg_context *)NULL : (conn->ctx);
 }
 }
@@ -5755,7 +5755,7 @@ static void read_websocket(struct mg_connection *conn, mg_websocket_data_handler
        The original websocket upgrade request is never removed, so the queue
        The original websocket upgrade request is never removed, so the queue
        begins after it. */
        begins after it. */
     unsigned char *buf = (unsigned char *) conn->buf + conn->request_len;
     unsigned char *buf = (unsigned char *) conn->buf + conn->request_len;
-    int n, error;
+    int n, error, exit_by_callback;
 
 
     /* body_len is the length of the entire queue in bytes
     /* body_len is the length of the entire queue in bytes
        len is the length of the current message
        len is the length of the current message
@@ -5867,6 +5867,7 @@ static void read_websocket(struct mg_connection *conn, mg_websocket_data_handler
 
 
             /* Exit the loop if callback signalled to exit,
             /* Exit the loop if callback signalled to exit,
                or "connection close" opcode received. */
                or "connection close" opcode received. */
+            exit_by_callback = 0;
             if ((ws_data_handler != NULL &&
             if ((ws_data_handler != NULL &&
 #ifdef USE_LUA
 #ifdef USE_LUA
                  (conn->lua_websocket_state == NULL) &&
                  (conn->lua_websocket_state == NULL) &&
@@ -5876,13 +5877,19 @@ static void read_websocket(struct mg_connection *conn, mg_websocket_data_handler
                 (conn->lua_websocket_state &&
                 (conn->lua_websocket_state &&
                  !lua_websocket_data(conn, conn->lua_websocket_state, mop, data, data_len)) ||
                  !lua_websocket_data(conn, conn->lua_websocket_state, mop, data, data_len)) ||
 #endif
 #endif
-                (mop & 0xf) == WEBSOCKET_OPCODE_CONNECTION_CLOSE) {  /* Opcode == 8, connection close */
-                break;
+                0) {
+                exit_by_callback = 1;
             }
             }
 
 
             if (data != mem) {
             if (data != mem) {
                 mg_free(data);
                 mg_free(data);
             }
             }
+
+            if (exit_by_callback || ((mop & 0xf) == WEBSOCKET_OPCODE_CONNECTION_CLOSE)) {
+                /* Opcode == 8, connection close */
+                break;
+            }
+
             /* Not breaking the loop, process next websocket frame. */
             /* Not breaking the loop, process next websocket frame. */
         } else {
         } else {
             /* Read from the socket into the next available location in the
             /* Read from the socket into the next available location in the
@@ -5952,9 +5959,8 @@ static void handle_websocket_request(struct mg_connection *conn,
     const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
     const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
     int lua_websock = 0;
     int lua_websock = 0;
 
 
-#ifndef USE_LUA
+#if !defined(USE_LUA)
     (void)path;
     (void)path;
-    (void)is_callback_resource;
 #endif
 #endif
 
 
     /* Step 1: Check websocket protocol version. */
     /* Step 1: Check websocket protocol version. */
@@ -5974,7 +5980,7 @@ static void handle_websocket_request(struct mg_connection *conn,
         }
         }
     }
     }
 
 
-#ifdef USE_LUA
+#if defined(USE_LUA)
     /* Step 3: No callback. Check if Lua is responsible. */
     /* Step 3: No callback. Check if Lua is responsible. */
     else {
     else {
         /* Step 3.1: Check if Lua is responsible. */
         /* Step 3.1: Check if Lua is responsible. */
@@ -6011,11 +6017,13 @@ static void handle_websocket_request(struct mg_connection *conn,
         if (ws_ready_handler != NULL) {
         if (ws_ready_handler != NULL) {
             ws_ready_handler(conn, cbData);
             ws_ready_handler(conn, cbData);
         }
         }
+#if defined(USE_LUA)
     } else if (lua_websock) {
     } else if (lua_websock) {
         if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
         if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
             /* the ready handler returned false */
             /* the ready handler returned false */
             return;
             return;
         }
         }
+#endif
     }
     }
 
 
     /* Step 7: Enter the read loop */
     /* Step 7: Enter the read loop */

+ 1 - 0
testutils/testclient/testclient.vcxproj

@@ -26,6 +26,7 @@
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
     <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v100</PlatformToolset>
   </PropertyGroup>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   <ImportGroup Label="ExtensionSettings">

+ 1 - 0
testutils/testclient_chunked_linux/testclient2.vcxproj

@@ -26,6 +26,7 @@
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
     <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v100</PlatformToolset>
   </PropertyGroup>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   <ImportGroup Label="ExtensionSettings">