}
}
-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
bail2:
- libwebsocket_client_close(wsi);
+ libwebsocket_close_and_free_session(this, wsi);
bail1:
free(wsi);
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;
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)
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);
this->fds_count--;
}
- libwebsocket_close_and_free_session(wsi);
+ libwebsocket_close_and_free_session(this, wsi);
}
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 */
MAX_BROADCAST_PAYLOAD);
if (len < 0) {
fprintf(stderr, "Error reading broadcast payload\n");
- break;;
+ break;
}
/* broadcast it to all guys with this protocol index */
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 */
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;
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);