From c9bbe6c15fb64e32a944ec1b332c6891c80fb866 Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Wed, 16 Mar 2016 23:56:23 +0100 Subject: [PATCH] Optimize payload exhaustion --- lib/parsers.c | 50 +++++++++++++++++++++++++++++++++++++ lib/private-libwebsockets.h | 3 +++ lib/server.c | 3 +++ 3 files changed, 56 insertions(+) diff --git a/lib/parsers.c b/lib/parsers.c index fab799ef1..727d36f0f 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -1455,3 +1455,53 @@ lws_remaining_packet_payload(struct lws *wsi) { return wsi->u.ws.rx_packet_length; } + +/* bypass slow per-byte parsing of payload data when in + * parser state LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED */ + +void +lws_payload_until_length_exhausted(struct lws *wsi, unsigned char **buf, size_t *len) +{ + int buffer_size, consumable, i; + unsigned char *buffer, *mask; + char *rx_ubuf; + unsigned char mask_idx; + + if (wsi->lws_rx_parse_state == LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED) { + buffer_size = (wsi->protocol->rx_buffer_size ? wsi->protocol->rx_buffer_size + : LWS_MAX_SOCKET_IO_BUF); + consumable = buffer_size - wsi->u.ws.rx_ubuf_head; + + /* do not consume more than what we should */ + if (consumable > wsi->u.ws.rx_packet_length) + consumable = wsi->u.ws.rx_packet_length; + + /* do not consume more than what is in the buffer */ + if (consumable > *len) + consumable = *len; + + /* we want to leave 1 byte for the parser to handle properly */ + if (consumable > 1) { + consumable--; + rx_ubuf = wsi->u.ws.rx_ubuf + LWS_PRE + wsi->u.ws.rx_ubuf_head; + if (wsi->u.ws.all_zero_nonce) + memcpy(rx_ubuf, (*buf), consumable); + else { + buffer = *buf; + mask = wsi->u.ws.mask; + mask_idx = wsi->u.ws.mask_idx; + + /* this is the main computation, can be further optimized */ + for (i = 0; i < consumable; i++) + rx_ubuf[i] = buffer[i] ^ mask[(mask_idx++) & 3]; + + wsi->u.ws.mask_idx = mask_idx; + } + + (*buf) += consumable; + wsi->u.ws.rx_ubuf_head += consumable; + wsi->u.ws.rx_packet_length -= consumable; + *len -= consumable; + } + } +} diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 0874e9fa5..a83ab8bcd 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -1289,6 +1289,9 @@ lws_client_interpret_server_handshake(struct lws *wsi); LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_rx_sm(struct lws *wsi, unsigned char c); +LWS_EXTERN void +lws_payload_until_length_exhausted(struct lws *wsi, unsigned char **buf, size_t *len); + LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len); diff --git a/lib/server.c b/lib/server.c index 2fac4aba1..e0a96ca21 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1235,6 +1235,9 @@ lws_interpret_incoming_packet(struct lws *wsi, unsigned char **buf, size_t len) if (wsi->rxflow_buffer) wsi->rxflow_pos++; + /* consume payload bytes efficiently */ + lws_payload_until_length_exhausted(wsi, buf, &len); + /* process the byte */ m = lws_rx_sm(wsi, *(*buf)++); if (m < 0)