#include "private-libwebsockets.h"
+/*
+ * parsers.c: lws_rx_sm() needs to be roughly kept in
+ * sync with changes here, esp related to ext draining
+ */
+
int lws_client_rx_sm(struct lws *wsi, unsigned char c)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
unsigned char *pp;
if (wsi->u.ws.rx_draining_ext) {
- struct lws **w = &pt->rx_draining_ext_list;
- lwsl_ext("%s: RX EXT DRAINING: Removing from list\n", __func__);
assert(!c);
eff_buf.token = NULL;
eff_buf.token_len = 0;
- wsi->u.ws.rx_draining_ext = 0;
- /* remove us from context draining ext list */
- while (*w) {
- if (*w == wsi) {
- *w = wsi->u.ws.rx_draining_ext_list;
- break;
- }
- w = &((*w)->u.ws.rx_draining_ext_list);
- }
- wsi->u.ws.rx_draining_ext_list = NULL;
+ lws_remove_wsi_from_draining_ext_list(wsi);
rx_draining_ext = 1;
+ lwsl_debug("%s: doing draining flow\n", __func__);
goto drain_extension;
}
+ if (wsi->socket_is_permanently_unusable)
+ return -1;
+
switch (wsi->lws_rx_parse_state) {
case LWS_RXPS_NEW:
/* control frames (PING) may interrupt checkable sequences */
assert(wsi->u.ws.rx_ubuf);
+ if (wsi->u.ws.rx_draining_ext)
+ goto drain_extension;
+
if (wsi->u.ws.this_frame_masked && !wsi->u.ws.all_zero_nonce)
c ^= wsi->u.ws.mask[(wsi->u.ws.mask_idx++) & 3];
wsi->u.ws.rx_ubuf_head);
if (wsi->u.ws.rx_ubuf_head >= 2) {
close_code = (pp[0] << 8) | pp[1];
- if (close_code < 1000 || close_code == 1004 ||
- close_code == 1005 || close_code == 1006 ||
- close_code == 1012 || close_code == 1013 ||
- close_code == 1014 || close_code == 1015 ||
+ if (close_code < 1000 ||
+ close_code == 1004 ||
+ close_code == 1005 ||
+ close_code == 1006 ||
+ close_code == 1012 ||
+ close_code == 1013 ||
+ close_code == 1014 ||
+ close_code == 1015 ||
(close_code >= 1016 && close_code < 3000)
) {
pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
wsi->user_space, pp,
wsi->u.ws.rx_ubuf_head))
return -1;
+
if (lws_partial_buffered(wsi))
/*
* if we're in the middle of something,
eff_buf.token_len = wsi->u.ws.rx_ubuf_head;
drain_extension:
+ lwsl_ext("%s: passing %d to ext\n", __func__, eff_buf.token_len);
+
n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &eff_buf, 0);
lwsl_ext("Ext RX returned %d\n", n);
- if (n < 0) /* fail */
+ if (n < 0) {
+ wsi->socket_is_permanently_unusable = 1;
return -1;
+ }
lwsl_ext("post inflate eff_buf len %d\n", eff_buf.token_len);
goto utf8_fail;
/* we are ending partway through utf-8 character? */
- if (!wsi->u.ws.rx_packet_length && wsi->u.ws.final && wsi->u.ws.utf8 && !n) {
+ if (!wsi->u.ws.rx_packet_length && wsi->u.ws.final &&
+ wsi->u.ws.utf8 && !n) {
lwsl_info("FINAL utf8 error\n");
utf8_fail: lwsl_info("utf8 error\n");
return -1;
wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
pt->rx_draining_ext_list = wsi;
lwsl_ext("%s: RX EXT DRAINING: Adding to list\n", __func__);
- }
+ } else
+ lws_remove_wsi_from_draining_ext_list(wsi);
+
if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
wsi->state == LWSS_AWAITING_CLOSE_ACK)
goto already_done;
{
return wsi->u.ws.frame_is_binary;
}
-static void
+void
lws_remove_wsi_from_draining_ext_list(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
wsi->u.ws.rx_draining_ext_list = NULL;
}
+/*
+ * client-parser.c: lws_client_rx_sm() needs to be roughly kept in
+ * sync with changes here, esp related to ext draining
+ */
int
lws_rx_sm(struct lws *wsi, unsigned char c)
eff_buf.token_len = 0;
lws_remove_wsi_from_draining_ext_list(wsi);
rx_draining_ext = 1;
- lwsl_err("%s: doing draining flow\n", __func__);
+ lwsl_debug("%s: doing draining flow\n", __func__);
goto drain_extension;
}
wsi->u.ws.rx_draining_ext = 1;
wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
pt->rx_draining_ext_list = wsi;
- } else {
+ } else
lws_remove_wsi_from_draining_ext_list(wsi);
- }
if (eff_buf.token_len > 0 ||
callback_action == LWS_CALLBACK_RECEIVE_PONG) {