Selaa lähdekoodia

Merge pull request #466 from feneuilflo/master

quick fix for multiple Sec-WebSocket-Protocol headers
bel2125 8 vuotta sitten
vanhempi
commit
e548eeac40
1 muutettua tiedostoa jossa 43 lisäystä ja 24 poistoa
  1. 43 24
      src/civetweb.c

+ 43 - 24
src/civetweb.c

@@ -3203,6 +3203,21 @@ get_header(const struct mg_request_info *ri, const char *name)
 	return NULL;
 }
 
+/* Retrieve requested HTTP header multiple values, and return the number of found occurences */
+static int get_headers(const struct mg_request_info *ri, const char *name,
+		const char** output, int output_max_size) {
+	int i;
+	int cnt = 0;
+	if (ri) {
+		for (i = 0; i < ri->num_headers && cnt < output_max_size; i++) {
+			if (!mg_strcasecmp(name, ri->http_headers[i].name)) {
+				output[cnt++] = ri->http_headers[i].value;
+			}
+		}
+	}
+	return cnt;
+}
+
 
 const char *
 mg_get_header(const struct mg_connection *conn, const char *name)
@@ -10518,8 +10533,10 @@ handle_websocket_request(struct mg_connection *conn,
 	/* Step 2: If a callback is responsible, call it. */
 	if (is_callback_resource) {
 		/* Step 2.1 check and select subprotocol */
-		const char *protocol = mg_get_header(conn, "Sec-WebSocket-Protocol");
-		if (protocol && subprotocols) {
+		const char* protocols[64]; // max 64 headers
+		int nbSubprotocolHeader = get_headers(&conn->request_info, "Sec-WebSocket-Protocol", protocols, 64);
+		if (nbSubprotocolHeader > 0 && subprotocols) {
+			int cnt = 0;
 			int idx;
 			unsigned long len;
 			const char *sep, *curSubProtocol,
@@ -10528,34 +10545,36 @@ handle_websocket_request(struct mg_connection *conn,
 
 			/* look for matching subprotocol */
 			do {
-				sep = strchr(protocol, ',');
-				curSubProtocol = protocol;
-				len = sep ? (unsigned long)(sep - protocol)
-				          : (unsigned long)strlen(protocol);
-				while (sep && isspace(*++sep)) {
-					; /* ignore leading whitespaces */
-				}
-				protocol = sep;
-
-
-				for (idx = 0; idx < subprotocols->nb_subprotocols; idx++) {
-					if ((strlen(subprotocols->subprotocols[idx]) == len)
-					    && (strncmp(curSubProtocol,
-					                subprotocols->subprotocols[idx],
-					                len) == 0)) {
-						acceptedWebSocketSubprotocol =
-						    subprotocols->subprotocols[idx];
-						break;
+				const char *protocol = protocols[cnt];
+
+				do {
+					sep = strchr(protocol, ',');
+					curSubProtocol = protocol;
+					len = sep ? (unsigned long)(sep - protocol) : strlen(protocol);
+					while(sep && isspace(*++sep)); // ignore leading whitespaces
+					protocol = sep;
+
+
+					for (idx = 0; idx < subprotocols->nb_subprotocols; idx++) {
+						if ((strlen(subprotocols->subprotocols[idx]) == len)
+							&& (strncmp(curSubProtocol,
+										subprotocols->subprotocols[idx],
+										len) == 0)) {
+							acceptedWebSocketSubprotocol =
+								subprotocols->subprotocols[idx];
+							break;
+						}
 					}
-				}
-			} while (sep && !acceptedWebSocketSubprotocol);
+				} while (sep && !acceptedWebSocketSubprotocol);
+			} while (++cnt < nbSubprotocolHeader && !acceptedWebSocketSubprotocol);
 
 			conn->request_info.acceptedWebSocketSubprotocol =
 			    acceptedWebSocketSubprotocol;
-		} else if (protocol) {
+		} else if (nbSubprotocolHeader > 0) {
 			/* keep legacy behavior */
+			const char *protocol = protocols[0];
 
-			/* The protocol is a comma seperated list of names. */
+			/* The protocol is a comma separated list of names. */
 			/* The server must only return one value from this list. */
 			/* First check if it is a list or just a single value. */
 			const char *sep = strrchr(protocol, ',');