Subject: [PATCH] Fix bug parsing unknown headers.
[platform/upstream/libwebsockets.git] / lib / parsers.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2013 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 unsigned char lextable[] = {
25         #include "lextable.h"
26 };
27
28 #define FAIL_CHAR 0x08
29
30 int lextable_decode(int pos, char c)
31 {
32
33         c = tolower(c);
34
35         while (1) {
36                 if (lextable[pos] & (1 << 7)) { /* 1-byte, fail on mismatch */
37                         if ((lextable[pos] & 0x7f) != c)
38                                 return -1;
39                         /* fall thru */
40                         pos++;
41                         if (lextable[pos] == FAIL_CHAR)
42                                 return -1;
43                         return pos;
44                 }
45
46                 if (lextable[pos] == FAIL_CHAR)
47                         return -1;
48
49                 /* b7 = 0, end or 3-byte */
50                 if (lextable[pos] < FAIL_CHAR) /* terminal marker */
51                         return pos;
52
53                 if (lextable[pos] == c) /* goto */
54                         return pos + (lextable[pos + 1]) +
55                                                 (lextable[pos + 2] << 8);
56                 /* fall thru goto */
57                 pos += 3;
58                 /* continue */
59         }
60 }
61
62 int lws_allocate_header_table(struct libwebsocket *wsi)
63 {
64         /* Be sure to free any existing header data to avoid mem leak: */
65         lws_free_header_table(wsi);
66         wsi->u.hdr.ah = lws_malloc(sizeof(*wsi->u.hdr.ah));
67         if (wsi->u.hdr.ah == NULL) {
68                 lwsl_err("Out of memory\n");
69                 return -1;
70         }
71         memset(wsi->u.hdr.ah->frag_index, 0, sizeof(wsi->u.hdr.ah->frag_index));
72         wsi->u.hdr.ah->next_frag_index = 0;
73         wsi->u.hdr.ah->pos = 0;
74
75         return 0;
76 }
77
78 int lws_free_header_table(struct libwebsocket *wsi)
79 {
80         lws_free2(wsi->u.hdr.ah);
81         wsi->u.hdr.ah = NULL;
82         return 0;
83 };
84
85 LWS_VISIBLE int lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h)
86 {
87         int n;
88         int len = 0;
89
90         n = wsi->u.hdr.ah->frag_index[h];
91         if (!n)
92                 return 0;
93         do {
94                 len += wsi->u.hdr.ah->frags[n].len;
95                 n = wsi->u.hdr.ah->frags[n].next_frag_index;
96         } while (n);
97
98         return len;
99 }
100
101 LWS_VISIBLE int lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
102                                                 enum lws_token_indexes h)
103 {
104         int toklen = lws_hdr_total_length(wsi, h);
105         int n;
106
107         if (toklen >= len)
108                 return -1;
109
110         n = wsi->u.hdr.ah->frag_index[h];
111         if (!n)
112                 return 0;
113
114         do {
115                 strcpy(dest,
116                         &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset]);
117                 dest += wsi->u.hdr.ah->frags[n].len;
118                 n = wsi->u.hdr.ah->frags[n].next_frag_index;
119         } while (n);
120
121         return toklen;
122 }
123
124 char *lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h)
125 {
126         int n;
127
128         n = wsi->u.hdr.ah->frag_index[h];
129         if (!n)
130                 return NULL;
131
132         return &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset];
133 }
134
135 int lws_hdr_simple_create(struct libwebsocket *wsi,
136                                 enum lws_token_indexes h, const char *s)
137 {
138         wsi->u.hdr.ah->next_frag_index++;
139         if (wsi->u.hdr.ah->next_frag_index ==
140                sizeof(wsi->u.hdr.ah->frags) / sizeof(wsi->u.hdr.ah->frags[0])) {
141                 lwsl_warn("More hdr frags than we can deal with, dropping\n");
142                 return -1;
143         }
144
145         wsi->u.hdr.ah->frag_index[h] = wsi->u.hdr.ah->next_frag_index;
146
147         wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset =
148                                                              wsi->u.hdr.ah->pos;
149         wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len = 0;
150         wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].next_frag_index =
151                                                                               0;
152
153         do {
154                 if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
155                         lwsl_err("Ran out of header data space\n");
156                         return -1;
157                 }
158                 wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = *s;
159                 if (*s)
160                         wsi->u.hdr.ah->frags[
161                                         wsi->u.hdr.ah->next_frag_index].len++;
162         } while (*s++);
163
164         return 0;
165 }
166
167 static char char_to_hex(const char c)
168 {
169         if (c >= '0' && c <= '9')
170                 return c - '0';
171
172         if (c >= 'a' && c <= 'f')
173                 return c - 'a' + 10;
174
175         if (c >= 'A' && c <= 'F')
176                 return c - 'A' + 10;
177
178         return -1;
179 }
180
181 static int issue_char(struct libwebsocket *wsi, unsigned char c)
182 {
183         if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
184                 lwsl_warn("excessive header content\n");
185                 return -1;
186         }
187
188         if( wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len >= 
189                 wsi->u.hdr.current_token_limit) {
190                 lwsl_warn("header %i exceeds limit\n", wsi->u.hdr.parser_state);
191                 return 1;
192         };
193
194         wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = c;
195         if (c)
196                 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
197
198         return 0;
199 }
200
201 int libwebsocket_parse(
202                 struct libwebsocket_context *context,
203                 struct libwebsocket *wsi, unsigned char c)
204 {
205         static const unsigned char methods[] = {
206                 WSI_TOKEN_GET_URI,
207                 WSI_TOKEN_POST_URI,
208                 WSI_TOKEN_OPTIONS_URI,
209                 WSI_TOKEN_PUT_URI,
210                 WSI_TOKEN_PATCH_URI,
211                 WSI_TOKEN_DELETE_URI,
212         };
213         int n, m;
214
215         switch (wsi->u.hdr.parser_state) {
216         default:
217
218                 lwsl_parser("WSI_TOK_(%d) '%c'\n", wsi->u.hdr.parser_state, c);
219
220                 /* collect into malloc'd buffers */
221                 /* optional initial space swallow */
222                 if (!wsi->u.hdr.ah->frags[wsi->u.hdr.ah->frag_index[
223                                       wsi->u.hdr.parser_state]].len && c == ' ')
224                         break;
225
226                 for (m = 0; m < ARRAY_SIZE(methods); m++)
227                         if (wsi->u.hdr.parser_state == methods[m])
228                                 break;
229                 if (m == ARRAY_SIZE(methods))
230                         /* it was not any of the methods */
231                         goto check_eol;
232
233                 /* special URI processing... end at space */
234
235                 if (c == ' ') {
236                         /* enforce starting with / */
237                         if (!wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len)
238                                 if (issue_char(wsi, '/') < 0)
239                                         return -1;
240
241                         /* begin parsing HTTP version: */
242                         if (issue_char(wsi, '\0') < 0)
243                                 return -1;
244                         wsi->u.hdr.parser_state = WSI_TOKEN_HTTP;
245                         goto start_fragment;
246                 }
247
248                 /* special URI processing... convert %xx */
249
250                 switch (wsi->u.hdr.ues) {
251                 case URIES_IDLE:
252                         if (c == '%') {
253                                 wsi->u.hdr.ues = URIES_SEEN_PERCENT;
254                                 goto swallow;
255                         }
256                         break;
257                 case URIES_SEEN_PERCENT:
258                         if (char_to_hex(c) < 0) {
259                                 /* regurgitate */
260                                 if (issue_char(wsi, '%') < 0)
261                                         return -1;
262                                 wsi->u.hdr.ues = URIES_IDLE;
263                                 /* continue on to assess c */
264                                 break;
265                         }
266                         wsi->u.hdr.esc_stash = c;
267                         wsi->u.hdr.ues = URIES_SEEN_PERCENT_H1;
268                         goto swallow;
269                         
270                 case URIES_SEEN_PERCENT_H1:
271                         if (char_to_hex(c) < 0) {
272                                 /* regurgitate */
273                                 issue_char(wsi, '%');
274                                 wsi->u.hdr.ues = URIES_IDLE;
275                                 /* regurgitate + assess */
276                                 if (libwebsocket_parse(context, wsi, wsi->u.hdr.esc_stash) < 0)
277                                         return -1;
278                                 /* continue on to assess c */
279                                 break;
280                         }
281                         c = (char_to_hex(wsi->u.hdr.esc_stash) << 4) |
282                                         char_to_hex(c);
283                         wsi->u.hdr.ues = URIES_IDLE;
284                         break;
285                 }
286
287                 /*
288                  * special URI processing... 
289                  *  convert /.. or /... or /../ etc to /
290                  *  convert /./ to /
291                  *  convert // or /// etc to /
292                  *  leave /.dir or whatever alone
293                  */
294
295                 switch (wsi->u.hdr.ups) {
296                 case URIPS_IDLE:
297                         /* issue the first / always */
298                         if (c == '/')
299                                 wsi->u.hdr.ups = URIPS_SEEN_SLASH;
300                         break;
301                 case URIPS_SEEN_SLASH:
302                         /* swallow subsequent slashes */
303                         if (c == '/')
304                                 goto swallow;
305                         /* track and swallow the first . after / */
306                         if (c == '.') {
307                                 wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT;
308                                 goto swallow;
309                         }
310                         wsi->u.hdr.ups = URIPS_IDLE;
311                         break;
312                 case URIPS_SEEN_SLASH_DOT:
313                         /* swallow second . */
314                         if (c == '.') {
315                                 /* 
316                                  * back up one dir level if possible
317                                  * safe against header fragmentation because
318                                  * the method URI can only be in 1 fragment
319                                  */
320                                 if (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len > 2) {
321                                         wsi->u.hdr.ah->pos--;
322                                         wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len--;
323                                         do {
324                                                 wsi->u.hdr.ah->pos--;
325                                                 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len--;
326                                         } while (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len > 1 &&
327                                                         wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos] != '/');
328                                 }
329                                 wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT_DOT;
330                                 goto swallow;
331                         }
332                         /* change /./ to / */
333                         if (c == '/') {
334                                 wsi->u.hdr.ups = URIPS_SEEN_SLASH;
335                                 goto swallow;
336                         }
337                         /* it was like /.dir ... regurgitate the . */
338                         wsi->u.hdr.ups = URIPS_IDLE;
339                         issue_char(wsi, '.');
340                         break;
341                         
342                 case URIPS_SEEN_SLASH_DOT_DOT:
343                         /* swallow prior .. chars and any subsequent . */
344                         if (c == '.')
345                                 goto swallow;
346                         /* last issued was /, so another / == // */
347                         if (c == '/')
348                                 goto swallow;
349                         /* last we issued was / so SEEN_SLASH */
350                         wsi->u.hdr.ups = URIPS_SEEN_SLASH;
351                         break;
352                 case URIPS_ARGUMENTS:
353                         /* leave them alone */
354                         break;
355                 }
356
357                 if (c == '?') { /* start of URI arguments */
358                         /* seal off uri header */
359                         wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = '\0';
360
361                         /* move to using WSI_TOKEN_HTTP_URI_ARGS */
362                         wsi->u.hdr.ah->next_frag_index++;
363                         wsi->u.hdr.ah->frags[
364                                 wsi->u.hdr.ah->next_frag_index].offset =
365                                                              wsi->u.hdr.ah->pos;
366                         wsi->u.hdr.ah->frags[
367                                         wsi->u.hdr.ah->next_frag_index].len = 0;
368                         wsi->u.hdr.ah->frags[
369                             wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
370
371                         wsi->u.hdr.ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] =
372                                                  wsi->u.hdr.ah->next_frag_index;
373
374                         /* defeat normal uri path processing */
375                         wsi->u.hdr.ups = URIPS_ARGUMENTS;
376                         goto swallow;
377                 }
378
379 check_eol:
380
381                 /* bail at EOL */
382                 if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE &&
383                                                                   c == '\x0d') {
384                         c = '\0';
385                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
386                         lwsl_parser("*\n");
387                 }
388
389                 n = issue_char(wsi, c);
390                 if (n < 0)
391                         return -1;
392                 if (n > 0)
393                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
394
395 swallow:
396                 /* per-protocol end of headers management */
397
398                 if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
399                         goto set_parsing_complete;
400                 break;
401
402                 /* collecting and checking a name part */
403         case WSI_TOKEN_NAME_PART:
404                 lwsl_parser("WSI_TOKEN_NAME_PART '%c'\n", c);
405
406                 wsi->u.hdr.lextable_pos =
407                                 lextable_decode(wsi->u.hdr.lextable_pos, c);
408
409                 if (wsi->u.hdr.lextable_pos < 0) {
410                         /* this is not a header we know about */
411                         for (m = 0; m < ARRAY_SIZE(methods); m++)
412                                 if (wsi->u.hdr.ah->frag_index[methods[m]]) {
413                                         /*
414                                          * already had the method, no idea what
415                                          * this crap is, ignore
416                                          */
417                                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
418                                         break;
419                                 }
420                         /*
421                          * hm it's an unknown http method in fact,
422                          * treat as dangerous
423                          */
424
425                         if (m == ARRAY_SIZE(methods)) {
426                                 lwsl_info("Unknown method - dropping\n");
427                                 return -1;
428                         }
429                         break;
430                 }
431                 if (lextable[wsi->u.hdr.lextable_pos] < FAIL_CHAR) {
432                         /* terminal state */
433
434                         n = ((unsigned int)lextable[wsi->u.hdr.lextable_pos] << 8) |
435                                         lextable[wsi->u.hdr.lextable_pos + 1];
436
437                         lwsl_parser("known hdr %d\n", n);
438                         for (m = 0; m < ARRAY_SIZE(methods); m++)
439                                 if (n == methods[m] &&
440                                                 wsi->u.hdr.ah->frag_index[
441                                                         methods[m]]) {
442                                         lwsl_warn("Duplicated method\n");
443                                         return -1;
444                                 }
445
446                         /*
447                          * WSORIGIN is protocol equiv to ORIGIN,
448                          * JWebSocket likes to send it, map to ORIGIN
449                          */
450                         if (n == WSI_TOKEN_SWORIGIN)
451                                 n = WSI_TOKEN_ORIGIN;
452
453                         wsi->u.hdr.parser_state = (enum lws_token_indexes)
454                                                         (WSI_TOKEN_GET_URI + n);
455
456                         if (context->token_limits)
457                                 wsi->u.hdr.current_token_limit =
458                                         context->token_limits->token_limit[wsi->u.hdr.parser_state];
459                         else
460                                 wsi->u.hdr.current_token_limit = sizeof(wsi->u.hdr.ah->data);
461
462                         if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
463                                 goto set_parsing_complete;
464
465                         goto start_fragment;
466                 }
467                 break;
468
469 start_fragment:
470                 wsi->u.hdr.ah->next_frag_index++;
471                 if (wsi->u.hdr.ah->next_frag_index ==
472                                 sizeof(wsi->u.hdr.ah->frags) /
473                                               sizeof(wsi->u.hdr.ah->frags[0])) {
474                         lwsl_warn("More hdr frags than we can deal with\n");
475                         return -1;
476                 }
477
478                 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset =
479                                                              wsi->u.hdr.ah->pos;
480                 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len = 0;
481                 wsi->u.hdr.ah->frags[
482                             wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
483
484                 n = wsi->u.hdr.ah->frag_index[wsi->u.hdr.parser_state];
485                 if (!n) { /* first fragment */
486                         wsi->u.hdr.ah->frag_index[wsi->u.hdr.parser_state] =
487                                                  wsi->u.hdr.ah->next_frag_index;
488                         break;
489                 }
490                 /* continuation */
491                 while (wsi->u.hdr.ah->frags[n].next_frag_index)
492                                 n = wsi->u.hdr.ah->frags[n].next_frag_index;
493                 wsi->u.hdr.ah->frags[n].next_frag_index =
494                                                  wsi->u.hdr.ah->next_frag_index;
495
496                 if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
497                         lwsl_warn("excessive header content\n");
498                         return -1;
499                 }
500
501                 wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = ' ';
502                 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
503                 break;
504
505                 /* skipping arg part of a name we didn't recognize */
506         case WSI_TOKEN_SKIPPING:
507                 lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c);
508
509                 if (c == '\x0d')
510                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
511                 break;
512
513         case WSI_TOKEN_SKIPPING_SAW_CR:
514                 lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
515                 if (c == '\x0a') {
516                         wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
517                         wsi->u.hdr.lextable_pos = 0;
518                 } else
519                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
520                 break;
521                 /* we're done, ignore anything else */
522
523         case WSI_PARSING_COMPLETE:
524                 lwsl_parser("WSI_PARSING_COMPLETE '%c'\n", c);
525                 break;
526         }
527
528         return 0;
529
530 set_parsing_complete:
531
532         if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
533                 if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
534                         wsi->ietf_spec_revision =
535                                atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
536
537                 lwsl_parser("v%02d hdrs completed\n", wsi->ietf_spec_revision);
538         }
539         wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE;
540         wsi->hdr_parsing_completed = 1;
541
542         return 0;
543 }
544
545
546 /**
547  * lws_frame_is_binary: true if the current frame was sent in binary mode
548  *
549  * @wsi: the connection we are inquiring about
550  *
551  * This is intended to be called from the LWS_CALLBACK_RECEIVE callback if
552  * it's interested to see if the frame it's dealing with was sent in binary
553  * mode.
554  */
555
556 LWS_VISIBLE int lws_frame_is_binary(struct libwebsocket *wsi)
557 {
558         return wsi->u.ws.frame_is_binary;
559 }
560
561 int
562 libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
563 {
564         int n;
565         struct lws_tokens eff_buf;
566         int ret = 0;
567
568         switch (wsi->lws_rx_parse_state) {
569         case LWS_RXPS_NEW:
570
571                 switch (wsi->ietf_spec_revision) {
572                 case 13:
573                         /*
574                          * no prepended frame key any more
575                          */
576                         wsi->u.ws.all_zero_nonce = 1;
577                         goto handle_first;
578
579                 default:
580                         lwsl_warn("lws_rx_sm: unknown spec version %d\n",
581                                                        wsi->ietf_spec_revision);
582                         break;
583                 }
584                 break;
585         case LWS_RXPS_04_MASK_NONCE_1:
586                 wsi->u.ws.frame_masking_nonce_04[1] = c;
587                 if (c)
588                         wsi->u.ws.all_zero_nonce = 0;
589                 wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_2;
590                 break;
591         case LWS_RXPS_04_MASK_NONCE_2:
592                 wsi->u.ws.frame_masking_nonce_04[2] = c;
593                 if (c)
594                         wsi->u.ws.all_zero_nonce = 0;
595                 wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_3;
596                 break;
597         case LWS_RXPS_04_MASK_NONCE_3:
598                 wsi->u.ws.frame_masking_nonce_04[3] = c;
599                 if (c)
600                         wsi->u.ws.all_zero_nonce = 0;
601
602                 /*
603                  * start from the zero'th byte in the XOR key buffer since
604                  * this is the start of a frame with a new key
605                  */
606
607                 wsi->u.ws.frame_mask_index = 0;
608
609                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
610                 break;
611
612         /*
613          *  04 logical framing from the spec (all this is masked when incoming
614          *  and has to be unmasked)
615          *
616          * We ignore the possibility of extension data because we don't
617          * negotiate any extensions at the moment.
618          *
619          *    0                   1                   2                   3
620          *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
621          *   +-+-+-+-+-------+-+-------------+-------------------------------+
622          *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
623          *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
624          *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
625          *   | |1|2|3|       |4|             |                               |
626          *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
627          *   |     Extended payload length continued, if payload len == 127  |
628          *   + - - - - - - - - - - - - - - - +-------------------------------+
629          *   |                               |         Extension data        |
630          *   +-------------------------------+ - - - - - - - - - - - - - - - +
631          *   :                                                               :
632          *   +---------------------------------------------------------------+
633          *   :                       Application data                        :
634          *   +---------------------------------------------------------------+
635          *
636          *  We pass payload through to userland as soon as we get it, ignoring
637          *  FIN.  It's up to userland to buffer it up if it wants to see a
638          *  whole unfragmented block of the original size (which may be up to
639          *  2^63 long!)
640          */
641
642         case LWS_RXPS_04_FRAME_HDR_1:
643 handle_first:
644
645                 wsi->u.ws.opcode = c & 0xf;
646                 wsi->u.ws.rsv = c & 0x70;
647                 wsi->u.ws.final = !!((c >> 7) & 1);
648
649                 switch (wsi->u.ws.opcode) {
650                 case LWS_WS_OPCODE_07__TEXT_FRAME:
651                 case LWS_WS_OPCODE_07__BINARY_FRAME:
652                         wsi->u.ws.frame_is_binary =
653                              wsi->u.ws.opcode == LWS_WS_OPCODE_07__BINARY_FRAME;
654                         break;
655                 }
656                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
657                 break;
658
659         case LWS_RXPS_04_FRAME_HDR_LEN:
660
661                 wsi->u.ws.this_frame_masked = !!(c & 0x80);
662
663                 switch (c & 0x7f) {
664                 case 126:
665                         /* control frames are not allowed to have big lengths */
666                         if (wsi->u.ws.opcode & 8)
667                                 goto illegal_ctl_length;
668
669                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
670                         break;
671                 case 127:
672                         /* control frames are not allowed to have big lengths */
673                         if (wsi->u.ws.opcode & 8)
674                                 goto illegal_ctl_length;
675
676                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
677                         break;
678                 default:
679                         wsi->u.ws.rx_packet_length = c & 0x7f;
680                         if (wsi->u.ws.this_frame_masked)
681                                 wsi->lws_rx_parse_state =
682                                                 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
683                         else
684                                 if (wsi->u.ws.rx_packet_length)
685                                         wsi->lws_rx_parse_state =
686                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
687                                 else {
688                                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
689                                         goto spill;
690                                 }
691                         break;
692                 }
693                 break;
694
695         case LWS_RXPS_04_FRAME_HDR_LEN16_2:
696                 wsi->u.ws.rx_packet_length = c << 8;
697                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
698                 break;
699
700         case LWS_RXPS_04_FRAME_HDR_LEN16_1:
701                 wsi->u.ws.rx_packet_length |= c;
702                 if (wsi->u.ws.this_frame_masked)
703                         wsi->lws_rx_parse_state =
704                                         LWS_RXPS_07_COLLECT_FRAME_KEY_1;
705                 else
706                         wsi->lws_rx_parse_state =
707                                 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
708                 break;
709
710         case LWS_RXPS_04_FRAME_HDR_LEN64_8:
711                 if (c & 0x80) {
712                         lwsl_warn("b63 of length must be zero\n");
713                         /* kill the connection */
714                         return -1;
715                 }
716 #if defined __LP64__
717                 wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
718 #else
719                 wsi->u.ws.rx_packet_length = 0;
720 #endif
721                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
722                 break;
723
724         case LWS_RXPS_04_FRAME_HDR_LEN64_7:
725 #if defined __LP64__
726                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
727 #endif
728                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
729                 break;
730
731         case LWS_RXPS_04_FRAME_HDR_LEN64_6:
732 #if defined __LP64__
733                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
734 #endif
735                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
736                 break;
737
738         case LWS_RXPS_04_FRAME_HDR_LEN64_5:
739 #if defined __LP64__
740                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
741 #endif
742                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
743                 break;
744
745         case LWS_RXPS_04_FRAME_HDR_LEN64_4:
746                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
747                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
748                 break;
749
750         case LWS_RXPS_04_FRAME_HDR_LEN64_3:
751                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
752                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
753                 break;
754
755         case LWS_RXPS_04_FRAME_HDR_LEN64_2:
756                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
757                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
758                 break;
759
760         case LWS_RXPS_04_FRAME_HDR_LEN64_1:
761                 wsi->u.ws.rx_packet_length |= ((size_t)c);
762                 if (wsi->u.ws.this_frame_masked)
763                         wsi->lws_rx_parse_state =
764                                         LWS_RXPS_07_COLLECT_FRAME_KEY_1;
765                 else
766                         wsi->lws_rx_parse_state =
767                                 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
768                 break;
769
770         case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
771                 wsi->u.ws.frame_masking_nonce_04[0] = c;
772                 if (c)
773                         wsi->u.ws.all_zero_nonce = 0;
774                 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
775                 break;
776
777         case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
778                 wsi->u.ws.frame_masking_nonce_04[1] = c;
779                 if (c)
780                         wsi->u.ws.all_zero_nonce = 0;
781                 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
782                 break;
783
784         case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
785                 wsi->u.ws.frame_masking_nonce_04[2] = c;
786                 if (c)
787                         wsi->u.ws.all_zero_nonce = 0;
788                 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
789                 break;
790
791         case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
792                 wsi->u.ws.frame_masking_nonce_04[3] = c;
793                 if (c)
794                         wsi->u.ws.all_zero_nonce = 0;
795                 wsi->lws_rx_parse_state =
796                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
797                 wsi->u.ws.frame_mask_index = 0;
798                 if (wsi->u.ws.rx_packet_length == 0) {
799                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
800                         goto spill;
801                 }
802                 break;
803
804
805         case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
806
807                 if (!wsi->u.ws.rx_user_buffer) {
808                         lwsl_err("NULL user buffer...\n");
809                         return 1;
810                 }
811
812                 if (wsi->u.ws.all_zero_nonce)
813                         wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
814                                (wsi->u.ws.rx_user_buffer_head++)] = c;
815                 else
816                         wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
817                                (wsi->u.ws.rx_user_buffer_head++)] =
818                                    c ^ wsi->u.ws.frame_masking_nonce_04[
819                                             (wsi->u.ws.frame_mask_index++) & 3];
820
821                 if (--wsi->u.ws.rx_packet_length == 0) {
822                         /* spill because we have the whole frame */
823                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
824                         goto spill;
825                 }
826
827                 /*
828                  * if there's no protocol max frame size given, we are
829                  * supposed to default to LWS_MAX_SOCKET_IO_BUF
830                  */
831
832                 if (!wsi->protocol->rx_buffer_size &&
833                                         wsi->u.ws.rx_user_buffer_head !=
834                                                           LWS_MAX_SOCKET_IO_BUF)
835                         break;
836                 else
837                         if (wsi->protocol->rx_buffer_size &&
838                                         wsi->u.ws.rx_user_buffer_head !=
839                                                   wsi->protocol->rx_buffer_size)
840                         break;
841
842                 /* spill because we filled our rx buffer */
843 spill:
844                 /*
845                  * is this frame a control packet we should take care of at this
846                  * layer?  If so service it and hide it from the user callback
847                  */
848
849                 lwsl_parser("spill on %s\n", wsi->protocol->name);
850
851                 switch (wsi->u.ws.opcode) {
852                 case LWS_WS_OPCODE_07__CLOSE:
853                         /* is this an acknowledgement of our close? */
854                         if (wsi->state == WSI_STATE_AWAITING_CLOSE_ACK) {
855                                 /*
856                                  * fine he has told us he is closing too, let's
857                                  * finish our close
858                                  */
859                                 lwsl_parser("seen client close ack\n");
860                                 return -1;
861                         }
862                         lwsl_parser("server sees client close packet\n");
863                         /* parrot the close packet payload back */
864                         n = libwebsocket_write(wsi, (unsigned char *)
865                                 &wsi->u.ws.rx_user_buffer[
866                                         LWS_SEND_BUFFER_PRE_PADDING],
867                                         wsi->u.ws.rx_user_buffer_head,
868                                                                LWS_WRITE_CLOSE);
869                         if (n < 0)
870                                 lwsl_info("write of close ack failed %d\n", n);
871                         wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
872                         /* close the connection */
873                         return -1;
874
875                 case LWS_WS_OPCODE_07__PING:
876                         lwsl_info("received %d byte ping, sending pong\n",
877                                                  wsi->u.ws.rx_user_buffer_head);
878
879                         if (wsi->u.ws.ping_payload_len) {
880                                 /* 
881                                  * there is already a pending ping payload
882                                  * we should just log and drop
883                                  */
884                                 lwsl_parser("DROP PING since one pending\n");
885                                 goto ping_drop;
886                         }
887                         
888                         /* control packets can only be < 128 bytes long */
889                         if (wsi->u.ws.ping_payload_len > 128 - 4) {
890                                 lwsl_parser("DROP PING payload too large\n");
891                                 goto ping_drop;
892                         }
893                         
894                         /* if existing buffer is too small, drop it */
895                         if (wsi->u.ws.ping_payload_buf &&
896                             wsi->u.ws.ping_payload_alloc < wsi->u.ws.rx_user_buffer_head) {
897                                 lws_free2(wsi->u.ws.ping_payload_buf);
898                         }
899
900                         /* if no buffer, allocate it */
901                         if (!wsi->u.ws.ping_payload_buf) {
902                                 wsi->u.ws.ping_payload_buf = lws_malloc(wsi->u.ws.rx_user_buffer_head
903                                                                         + LWS_SEND_BUFFER_PRE_PADDING);
904                                 wsi->u.ws.ping_payload_alloc = wsi->u.ws.rx_user_buffer_head;
905                         }
906                         
907                         /* stash the pong payload */
908                         memcpy(wsi->u.ws.ping_payload_buf + LWS_SEND_BUFFER_PRE_PADDING,
909                                &wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
910                                 wsi->u.ws.rx_user_buffer_head);
911                         
912                         wsi->u.ws.ping_payload_len = wsi->u.ws.rx_user_buffer_head;
913                         
914                         /* get it sent as soon as possible */
915                         libwebsocket_callback_on_writable(wsi->protocol->owning_server, wsi);
916 ping_drop:
917                         wsi->u.ws.rx_user_buffer_head = 0;
918                         return 0;
919
920                 case LWS_WS_OPCODE_07__PONG:
921                         /* ... then just drop it */
922                         wsi->u.ws.rx_user_buffer_head = 0;
923                         return 0;
924
925                 case LWS_WS_OPCODE_07__TEXT_FRAME:
926                 case LWS_WS_OPCODE_07__BINARY_FRAME:
927                 case LWS_WS_OPCODE_07__CONTINUATION:
928                         break;
929
930                 default:
931                         lwsl_parser("passing opc %x up to exts\n",
932                                                         wsi->u.ws.opcode);
933                         /*
934                          * It's something special we can't understand here.
935                          * Pass the payload up to the extension's parsing
936                          * state machine.
937                          */
938
939                         eff_buf.token = &wsi->u.ws.rx_user_buffer[
940                                                    LWS_SEND_BUFFER_PRE_PADDING];
941                         eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
942
943                         if (lws_ext_callback_for_each_active(wsi,
944                                 LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
945                                         &eff_buf, 0) <= 0) /* not handle or fail */
946                                 lwsl_ext("ext opc opcode 0x%x unknown\n",
947                                                               wsi->u.ws.opcode);
948
949                         wsi->u.ws.rx_user_buffer_head = 0;
950                         return 0;
951                 }
952
953                 /*
954                  * No it's real payload, pass it up to the user callback.
955                  * It's nicely buffered with the pre-padding taken care of
956                  * so it can be sent straight out again using libwebsocket_write
957                  */
958
959                 eff_buf.token = &wsi->u.ws.rx_user_buffer[
960                                                 LWS_SEND_BUFFER_PRE_PADDING];
961                 eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
962                 
963                 if (lws_ext_callback_for_each_active(wsi,
964                                 LWS_EXT_CALLBACK_PAYLOAD_RX, &eff_buf, 0) < 0)
965                         return -1;
966
967                 if (eff_buf.token_len > 0) {
968                         eff_buf.token[eff_buf.token_len] = '\0';
969
970                         if (wsi->protocol->callback)
971                                 ret = user_callback_handle_rxflow(
972                                                 wsi->protocol->callback,
973                                                 wsi->protocol->owning_server,
974                                                 wsi, LWS_CALLBACK_RECEIVE,
975                                                 wsi->user_space,
976                                                 eff_buf.token,
977                                                 eff_buf.token_len);
978                     else
979                             lwsl_err("No callback on payload spill!\n");
980                 }
981
982                 wsi->u.ws.rx_user_buffer_head = 0;
983                 break;
984         }
985
986         return ret;
987
988 illegal_ctl_length:
989
990         lwsl_warn("Control frame with xtended length is illegal\n");
991         /* kill the connection */
992         return -1;
993 }
994
995
996 /**
997  * libwebsockets_remaining_packet_payload() - Bytes to come before "overall"
998  *                                            rx packet is complete
999  * @wsi:                Websocket instance (available from user callback)
1000  *
1001  *      This function is intended to be called from the callback if the
1002  *  user code is interested in "complete packets" from the client.
1003  *  libwebsockets just passes through payload as it comes and issues a buffer
1004  *  additionally when it hits a built-in limit.  The LWS_CALLBACK_RECEIVE
1005  *  callback handler can use this API to find out if the buffer it has just
1006  *  been given is the last piece of a "complete packet" from the client --
1007  *  when that is the case libwebsockets_remaining_packet_payload() will return
1008  *  0.
1009  *
1010  *  Many protocols won't care becuse their packets are always small.
1011  */
1012
1013 LWS_VISIBLE size_t
1014 libwebsockets_remaining_packet_payload(struct libwebsocket *wsi)
1015 {
1016         return wsi->u.ws.rx_packet_length;
1017 }