2
0

client-parser-ws.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010-2018 Andy Green <[email protected]>
  5. *
  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.
  10. *
  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.
  15. *
  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,
  19. * MA 02110-1301 USA
  20. */
  21. #include "core/private.h"
  22. /*
  23. * parsers.c: lws_ws_rx_sm() needs to be roughly kept in
  24. * sync with changes here, esp related to ext draining
  25. */
  26. int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c)
  27. {
  28. int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
  29. int handled, m;
  30. unsigned short close_code;
  31. struct lws_tokens ebuf;
  32. unsigned char *pp;
  33. #if !defined(LWS_WITHOUT_EXTENSIONS)
  34. int rx_draining_ext = 0, n;
  35. #endif
  36. ebuf.token = NULL;
  37. ebuf.len = 0;
  38. #if !defined(LWS_WITHOUT_EXTENSIONS)
  39. if (wsi->ws->rx_draining_ext) {
  40. assert(!c);
  41. lws_remove_wsi_from_draining_ext_list(wsi);
  42. rx_draining_ext = 1;
  43. lwsl_debug("%s: doing draining flow\n", __func__);
  44. goto drain_extension;
  45. }
  46. #endif
  47. if (wsi->socket_is_permanently_unusable)
  48. return -1;
  49. switch (wsi->lws_rx_parse_state) {
  50. case LWS_RXPS_NEW:
  51. /* control frames (PING) may interrupt checkable sequences */
  52. wsi->ws->defeat_check_utf8 = 0;
  53. switch (wsi->ws->ietf_spec_revision) {
  54. case 13:
  55. wsi->ws->opcode = c & 0xf;
  56. /* revisit if an extension wants them... */
  57. switch (wsi->ws->opcode) {
  58. case LWSWSOPC_TEXT_FRAME:
  59. wsi->ws->rsv_first_msg = (c & 0x70);
  60. wsi->ws->continuation_possible = 1;
  61. wsi->ws->check_utf8 = lws_check_opt(
  62. wsi->context->options,
  63. LWS_SERVER_OPTION_VALIDATE_UTF8);
  64. wsi->ws->utf8 = 0;
  65. wsi->ws->first_fragment = 1;
  66. break;
  67. case LWSWSOPC_BINARY_FRAME:
  68. wsi->ws->rsv_first_msg = (c & 0x70);
  69. wsi->ws->check_utf8 = 0;
  70. wsi->ws->continuation_possible = 1;
  71. wsi->ws->first_fragment = 1;
  72. break;
  73. case LWSWSOPC_CONTINUATION:
  74. if (!wsi->ws->continuation_possible) {
  75. lwsl_info("disordered continuation\n");
  76. return -1;
  77. }
  78. wsi->ws->first_fragment = 0;
  79. break;
  80. case LWSWSOPC_CLOSE:
  81. wsi->ws->check_utf8 = 0;
  82. wsi->ws->utf8 = 0;
  83. break;
  84. case 3:
  85. case 4:
  86. case 5:
  87. case 6:
  88. case 7:
  89. case 0xb:
  90. case 0xc:
  91. case 0xd:
  92. case 0xe:
  93. case 0xf:
  94. lwsl_info("illegal opcode\n");
  95. return -1;
  96. default:
  97. wsi->ws->defeat_check_utf8 = 1;
  98. break;
  99. }
  100. wsi->ws->rsv = (c & 0x70);
  101. /* revisit if an extension wants them... */
  102. if (
  103. #if !defined(LWS_WITHOUT_EXTENSIONS)
  104. !wsi->ws->count_act_ext &&
  105. #endif
  106. wsi->ws->rsv) {
  107. lwsl_info("illegal rsv bits set\n");
  108. return -1;
  109. }
  110. wsi->ws->final = !!((c >> 7) & 1);
  111. lwsl_ext("%s: This RX frame Final %d\n", __func__,
  112. wsi->ws->final);
  113. if (wsi->ws->owed_a_fin &&
  114. (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
  115. wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)) {
  116. lwsl_info("hey you owed us a FIN\n");
  117. return -1;
  118. }
  119. if ((!(wsi->ws->opcode & 8)) && wsi->ws->final) {
  120. wsi->ws->continuation_possible = 0;
  121. wsi->ws->owed_a_fin = 0;
  122. }
  123. if ((wsi->ws->opcode & 8) && !wsi->ws->final) {
  124. lwsl_info("control msg can't be fragmented\n");
  125. return -1;
  126. }
  127. if (!wsi->ws->final)
  128. wsi->ws->owed_a_fin = 1;
  129. switch (wsi->ws->opcode) {
  130. case LWSWSOPC_TEXT_FRAME:
  131. case LWSWSOPC_BINARY_FRAME:
  132. wsi->ws->frame_is_binary = wsi->ws->opcode ==
  133. LWSWSOPC_BINARY_FRAME;
  134. break;
  135. }
  136. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
  137. break;
  138. default:
  139. lwsl_err("unknown spec version %02d\n",
  140. wsi->ws->ietf_spec_revision);
  141. break;
  142. }
  143. break;
  144. case LWS_RXPS_04_FRAME_HDR_LEN:
  145. wsi->ws->this_frame_masked = !!(c & 0x80);
  146. switch (c & 0x7f) {
  147. case 126:
  148. /* control frames are not allowed to have big lengths */
  149. if (wsi->ws->opcode & 8)
  150. goto illegal_ctl_length;
  151. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
  152. break;
  153. case 127:
  154. /* control frames are not allowed to have big lengths */
  155. if (wsi->ws->opcode & 8)
  156. goto illegal_ctl_length;
  157. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
  158. break;
  159. default:
  160. wsi->ws->rx_packet_length = c & 0x7f;
  161. if (wsi->ws->this_frame_masked)
  162. wsi->lws_rx_parse_state =
  163. LWS_RXPS_07_COLLECT_FRAME_KEY_1;
  164. else {
  165. if (wsi->ws->rx_packet_length) {
  166. wsi->lws_rx_parse_state =
  167. LWS_RXPS_WS_FRAME_PAYLOAD;
  168. } else {
  169. wsi->lws_rx_parse_state = LWS_RXPS_NEW;
  170. goto spill;
  171. }
  172. }
  173. break;
  174. }
  175. break;
  176. case LWS_RXPS_04_FRAME_HDR_LEN16_2:
  177. wsi->ws->rx_packet_length = c << 8;
  178. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
  179. break;
  180. case LWS_RXPS_04_FRAME_HDR_LEN16_1:
  181. wsi->ws->rx_packet_length |= c;
  182. if (wsi->ws->this_frame_masked)
  183. wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1;
  184. else {
  185. if (wsi->ws->rx_packet_length)
  186. wsi->lws_rx_parse_state =
  187. LWS_RXPS_WS_FRAME_PAYLOAD;
  188. else {
  189. wsi->lws_rx_parse_state = LWS_RXPS_NEW;
  190. goto spill;
  191. }
  192. }
  193. break;
  194. case LWS_RXPS_04_FRAME_HDR_LEN64_8:
  195. if (c & 0x80) {
  196. lwsl_warn("b63 of length must be zero\n");
  197. /* kill the connection */
  198. return -1;
  199. }
  200. #if defined __LP64__
  201. wsi->ws->rx_packet_length = ((size_t)c) << 56;
  202. #else
  203. wsi->ws->rx_packet_length = 0;
  204. #endif
  205. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
  206. break;
  207. case LWS_RXPS_04_FRAME_HDR_LEN64_7:
  208. #if defined __LP64__
  209. wsi->ws->rx_packet_length |= ((size_t)c) << 48;
  210. #endif
  211. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
  212. break;
  213. case LWS_RXPS_04_FRAME_HDR_LEN64_6:
  214. #if defined __LP64__
  215. wsi->ws->rx_packet_length |= ((size_t)c) << 40;
  216. #endif
  217. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
  218. break;
  219. case LWS_RXPS_04_FRAME_HDR_LEN64_5:
  220. #if defined __LP64__
  221. wsi->ws->rx_packet_length |= ((size_t)c) << 32;
  222. #endif
  223. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
  224. break;
  225. case LWS_RXPS_04_FRAME_HDR_LEN64_4:
  226. wsi->ws->rx_packet_length |= ((size_t)c) << 24;
  227. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
  228. break;
  229. case LWS_RXPS_04_FRAME_HDR_LEN64_3:
  230. wsi->ws->rx_packet_length |= ((size_t)c) << 16;
  231. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
  232. break;
  233. case LWS_RXPS_04_FRAME_HDR_LEN64_2:
  234. wsi->ws->rx_packet_length |= ((size_t)c) << 8;
  235. wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
  236. break;
  237. case LWS_RXPS_04_FRAME_HDR_LEN64_1:
  238. wsi->ws->rx_packet_length |= (size_t)c;
  239. if (wsi->ws->this_frame_masked)
  240. wsi->lws_rx_parse_state =
  241. LWS_RXPS_07_COLLECT_FRAME_KEY_1;
  242. else {
  243. if (wsi->ws->rx_packet_length)
  244. wsi->lws_rx_parse_state =
  245. LWS_RXPS_WS_FRAME_PAYLOAD;
  246. else {
  247. wsi->lws_rx_parse_state = LWS_RXPS_NEW;
  248. goto spill;
  249. }
  250. }
  251. break;
  252. case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
  253. wsi->ws->mask[0] = c;
  254. if (c)
  255. wsi->ws->all_zero_nonce = 0;
  256. wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
  257. break;
  258. case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
  259. wsi->ws->mask[1] = c;
  260. if (c)
  261. wsi->ws->all_zero_nonce = 0;
  262. wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
  263. break;
  264. case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
  265. wsi->ws->mask[2] = c;
  266. if (c)
  267. wsi->ws->all_zero_nonce = 0;
  268. wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
  269. break;
  270. case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
  271. wsi->ws->mask[3] = c;
  272. if (c)
  273. wsi->ws->all_zero_nonce = 0;
  274. if (wsi->ws->rx_packet_length)
  275. wsi->lws_rx_parse_state =
  276. LWS_RXPS_WS_FRAME_PAYLOAD;
  277. else {
  278. wsi->lws_rx_parse_state = LWS_RXPS_NEW;
  279. goto spill;
  280. }
  281. break;
  282. case LWS_RXPS_WS_FRAME_PAYLOAD:
  283. assert(wsi->ws->rx_ubuf);
  284. #if !defined(LWS_WITHOUT_EXTENSIONS)
  285. if (wsi->ws->rx_draining_ext)
  286. goto drain_extension;
  287. #endif
  288. if (wsi->ws->this_frame_masked && !wsi->ws->all_zero_nonce)
  289. c ^= wsi->ws->mask[(wsi->ws->mask_idx++) & 3];
  290. wsi->ws->rx_ubuf[LWS_PRE + (wsi->ws->rx_ubuf_head++)] = c;
  291. if (--wsi->ws->rx_packet_length == 0) {
  292. /* spill because we have the whole frame */
  293. wsi->lws_rx_parse_state = LWS_RXPS_NEW;
  294. goto spill;
  295. }
  296. /*
  297. * if there's no protocol max frame size given, we are
  298. * supposed to default to context->pt_serv_buf_size
  299. */
  300. if (!wsi->protocol->rx_buffer_size &&
  301. wsi->ws->rx_ubuf_head != wsi->context->pt_serv_buf_size)
  302. break;
  303. if (wsi->protocol->rx_buffer_size &&
  304. wsi->ws->rx_ubuf_head != wsi->protocol->rx_buffer_size)
  305. break;
  306. /* spill because we filled our rx buffer */
  307. spill:
  308. handled = 0;
  309. /*
  310. * is this frame a control packet we should take care of at this
  311. * layer? If so service it and hide it from the user callback
  312. */
  313. switch (wsi->ws->opcode) {
  314. case LWSWSOPC_CLOSE:
  315. pp = (unsigned char *)&wsi->ws->rx_ubuf[LWS_PRE];
  316. if (lws_check_opt(wsi->context->options,
  317. LWS_SERVER_OPTION_VALIDATE_UTF8) &&
  318. wsi->ws->rx_ubuf_head > 2 &&
  319. lws_check_utf8(&wsi->ws->utf8, pp + 2,
  320. wsi->ws->rx_ubuf_head - 2))
  321. goto utf8_fail;
  322. /* is this an acknowledgment of our close? */
  323. if (lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK) {
  324. /*
  325. * fine he has told us he is closing too, let's
  326. * finish our close
  327. */
  328. lwsl_parser("seen server's close ack\n");
  329. return -1;
  330. }
  331. lwsl_parser("client sees server close len = %d\n",
  332. wsi->ws->rx_ubuf_head);
  333. if (wsi->ws->rx_ubuf_head >= 2) {
  334. close_code = (pp[0] << 8) | pp[1];
  335. if (close_code < 1000 ||
  336. close_code == 1004 ||
  337. close_code == 1005 ||
  338. close_code == 1006 ||
  339. close_code == 1012 ||
  340. close_code == 1013 ||
  341. close_code == 1014 ||
  342. close_code == 1015 ||
  343. (close_code >= 1016 && close_code < 3000)
  344. ) {
  345. pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
  346. pp[1] = LWS_CLOSE_STATUS_PROTOCOL_ERR & 0xff;
  347. }
  348. }
  349. if (user_callback_handle_rxflow(
  350. wsi->protocol->callback, wsi,
  351. LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
  352. wsi->user_space, pp,
  353. wsi->ws->rx_ubuf_head))
  354. return -1;
  355. memcpy(wsi->ws->ping_payload_buf + LWS_PRE, pp,
  356. wsi->ws->rx_ubuf_head);
  357. wsi->ws->close_in_ping_buffer_len =
  358. wsi->ws->rx_ubuf_head;
  359. lwsl_info("%s: scheduling return close as ack\n",
  360. __func__);
  361. __lws_change_pollfd(wsi, LWS_POLLIN, 0);
  362. lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 3);
  363. wsi->waiting_to_send_close_frame = 1;
  364. wsi->close_needs_ack = 0;
  365. lwsi_set_state(wsi, LRS_WAITING_TO_SEND_CLOSE);
  366. lws_callback_on_writable(wsi);
  367. handled = 1;
  368. break;
  369. case LWSWSOPC_PING:
  370. lwsl_info("received %d byte ping, sending pong\n",
  371. wsi->ws->rx_ubuf_head);
  372. /* he set a close reason on this guy, ignore PING */
  373. if (wsi->ws->close_in_ping_buffer_len)
  374. goto ping_drop;
  375. if (wsi->ws->ping_pending_flag) {
  376. /*
  377. * there is already a pending ping payload
  378. * we should just log and drop
  379. */
  380. lwsl_parser("DROP PING since one pending\n");
  381. goto ping_drop;
  382. }
  383. /* control packets can only be < 128 bytes long */
  384. if (wsi->ws->rx_ubuf_head > 128 - 3) {
  385. lwsl_parser("DROP PING payload too large\n");
  386. goto ping_drop;
  387. }
  388. /* stash the pong payload */
  389. memcpy(wsi->ws->ping_payload_buf + LWS_PRE,
  390. &wsi->ws->rx_ubuf[LWS_PRE],
  391. wsi->ws->rx_ubuf_head);
  392. wsi->ws->ping_payload_len = wsi->ws->rx_ubuf_head;
  393. wsi->ws->ping_pending_flag = 1;
  394. /* get it sent as soon as possible */
  395. lws_callback_on_writable(wsi);
  396. ping_drop:
  397. wsi->ws->rx_ubuf_head = 0;
  398. handled = 1;
  399. break;
  400. case LWSWSOPC_PONG:
  401. lwsl_info("client received pong\n");
  402. lwsl_hexdump(&wsi->ws->rx_ubuf[LWS_PRE],
  403. wsi->ws->rx_ubuf_head);
  404. if (wsi->pending_timeout ==
  405. PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG) {
  406. lwsl_info("%p: received expected PONG\n", wsi);
  407. lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
  408. }
  409. /* issue it */
  410. callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
  411. break;
  412. case LWSWSOPC_CONTINUATION:
  413. case LWSWSOPC_TEXT_FRAME:
  414. case LWSWSOPC_BINARY_FRAME:
  415. break;
  416. default:
  417. /* not handled or failed */
  418. lwsl_ext("Unhandled ext opc 0x%x\n", wsi->ws->opcode);
  419. wsi->ws->rx_ubuf_head = 0;
  420. return -1;
  421. }
  422. /*
  423. * No it's real payload, pass it up to the user callback.
  424. * It's nicely buffered with the pre-padding taken care of
  425. * so it can be sent straight out again using lws_write
  426. */
  427. if (handled)
  428. goto already_done;
  429. ebuf.token = &wsi->ws->rx_ubuf[LWS_PRE];
  430. ebuf.len = wsi->ws->rx_ubuf_head;
  431. #if !defined(LWS_WITHOUT_EXTENSIONS)
  432. drain_extension:
  433. lwsl_ext("%s: passing %d to ext\n", __func__, ebuf.len);
  434. n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &ebuf, 0);
  435. lwsl_ext("Ext RX returned %d\n", n);
  436. if (n < 0) {
  437. wsi->socket_is_permanently_unusable = 1;
  438. return -1;
  439. }
  440. #endif
  441. lwsl_debug("post inflate ebuf len %d\n", ebuf.len);
  442. #if !defined(LWS_WITHOUT_EXTENSIONS)
  443. if (rx_draining_ext && !ebuf.len) {
  444. lwsl_debug(" --- ending drain on 0 read result\n");
  445. goto already_done;
  446. }
  447. #endif
  448. if (wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
  449. if (lws_check_utf8(&wsi->ws->utf8,
  450. (unsigned char *)ebuf.token,
  451. ebuf.len)) {
  452. lws_close_reason(wsi,
  453. LWS_CLOSE_STATUS_INVALID_PAYLOAD,
  454. (uint8_t *)"bad utf8", 8);
  455. goto utf8_fail;
  456. }
  457. /* we are ending partway through utf-8 character? */
  458. if (!wsi->ws->rx_packet_length && wsi->ws->final &&
  459. wsi->ws->utf8
  460. #if !defined(LWS_WITHOUT_EXTENSIONS)
  461. && !n
  462. #endif
  463. ) {
  464. lwsl_info("FINAL utf8 error\n");
  465. lws_close_reason(wsi,
  466. LWS_CLOSE_STATUS_INVALID_PAYLOAD,
  467. (uint8_t *)"partial utf8", 12);
  468. utf8_fail:
  469. lwsl_info("utf8 error\n");
  470. lwsl_hexdump_info(ebuf.token, ebuf.len);
  471. return -1;
  472. }
  473. }
  474. if (ebuf.len < 0 &&
  475. callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
  476. goto already_done;
  477. if (!ebuf.token)
  478. goto already_done;
  479. ebuf.token[ebuf.len] = '\0';
  480. if (!wsi->protocol->callback)
  481. goto already_done;
  482. if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
  483. lwsl_info("Client doing pong callback\n");
  484. if (
  485. /* coverity says dead code otherwise */
  486. #if !defined(LWS_WITHOUT_EXTENSIONS)
  487. n &&
  488. #endif
  489. ebuf.len)
  490. /* extension had more... main loop will come back
  491. * we want callback to be done with this set, if so,
  492. * because lws_is_final() hides it was final until the
  493. * last chunk
  494. */
  495. lws_add_wsi_to_draining_ext_list(wsi);
  496. else
  497. lws_remove_wsi_from_draining_ext_list(wsi);
  498. if (lwsi_state(wsi) == LRS_RETURNED_CLOSE ||
  499. lwsi_state(wsi) == LRS_WAITING_TO_SEND_CLOSE ||
  500. lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK)
  501. goto already_done;
  502. m = wsi->protocol->callback(wsi,
  503. (enum lws_callback_reasons)callback_action,
  504. wsi->user_space, ebuf.token, ebuf.len);
  505. wsi->ws->first_fragment = 0;
  506. // lwsl_notice("%s: bulk ws rx: input used %d, output %d\n",
  507. // __func__, wsi->ws->rx_ubuf_head, ebuf.len);
  508. /* if user code wants to close, let caller know */
  509. if (m)
  510. return 1;
  511. already_done:
  512. wsi->ws->rx_ubuf_head = 0;
  513. break;
  514. default:
  515. lwsl_err("client rx illegal state\n");
  516. return 1;
  517. }
  518. return 0;
  519. illegal_ctl_length:
  520. lwsl_warn("Control frame asking for extended length is illegal\n");
  521. /* kill the connection */
  522. return -1;
  523. }