From 8f70db179f516034666e7e2a7bf2ef8d080ece57 Mon Sep 17 00:00:00 2001 From: Jessie Murray Date: Sun, 18 Jul 2021 16:49:13 -0700 Subject: [PATCH] Send WS handshake using event loop instead of write(2) ws_handshake_reply was sending its response using a single write(2) call without error-checking, which could well send only part of it and leave the client hanging. This change creates an HTTP response object and schedules it for writing using the event loop. Tested with Valgrind, no memory is leaked. --- src/websocket.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/websocket.c b/src/websocket.c index 4a41ae0..861605c 100644 --- a/src/websocket.c +++ b/src/websocket.c @@ -89,7 +89,6 @@ ws_compute_handshake(struct http_client *c, char *out, size_t *out_sz) { int ws_handshake_reply(struct http_client *c) { - int ret; char sha1_handshake[40]; char *buffer = NULL, *p; const char *origin = NULL, *host = NULL; @@ -135,7 +134,7 @@ ws_handshake_reply(struct http_client *c) { p = buffer = malloc(sz); if(!p) { - slog(c->s, WEBDIS_ERROR, "Failed to allocate memory for WS handshake", 0); + slog(c->s, WEBDIS_ERROR, "Failed to allocate buffer for WS handshake", 0); return -1; } @@ -171,10 +170,19 @@ ws_handshake_reply(struct http_client *c) { memcpy(p, template4, sizeof(template4)-1); p += sizeof(template4)-1; - /* send data to client */ - ret = write(c->fd, buffer, sz); /* FIXME: this needs to use the event loop */ - (void)ret; - free(buffer); + /* build HTTP response object by hand, since we have the full response already */ + struct http_response *r = calloc(1, sizeof(struct http_response)); + if(!r) { + slog(c->s, WEBDIS_ERROR, "Failed to allocate response for WS handshake", 0); + free(buffer); + return -1; + } + r->w = c->w; + r->keep_alive = 1; + r->out = buffer; + r->out_sz = sz; + r->sent = 0; + http_schedule_write(c->fd, r); /* will free buffer and response once sent */ return 0; }