From 4b6fbe125e5f7fc9982737fdc87b9fabe7577ced Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 14 Feb 2011 08:03:48 +0000 Subject: [PATCH] unify server and client close Signed-off-by: Andy Green --- lib/client-handshake.c | 72 +------------------------------ lib/handshake.c | 5 ++- lib/libwebsockets.c | 101 ++++++++++++++++++++------------------------ lib/libwebsockets.h | 6 ++- lib/private-libwebsockets.h | 6 +-- 5 files changed, 56 insertions(+), 134 deletions(-) diff --git a/lib/client-handshake.c b/lib/client-handshake.c index fd786cd..e219450 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -15,76 +15,6 @@ strtolower(char *s) } } -void -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; - - if (wsi->protocol) { - if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED) - wsi->protocol->callback(wsi, LWS_CALLBACK_CLOSED, - wsi->user_space, NULL, 0); - - /* remove it from the client polling list */ - clients = wsi->protocol->owning_server; - if (clients) - for (n = 0; n < clients->fds_count; n++) { - if (clients->fds[n].fd != wsi->sock) - continue; - while (n < clients->fds_count - 1) { - clients->fds[n] = clients->fds[n + 1]; - n++; - } - /* we only have to deal with one */ - n = clients->fds_count; - } - - } - - /* clean out any parsing allocations */ - - for (n = 0; n < WSI_TOKEN_COUNT; n++) - if (wsi->utf8_token[n].token) - free(wsi->utf8_token[n].token); - - /* shut down reasonably cleanly */ - -#ifdef LWS_OPENSSL_SUPPORT - if (wsi->ssl) { - n = SSL_get_fd(wsi->ssl); - SSL_shutdown(wsi->ssl); - close(n); - SSL_free(wsi->ssl); - } else { -#endif - shutdown(wsi->sock, SHUT_RDWR); - close(wsi->sock); -#ifdef LWS_OPENSSL_SUPPORT - } -#endif -} - /** * libwebsocket_client_connect() - Connect to another websocket server @@ -588,7 +518,7 @@ check_accept: bail2: - libwebsocket_client_close(wsi); + libwebsocket_close_and_free_session(this, wsi); bail1: free(wsi); diff --git a/lib/handshake.c b/lib/handshake.c index 7ba9683..1ba4b92 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -442,7 +442,8 @@ bail: */ int -libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len) +libwebsocket_read(struct libwebsocket_context *this, struct libwebsocket *wsi, + unsigned char * buf, size_t len) { size_t n; @@ -604,7 +605,7 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len) return 0; bail: - libwebsocket_close_and_free_session(wsi); + libwebsocket_close_and_free_session(this, wsi); return -1; } diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index e1ab1c5..d4db3f3 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -76,13 +76,14 @@ delete_from_fd(struct libwebsocket_context *this, int fd) void -libwebsocket_close_and_free_session(struct libwebsocket *wsi) +libwebsocket_close_and_free_session(struct libwebsocket_context *this, + 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) + if (!wsi) return; n = wsi->state; @@ -90,12 +91,35 @@ libwebsocket_close_and_free_session(struct libwebsocket *wsi) if (n == WSI_STATE_DEAD_SOCKET) return; + /* remove this fd from wsi mapping hashtable */ + + delete_from_fd(this, wsi->sock); + + /* delete it from the internal poll list if still present */ + + for (n = 0; n < this->fds_count; n++) { + if (this->fds[n].fd != wsi->sock) + continue; + while (n < this->fds_count - 1) { + this->fds[n] = this->fds[n + 1]; + n++; + } + this->fds_count--; + /* we only have to deal with one */ + n = this->fds_count; + } + + /* remove also from external POLL support via protocol 0 */ + + this->protocols[0].callback(wsi, + LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0); + /* * 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 + * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this */ if (n == WSI_STATE_ESTABLISHED) @@ -104,10 +128,14 @@ libwebsocket_close_and_free_session(struct libwebsocket *wsi) wsi->state = WSI_STATE_DEAD_SOCKET; + /* tell the user it's all over for this guy */ + if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED) wsi->protocol->callback(wsi, LWS_CALLBACK_CLOSED, wsi->user_space, NULL, 0); + /* free up his allocations */ + for (n = 0; n < WSI_TOKEN_COUNT; n++) if (wsi->utf8_token[n].token) free(wsi->utf8_token[n].token); @@ -161,7 +189,7 @@ libwebsockets_hangup_on_client(struct libwebsocket_context *this, int fd) this->fds_count--; } - libwebsocket_close_and_free_session(wsi); + libwebsocket_close_and_free_session(this, wsi); } @@ -456,8 +484,8 @@ libwebsocket_service_fd(struct libwebsocket_context *this, debug("Session Socket %p (fd=%d) dead\n", (void *)wsi, accept_fd); - libwebsocket_close_and_free_session(wsi); - goto nuke_this; + libwebsocket_close_and_free_session(this, wsi); + return 1; } /* the guy requested a callback when it was OK to write */ @@ -490,7 +518,7 @@ libwebsocket_service_fd(struct libwebsocket_context *this, MAX_BROADCAST_PAYLOAD); if (len < 0) { fprintf(stderr, "Error reading broadcast payload\n"); - break;; + break; } /* broadcast it to all guys with this protocol index */ @@ -543,8 +571,8 @@ libwebsocket_service_fd(struct libwebsocket_context *this, debug("Session Socket %p (fd=%d) dead\n", (void *)wsi, pollfd->fd); - libwebsocket_close_and_free_session(wsi); - goto nuke_this; + libwebsocket_close_and_free_session(this, wsi); + return 1; } /* the guy requested a callback when it was OK to write */ @@ -578,46 +606,22 @@ libwebsocket_service_fd(struct libwebsocket_context *this, if (n < 0) { fprintf(stderr, "Socket read returned %d\n", n); - break;; + break; } if (!n) { - libwebsocket_close_and_free_session(wsi); - goto nuke_this; + libwebsocket_close_and_free_session(this, wsi); + return 1; } /* service incoming data */ - n = libwebsocket_read(wsi, buf, n); + n = libwebsocket_read(this, wsi, buf, n); if (n >= 0) - break;; - /* - * it closed and nuked wsi[client], so remove the - * socket handle and wsi from our service list - */ -nuke_this: - - debug("nuking wsi %p, fsd_count = %d\n", - (void *)wsi, this->fds_count - 1); - - delete_from_fd(this, pollfd->fd); - - this->fds_count--; - for (n = 0; n < this->fds_count; n++) - if (this->fds[n].fd == pollfd->fd) { - while (n < this->fds_count) { - this->fds[n] = this->fds[n + 1]; - n++; - } - n = this->fds_count; - } - - /* external POLL support via protocol 0 */ - this->protocols[0].callback(wsi, - LWS_CALLBACK_DEL_POLL_FD, - (void *)(long)pollfd->fd, NULL, 0); + break; + /* we closed wsi */ - break; + return 1; } return 0; @@ -639,24 +643,11 @@ libwebsocket_context_destroy(struct libwebsocket_context *this) int m; struct libwebsocket *wsi; - for (n = 0; n < FD_HASHTABLE_MODULUS; n++) { - + for (n = 0; n < FD_HASHTABLE_MODULUS; n++) for (m = 0; m < this->fd_hashtable[n].length; m++) { - wsi = this->fd_hashtable[n].wsi[m]; - - switch (wsi->mode) { - case LWS_CONNMODE_WS_SERVING: - libwebsocket_close_and_free_session(wsi); - break; - case LWS_CONNMODE_WS_CLIENT: - libwebsocket_client_close(wsi); - break; - default: - break; - } + libwebsocket_close_and_free_session(this, wsi); } - } close(this->fd_random); diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index f227073..5a65c21 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -381,8 +381,6 @@ libwebsocket_client_connect(struct libwebsocket_context *clients, extern const char * libwebsocket_canonical_hostname(struct libwebsocket_context *this); -extern void -libwebsocket_client_close(struct libwebsocket *wsi); extern void libwebsockets_get_peer_addresses(int fd, char *name, int name_len, @@ -391,4 +389,8 @@ libwebsockets_get_peer_addresses(int fd, char *name, int name_len, extern void libwebsockets_hangup_on_client(struct libwebsocket_context *this, int fd); +extern void +libwebsocket_close_and_free_session(struct libwebsocket_context *this, + struct libwebsocket *wsi); + #endif diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 9376025..a097d53 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -225,9 +225,6 @@ struct libwebsocket { extern int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c); -extern void -libwebsocket_close_and_free_session(struct libwebsocket *wsi); - extern int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c); @@ -236,7 +233,8 @@ libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi, unsigned char *buf, size_t len); extern int -libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len); +libwebsocket_read(struct libwebsocket_context *this, struct libwebsocket *wsi, + unsigned char * buf, size_t len); extern int lws_b64_encode_string(const char *in, int in_len, char *out, int out_size); -- 2.7.4