int
libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
{
- int n;
struct lws_tokens eff_buf;
int ret = 0;
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",
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");
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 */
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;
}