add-protocol-filter.patch

Signed-off-by: Andy Green <andy@warmcat.com>
diff --git a/lib/handshake.c b/lib/handshake.c
index a1f0f0d..05547b0 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -97,7 +97,7 @@
 			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 @@
 				     !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 cba14ca..f443d8f 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -28,7 +28,8 @@
 	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 @@
 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 abfa53d..c3696a7 100644
--- a/lib/parsers.c
+++ b/lib/parsers.c
@@ -45,10 +45,21 @@
 
 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 0c2d8eb..7581b27 100644
--- a/libwebsockets-api-doc.html
+++ b/libwebsockets-api-doc.html
@@ -69,6 +69,22 @@
 then this call will return a pointer to "/xyz/abc.d"
 </blockquote>
 <hr>
+<h2>libwebsocket_get_protocol - Return the list of protocols being requested</h2>
+<i>const char *</i>
+<b>libwebsocket_get_protocol</b>
+(<i>struct libwebsocket *</i> <b>wsi</b>)
+<h3>Arguments</h3>
+<dl>
+<dt><b>wsi</b>
+<dd>Websocket instance
+</dl>
+<h3>Description</h3>
+<blockquote>
+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.
+</blockquote>
+<hr>
 <h2>libwebsocket_write - Apply protocol then write data to client</h2>
 <i>int</i>
 <b>libwebsocket_write</b>
diff --git a/test-server/test-server.c b/test-server/test-server.c
index 74c3f61..bfc3c85 100644
--- a/test-server/test-server.c
+++ b/test-server/test-server.c
@@ -55,21 +55,32 @@
  * 	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 @@
 	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 @@
 		 
 	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 @@
 		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;