diff --git a/lib/parsers.c b/lib/parsers.c index bcf1d305..cc2e2d52 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -572,7 +572,6 @@ LWS_VISIBLE int lws_frame_is_binary(struct libwebsocket *wsi) int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c) { - int n; struct lws_tokens eff_buf; int ret = 0; @@ -870,18 +869,15 @@ spill: lwsl_parser("seen client close ack\n"); return -1; } + if (wsi->state == WSI_STATE_RETURNED_CLOSE_ALREADY) + /* if he sends us 2 CLOSE, kill him */ + return -1; + lwsl_parser("server sees client close packet\n"); - /* parrot the close packet payload back */ - n = libwebsocket_write(wsi, (unsigned char *) - &wsi->u.ws.rx_user_buffer[ - LWS_SEND_BUFFER_PRE_PADDING], - wsi->u.ws.rx_user_buffer_head, - LWS_WRITE_CLOSE); - if (n < 0) - lwsl_info("write of close ack failed %d\n", n); wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY; - /* close the connection */ - return -1; + /* deal with the close packet contents as a PONG */ + wsi->u.ws.payload_is_close = 1; + goto process_as_ping; case LWS_WS_OPCODE_07__PING: lwsl_info("received %d byte ping, sending pong\n", @@ -895,7 +891,7 @@ spill: lwsl_parser("DROP PING since one pending\n"); goto ping_drop; } - +process_as_ping: /* control packets can only be < 128 bytes long */ if (wsi->u.ws.rx_user_buffer_head > 128 - 4) { lwsl_parser("DROP PING payload too large\n"); diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 5e73dff3..3e8657c3 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -791,6 +791,7 @@ struct _lws_websocket_related { unsigned int this_frame_masked:1; unsigned int inside_frame:1; /* next write will be more of frame */ unsigned int clean_buffer:1; /* buffer not rewritten by extension */ + unsigned int payload_is_close:1; /* process as PONG, but it is close */ unsigned char *ping_payload_buf; /* non-NULL if malloc'd */ unsigned int ping_payload_alloc; /* length malloc'd */ diff --git a/lib/service.c b/lib/service.c index f1cb9341..40cef568 100644 --- a/lib/service.c +++ b/lib/service.c @@ -101,9 +101,14 @@ lws_handle_POLLOUT_event(struct libwebsocket_context *context, LWS_WRITE_PONG); if (n < 0) return -1; + /* well he is sent, mark him done */ wsi->u.ws.ping_pending_flag = 0; - /* leave POLLOUT active either way */ + if (wsi->u.ws.payload_is_close) + /* oh... a close frame was it... then we are done */ + return -1; + + /* otherwise for PING, leave POLLOUT active either way */ return 0; }