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;