diff --git a/websocket.c b/websocket.c index d6edb7a..f214cd8 100644 --- a/websocket.c +++ b/websocket.c @@ -25,32 +25,37 @@ static int ws_compute_handshake(struct http_client *c, char *out, size_t *out_sz) { unsigned char *buffer, sha1_output[20]; - char magic[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + char magic[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; SHA1Context ctx; - base64_encodestate b64_ctx; - int pos; + base64_encodestate b64_ctx; + int pos; // websocket handshake const char *key = client_get_header(c, "Sec-WebSocket-Key"); - size_t key_sz = strlen(key), buffer_sz = key_sz + sizeof(magic) - 1; - buffer = calloc(key_sz, 1); - - // concatenate key and guid in buffer - memcpy(buffer, key, key_sz); - memcpy(buffer+key_sz, magic, sizeof(magic)-1); - - // compute sha-1 - SHA1Reset(&ctx); - SHA1Input(&ctx, buffer, buffer_sz); - SHA1Result(&ctx); - memcpy(sha1_output, &ctx.Message_Digest[0], 20); - - // encode `sha1_output' in base 64, into `out'. - base64_init_encodestate(&b64_ctx); - pos = base64_encode_block((const char*)sha1_output, 20, out, &b64_ctx); - base64_encode_blockend(out + pos, &b64_ctx); - - *out_sz = strlen(out); + size_t key_sz = key?strlen(key):0, buffer_sz = key_sz + sizeof(magic) - 1; + buffer = calloc(buffer_sz, 1); + + // concatenate key and guid in buffer + memcpy(buffer, key, key_sz); + memcpy(buffer+key_sz, magic, sizeof(magic)-1); + + // compute sha-1 + SHA1Reset(&ctx); + SHA1Input(&ctx, buffer, buffer_sz); + SHA1Result(&ctx); + memcpy(sha1_output, &ctx.Message_Digest[0], 20); + + // encode `sha1_output' in base 64, into `out'. + base64_init_encodestate(&b64_ctx); + pos = base64_encode_block((const char*)sha1_output, 20, out, &b64_ctx); + base64_encode_blockend(out + pos, &b64_ctx); + + // compute length, without \n + *out_sz = strlen(out); + if(out[*out_sz-1] == '\n') + (*out_sz)--; + + free(buffer); return 0; } @@ -72,7 +77,9 @@ ws_handshake_reply(struct http_client *c) { "Sec-WebSocket-Location: ws://"; /* %s%s */ char template2[] = "\r\n" "Origin: http://"; /* %s */ - char template3[] = "\r\n\r\n"; + char template3[] = "\r\n" + "Sec-WebSocket-Accept: "; /* %s */ + char template4[] = "\r\n\r\n"; if((origin = client_get_header(c, "Origin"))) { origin_sz = strlen(origin); @@ -86,6 +93,7 @@ ws_handshake_reply(struct http_client *c) { return -1; } + memset(sha1_handshake, 0, sizeof(sha1_handshake)); if(ws_compute_handshake(c, &sha1_handshake[0], &handshake_sz) != 0) { /* failed to compute handshake. */ return -1; @@ -94,20 +102,21 @@ ws_handshake_reply(struct http_client *c) { sz = sizeof(template0)-1 + origin_sz + sizeof(template1)-1 + host_sz + c->path_sz + sizeof(template2)-1 + host_sz - + sizeof(template3)-1 + handshake_sz + 1; + + sizeof(template3)-1 + handshake_sz + + sizeof(template4)-1; p = buffer = malloc(sz); /* Concat all */ /* template0 */ - memcpy(p, template0, sizeof(template0)-1); + memcpy(p, template0, sizeof(template0)-1); p += sizeof(template0)-1; memcpy(p, origin, origin_sz); p += origin_sz; /* template1 */ - memcpy(p, template1, sizeof(template1)-1); + memcpy(p, template1, sizeof(template1)-1); p += sizeof(template1)-1; memcpy(p, host, host_sz); p += host_sz; @@ -115,16 +124,22 @@ ws_handshake_reply(struct http_client *c) { p += c->path_sz; /* template2 */ - memcpy(p, template2, sizeof(template2)-1); + memcpy(p, template2, sizeof(template2)-1); p += sizeof(template2)-1; memcpy(p, host, host_sz); p += host_sz; /* template3 */ - memcpy(p, template3, sizeof(template3)-1); + memcpy(p, template3, sizeof(template3)-1); p += sizeof(template3)-1; memcpy(p, &sha1_handshake[0], handshake_sz); + p += handshake_sz; + + /* template4 */ + memcpy(p, template4, sizeof(template4)-1); + p += sizeof(template4)-1; + /* send data to client */ ret = write(c->fd, buffer, sz); free(buffer);