瀏覽代碼

Handler for websocket connection (Step 5/?)

Add an interface to register handler for websocket connections.
See enhancement #30 and question #101
bel 10 年之前
父節點
當前提交
7a709e5633
共有 1 個文件被更改,包括 63 次插入30 次删除
  1. 63 30
      src/civetweb.c

+ 63 - 30
src/civetweb.c

@@ -5941,7 +5941,7 @@ int mg_websocket_write(struct mg_connection* conn, int opcode, const char* data,
 
 
 static void handle_websocket_request(struct mg_connection *conn,
 static void handle_websocket_request(struct mg_connection *conn,
                                      const char *path,
                                      const char *path,
-                                     int is_script_resource,
+                                     int is_callback_resource,
                                      mg_websocket_connect_handler ws_connect_handler,
                                      mg_websocket_connect_handler ws_connect_handler,
                                      mg_websocket_ready_handler ws_ready_handler,
                                      mg_websocket_ready_handler ws_ready_handler,
                                      mg_websocket_data_handler ws_data_handler,
                                      mg_websocket_data_handler ws_data_handler,
@@ -5950,23 +5950,34 @@ 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");
-#ifdef USE_LUA
     int lua_websock = 0;
     int lua_websock = 0;
-#endif
 
 
 #ifndef USE_LUA
 #ifndef USE_LUA
     (void)path;
     (void)path;
-    (void)is_script_resource;
+    (void)is_callback_resource;
 #endif
 #endif
 
 
+    /* Step 1: Check websocket protocol version. */
     if (version == NULL || strcmp(version, "13") != 0) {
     if (version == NULL || strcmp(version, "13") != 0) {
+        /* Reject wrong versions */
         send_http_error(conn, 426, "%s", "Protocol upgrade required");
         send_http_error(conn, 426, "%s", "Protocol upgrade required");
-    } else if (ws_connect_handler != NULL &&
-               ws_connect_handler(conn, cbData) != 0) {
-        /* C callback has returned non-zero, do not proceed with handshake. */
-        /* The C callback is called before Lua and may prevent Lua from handling the websocket. */
-    } else {
+        return;
+    }
+
+    /* Step 2: If a callback is responsible, call it. */
+    if (is_callback_resource) {
+        if (ws_connect_handler != NULL && ws_connect_handler(conn, cbData) != 0) {
+            /* C callback has returned non-zero, do not proceed with handshake. */
+            /* Note that C callbacks are no longer called when Lua is responsible,
+               so C can no longer filter callbacks for Lua. */
+            return;
+        }
+    }
+
 #ifdef USE_LUA
 #ifdef USE_LUA
+    /* Step 3: No callback. Check if Lua is responsible. */
+    else {
+        /* Step 3.1: Check if Lua is responsible. */
         if (conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
         if (conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
             lua_websock = match_prefix(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS],
             lua_websock = match_prefix(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS],
                                        (int)strlen(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
                                        (int)strlen(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
@@ -5974,27 +5985,49 @@ static void handle_websocket_request(struct mg_connection *conn,
         }
         }
 
 
         if (lua_websock) {
         if (lua_websock) {
+            /* Step 3.2: Lua is responsible: call it. */
             conn->lua_websocket_state = lua_websocket_new(path, conn);
             conn->lua_websocket_state = lua_websocket_new(path, conn);
-            if (conn->lua_websocket_state) {
-                send_websocket_handshake(conn);
-                if (lua_websocket_ready(conn, conn->lua_websocket_state)) {
-                    read_websocket(conn, NULL, NULL);
-                }
-            }
-        } else
-#endif
-        {
-            /* No Lua websock script specified. */
-            send_websocket_handshake(conn);
-            if (ws_ready_handler != NULL) {
-                ws_ready_handler(conn, cbData);
+            if (!conn->lua_websocket_state) {
+                /* Lua rejected the new client */
+                return;
             }
             }
-            read_websocket(conn, ws_data_handler, cbData);
         }
         }
+    }
+#endif
+
+    /* Step 4: Check if there is a responsible websocket handler. */
+    if (!is_callback_resource && !lua_websock) {
+        /* There is no callback, an Lua is not responsible either. */
+        /* Reply with a 404 Not Found or with nothing at all? TODO: check if this is correct for websockets */
+        send_http_error(conn, 404, "%s", "Not found");
+        return;
+    }
 
 
-        if (ws_close_handler) {
-            ws_close_handler(conn, cbData);
+    /* Step 5: The websocket connection has been accepted */
+    send_websocket_handshake(conn);
+
+    /* Step 6: Call the ready handler */
+    if (is_callback_resource) {
+        if (ws_ready_handler != NULL) {
+            ws_ready_handler(conn, cbData);
         }
         }
+    } else if (lua_websock) {
+        if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
+            /* the ready handler returned false */
+            return;
+        }
+    }
+
+    /* Step 7: Enter the read loop */
+    if (is_callback_resource) {
+        read_websocket(conn, ws_data_handler, cbData);
+    } else if (lua_websock) {
+        read_websocket(conn, NULL, NULL);
+    }
+
+    /* Step 8: Call the close handler */
+    if (ws_close_handler) {
+        ws_close_handler(conn, cbData);
     }
     }
 }
 }
 
 
@@ -6649,10 +6682,10 @@ static void handle_request(struct mg_connection *conn)
                 goto auth_check;
                 goto auth_check;
             }
             }
         } else {
         } else {
-#if defined(USE_WEBSOCKET)            
-            handle_websocket_request(conn, path, 
-                                     0 /* do not use is_script_resource here */, 
-                                     ws_connect_handler, ws_ready_handler, ws_data_handler, ws_close_handler, 
+#if defined(USE_WEBSOCKET)
+            handle_websocket_request(conn, path,
+                                     is_callback_resource,
+                                     ws_connect_handler, ws_ready_handler, ws_data_handler, ws_close_handler,
                                      callback_data
                                      callback_data
                                      );
                                      );
 #endif
 #endif
@@ -6663,7 +6696,7 @@ static void handle_request(struct mg_connection *conn)
     /* 8. handle websocket requests */
     /* 8. handle websocket requests */
 #if defined(USE_WEBSOCKET)
 #if defined(USE_WEBSOCKET)
     if (is_websocket_request) {
     if (is_websocket_request) {
-        handle_websocket_request(conn, path, is_script_resource,
+        handle_websocket_request(conn, path, is_callback_resource,
                                  deprecated_websocket_connect_wrapper,
                                  deprecated_websocket_connect_wrapper,
                                  deprecated_websocket_ready_wrapper,
                                  deprecated_websocket_ready_wrapper,
                                  deprecated_websocket_data_wrapper,
                                  deprecated_websocket_data_wrapper,