unify server and client close

Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
Andy Green 2011-02-14 08:03:48 +00:00
parent de6ab32861
commit 4b6fbe125e
5 changed files with 56 additions and 134 deletions

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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);