|  | @@ -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,
 | 
	
		
			
				|  |  |                                       const char *path,
 | 
	
		
			
				|  |  | -                                     int is_script_resource,
 | 
	
		
			
				|  |  | +                                     int is_callback_resource,
 | 
	
		
			
				|  |  |                                       mg_websocket_connect_handler ws_connect_handler,
 | 
	
		
			
				|  |  |                                       mg_websocket_ready_handler ws_ready_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");
 | 
	
		
			
				|  |  | -#ifdef USE_LUA
 | 
	
		
			
				|  |  |      int lua_websock = 0;
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifndef USE_LUA
 | 
	
		
			
				|  |  |      (void)path;
 | 
	
		
			
				|  |  | -    (void)is_script_resource;
 | 
	
		
			
				|  |  | +    (void)is_callback_resource;
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /* Step 1: Check websocket protocol version. */
 | 
	
		
			
				|  |  |      if (version == NULL || strcmp(version, "13") != 0) {
 | 
	
		
			
				|  |  | +        /* Reject wrong versions */
 | 
	
		
			
				|  |  |          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
 | 
	
		
			
				|  |  | +    /* 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]) {
 | 
	
		
			
				|  |  |              lua_websock = match_prefix(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) {
 | 
	
		
			
				|  |  | +            /* Step 3.2: Lua is responsible: call it. */
 | 
	
		
			
				|  |  |              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;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          } 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
 | 
	
		
			
				|  |  |                                       );
 | 
	
		
			
				|  |  |  #endif
 | 
	
	
		
			
				|  | @@ -6663,7 +6696,7 @@ static void handle_request(struct mg_connection *conn)
 | 
	
		
			
				|  |  |      /* 8. handle websocket requests */
 | 
	
		
			
				|  |  |  #if defined(USE_WEBSOCKET)
 | 
	
		
			
				|  |  |      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_ready_wrapper,
 | 
	
		
			
				|  |  |                                   deprecated_websocket_data_wrapper,
 |