1
0
mirror of https://github.com/lammertb/libhttp.git synced 2025-07-29 21:01:13 +03:00

Handler for websocket connection (Step 6/7)

Add an interface to register handler for websocket connections.
See enhancement #30 and question #101
This commit is contained in:
bel
2015-04-19 22:09:09 +02:00
parent c9f84988c7
commit 121ae6c7f6
13 changed files with 36 additions and 24 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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">

View File

@ -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>

View File

@ -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(conn, WEBSOCKET_OPCODE_TEXT, text, strlen(text));
mg_websocket_write((struct mg_connection *)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);

View File

@ -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");

View File

@ -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 void (*mg_websocket_ready_handler)(struct mg_connection *, void *);
typedef int (*mg_websocket_data_handler)(const struct mg_connection *, int, char *, size_t, 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. */

View File

@ -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 */ 0) {
break; 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 */

View File

@ -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">

View File

@ -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">