mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
add extra state for waiting on close ack with timeout
Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
parent
69758fa809
commit
da527dfdee
4 changed files with 76 additions and 20 deletions
|
@ -686,6 +686,7 @@ libwebsocket_read(struct libwebsocket_context *context, struct libwebsocket *wsi
|
|||
|
||||
break;
|
||||
|
||||
case WSI_STATE_AWAITING_CLOSE_ACK:
|
||||
case WSI_STATE_ESTABLISHED:
|
||||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_WS_CLIENT:
|
||||
|
|
|
@ -158,7 +158,49 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
|||
if (old_state == WSI_STATE_DEAD_SOCKET)
|
||||
return;
|
||||
|
||||
/* remove this fd from wsi mapping hashtable */
|
||||
wsi->close_reason = reason;
|
||||
|
||||
/*
|
||||
* 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 will skip this.
|
||||
*
|
||||
* Likewise if it's a second call to close this connection after we
|
||||
* sent the close indication to the peer already, we are in state
|
||||
* WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
|
||||
*/
|
||||
|
||||
if (old_state == WSI_STATE_ESTABLISHED &&
|
||||
reason != LWS_CLOSE_STATUS_NOSTATUS) {
|
||||
n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
0, LWS_WRITE_CLOSE);
|
||||
if (!n) {
|
||||
/*
|
||||
* we have sent a nice protocol level indication we
|
||||
* now wish to close, we should not send anything more
|
||||
*/
|
||||
|
||||
wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
|
||||
|
||||
/* and we should wait for a reply for a bit */
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_CLOSE_ACK, 5);
|
||||
|
||||
fprintf(stderr, "sent close indication, awaiting ack\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* else, the send failed and we should just hang up */
|
||||
}
|
||||
|
||||
/*
|
||||
* we won't be servicing or receiving anything further from this guy
|
||||
* remove this fd from wsi mapping hashtable
|
||||
*/
|
||||
|
||||
delete_from_fd(context, wsi->sock);
|
||||
|
||||
|
@ -181,20 +223,6 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
|||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
|
||||
|
||||
wsi->close_reason = reason;
|
||||
|
||||
/*
|
||||
* 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 will skip this
|
||||
*/
|
||||
|
||||
if (old_state == WSI_STATE_ESTABLISHED)
|
||||
libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 0,
|
||||
LWS_WRITE_CLOSE);
|
||||
|
||||
wsi->state = WSI_STATE_DEAD_SOCKET;
|
||||
|
||||
/* tell the user it's all over for this guy */
|
||||
|
@ -586,9 +614,11 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
* connection
|
||||
*/
|
||||
|
||||
if (tv.tv_sec > wsi->pending_timeout_limit)
|
||||
if (tv.tv_sec > wsi->pending_timeout_limit) {
|
||||
fprintf(stderr, "TIMEDOUT WAITING\n");
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1607,10 +1637,12 @@ bail2:
|
|||
|
||||
/* the guy requested a callback when it was OK to write */
|
||||
|
||||
if (pollfd->revents & POLLOUT)
|
||||
if (lws_handle_POLLOUT_event(context, wsi, pollfd) < 0) {
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NORMAL);
|
||||
if ((pollfd->revents & POLLOUT) &&
|
||||
wsi->state == WSI_STATE_ESTABLISHED)
|
||||
if (lws_handle_POLLOUT_event(context, wsi,
|
||||
pollfd) < 0) {
|
||||
libwebsocket_close_and_free_session(
|
||||
context, wsi, LWS_CLOSE_STATUS_NORMAL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -617,6 +617,16 @@ spill:
|
|||
|
||||
switch (wsi->opcode) {
|
||||
case LWS_WS_OPCODE_04__CLOSE:
|
||||
/* is this an acknowledgement of our close? */
|
||||
if (wsi->state == WSI_STATE_AWAITING_CLOSE_ACK) {
|
||||
/*
|
||||
* fine he has told us he is closing too, let's
|
||||
* finish our close
|
||||
*/
|
||||
fprintf(stderr, "seen client close ack\n");
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "server sees client close packet\n");
|
||||
/* parrot the close packet payload back */
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
|
@ -940,10 +950,21 @@ spill:
|
|||
|
||||
switch (wsi->opcode) {
|
||||
case LWS_WS_OPCODE_04__CLOSE:
|
||||
/* is this an acknowledgement of our close? */
|
||||
if (wsi->state == WSI_STATE_AWAITING_CLOSE_ACK) {
|
||||
/*
|
||||
* fine he has told us he is closing too, let's
|
||||
* finish our close
|
||||
*/
|
||||
fprintf(stderr, "seen server's close ack\n");
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "client sees server close packet len = %d\n", wsi->rx_user_buffer_head);
|
||||
/* parrot the close packet payload back */
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->rx_user_buffer_head, LWS_WRITE_CLOSE);
|
||||
fprintf(stderr, "client writing close ack returned %d\n", n);
|
||||
wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
|
||||
/* close the connection */
|
||||
return -1;
|
||||
|
|
|
@ -129,6 +129,7 @@ enum lws_connection_states {
|
|||
WSI_STATE_ESTABLISHED,
|
||||
WSI_STATE_CLIENT_UNCONNECTED,
|
||||
WSI_STATE_RETURNED_CLOSE_ALREADY,
|
||||
WSI_STATE_AWAITING_CLOSE_ACK
|
||||
};
|
||||
|
||||
enum lws_rx_parse_state {
|
||||
|
@ -214,6 +215,7 @@ enum pending_timeout {
|
|||
PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
|
||||
PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
|
||||
PENDING_TIMEOUT_AWAITING_PING,
|
||||
PENDING_TIMEOUT_CLOSE_ACK,
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue