Skip to content

Commit

Permalink
Merge pull request ceph#3 from feneuilflo/feneuilflo-patch-1
Browse files Browse the repository at this point in the history
fix for multiple Sec-Websocket-Protocol headers
  • Loading branch information
feneuilflo authored May 30, 2017
2 parents 0f02980 + 860f767 commit 90c5039
Showing 1 changed file with 43 additions and 24 deletions.
67 changes: 43 additions & 24 deletions src/civetweb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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, ',');
Expand Down

0 comments on commit 90c5039

Please sign in to comment.