blob: 7eaf220092cc7bc2619afc3be043bbfd2be7624e [file] [log] [blame]
Andy Green76f61e72013-01-16 11:53:05 +08001/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
Andy Green5ac7e7a2014-03-15 09:32:40 +08004 * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
Andy Green76f61e72013-01-16 11:53:05 +08005 *
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
22#include "private-libwebsockets.h"
23
Andy Green4b85c1d2015-12-04 11:08:32 +080024int lws_client_rx_sm(struct lws *wsi, unsigned char c)
Andy Green76f61e72013-01-16 11:53:05 +080025{
Andy Green76f61e72013-01-16 11:53:05 +080026 int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
27 int handled;
28 struct lws_tokens eff_buf;
Andy Green9ed754d2014-03-23 15:15:54 +080029 int m;
Andy Green76f61e72013-01-16 11:53:05 +080030
Andy Green76f61e72013-01-16 11:53:05 +080031 switch (wsi->lws_rx_parse_state) {
32 case LWS_RXPS_NEW:
33
34 switch (wsi->ietf_spec_revision) {
Andy Green5738c0e2013-01-21 09:53:35 +080035
Andy Green76f61e72013-01-16 11:53:05 +080036 case 13:
Andy Green623a98d2013-01-21 11:04:23 +080037 wsi->u.ws.opcode = c & 0xf;
38 wsi->u.ws.rsv = (c & 0x70);
39 wsi->u.ws.final = !!((c >> 7) & 1);
40 switch (wsi->u.ws.opcode) {
Andy Green10601c12013-01-19 10:39:35 +080041 case LWS_WS_OPCODE_07__TEXT_FRAME:
Andy Green10601c12013-01-19 10:39:35 +080042 case LWS_WS_OPCODE_07__BINARY_FRAME:
Andy Greenb5b23192013-02-11 17:13:32 +080043 wsi->u.ws.frame_is_binary = wsi->u.ws.opcode ==
44 LWS_WS_OPCODE_07__BINARY_FRAME;
Andy Green10601c12013-01-19 10:39:35 +080045 break;
46 }
Andy Green76f61e72013-01-16 11:53:05 +080047 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
48 break;
49
50 default:
Andy Greenb5b23192013-02-11 17:13:32 +080051 lwsl_err("unknown spec version %02d\n",
Andy Green76f61e72013-01-16 11:53:05 +080052 wsi->ietf_spec_revision);
53 break;
54 }
55 break;
56
57
58 case LWS_RXPS_04_FRAME_HDR_LEN:
59
Andy Green623a98d2013-01-21 11:04:23 +080060 wsi->u.ws.this_frame_masked = !!(c & 0x80);
Andy Green76f61e72013-01-16 11:53:05 +080061
62 switch (c & 0x7f) {
63 case 126:
64 /* control frames are not allowed to have big lengths */
Andy Green623a98d2013-01-21 11:04:23 +080065 if (wsi->u.ws.opcode & 8)
Andy Green76f61e72013-01-16 11:53:05 +080066 goto illegal_ctl_length;
67 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
68 break;
69 case 127:
70 /* control frames are not allowed to have big lengths */
Andy Green623a98d2013-01-21 11:04:23 +080071 if (wsi->u.ws.opcode & 8)
Andy Green76f61e72013-01-16 11:53:05 +080072 goto illegal_ctl_length;
73 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
74 break;
75 default:
Andy Green623a98d2013-01-21 11:04:23 +080076 wsi->u.ws.rx_packet_length = c;
77 if (wsi->u.ws.this_frame_masked)
Andy Green76f61e72013-01-16 11:53:05 +080078 wsi->lws_rx_parse_state =
79 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
80 else {
81 if (c)
82 wsi->lws_rx_parse_state =
83 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
84 else {
85 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
86 goto spill;
87 }
88 }
89 break;
90 }
91 break;
92
93 case LWS_RXPS_04_FRAME_HDR_LEN16_2:
Andy Green623a98d2013-01-21 11:04:23 +080094 wsi->u.ws.rx_packet_length = c << 8;
Andy Green76f61e72013-01-16 11:53:05 +080095 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
96 break;
97
98 case LWS_RXPS_04_FRAME_HDR_LEN16_1:
Andy Green623a98d2013-01-21 11:04:23 +080099 wsi->u.ws.rx_packet_length |= c;
100 if (wsi->u.ws.this_frame_masked)
Andy Green76f61e72013-01-16 11:53:05 +0800101 wsi->lws_rx_parse_state =
102 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
103 else {
Andy Green623a98d2013-01-21 11:04:23 +0800104 if (wsi->u.ws.rx_packet_length)
Andy Green76f61e72013-01-16 11:53:05 +0800105 wsi->lws_rx_parse_state =
106 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
107 else {
108 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
109 goto spill;
110 }
111 }
112 break;
113
114 case LWS_RXPS_04_FRAME_HDR_LEN64_8:
115 if (c & 0x80) {
116 lwsl_warn("b63 of length must be zero\n");
117 /* kill the connection */
118 return -1;
119 }
120#if defined __LP64__
Andy Green623a98d2013-01-21 11:04:23 +0800121 wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
Andy Green76f61e72013-01-16 11:53:05 +0800122#else
Andy Green623a98d2013-01-21 11:04:23 +0800123 wsi->u.ws.rx_packet_length = 0;
Andy Green76f61e72013-01-16 11:53:05 +0800124#endif
125 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
126 break;
127
128 case LWS_RXPS_04_FRAME_HDR_LEN64_7:
129#if defined __LP64__
Andy Green623a98d2013-01-21 11:04:23 +0800130 wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
Andy Green76f61e72013-01-16 11:53:05 +0800131#endif
132 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
133 break;
134
135 case LWS_RXPS_04_FRAME_HDR_LEN64_6:
136#if defined __LP64__
Andy Green623a98d2013-01-21 11:04:23 +0800137 wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
Andy Green76f61e72013-01-16 11:53:05 +0800138#endif
139 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
140 break;
141
142 case LWS_RXPS_04_FRAME_HDR_LEN64_5:
143#if defined __LP64__
Andy Green623a98d2013-01-21 11:04:23 +0800144 wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
Andy Green76f61e72013-01-16 11:53:05 +0800145#endif
146 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
147 break;
148
149 case LWS_RXPS_04_FRAME_HDR_LEN64_4:
Andy Green623a98d2013-01-21 11:04:23 +0800150 wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
Andy Green76f61e72013-01-16 11:53:05 +0800151 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
152 break;
153
154 case LWS_RXPS_04_FRAME_HDR_LEN64_3:
Andy Green623a98d2013-01-21 11:04:23 +0800155 wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
Andy Green76f61e72013-01-16 11:53:05 +0800156 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
157 break;
158
159 case LWS_RXPS_04_FRAME_HDR_LEN64_2:
Andy Green623a98d2013-01-21 11:04:23 +0800160 wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
Andy Green76f61e72013-01-16 11:53:05 +0800161 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
162 break;
163
164 case LWS_RXPS_04_FRAME_HDR_LEN64_1:
Andy Green623a98d2013-01-21 11:04:23 +0800165 wsi->u.ws.rx_packet_length |= (size_t)c;
166 if (wsi->u.ws.this_frame_masked)
Andy Green76f61e72013-01-16 11:53:05 +0800167 wsi->lws_rx_parse_state =
168 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
169 else {
Andy Green623a98d2013-01-21 11:04:23 +0800170 if (wsi->u.ws.rx_packet_length)
Andy Green76f61e72013-01-16 11:53:05 +0800171 wsi->lws_rx_parse_state =
172 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
173 else {
174 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
175 goto spill;
176 }
177 }
178 break;
179
180 case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
Andy Green623a98d2013-01-21 11:04:23 +0800181 wsi->u.ws.frame_masking_nonce_04[0] = c;
Andy Green76f61e72013-01-16 11:53:05 +0800182 if (c)
Andy Green623a98d2013-01-21 11:04:23 +0800183 wsi->u.ws.all_zero_nonce = 0;
Andy Green76f61e72013-01-16 11:53:05 +0800184 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
185 break;
186
187 case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
Andy Green623a98d2013-01-21 11:04:23 +0800188 wsi->u.ws.frame_masking_nonce_04[1] = c;
Andy Green76f61e72013-01-16 11:53:05 +0800189 if (c)
Andy Green623a98d2013-01-21 11:04:23 +0800190 wsi->u.ws.all_zero_nonce = 0;
Andy Green76f61e72013-01-16 11:53:05 +0800191 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
192 break;
193
194 case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
Andy Green623a98d2013-01-21 11:04:23 +0800195 wsi->u.ws.frame_masking_nonce_04[2] = c;
Andy Green76f61e72013-01-16 11:53:05 +0800196 if (c)
Andy Green623a98d2013-01-21 11:04:23 +0800197 wsi->u.ws.all_zero_nonce = 0;
Andy Green76f61e72013-01-16 11:53:05 +0800198 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
199 break;
200
201 case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
Andy Green623a98d2013-01-21 11:04:23 +0800202 wsi->u.ws.frame_masking_nonce_04[3] = c;
Andy Green76f61e72013-01-16 11:53:05 +0800203 if (c)
Andy Green623a98d2013-01-21 11:04:23 +0800204 wsi->u.ws.all_zero_nonce = 0;
Andy Green76f61e72013-01-16 11:53:05 +0800205
Andy Green623a98d2013-01-21 11:04:23 +0800206 if (wsi->u.ws.rx_packet_length)
Andy Green76f61e72013-01-16 11:53:05 +0800207 wsi->lws_rx_parse_state =
208 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
209 else {
210 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
211 goto spill;
212 }
213 break;
214
Andy Green76f61e72013-01-16 11:53:05 +0800215 case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
Andy Green54495112013-02-06 21:10:16 +0900216
Andy Greenadc720d2014-11-30 12:54:48 +0800217 if (!wsi->u.ws.rx_user_buffer) {
Andy Green54495112013-02-06 21:10:16 +0900218 lwsl_err("NULL client rx_user_buffer\n");
Andy Greenadc720d2014-11-30 12:54:48 +0800219 return 1;
220 }
Andy Green54495112013-02-06 21:10:16 +0900221
Andy Green623a98d2013-01-21 11:04:23 +0800222 if ((!wsi->u.ws.this_frame_masked) || wsi->u.ws.all_zero_nonce)
223 wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
224 (wsi->u.ws.rx_user_buffer_head++)] = c;
Andy Green76f61e72013-01-16 11:53:05 +0800225 else
Andy Green623a98d2013-01-21 11:04:23 +0800226 wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
227 (wsi->u.ws.rx_user_buffer_head++)] =
Andy Greenb5b23192013-02-11 17:13:32 +0800228 c ^ wsi->u.ws.frame_masking_nonce_04[
229 (wsi->u.ws.frame_mask_index++) & 3];
Andy Green76f61e72013-01-16 11:53:05 +0800230
Andy Green623a98d2013-01-21 11:04:23 +0800231 if (--wsi->u.ws.rx_packet_length == 0) {
Andy Greenff5dbf92013-02-14 10:18:31 +0800232 /* spill because we have the whole frame */
Andy Green76f61e72013-01-16 11:53:05 +0800233 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
234 goto spill;
235 }
Andy Greenff5dbf92013-02-14 10:18:31 +0800236
237 /*
238 * if there's no protocol max frame size given, we are
239 * supposed to default to LWS_MAX_SOCKET_IO_BUF
240 */
241
242 if (!wsi->protocol->rx_buffer_size &&
243 wsi->u.ws.rx_user_buffer_head !=
244 LWS_MAX_SOCKET_IO_BUF)
Andy Green76f61e72013-01-16 11:53:05 +0800245 break;
Andy Greenff5dbf92013-02-14 10:18:31 +0800246 else
247 if (wsi->protocol->rx_buffer_size &&
248 wsi->u.ws.rx_user_buffer_head !=
249 wsi->protocol->rx_buffer_size)
250 break;
251
252 /* spill because we filled our rx buffer */
Andy Green76f61e72013-01-16 11:53:05 +0800253spill:
254
255 handled = 0;
256
257 /*
258 * is this frame a control packet we should take care of at this
259 * layer? If so service it and hide it from the user callback
260 */
261
Andy Green623a98d2013-01-21 11:04:23 +0800262 switch (wsi->u.ws.opcode) {
Andy Green76f61e72013-01-16 11:53:05 +0800263 case LWS_WS_OPCODE_07__CLOSE:
264 /* is this an acknowledgement of our close? */
265 if (wsi->state == WSI_STATE_AWAITING_CLOSE_ACK) {
266 /*
267 * fine he has told us he is closing too, let's
268 * finish our close
269 */
270 lwsl_parser("seen server's close ack\n");
271 return -1;
272 }
Andy Greenb5b23192013-02-11 17:13:32 +0800273 lwsl_parser("client sees server close len = %d\n",
274 wsi->u.ws.rx_user_buffer_head);
Andy Greenfc7c5e42013-02-23 10:50:10 +0800275 /*
276 * parrot the close packet payload back
277 * we do not care about how it went, we are closing
278 * immediately afterwards
279 */
Andy Green62304762015-12-04 08:43:54 +0800280 lws_write(wsi, (unsigned char *)
Andy Greenb5b23192013-02-11 17:13:32 +0800281 &wsi->u.ws.rx_user_buffer[
282 LWS_SEND_BUFFER_PRE_PADDING],
283 wsi->u.ws.rx_user_buffer_head, LWS_WRITE_CLOSE);
Andy Green76f61e72013-01-16 11:53:05 +0800284 wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
285 /* close the connection */
286 return -1;
287
288 case LWS_WS_OPCODE_07__PING:
Andy Green106d4a82015-03-24 21:22:52 +0800289 lwsl_info("received %d byte ping, sending pong\n",
290 wsi->u.ws.rx_user_buffer_head);
291
292 if (wsi->u.ws.ping_pending_flag) {
293 /*
294 * there is already a pending ping payload
295 * we should just log and drop
296 */
297 lwsl_parser("DROP PING since one pending\n");
298 goto ping_drop;
299 }
300
301 /* control packets can only be < 128 bytes long */
302 if (wsi->u.ws.rx_user_buffer_head > 128 - 4) {
303 lwsl_parser("DROP PING payload too large\n");
304 goto ping_drop;
305 }
306
307 /* if existing buffer is too small, drop it */
308 if (wsi->u.ws.ping_payload_buf &&
309 wsi->u.ws.ping_payload_alloc < wsi->u.ws.rx_user_buffer_head)
310 lws_free2(wsi->u.ws.ping_payload_buf);
311
312 /* if no buffer, allocate it */
313 if (!wsi->u.ws.ping_payload_buf) {
314 wsi->u.ws.ping_payload_buf = lws_malloc(wsi->u.ws.rx_user_buffer_head
315 + LWS_SEND_BUFFER_PRE_PADDING);
316 wsi->u.ws.ping_payload_alloc =
317 wsi->u.ws.rx_user_buffer_head;
318 }
319
320 /* stash the pong payload */
321 memcpy(wsi->u.ws.ping_payload_buf + LWS_SEND_BUFFER_PRE_PADDING,
322 &wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
323 wsi->u.ws.rx_user_buffer_head);
324
325 wsi->u.ws.ping_payload_len = wsi->u.ws.rx_user_buffer_head;
326 wsi->u.ws.ping_pending_flag = 1;
327
328 /* get it sent as soon as possible */
Andy Green62304762015-12-04 08:43:54 +0800329 lws_callback_on_writable(wsi->protocol->owning_server, wsi);
Andy Green106d4a82015-03-24 21:22:52 +0800330ping_drop:
331 wsi->u.ws.rx_user_buffer_head = 0;
Andy Green76f61e72013-01-16 11:53:05 +0800332 handled = 1;
333 break;
334
335 case LWS_WS_OPCODE_07__PONG:
Andy Greenf7248f82013-01-16 14:35:12 +0800336 lwsl_info("client receied pong\n");
Andy Greenb5b23192013-02-11 17:13:32 +0800337 lwsl_hexdump(&wsi->u.ws.rx_user_buffer[
338 LWS_SEND_BUFFER_PRE_PADDING],
Andy Green623a98d2013-01-21 11:04:23 +0800339 wsi->u.ws.rx_user_buffer_head);
Andy Green76f61e72013-01-16 11:53:05 +0800340
341 /* issue it */
342 callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
343 break;
344
345 case LWS_WS_OPCODE_07__CONTINUATION:
346 case LWS_WS_OPCODE_07__TEXT_FRAME:
347 case LWS_WS_OPCODE_07__BINARY_FRAME:
348 break;
349
350 default:
351
Andy Greenb5b23192013-02-11 17:13:32 +0800352 lwsl_parser("Reserved opc 0x%2X\n", wsi->u.ws.opcode);
Andy Green2c24ec02014-04-02 19:45:42 +0800353
Andy Green76f61e72013-01-16 11:53:05 +0800354 /*
355 * It's something special we can't understand here.
356 * Pass the payload up to the extension's parsing
357 * state machine.
358 */
359
Andy Green623a98d2013-01-21 11:04:23 +0800360 eff_buf.token = &wsi->u.ws.rx_user_buffer[
Andy Green76f61e72013-01-16 11:53:05 +0800361 LWS_SEND_BUFFER_PRE_PADDING];
Andy Green623a98d2013-01-21 11:04:23 +0800362 eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
Andy Green2c24ec02014-04-02 19:45:42 +0800363
364 if (lws_ext_callback_for_each_active(wsi,
365 LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
366 &eff_buf, 0) <= 0) { /* not handle or fail */
Andy Green76f61e72013-01-16 11:53:05 +0800367
Andy Greenb5b23192013-02-11 17:13:32 +0800368 lwsl_ext("Unhandled ext opc 0x%x\n",
369 wsi->u.ws.opcode);
Andy Green623a98d2013-01-21 11:04:23 +0800370 wsi->u.ws.rx_user_buffer_head = 0;
Andy Green76f61e72013-01-16 11:53:05 +0800371
372 return 0;
373 }
Andy Green2c24ec02014-04-02 19:45:42 +0800374 handled = 1;
Andy Green76f61e72013-01-16 11:53:05 +0800375 break;
376 }
377
378 /*
379 * No it's real payload, pass it up to the user callback.
380 * It's nicely buffered with the pre-padding taken care of
Andy Green62304762015-12-04 08:43:54 +0800381 * so it can be sent straight out again using lws_write
Andy Green76f61e72013-01-16 11:53:05 +0800382 */
383 if (handled)
384 goto already_done;
385
Andy Green623a98d2013-01-21 11:04:23 +0800386 eff_buf.token = &wsi->u.ws.rx_user_buffer[
Andy Green76f61e72013-01-16 11:53:05 +0800387 LWS_SEND_BUFFER_PRE_PADDING];
Andy Green623a98d2013-01-21 11:04:23 +0800388 eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
Andy Green2c24ec02014-04-02 19:45:42 +0800389
390 if (lws_ext_callback_for_each_active(wsi,
Andy Green76f61e72013-01-16 11:53:05 +0800391 LWS_EXT_CALLBACK_PAYLOAD_RX,
Andy Green2c24ec02014-04-02 19:45:42 +0800392 &eff_buf, 0) < 0) /* fail */
393 return -1;
394
Andy Green5ac7e7a2014-03-15 09:32:40 +0800395 if (eff_buf.token_len <= 0 &&
396 callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
Andy Greenb5b23192013-02-11 17:13:32 +0800397 goto already_done;
Andy Green76f61e72013-01-16 11:53:05 +0800398
Andy Greenb5b23192013-02-11 17:13:32 +0800399 eff_buf.token[eff_buf.token_len] = '\0';
400
401 if (!wsi->protocol->callback)
402 goto already_done;
403
404 if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
405 lwsl_info("Client doing pong callback\n");
406
Andy Green5ac7e7a2014-03-15 09:32:40 +0800407 m = wsi->protocol->callback(
Andy Greenb5b23192013-02-11 17:13:32 +0800408 wsi->protocol->owning_server,
409 wsi,
Andy Green4b85c1d2015-12-04 11:08:32 +0800410 (enum lws_callback_reasons)callback_action,
Andy Greenb5b23192013-02-11 17:13:32 +0800411 wsi->user_space,
412 eff_buf.token,
413 eff_buf.token_len);
414
Andy Green5ac7e7a2014-03-15 09:32:40 +0800415 /* if user code wants to close, let caller know */
416 if (m)
417 return 1;
418
Andy Green76f61e72013-01-16 11:53:05 +0800419already_done:
Andy Green623a98d2013-01-21 11:04:23 +0800420 wsi->u.ws.rx_user_buffer_head = 0;
Andy Green76f61e72013-01-16 11:53:05 +0800421 break;
422 default:
423 lwsl_err("client rx illegal state\n");
424 return 1;
425 }
426
427 return 0;
428
429illegal_ctl_length:
430
Andy Greenb5b23192013-02-11 17:13:32 +0800431 lwsl_warn("Control frame asking for extended length is illegal\n");
Andy Green76f61e72013-01-16 11:53:05 +0800432 /* kill the connection */
433 return -1;
Andy Green76f61e72013-01-16 11:53:05 +0800434}
435
436