unify server and client close
Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
parent
de6ab32861
commit
4b6fbe125e
5 changed files with 56 additions and 134 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
break;
|
||||
|
||||
debug("nuking wsi %p, fsd_count = %d\n",
|
||||
(void *)wsi, this->fds_count - 1);
|
||||
/* we closed wsi */
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue