From 5e1fa17a6c98a8d5c8c7478dc24fb4c29fa2685f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 10 Feb 2011 09:07:05 +0000 Subject: [PATCH] introduce-new-05-socket-closure-rules.patch Signed-off-by: Andy Green --- lib/client-handshake.c | 13 +++++++++++++ lib/libwebsockets.c | 40 +++++++++++++++++++++++----------------- lib/libwebsockets.h | 2 +- lib/parsers.c | 40 +++++++++++++++++++++++++++++++++++----- lib/private-libwebsockets.h | 3 ++- test-server/test-client.c | 2 +- test-server/test-ping.c | 1 + 7 files changed, 76 insertions(+), 25 deletions(-) diff --git a/lib/client-handshake.c b/lib/client-handshake.c index 0624dcb..fa0f5a5 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -20,10 +20,23 @@ libwebsocket_client_close(struct libwebsocket *wsi) { int n = wsi->state; struct libwebsocket_context *clients; + unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 + + LWS_SEND_BUFFER_POST_PADDING]; if (n == WSI_STATE_DEAD_SOCKET) return; + /* + * signal we are closing, libsocket_write will + * add any necessary version-specific stuff. If the write fails, + * no worries we are closing anyway. If we didn't initiate this + * close, then our state has been changed to + * WSI_STATE_RETURNED_CLOSE_ALREADY and we can skip this + */ + + if (n == WSI_STATE_ESTABLISHED) + libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 0, + LWS_WRITE_CLOSE); /* mark the WSI as dead and let the callback know */ wsi->state = WSI_STATE_DEAD_SOCKET; diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index d4c8ac4..afb0f07 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -25,12 +25,29 @@ void libwebsocket_close_and_free_session(struct libwebsocket *wsi) { int n; + unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 + + LWS_SEND_BUFFER_POST_PADDING]; if ((unsigned long)wsi < LWS_MAX_PROTOCOLS) return; n = wsi->state; + if (n == WSI_STATE_DEAD_SOCKET) + return; + + /* + * signal we are closing, libsocket_write will + * add any necessary version-specific stuff. If the write fails, + * no worries we are closing anyway. If we didn't initiate this + * close, then our state has been changed to + * WSI_STATE_RETURNED_CLOSE_ALREADY and we can skip this + */ + + if (n == WSI_STATE_ESTABLISHED) + libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 0, + LWS_WRITE_CLOSE); + wsi->state = WSI_STATE_DEAD_SOCKET; if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED) @@ -233,8 +250,10 @@ libwebsocket_context_destroy(struct libwebsocket_context *this) } #ifdef LWS_OPENSSL_SUPPORT - if (this->ssl_ctx) + if (this && this->ssl_ctx) SSL_CTX_free(this->ssl_ctx); + if (this && this->ssl_client_ctx) + SSL_CTX_free(this->ssl_client_ctx); #endif if (this) @@ -300,7 +319,9 @@ libwebsocket_service(struct libwebsocket_context *this, int timeout_ms) if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) { + /* fprintf(stderr, "Listen Socket dead\n"); + */ goto fatal; } if (n == 0) /* poll timeout */ @@ -352,6 +373,7 @@ libwebsocket_service(struct libwebsocket_context *this, int timeout_ms) #ifdef LWS_OPENSSL_SUPPORT this->wsi[this->fds_count]->ssl = NULL; + this->ssl_ctx = NULL; if (this->use_ssl) { @@ -451,22 +473,6 @@ fill_in_fds: fatal: - fprintf(stderr, "service hits fatal\n"); - - /* close listening skt and per-protocol broadcast sockets */ - for (client = 0; client < this->fds_count; client++) - close(this->fds[0].fd); - -#ifdef LWS_OPENSSL_SUPPORT - if (this->ssl_ctx) - SSL_CTX_free(this->ssl_ctx); -#endif - - if (this) - free(this); - - this = NULL; - /* inform caller we are dead */ return 1; diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 10d8584..0549a50 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -46,7 +46,7 @@ enum libwebsocket_write_protocol { LWS_WRITE_BINARY, LWS_WRITE_HTTP, - /* special 04 opcodes */ + /* special 04+ opcodes */ LWS_WRITE_CLOSE, LWS_WRITE_PING, diff --git a/lib/parsers.c b/lib/parsers.c index 45a64f4..a785438 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -583,11 +583,12 @@ spill: n = libwebsocket_write(wsi, (unsigned char *) &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], wsi->rx_user_buffer_head, LWS_WRITE_CLOSE); + wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY; /* close the connection */ return -1; case LWS_WS_OPCODE_04__PING: - /* parrot the ping packet payload back as a pong*/ + /* parrot the ping packet payload back as a pong */ n = libwebsocket_write(wsi, (unsigned char *) &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], wsi->rx_user_buffer_head, LWS_WRITE_PONG); @@ -902,6 +903,7 @@ spill: n = libwebsocket_write(wsi, (unsigned char *) &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], wsi->rx_user_buffer_head, LWS_WRITE_CLOSE); + wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY; /* close the connection */ return -1; @@ -980,9 +982,9 @@ libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi) /* fetch the per-frame nonce */ fd = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY); - if (fd < 1) { - fprintf(stderr, "Unable to open random device %s\n", - SYSTEM_RANDOM_FILEPATH); + if (fd < 0) { + fprintf(stderr, "Unable to open random device %s %d\n", + SYSTEM_RANDOM_FILEPATH, fd); return 1; } n = read(fd, wsi->frame_masking_nonce_04, 4); @@ -1051,7 +1053,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, int post = 0; unsigned int shift = 7; - if (len == 0) { + if (len == 0 && protocol != LWS_WRITE_CLOSE) { fprintf(stderr, "zero length libwebsocket_write attempt\n"); return 0; } @@ -1109,6 +1111,34 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, break; case LWS_WRITE_CLOSE: n = LWS_WS_OPCODE_04__CLOSE; + + /* + * v5 mandates the first byte of close packet + * in both client and server directions + */ + + if (wsi->ietf_spec_revision >= 5) { + + /* we can do this because we demand post-buf */ + + if (len < 1) + len = 1; + + switch (wsi->mode) { + case LWS_CONNMODE_WS_SERVING: + /* + fprintf(stderr, "LWS_WRITE_CLOSE S\n"); + */ + buf[0] = 'S'; + break; + case LWS_CONNMODE_WS_CLIENT: + /* + fprintf(stderr, "LWS_WRITE_CLOSE C\n"); + */ + buf[0] = 'C'; + break; + } + } break; case LWS_WRITE_PING: n = LWS_WS_OPCODE_04__PING; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 5c8de5d..71241e7 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -95,7 +95,8 @@ enum lws_connection_states { WSI_STATE_HTTP_HEADERS, WSI_STATE_DEAD_SOCKET, WSI_STATE_ESTABLISHED, - WSI_STATE_CLIENT_UNCONNECTED + WSI_STATE_CLIENT_UNCONNECTED, + WSI_STATE_RETURNED_CLOSE_ALREADY }; enum lws_token_indexes { diff --git a/test-server/test-client.c b/test-server/test-client.c index 3508a52..298d013 100644 --- a/test-server/test-client.c +++ b/test-server/test-client.c @@ -264,6 +264,6 @@ int main(int argc, char **argv) usage: fprintf(stderr, "Usage: libwebsockets-test-client " " [--port=

] " - "[--ssl]\n"); + "[--ssl] [-k] [-v ]\n"); return 1; } diff --git a/test-server/test-ping.c b/test-server/test-ping.c index 25a3226..0022ac5 100644 --- a/test-server/test-ping.c +++ b/test-server/test-ping.c @@ -514,6 +514,7 @@ usage: "[--protocol=] " "[--mirror] " "[--replicate=clients>]" + "[--version ]" "\n"); return 1; } -- 2.7.4