clean internal refactor
[platform/upstream/libwebsockets.git] / lib / client-parser.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
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
22 #include "private-libwebsockets.h"
23
24 int lws_client_rx_sm(struct lws *wsi, unsigned char c)
25 {
26         int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
27         struct lws_tokens eff_buf;
28         int handled, m;
29
30         switch (wsi->lws_rx_parse_state) {
31         case LWS_RXPS_NEW:
32
33                 switch (wsi->ietf_spec_revision) {
34
35                 case 13:
36                         wsi->u.ws.opcode = c & 0xf;
37                         wsi->u.ws.rsv = (c & 0x70);
38                         wsi->u.ws.final = !!((c >> 7) & 1);
39                         switch (wsi->u.ws.opcode) {
40                         case LWSWSOPC_TEXT_FRAME:
41                         case LWSWSOPC_BINARY_FRAME:
42                                 wsi->u.ws.frame_is_binary = wsi->u.ws.opcode ==
43                                                  LWSWSOPC_BINARY_FRAME;
44                                 break;
45                         }
46                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
47                         break;
48
49                 default:
50                         lwsl_err("unknown spec version %02d\n",
51                                                        wsi->ietf_spec_revision);
52                         break;
53                 }
54                 break;
55
56         case LWS_RXPS_04_FRAME_HDR_LEN:
57
58                 wsi->u.ws.this_frame_masked = !!(c & 0x80);
59
60                 switch (c & 0x7f) {
61                 case 126:
62                         /* control frames are not allowed to have big lengths */
63                         if (wsi->u.ws.opcode & 8)
64                                 goto illegal_ctl_length;
65                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
66                         break;
67                 case 127:
68                         /* control frames are not allowed to have big lengths */
69                         if (wsi->u.ws.opcode & 8)
70                                 goto illegal_ctl_length;
71                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
72                         break;
73                 default:
74                         wsi->u.ws.rx_packet_length = c;
75                         if (wsi->u.ws.this_frame_masked)
76                                 wsi->lws_rx_parse_state =
77                                                 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
78                         else {
79                                 if (c)
80                                         wsi->lws_rx_parse_state =
81                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
82                                 else {
83                                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
84                                         goto spill;
85                                 }
86                         }
87                         break;
88                 }
89                 break;
90
91         case LWS_RXPS_04_FRAME_HDR_LEN16_2:
92                 wsi->u.ws.rx_packet_length = c << 8;
93                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
94                 break;
95
96         case LWS_RXPS_04_FRAME_HDR_LEN16_1:
97                 wsi->u.ws.rx_packet_length |= c;
98                 if (wsi->u.ws.this_frame_masked)
99                         wsi->lws_rx_parse_state =
100                                         LWS_RXPS_07_COLLECT_FRAME_KEY_1;
101                 else {
102                         if (wsi->u.ws.rx_packet_length)
103                                 wsi->lws_rx_parse_state =
104                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
105                         else {
106                                 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
107                                 goto spill;
108                         }
109                 }
110                 break;
111
112         case LWS_RXPS_04_FRAME_HDR_LEN64_8:
113                 if (c & 0x80) {
114                         lwsl_warn("b63 of length must be zero\n");
115                         /* kill the connection */
116                         return -1;
117                 }
118 #if defined __LP64__
119                 wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
120 #else
121                 wsi->u.ws.rx_packet_length = 0;
122 #endif
123                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
124                 break;
125
126         case LWS_RXPS_04_FRAME_HDR_LEN64_7:
127 #if defined __LP64__
128                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
129 #endif
130                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
131                 break;
132
133         case LWS_RXPS_04_FRAME_HDR_LEN64_6:
134 #if defined __LP64__
135                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
136 #endif
137                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
138                 break;
139
140         case LWS_RXPS_04_FRAME_HDR_LEN64_5:
141 #if defined __LP64__
142                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
143 #endif
144                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
145                 break;
146
147         case LWS_RXPS_04_FRAME_HDR_LEN64_4:
148                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
149                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
150                 break;
151
152         case LWS_RXPS_04_FRAME_HDR_LEN64_3:
153                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
154                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
155                 break;
156
157         case LWS_RXPS_04_FRAME_HDR_LEN64_2:
158                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
159                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
160                 break;
161
162         case LWS_RXPS_04_FRAME_HDR_LEN64_1:
163                 wsi->u.ws.rx_packet_length |= (size_t)c;
164                 if (wsi->u.ws.this_frame_masked)
165                         wsi->lws_rx_parse_state =
166                                         LWS_RXPS_07_COLLECT_FRAME_KEY_1;
167                 else {
168                         if (wsi->u.ws.rx_packet_length)
169                                 wsi->lws_rx_parse_state =
170                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
171                         else {
172                                 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
173                                 goto spill;
174                         }
175                 }
176                 break;
177
178         case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
179                 wsi->u.ws.mask_nonce[0] = c;
180                 if (c)
181                         wsi->u.ws.all_zero_nonce = 0;
182                 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
183                 break;
184
185         case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
186                 wsi->u.ws.mask_nonce[1] = c;
187                 if (c)
188                         wsi->u.ws.all_zero_nonce = 0;
189                 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
190                 break;
191
192         case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
193                 wsi->u.ws.mask_nonce[2] = c;
194                 if (c)
195                         wsi->u.ws.all_zero_nonce = 0;
196                 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
197                 break;
198
199         case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
200                 wsi->u.ws.mask_nonce[3] = c;
201                 if (c)
202                         wsi->u.ws.all_zero_nonce = 0;
203
204                 if (wsi->u.ws.rx_packet_length)
205                         wsi->lws_rx_parse_state =
206                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
207                 else {
208                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
209                         goto spill;
210                 }
211                 break;
212
213         case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
214
215                 if (!wsi->u.ws.rx_user_buffer) {
216                         lwsl_err("NULL client rx_user_buffer\n");
217                         return 1;
218                 }
219
220                 if ((!wsi->u.ws.this_frame_masked) || wsi->u.ws.all_zero_nonce)
221                         wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
222                                (wsi->u.ws.rx_user_buffer_head++)] = c;
223                 else
224                         wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
225                                (wsi->u.ws.rx_user_buffer_head++)] =
226                         c ^ wsi->u.ws.mask_nonce[
227                                             (wsi->u.ws.frame_mask_index++) & 3];
228
229                 if (--wsi->u.ws.rx_packet_length == 0) {
230                         /* spill because we have the whole frame */
231                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
232                         goto spill;
233                 }
234
235                 /*
236                  * if there's no protocol max frame size given, we are
237                  * supposed to default to LWS_MAX_SOCKET_IO_BUF
238                  */
239
240                 if (!wsi->protocol->rx_buffer_size &&
241                                         wsi->u.ws.rx_user_buffer_head !=
242                                                           LWS_MAX_SOCKET_IO_BUF)
243                         break;
244                 else
245                         if (wsi->protocol->rx_buffer_size &&
246                                         wsi->u.ws.rx_user_buffer_head !=
247                                                   wsi->protocol->rx_buffer_size)
248                         break;
249
250                 /* spill because we filled our rx buffer */
251 spill:
252
253                 handled = 0;
254
255                 /*
256                  * is this frame a control packet we should take care of at this
257                  * layer?  If so service it and hide it from the user callback
258                  */
259
260                 switch (wsi->u.ws.opcode) {
261                 case LWSWSOPC_CLOSE:
262                         /* is this an acknowledgement of our close? */
263                         if (wsi->state == LWSS_AWAITING_CLOSE_ACK) {
264                                 /*
265                                  * fine he has told us he is closing too, let's
266                                  * finish our close
267                                  */
268                                 lwsl_parser("seen server's close ack\n");
269                                 return -1;
270                         }
271                         lwsl_parser("client sees server close len = %d\n",
272                                                  wsi->u.ws.rx_user_buffer_head);
273                         /*
274                          * parrot the close packet payload back
275                          * we do not care about how it went, we are closing
276                          * immediately afterwards
277                          */
278                         lws_write(wsi, (unsigned char *)
279                            &wsi->u.ws.rx_user_buffer[
280                                 LWS_SEND_BUFFER_PRE_PADDING],
281                                 wsi->u.ws.rx_user_buffer_head, LWS_WRITE_CLOSE);
282                         wsi->state = LWSS_RETURNED_CLOSE_ALREADY;
283                         /* close the connection */
284                         return -1;
285
286                 case LWSWSOPC_PING:
287                         lwsl_info("received %d byte ping, sending pong\n",
288                                   wsi->u.ws.rx_user_buffer_head);
289
290                         if (wsi->u.ws.ping_pending_flag) {
291                                 /*
292                                  * there is already a pending ping payload
293                                  * we should just log and drop
294                                  */
295                                 lwsl_parser("DROP PING since one pending\n");
296                                 goto ping_drop;
297                         }
298
299                         /* control packets can only be < 128 bytes long */
300                         if (wsi->u.ws.rx_user_buffer_head > 128 - 4) {
301                                 lwsl_parser("DROP PING payload too large\n");
302                                 goto ping_drop;
303                         }
304
305                         /* if existing buffer is too small, drop it */
306                         if (wsi->u.ws.ping_payload_buf &&
307                             wsi->u.ws.ping_payload_alloc <
308                             wsi->u.ws.rx_user_buffer_head)
309                                 lws_free_set_NULL(wsi->u.ws.ping_payload_buf);
310
311                         /* if no buffer, allocate it */
312                         if (!wsi->u.ws.ping_payload_buf) {
313                                 wsi->u.ws.ping_payload_buf =
314                                         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 */
329                         lws_callback_on_writable(wsi);
330 ping_drop:
331                         wsi->u.ws.rx_user_buffer_head = 0;
332                         handled = 1;
333                         break;
334
335                 case LWSWSOPC_PONG:
336                         lwsl_info("client receied pong\n");
337                         lwsl_hexdump(&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
338                                      wsi->u.ws.rx_user_buffer_head);
339
340                         /* issue it */
341                         callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
342                         break;
343
344                 case LWSWSOPC_CONTINUATION:
345                 case LWSWSOPC_TEXT_FRAME:
346                 case LWSWSOPC_BINARY_FRAME:
347                         break;
348
349                 default:
350
351                         lwsl_parser("Reserved opc 0x%2X\n", wsi->u.ws.opcode);
352
353                         /*
354                          * It's something special we can't understand here.
355                          * Pass the payload up to the extension's parsing
356                          * state machine.
357                          */
358
359                         eff_buf.token = &wsi->u.ws.rx_user_buffer[
360                                                    LWS_SEND_BUFFER_PRE_PADDING];
361                         eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
362
363                         if (lws_ext_cb_wsi_active_exts(wsi,
364                                 LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
365                                         &eff_buf, 0) <= 0) { /* not handle or fail */
366
367                                 lwsl_ext("Unhandled ext opc 0x%x\n",
368                                          wsi->u.ws.opcode);
369                                 wsi->u.ws.rx_user_buffer_head = 0;
370
371                                 return 0;
372                         }
373                         handled = 1;
374                         break;
375                 }
376
377                 /*
378                  * No it's real payload, pass it up to the user callback.
379                  * It's nicely buffered with the pre-padding taken care of
380                  * so it can be sent straight out again using lws_write
381                  */
382                 if (handled)
383                         goto already_done;
384
385                 eff_buf.token = &wsi->u.ws.rx_user_buffer[
386                                                 LWS_SEND_BUFFER_PRE_PADDING];
387                 eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
388
389                 if (lws_ext_cb_wsi_active_exts(wsi,
390                                                      LWS_EXT_CALLBACK_PAYLOAD_RX,
391                                                      &eff_buf, 0) < 0) /* fail */
392                         return -1;
393
394                 if (eff_buf.token_len <= 0 &&
395                     callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
396                         goto already_done;
397
398                 eff_buf.token[eff_buf.token_len] = '\0';
399
400                 if (!wsi->protocol->callback)
401                         goto already_done;
402
403                 if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
404                         lwsl_info("Client doing pong callback\n");
405
406                 m = wsi->protocol->callback(wsi,
407                         (enum lws_callback_reasons)callback_action,
408                         wsi->user_space, eff_buf.token, eff_buf.token_len);
409
410                 /* if user code wants to close, let caller know */
411                 if (m)
412                         return 1;
413
414 already_done:
415                 wsi->u.ws.rx_user_buffer_head = 0;
416                 break;
417         default:
418                 lwsl_err("client rx illegal state\n");
419                 return 1;
420         }
421
422         return 0;
423
424 illegal_ctl_length:
425
426         lwsl_warn("Control frame asking for extended length is illegal\n");
427         /* kill the connection */
428         return -1;
429 }
430
431