diff --git a/lib/handshake.c b/lib/handshake.c index a1f0f0de..05547b02 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -97,7 +97,7 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len) if (wsi->callback) (wsi->callback)(wsi, LWS_CALLBACK_HTTP, &wsi->user_space[0], - NULL, 0); + wsi->utf8_token[WSI_TOKEN_GET_URI].token, 0); wsi->state = WSI_STATE_HTTP; return 0; } @@ -111,6 +111,14 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len) !wsi->utf8_token[WSI_TOKEN_KEY2].token_len) /* completed header processing, but missing some bits */ goto bail; + + /* Make sure user side is happy about protocol */ + + if (wsi->callback) + wsi->callback(wsi, LWS_CALLBACK_PROTOCOL_FILTER, + &wsi->user_space[0], + wsi->utf8_token[WSI_TOKEN_PROTOCOL].token, + 0); /* create the response packet */ diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index cba14caf..f443d8f5 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -28,7 +28,8 @@ enum libwebsocket_callback_reasons { LWS_CALLBACK_CLOSED, LWS_CALLBACK_SEND, LWS_CALLBACK_RECEIVE, - LWS_CALLBACK_HTTP + LWS_CALLBACK_HTTP, + LWS_CALLBACK_PROTOCOL_FILTER, }; enum libwebsocket_write_protocol { @@ -81,6 +82,9 @@ libwebsocket_write(struct libwebsocket *, unsigned char *buf, size_t len, extern const char * libwebsocket_get_uri(struct libwebsocket *wsi); +extern const char * +libwebsocket_get_protocol(struct libwebsocket *wsi); + extern int libwebsockets_serve_http_file(struct libwebsocket *wsi, const char * file, const char * content_type); diff --git a/lib/parsers.c b/lib/parsers.c index abfa53d1..c3696a74 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -45,10 +45,21 @@ const struct lws_tokens lws_tokens[WSI_TOKEN_COUNT] = { const char * libwebsocket_get_uri(struct libwebsocket *wsi) { - if (wsi->utf8_token[WSI_TOKEN_GET_URI].token) - return wsi->utf8_token[WSI_TOKEN_GET_URI].token; - - return NULL; + return wsi->utf8_token[WSI_TOKEN_GET_URI].token; +} + +/** + * libwebsocket_get_protocol() - Return the list of protocols being requested + * @wsi: Websocket instance + * + * The user code can find out which protocols the client is asking to + * work with by calling this. It may return NULL if there was no + * protocol header specified. + */ + +const char * libwebsocket_get_protocol(struct libwebsocket *wsi) +{ + return wsi->utf8_token[WSI_TOKEN_PROTOCOL].token; } diff --git a/libwebsockets-api-doc.html b/libwebsockets-api-doc.html index 0c2d8eb4..7581b27c 100644 --- a/libwebsockets-api-doc.html +++ b/libwebsockets-api-doc.html @@ -69,6 +69,22 @@ If the client opened the connection with "http://127.0.0.1/xyz/abc.d" then this call will return a pointer to "/xyz/abc.d"
+

libwebsocket_get_protocol - Return the list of protocols being requested

+const char * +libwebsocket_get_protocol +(struct libwebsocket * wsi) +

Arguments

+
+
wsi +
Websocket instance +
+

Description

+
+The user code can find out which protocols the client is asking to +work with by calling this. It may return NULL if there was no +protocol header specified. +
+

libwebsocket_write - Apply protocol then write data to client

int libwebsocket_write diff --git a/test-server/test-server.c b/test-server/test-server.c index 74c3f61b..bfc3c857 100644 --- a/test-server/test-server.c +++ b/test-server/test-server.c @@ -55,21 +55,32 @@ struct per_session_data { * LWS_CALLBACK_ESTABLISHED reason. * * LWS_CALLBACK_ESTABLISHED: after successful websocket handshake + * * LWS_CALLBACK_CLOSED: when the websocket session ends + * * LWS_CALLBACK_SEND: opportunity to send to client (you would use * libwebsocket_write() taking care about the * special buffer requirements * LWS_CALLBACK_RECEIVE: data has appeared for the server, it can be - * found at *in and is len bytes long - * LWS_CALLBACK_HTTP: an http request has come from a client that is not + * found at *in and is len bytes long + * + * LWS_CALLBACK_HTTP: an http request has come from a client that is not * asking to upgrade the connection to a websocket * one. This is a chance to serve http content, * for example, to send a script to the client * which will then open the websockets connection. - * libwebsocket_get_uri() lets you find out the - * URI path requested and + * @in points to the URI path requested and * libwebsockets_serve_http_file() makes it very * simple to send back a file to the client. + * + * LWS_CALLBACK_PROTOCOL_FILTER: before the confirmation handshake is sent + * the user callback is given a chance to confirm + * it's OK with the protocol that was requested + * from the client. The protocol string (which + * may be NULL if no protocol header was sent) + * can be found at parameter @in. Return 0 from + * the callback to allow the connection or nonzero + * to abort the connection. */ static int websocket_callback(struct libwebsocket * wsi, @@ -80,7 +91,6 @@ static int websocket_callback(struct libwebsocket * wsi, char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 + LWS_SEND_BUFFER_POST_PADDING]; char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING]; - const char *uri; struct per_session_data * pss = user; switch (reason) { @@ -130,11 +140,9 @@ static int websocket_callback(struct libwebsocket * wsi, case LWS_CALLBACK_HTTP: - uri = libwebsocket_get_uri(wsi); - - fprintf(stderr, "serving HTTP URI %s\n", uri); + fprintf(stderr, "serving HTTP URI %s\n", in); - if (uri && strcmp(uri, "/favicon.ico") == 0) { + if (in && strcmp(in, "/favicon.ico") == 0) { if (libwebsockets_serve_http_file(wsi, LOCAL_RESOURCE_PATH"/favicon.ico", "image/x-icon")) fprintf(stderr, "Failed to send favicon\n"); @@ -146,8 +154,23 @@ static int websocket_callback(struct libwebsocket * wsi, if (libwebsockets_serve_http_file(wsi, LOCAL_RESOURCE_PATH"/test.html", "text/html")) fprintf(stderr, "Failed to send HTTP file\n"); - break; + + /* + * This is our chance to choose if we support one of the requested + * protocols or not. in points to the protocol string. Nonzero return + * aborts the connection handshake + */ + + case LWS_CALLBACK_PROTOCOL_FILTER: + if (in == NULL) { + fprintf(stderr, "Client did not request protocol\n"); + /* accept it */ + return 0; + } + fprintf(stderr, "Client requested protocol '%s'\n", in); + /* accept it */ + return 0; } return 0;