2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include "private-libwebsockets.h"
25 * parsers.c: lws_rx_sm() needs to be roughly kept in
26 * sync with changes here, esp related to ext draining
29 int lws_client_rx_sm(struct lws *wsi, unsigned char c)
31 int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
32 int handled, n, m, rx_draining_ext = 0;
33 unsigned short close_code;
34 struct lws_tokens eff_buf;
37 if (wsi->u.ws.rx_draining_ext) {
40 eff_buf.token_len = 0;
41 lws_remove_wsi_from_draining_ext_list(wsi);
43 lwsl_debug("%s: doing draining flow\n", __func__);
48 if (wsi->socket_is_permanently_unusable)
51 switch (wsi->lws_rx_parse_state) {
53 /* control frames (PING) may interrupt checkable sequences */
54 wsi->u.ws.defeat_check_utf8 = 0;
56 switch (wsi->ietf_spec_revision) {
58 wsi->u.ws.opcode = c & 0xf;
59 /* revisit if an extension wants them... */
60 switch (wsi->u.ws.opcode) {
61 case LWSWSOPC_TEXT_FRAME:
62 wsi->u.ws.rsv_first_msg = (c & 0x70);
63 wsi->u.ws.continuation_possible = 1;
64 wsi->u.ws.check_utf8 = lws_check_opt(
65 wsi->context->options,
66 LWS_SERVER_OPTION_VALIDATE_UTF8);
69 case LWSWSOPC_BINARY_FRAME:
70 wsi->u.ws.rsv_first_msg = (c & 0x70);
71 wsi->u.ws.check_utf8 = 0;
72 wsi->u.ws.continuation_possible = 1;
74 case LWSWSOPC_CONTINUATION:
75 if (!wsi->u.ws.continuation_possible) {
76 lwsl_info("disordered continuation\n");
81 wsi->u.ws.check_utf8 = 0;
94 lwsl_info("illegal opcode\n");
97 wsi->u.ws.defeat_check_utf8 = 1;
100 wsi->u.ws.rsv = (c & 0x70);
101 /* revisit if an extension wants them... */
103 #ifndef LWS_NO_EXTENSIONS
104 !wsi->count_act_ext &&
107 lwsl_info("illegal rsv bits set\n");
110 wsi->u.ws.final = !!((c >> 7) & 1);
111 lwsl_ext("%s: This RX frame Final %d\n", __func__, wsi->u.ws.final);
113 if (wsi->u.ws.owed_a_fin &&
114 (wsi->u.ws.opcode == LWSWSOPC_TEXT_FRAME ||
115 wsi->u.ws.opcode == LWSWSOPC_BINARY_FRAME)) {
116 lwsl_info("hey you owed us a FIN\n");
119 if ((!(wsi->u.ws.opcode & 8)) && wsi->u.ws.final) {
120 wsi->u.ws.continuation_possible = 0;
121 wsi->u.ws.owed_a_fin = 0;
124 if ((wsi->u.ws.opcode & 8) && !wsi->u.ws.final) {
125 lwsl_info("control message cannot be fragmented\n");
128 if (!wsi->u.ws.final)
129 wsi->u.ws.owed_a_fin = 1;
131 switch (wsi->u.ws.opcode) {
132 case LWSWSOPC_TEXT_FRAME:
133 case LWSWSOPC_BINARY_FRAME:
134 wsi->u.ws.frame_is_binary = wsi->u.ws.opcode ==
135 LWSWSOPC_BINARY_FRAME;
138 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
142 lwsl_err("unknown spec version %02d\n",
143 wsi->ietf_spec_revision);
148 case LWS_RXPS_04_FRAME_HDR_LEN:
150 wsi->u.ws.this_frame_masked = !!(c & 0x80);
154 /* control frames are not allowed to have big lengths */
155 if (wsi->u.ws.opcode & 8)
156 goto illegal_ctl_length;
157 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
160 /* control frames are not allowed to have big lengths */
161 if (wsi->u.ws.opcode & 8)
162 goto illegal_ctl_length;
163 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
166 wsi->u.ws.rx_packet_length = c;
167 if (wsi->u.ws.this_frame_masked)
168 wsi->lws_rx_parse_state =
169 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
172 wsi->lws_rx_parse_state =
173 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
175 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
183 case LWS_RXPS_04_FRAME_HDR_LEN16_2:
184 wsi->u.ws.rx_packet_length = c << 8;
185 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
188 case LWS_RXPS_04_FRAME_HDR_LEN16_1:
189 wsi->u.ws.rx_packet_length |= c;
190 if (wsi->u.ws.this_frame_masked)
191 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1;
193 if (wsi->u.ws.rx_packet_length)
194 wsi->lws_rx_parse_state =
195 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
197 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
203 case LWS_RXPS_04_FRAME_HDR_LEN64_8:
205 lwsl_warn("b63 of length must be zero\n");
206 /* kill the connection */
210 wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
212 wsi->u.ws.rx_packet_length = 0;
214 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
217 case LWS_RXPS_04_FRAME_HDR_LEN64_7:
219 wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
221 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
224 case LWS_RXPS_04_FRAME_HDR_LEN64_6:
226 wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
228 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
231 case LWS_RXPS_04_FRAME_HDR_LEN64_5:
233 wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
235 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
238 case LWS_RXPS_04_FRAME_HDR_LEN64_4:
239 wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
240 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
243 case LWS_RXPS_04_FRAME_HDR_LEN64_3:
244 wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
245 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
248 case LWS_RXPS_04_FRAME_HDR_LEN64_2:
249 wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
250 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
253 case LWS_RXPS_04_FRAME_HDR_LEN64_1:
254 wsi->u.ws.rx_packet_length |= (size_t)c;
255 if (wsi->u.ws.this_frame_masked)
256 wsi->lws_rx_parse_state =
257 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
259 if (wsi->u.ws.rx_packet_length)
260 wsi->lws_rx_parse_state =
261 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
263 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
269 case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
270 wsi->u.ws.mask[0] = c;
272 wsi->u.ws.all_zero_nonce = 0;
273 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
276 case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
277 wsi->u.ws.mask[1] = c;
279 wsi->u.ws.all_zero_nonce = 0;
280 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
283 case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
284 wsi->u.ws.mask[2] = c;
286 wsi->u.ws.all_zero_nonce = 0;
287 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
290 case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
291 wsi->u.ws.mask[3] = c;
293 wsi->u.ws.all_zero_nonce = 0;
295 if (wsi->u.ws.rx_packet_length)
296 wsi->lws_rx_parse_state =
297 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
299 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
304 case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
306 assert(wsi->u.ws.rx_ubuf);
308 if (wsi->u.ws.rx_draining_ext)
309 goto drain_extension;
311 if (wsi->u.ws.this_frame_masked && !wsi->u.ws.all_zero_nonce)
312 c ^= wsi->u.ws.mask[(wsi->u.ws.mask_idx++) & 3];
314 wsi->u.ws.rx_ubuf[LWS_PRE + (wsi->u.ws.rx_ubuf_head++)] = c;
316 if (--wsi->u.ws.rx_packet_length == 0) {
317 /* spill because we have the whole frame */
318 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
323 * if there's no protocol max frame size given, we are
324 * supposed to default to context->pt_serv_buf_size
326 if (!wsi->protocol->rx_buffer_size &&
327 wsi->u.ws.rx_ubuf_head != wsi->context->pt_serv_buf_size)
330 if (wsi->protocol->rx_buffer_size &&
331 wsi->u.ws.rx_ubuf_head != wsi->protocol->rx_buffer_size)
334 /* spill because we filled our rx buffer */
340 * is this frame a control packet we should take care of at this
341 * layer? If so service it and hide it from the user callback
344 switch (wsi->u.ws.opcode) {
346 pp = (unsigned char *)&wsi->u.ws.rx_ubuf[LWS_PRE];
347 if (lws_check_opt(wsi->context->options,
348 LWS_SERVER_OPTION_VALIDATE_UTF8) &&
349 wsi->u.ws.rx_ubuf_head > 2 &&
350 lws_check_utf8(&wsi->u.ws.utf8, pp + 2,
351 wsi->u.ws.rx_ubuf_head - 2))
354 /* is this an acknowledgement of our close? */
355 if (wsi->state == LWSS_AWAITING_CLOSE_ACK) {
357 * fine he has told us he is closing too, let's
360 lwsl_parser("seen server's close ack\n");
364 lwsl_parser("client sees server close len = %d\n",
365 wsi->u.ws.rx_ubuf_head);
366 if (wsi->u.ws.rx_ubuf_head >= 2) {
367 close_code = (pp[0] << 8) | pp[1];
368 if (close_code < 1000 ||
369 close_code == 1004 ||
370 close_code == 1005 ||
371 close_code == 1006 ||
372 close_code == 1012 ||
373 close_code == 1013 ||
374 close_code == 1014 ||
375 close_code == 1015 ||
376 (close_code >= 1016 && close_code < 3000)
378 pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
379 pp[1] = LWS_CLOSE_STATUS_PROTOCOL_ERR & 0xff;
382 if (user_callback_handle_rxflow(
383 wsi->protocol->callback, wsi,
384 LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
386 wsi->u.ws.rx_ubuf_head))
389 if (lws_partial_buffered(wsi))
391 * if we're in the middle of something,
392 * we can't do a normal close response and
393 * have to just close our end.
395 wsi->socket_is_permanently_unusable = 1;
398 * parrot the close packet payload back
399 * we do not care about how it went, we are closing
400 * immediately afterwards
402 lws_write(wsi, (unsigned char *)&wsi->u.ws.rx_ubuf[LWS_PRE],
403 wsi->u.ws.rx_ubuf_head,
405 wsi->state = LWSS_RETURNED_CLOSE_ALREADY;
406 /* close the connection */
410 lwsl_info("received %d byte ping, sending pong\n",
411 wsi->u.ws.rx_ubuf_head);
413 /* he set a close reason on this guy, ignore PING */
414 if (wsi->u.ws.close_in_ping_buffer_len)
417 if (wsi->u.ws.ping_pending_flag) {
419 * there is already a pending ping payload
420 * we should just log and drop
422 lwsl_parser("DROP PING since one pending\n");
426 /* control packets can only be < 128 bytes long */
427 if (wsi->u.ws.rx_ubuf_head > 128 - 3) {
428 lwsl_parser("DROP PING payload too large\n");
432 /* stash the pong payload */
433 memcpy(wsi->u.ws.ping_payload_buf + LWS_PRE,
434 &wsi->u.ws.rx_ubuf[LWS_PRE],
435 wsi->u.ws.rx_ubuf_head);
437 wsi->u.ws.ping_payload_len = wsi->u.ws.rx_ubuf_head;
438 wsi->u.ws.ping_pending_flag = 1;
440 /* get it sent as soon as possible */
441 lws_callback_on_writable(wsi);
443 wsi->u.ws.rx_ubuf_head = 0;
448 lwsl_info("client receied pong\n");
449 lwsl_hexdump(&wsi->u.ws.rx_ubuf[LWS_PRE],
450 wsi->u.ws.rx_ubuf_head);
452 if (wsi->pending_timeout == PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG) {
453 lwsl_info("received expected PONG on wsi %p\n", wsi);
454 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
458 callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
461 case LWSWSOPC_CONTINUATION:
462 case LWSWSOPC_TEXT_FRAME:
463 case LWSWSOPC_BINARY_FRAME:
468 lwsl_parser("Reserved opc 0x%2X\n", wsi->u.ws.opcode);
471 * It's something special we can't understand here.
472 * Pass the payload up to the extension's parsing
476 eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE];
477 eff_buf.token_len = wsi->u.ws.rx_ubuf_head;
479 if (lws_ext_cb_active(wsi,
480 LWS_EXT_CB_EXTENDED_PAYLOAD_RX,
481 &eff_buf, 0) <= 0) { /* not handle or fail */
483 lwsl_ext("Unhandled ext opc 0x%x\n", wsi->u.ws.opcode);
484 wsi->u.ws.rx_ubuf_head = 0;
493 * No it's real payload, pass it up to the user callback.
494 * It's nicely buffered with the pre-padding taken care of
495 * so it can be sent straight out again using lws_write
500 eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE];
501 eff_buf.token_len = wsi->u.ws.rx_ubuf_head;
504 lwsl_ext("%s: passing %d to ext\n", __func__, eff_buf.token_len);
506 n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &eff_buf, 0);
507 lwsl_ext("Ext RX returned %d\n", n);
509 wsi->socket_is_permanently_unusable = 1;
513 lwsl_ext("post inflate eff_buf len %d\n", eff_buf.token_len);
515 if (rx_draining_ext && !eff_buf.token_len) {
516 lwsl_err(" --- ignoring zero drain result, ending drain\n");
520 if (wsi->u.ws.check_utf8 && !wsi->u.ws.defeat_check_utf8) {
521 if (lws_check_utf8(&wsi->u.ws.utf8,
522 (unsigned char *)eff_buf.token,
526 /* we are ending partway through utf-8 character? */
527 if (!wsi->u.ws.rx_packet_length && wsi->u.ws.final &&
528 wsi->u.ws.utf8 && !n) {
529 lwsl_info("FINAL utf8 error\n");
530 utf8_fail: lwsl_info("utf8 error\n");
535 if (eff_buf.token_len < 0 &&
536 callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
542 eff_buf.token[eff_buf.token_len] = '\0';
544 if (!wsi->protocol->callback)
547 if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
548 lwsl_info("Client doing pong callback\n");
550 if (n && eff_buf.token_len)
551 /* extension had more... main loop will come back
552 * we want callback to be done with this set, if so,
553 * because lws_is_final() hides it was final until the
556 lws_add_wsi_to_draining_ext_list(wsi);
558 lws_remove_wsi_from_draining_ext_list(wsi);
560 if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
561 wsi->state == LWSS_AWAITING_CLOSE_ACK)
564 m = wsi->protocol->callback(wsi,
565 (enum lws_callback_reasons)callback_action,
566 wsi->user_space, eff_buf.token, eff_buf.token_len);
568 /* if user code wants to close, let caller know */
573 wsi->u.ws.rx_ubuf_head = 0;
576 lwsl_err("client rx illegal state\n");
583 lwsl_warn("Control frame asking for extended length is illegal\n");
584 /* kill the connection */