websockets: Properly parse Hixie-76 handshake.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
pull/1/head
Joel Martin 13 years ago committed by Johannes Schindelin
parent 430b8f2449
commit 7a77cc32b2

@ -41,11 +41,11 @@ Upgrade: WebSocket\r\n\
Connection: Upgrade\r\n\
%sWebSocket-Origin: %s\r\n\
%sWebSocket-Location: %s://%s%s\r\n\
%sWebSocket-Protocol: sample\r\n\
%sWebSocket-Protocol: %s\r\n\
\r\n%s"
#define WEBSOCKETS_CLIENT_CONNECT_WAIT_MS 100
#define WEBSOCKETS_CLIENT_SEND_WAIT_MS 20
#define WEBSOCKETS_CLIENT_SEND_WAIT_MS 100
#define WEBSOCKETS_MAX_HANDSHAKE_LEN 4096
#if defined(__linux__) && defined(NEED_TIMEVAL)
@ -123,7 +123,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
char *buf, *response, *line;
int n, linestart = 0, len = 0, llen;
char prefix[5], trailer[17];
char *path, *host, *origin;
char *path = NULL, *host = NULL, *origin = NULL, *protocol = NULL;
char *key1 = NULL, *key2 = NULL, *key3 = NULL;
buf = (char *) malloc(WEBSOCKETS_MAX_HANDSHAKE_LEN);
@ -155,7 +155,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
llen = len - linestart;
if (((llen >= 2)) && (buf[len-1] == '\n')) {
line = buf+linestart;
if ((llen == 2) && ((strncmp("\r\n\r\n", buf+len-4, 4)) == 0)) {
if ((llen == 2) && (strncmp("\r\n", line, 2) == 0)) {
if (key1 && key2) {
if ((n = rfbReadExact(cl, buf+len, 8)) <= 0) {
if ((n < 0) && (errno == ETIMEDOUT)) {
@ -176,32 +176,30 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
break;
} else if ((llen >= 16) && ((strncmp("GET ", line, min(llen,4))) == 0)) {
/* 16 = 4 ("GET ") + 1 ("/.*") + 11 (" HTTP/1.1\r\n") */
/* rfbLog("Got path\n"); */
path = line+4;
buf[len-11] = '\0'; /* Trim trailing " HTTP/1.1\r\n" */
if (strstr(path, "b64encode")) {
rfbLog(" - using base64 encoding\n");
cl->webSocketsBase64 = TRUE;
} else {
rfbLog(" - using UTF-8 encoding\n");
cl->webSocketsBase64 = FALSE;
}
} else if ((strncmp("Host: ", line, min(llen,6))) == 0) {
/* rfbLog("Got host\n"); */
cl->webSocketsBase64 = TRUE;
/* rfbLog("Got path: %s\n", path); */
} else if ((strncasecmp("host: ", line, min(llen,6))) == 0) {
host = line+6;
buf[len-2] = '\0';
} else if ((strncmp("Origin: ", line, min(llen,8))) == 0) {
/* rfbLog("Got origin\n"); */
/* rfbLog("Got host: %s\n", host); */
} else if ((strncasecmp("origin: ", line, min(llen,8))) == 0) {
origin = line+8;
buf[len-2] = '\0';
} else if ((strncmp("Sec-Websocket-Key1: ", line, min(llen,20))) == 0) {
/* rfbLog("Got key1\n"); */
/* rfbLog("Got origin: %s\n", origin); */
} else if ((strncasecmp("sec-websocket-key1: ", line, min(llen,20))) == 0) {
key1 = line+20;
buf[len-2] = '\0';
} else if ((strncmp("Sec-Websocket-Key2: ", line, min(llen,20))) == 0) {
/* rfbLog("Got key2\n"); */
/* rfbLog("Got key1: %s\n", key1); */
} else if ((strncasecmp("sec-websocket-key2: ", line, min(llen,20))) == 0) {
key2 = line+20;
buf[len-2] = '\0';
/* rfbLog("Got key2: %s\n", key2); */
} else if ((strncasecmp("sec-websocket-protocol: ", line, min(llen,24))) == 0) {
protocol = line+24;
buf[len-2] = '\0';
/* rfbLog("Got protocol: %s\n", protocol); */
}
linestart = len;
}
@ -214,6 +212,15 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
return FALSE;
}
/*
if ((!protocol) || (!strcasestr(protocol, "base64"))) {
rfbErr("webSocketsHandshake: base64 subprotocol not supported by client\n");
free(response);
free(buf);
return FALSE;
}
*/
/*
* Generate the WebSockets server response based on the the headers sent
* by the client.
@ -231,7 +238,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
snprintf(response, WEBSOCKETS_MAX_HANDSHAKE_LEN,
WEBSOCKETS_HANDSHAKE_RESPONSE, prefix, origin, prefix, scheme,
host, path, prefix, trailer);
host, path, prefix, protocol, trailer);
if (rfbWriteExact(cl, response, strlen(response)) < 0) {
rfbErr("webSocketsHandshake: failed sending WebSockets response\n");

Loading…
Cancel
Save