esp32: group tracking
[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 const unsigned char lextable[] = {
25         #include "lextable.h"
26 };
27
28 #define FAIL_CHAR 0x08
29
30 int LWS_WARN_UNUSED_RESULT
31 lextable_decode(int pos, char c)
32 {
33         if (c >= 'A' && c <= 'Z')
34                 c += 'a' - 'A';
35
36         while (1) {
37                 if (lextable[pos] & (1 << 7)) { /* 1-byte, fail on mismatch */
38                         if ((lextable[pos] & 0x7f) != c)
39                                 return -1;
40                         /* fall thru */
41                         pos++;
42                         if (lextable[pos] == FAIL_CHAR)
43                                 return -1;
44                         return pos;
45                 }
46
47                 if (lextable[pos] == FAIL_CHAR)
48                         return -1;
49
50                 /* b7 = 0, end or 3-byte */
51                 if (lextable[pos] < FAIL_CHAR) /* terminal marker */
52                         return pos;
53
54                 if (lextable[pos] == c) /* goto */
55                         return pos + (lextable[pos + 1]) +
56                                                 (lextable[pos + 2] << 8);
57                 /* fall thru goto */
58                 pos += 3;
59                 /* continue */
60         }
61 }
62
63 void
64 _lws_header_table_reset(struct allocated_headers *ah)
65 {
66         /* init the ah to reflect no headers or data have appeared yet */
67         memset(ah->frag_index, 0, sizeof(ah->frag_index));
68         ah->nfrag = 0;
69         ah->pos = 0;
70         ah->http_response = 0;
71 }
72
73 // doesn't scrub the ah rxbuffer by default, parent must do if needed
74
75 void
76 lws_header_table_reset(struct lws *wsi, int autoservice)
77 {
78         struct allocated_headers *ah = wsi->u.hdr.ah;
79         struct lws_context_per_thread *pt;
80         struct lws_pollfd *pfd;
81
82         /* if we have the idea we're resetting 'our' ah, must be bound to one */
83         assert(ah);
84         /* ah also concurs with ownership */
85         assert(ah->wsi == wsi);
86
87         _lws_header_table_reset(ah);
88
89         /* since we will restart the ah, our new headers are not completed */
90         // wsi->hdr_parsing_completed = 0;
91
92         /*
93          * if we inherited pending rx (from socket adoption deferred
94          * processing), apply and free it.
95          */
96         if (wsi->u.hdr.preamble_rx) {
97                 memcpy(ah->rx, wsi->u.hdr.preamble_rx,
98                        wsi->u.hdr.preamble_rx_len);
99                 ah->rxlen = wsi->u.hdr.preamble_rx_len;
100                 lws_free_set_NULL(wsi->u.hdr.preamble_rx);
101
102                 if (autoservice) {
103                         lwsl_notice("%s: calling service on readbuf ah\n", __func__);
104
105                         pt = &wsi->context->pt[(int)wsi->tsi];
106
107                         /* unlike a normal connect, we have the headers already
108                          * (or the first part of them anyway)
109                          */
110                         pfd = &pt->fds[wsi->position_in_fds_table];
111                         pfd->revents |= LWS_POLLIN;
112                         lwsl_err("%s: calling service\n", __func__);
113                         lws_service_fd_tsi(wsi->context, pfd, wsi->tsi);
114                 }
115         }
116 }
117
118 int LWS_WARN_UNUSED_RESULT
119 lws_header_table_attach(struct lws *wsi, int autoservice)
120 {
121         struct lws_context *context = wsi->context;
122         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
123         struct lws_pollargs pa;
124         struct lws **pwsi;
125         int n;
126
127         lwsl_info("%s: wsi %p: ah %p (tsi %d, count = %d) in\n", __func__, (void *)wsi,
128                  (void *)wsi->u.hdr.ah, wsi->tsi, pt->ah_count_in_use);
129
130         /* if we are already bound to one, just clear it down */
131         if (wsi->u.hdr.ah) {
132                 lwsl_info("cleardown\n");
133                 goto reset;
134         }
135
136         lws_pt_lock(pt);
137         pwsi = &pt->ah_wait_list;
138         while (*pwsi) {
139                 if (*pwsi == wsi) {
140                         /* if already waiting on list, if no new ah just ret */
141                         if (pt->ah_count_in_use ==
142                             context->max_http_header_pool) {
143                                 lwsl_notice("%s: no free ah to attach\n", __func__);
144                                 goto bail;
145                         }
146                         /* new ah.... remove ourselves from waiting list */
147                         *pwsi = wsi->u.hdr.ah_wait_list; /* set our prev to our next */
148                         wsi->u.hdr.ah_wait_list = NULL; /* no next any more */
149                         pt->ah_wait_list_length--;
150                         break;
151                 }
152                 pwsi = &(*pwsi)->u.hdr.ah_wait_list;
153         }
154         /*
155          * pool is all busy... add us to waiting list and return that we
156          * weren't able to deliver it right now
157          */
158         if (pt->ah_count_in_use == context->max_http_header_pool) {
159                 lwsl_info("%s: adding %p to ah waiting list\n", __func__, wsi);
160                 wsi->u.hdr.ah_wait_list = pt->ah_wait_list;
161                 pt->ah_wait_list = wsi;
162                 pt->ah_wait_list_length++;
163
164                 /* we cannot accept input then */
165
166                 _lws_change_pollfd(wsi, LWS_POLLIN, 0, &pa);
167                 goto bail;
168         }
169
170         for (n = 0; n < context->max_http_header_pool; n++)
171                 if (!pt->ah_pool[n].in_use)
172                         break;
173
174         /* if the count of in use said something free... */
175         assert(n != context->max_http_header_pool);
176
177         wsi->u.hdr.ah = &pt->ah_pool[n];
178         wsi->u.hdr.ah->in_use = 1;
179         pt->ah_pool[n].wsi = wsi; /* mark our owner */
180         pt->ah_count_in_use++;
181
182         _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
183
184         lwsl_info("%s: did attach wsi %p: ah %p: count %d (on exit)\n", __func__,
185                   (void *)wsi, (void *)wsi->u.hdr.ah, pt->ah_count_in_use);
186
187         lws_pt_unlock(pt);
188
189 reset:
190
191         /* and reset the rx state */
192         wsi->u.hdr.ah->rxpos = 0;
193         wsi->u.hdr.ah->rxlen = 0;
194
195         lws_header_table_reset(wsi, autoservice);
196         time(&wsi->u.hdr.ah->assigned);
197
198 #ifndef LWS_NO_CLIENT
199         if (wsi->state == LWSS_CLIENT_UNCONNECTED)
200                 if (!lws_client_connect_via_info2(wsi))
201                         /* our client connect has failed, the wsi
202                          * has been closed
203                          */
204                         return -1;
205 #endif
206
207         return 0;
208
209 bail:
210         lws_pt_unlock(pt);
211
212         return 1;
213 }
214
215 int lws_header_table_detach(struct lws *wsi, int autoservice)
216 {
217         struct lws_context *context = wsi->context;
218         struct allocated_headers *ah = wsi->u.hdr.ah;
219         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
220         struct lws_pollargs pa;
221         struct lws **pwsi;
222         time_t now;
223
224         lwsl_info("%s: wsi %p: ah %p (tsi=%d, count = %d)\n", __func__,
225                   (void *)wsi, (void *)ah, wsi->tsi,
226                   pt->ah_count_in_use);
227
228         if (wsi->u.hdr.preamble_rx)
229                 lws_free_set_NULL(wsi->u.hdr.preamble_rx);
230
231         /* may not be detached while he still has unprocessed rx */
232         if (ah && ah->rxpos != ah->rxlen) {
233                 lwsl_err("%s: %p: CANNOT DETACH rxpos:%d, rxlen:%d\n", __func__, wsi,
234                                 ah->rxpos, ah->rxlen);
235                 assert(ah->rxpos == ah->rxlen);
236
237                 return 0;
238         }
239
240         lws_pt_lock(pt);
241
242         pwsi = &pt->ah_wait_list;
243         if (!ah) { /* remove from wait list if none attached */
244                 while (*pwsi) {
245                         if (*pwsi == wsi) {
246                                 lwsl_info("%s: wsi %p, remv wait\n",
247                                           __func__, wsi);
248                                 *pwsi = wsi->u.hdr.ah_wait_list;
249                                 wsi->u.hdr.ah_wait_list = NULL;
250                                 pt->ah_wait_list_length--;
251                                 goto bail;
252                         }
253                         pwsi = &(*pwsi)->u.hdr.ah_wait_list;
254                 }
255                 /* no ah, not on list... no more business here */
256                 goto bail;
257         }
258         /* we did have an ah attached */
259         time(&now);
260         if (ah->assigned && now - ah->assigned > 3) {
261                 /*
262                  * we're detaching the ah, but it was held an
263                  * unreasonably long time
264                  */
265                 lwsl_notice("%s: wsi %p: ah held %ds, "
266                             "ah.rxpos %d, ah.rxlen %d, mode/state %d %d,"
267                             "wsi->more_rx_waiting %d\n", __func__, wsi,
268                             (int)(now - ah->assigned),
269                             ah->rxpos, ah->rxlen, wsi->mode, wsi->state,
270                             wsi->more_rx_waiting);
271         }
272
273         ah->assigned = 0;
274
275         /* if we think we're detaching one, there should be one in use */
276         assert(pt->ah_count_in_use > 0);
277         /* and this specific one should have been in use */
278         assert(ah->in_use);
279         wsi->u.hdr.ah = NULL;
280         ah->wsi = NULL; /* no owner */
281
282         /* oh there is nobody on the waiting list... leave it at that then */
283         if (!*pwsi) {
284                 ah->in_use = 0;
285                 pt->ah_count_in_use--;
286
287                 goto bail;
288         }
289
290         /* somebody else on same tsi is waiting, give it to oldest guy */
291
292         lwsl_info("pt wait list %p\n", *pwsi);
293         while ((*pwsi)->u.hdr.ah_wait_list)
294                 pwsi = &(*pwsi)->u.hdr.ah_wait_list;
295
296         wsi = *pwsi;
297         lwsl_info("last wsi in wait list %p\n", wsi);
298
299         wsi->u.hdr.ah = ah;
300         ah->wsi = wsi; /* new owner */
301         /* and reset the rx state */
302         ah->rxpos = 0;
303         ah->rxlen = 0;
304         lws_header_table_reset(wsi, autoservice);
305         time(&wsi->u.hdr.ah->assigned);
306
307         /* clients acquire the ah and then insert themselves in fds table... */
308         if (wsi->position_in_fds_table != -1) {
309                 lwsl_info("%s: Enabling %p POLLIN\n", __func__, wsi);
310
311                 /* he has been stuck waiting for an ah, but now his wait is over,
312                  * let him progress
313                  */
314                 _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
315         }
316
317         /* point prev guy to next guy in list instead */
318         *pwsi = wsi->u.hdr.ah_wait_list;
319         /* the guy who got one is out of the list */
320         wsi->u.hdr.ah_wait_list = NULL;
321         pt->ah_wait_list_length--;
322
323 #ifndef LWS_NO_CLIENT
324         if (wsi->state == LWSS_CLIENT_UNCONNECTED)
325                 if (!lws_client_connect_via_info2(wsi)) {
326                         /* our client connect has failed, the wsi
327                          * has been closed
328                          */
329                         lws_pt_unlock(pt);
330
331                         return -1;
332                 }
333 #endif
334
335         assert(!!pt->ah_wait_list_length == !!(int)(long)pt->ah_wait_list);
336 bail:
337         lwsl_info("%s: wsi %p: ah %p (tsi=%d, count = %d)\n", __func__,
338           (void *)wsi, (void *)ah, wsi->tsi,
339           pt->ah_count_in_use);
340         lws_pt_unlock(pt);
341
342         return 0;
343 }
344
345 LWS_VISIBLE int
346 lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, int frag_idx)
347 {
348         int n;
349
350         n = wsi->u.hdr.ah->frag_index[h];
351         if (!n)
352                 return 0;
353         do {
354                 if (!frag_idx)
355                         return wsi->u.hdr.ah->frags[n].len;
356                 n = wsi->u.hdr.ah->frags[n].nfrag;
357         } while (frag_idx-- && n);
358
359         return 0;
360 }
361
362 LWS_VISIBLE int lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h)
363 {
364         int n;
365         int len = 0;
366
367         n = wsi->u.hdr.ah->frag_index[h];
368         if (!n)
369                 return 0;
370         do {
371                 len += wsi->u.hdr.ah->frags[n].len;
372                 n = wsi->u.hdr.ah->frags[n].nfrag;
373         } while (n);
374
375         return len;
376 }
377
378 LWS_VISIBLE int lws_hdr_copy_fragment(struct lws *wsi, char *dst, int len,
379                                       enum lws_token_indexes h, int frag_idx)
380 {
381         int n = 0;
382         int f = wsi->u.hdr.ah->frag_index[h];
383
384         if (!f)
385                 return -1;
386
387         while (n < frag_idx) {
388                 f = wsi->u.hdr.ah->frags[f].nfrag;
389                 if (!f)
390                         return -1;
391                 n++;
392         }
393
394         if (wsi->u.hdr.ah->frags[f].len >= len)
395                 return -1;
396
397         memcpy(dst, wsi->u.hdr.ah->data + wsi->u.hdr.ah->frags[f].offset,
398                wsi->u.hdr.ah->frags[f].len);
399         dst[wsi->u.hdr.ah->frags[f].len] = '\0';
400
401         return wsi->u.hdr.ah->frags[f].len;
402 }
403
404 LWS_VISIBLE int lws_hdr_copy(struct lws *wsi, char *dst, int len,
405                              enum lws_token_indexes h)
406 {
407         int toklen = lws_hdr_total_length(wsi, h);
408         int n;
409
410         if (toklen >= len)
411                 return -1;
412
413         n = wsi->u.hdr.ah->frag_index[h];
414         if (!n)
415                 return 0;
416
417         do {
418                 strcpy(dst, &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset]);
419                 dst += wsi->u.hdr.ah->frags[n].len;
420                 n = wsi->u.hdr.ah->frags[n].nfrag;
421         } while (n);
422
423         return toklen;
424 }
425
426 char *lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h)
427 {
428         int n;
429
430         n = wsi->u.hdr.ah->frag_index[h];
431         if (!n)
432                 return NULL;
433
434         return wsi->u.hdr.ah->data + wsi->u.hdr.ah->frags[n].offset;
435 }
436
437 int LWS_WARN_UNUSED_RESULT
438 lws_pos_in_bounds(struct lws *wsi)
439 {
440         if (wsi->u.hdr.ah->pos < (unsigned int)wsi->context->max_http_header_data)
441                 return 0;
442
443         if (wsi->u.hdr.ah->pos == wsi->context->max_http_header_data) {
444                 lwsl_err("Ran out of header data space\n");
445                 return 1;
446         }
447
448         /*
449          * with these tests everywhere, it should never be able to exceed
450          * the limit, only meet the limit
451          */
452
453         lwsl_err("%s: pos %d, limit %d\n", __func__, wsi->u.hdr.ah->pos,
454                  wsi->context->max_http_header_data);
455         assert(0);
456
457         return 1;
458 }
459
460 int LWS_WARN_UNUSED_RESULT
461 lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s)
462 {
463         wsi->u.hdr.ah->nfrag++;
464         if (wsi->u.hdr.ah->nfrag == ARRAY_SIZE(wsi->u.hdr.ah->frags)) {
465                 lwsl_warn("More hdr frags than we can deal with, dropping\n");
466                 return -1;
467         }
468
469         wsi->u.hdr.ah->frag_index[h] = wsi->u.hdr.ah->nfrag;
470
471         wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].offset = wsi->u.hdr.ah->pos;
472         wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len = 0;
473         wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].nfrag = 0;
474
475         do {
476                 if (lws_pos_in_bounds(wsi))
477                         return -1;
478
479                 wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = *s;
480                 if (*s)
481                         wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len++;
482         } while (*s++);
483
484         return 0;
485 }
486
487 signed char char_to_hex(const char c)
488 {
489         if (c >= '0' && c <= '9')
490                 return c - '0';
491
492         if (c >= 'a' && c <= 'f')
493                 return c - 'a' + 10;
494
495         if (c >= 'A' && c <= 'F')
496                 return c - 'A' + 10;
497
498         return -1;
499 }
500
501 static int LWS_WARN_UNUSED_RESULT
502 issue_char(struct lws *wsi, unsigned char c)
503 {
504         unsigned short frag_len;
505
506         if (lws_pos_in_bounds(wsi))
507                 return -1;
508
509         frag_len = wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len;
510         /*
511          * If we haven't hit the token limit, just copy the character into
512          * the header
513          */
514         if (frag_len < wsi->u.hdr.current_token_limit) {
515                 wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = c;
516                 if (c)
517                         wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len++;
518                 return 0;
519         }
520
521         /* Insert a null character when we *hit* the limit: */
522         if (frag_len == wsi->u.hdr.current_token_limit) {
523                 if (lws_pos_in_bounds(wsi))
524                         return -1;
525                 wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = '\0';
526                 lwsl_warn("header %i exceeds limit %d\n",
527                           wsi->u.hdr.parser_state,
528                           wsi->u.hdr.current_token_limit);
529         }
530
531         return 1;
532 }
533
534 int LWS_WARN_UNUSED_RESULT
535 lws_parse(struct lws *wsi, unsigned char c)
536 {
537         static const unsigned char methods[] = {
538                 WSI_TOKEN_GET_URI,
539                 WSI_TOKEN_POST_URI,
540                 WSI_TOKEN_OPTIONS_URI,
541                 WSI_TOKEN_PUT_URI,
542                 WSI_TOKEN_PATCH_URI,
543                 WSI_TOKEN_DELETE_URI,
544                 WSI_TOKEN_CONNECT,
545         };
546         struct allocated_headers *ah = wsi->u.hdr.ah;
547         struct lws_context *context = wsi->context;
548         unsigned int n, m, enc = 0;
549
550         assert(wsi->u.hdr.ah);
551
552         switch (wsi->u.hdr.parser_state) {
553         default:
554
555                 lwsl_parser("WSI_TOK_(%d) '%c'\n", wsi->u.hdr.parser_state, c);
556
557                 /* collect into malloc'd buffers */
558                 /* optional initial space swallow */
559                 if (!ah->frags[ah->frag_index[wsi->u.hdr.parser_state]].len &&
560                     c == ' ')
561                         break;
562
563                 for (m = 0; m < ARRAY_SIZE(methods); m++)
564                         if (wsi->u.hdr.parser_state == methods[m])
565                                 break;
566                 if (m == ARRAY_SIZE(methods))
567                         /* it was not any of the methods */
568                         goto check_eol;
569
570                 /* special URI processing... end at space */
571
572                 if (c == ' ') {
573                         /* enforce starting with / */
574                         if (!ah->frags[ah->nfrag].len)
575                                 if (issue_char(wsi, '/') < 0)
576                                         return -1;
577
578                         if (wsi->u.hdr.ups == URIPS_SEEN_SLASH_DOT_DOT) {
579                                 /*
580                                  * back up one dir level if possible
581                                  * safe against header fragmentation because
582                                  * the method URI can only be in 1 fragment
583                                  */
584                                 if (ah->frags[ah->nfrag].len > 2) {
585                                         ah->pos--;
586                                         ah->frags[ah->nfrag].len--;
587                                         do {
588                                                 ah->pos--;
589                                                 ah->frags[ah->nfrag].len--;
590                                         } while (ah->frags[ah->nfrag].len > 1 &&
591                                                  ah->data[ah->pos] != '/');
592                                 }
593                         }
594
595                         /* begin parsing HTTP version: */
596                         if (issue_char(wsi, '\0') < 0)
597                                 return -1;
598                         wsi->u.hdr.parser_state = WSI_TOKEN_HTTP;
599                         goto start_fragment;
600                 }
601
602                 /*
603                  * PRIORITY 1
604                  * special URI processing... convert %xx
605                  */
606
607                 switch (wsi->u.hdr.ues) {
608                 case URIES_IDLE:
609                         if (c == '%') {
610                                 wsi->u.hdr.ues = URIES_SEEN_PERCENT;
611                                 goto swallow;
612                         }
613                         break;
614                 case URIES_SEEN_PERCENT:
615                         if (char_to_hex(c) < 0)
616                                 /* illegal post-% char */
617                                 goto forbid;
618
619                         wsi->u.hdr.esc_stash = c;
620                         wsi->u.hdr.ues = URIES_SEEN_PERCENT_H1;
621                         goto swallow;
622
623                 case URIES_SEEN_PERCENT_H1:
624                         if (char_to_hex(c) < 0)
625                                 /* illegal post-% char */
626                                 goto forbid;
627
628                         c = (char_to_hex(wsi->u.hdr.esc_stash) << 4) |
629                                         char_to_hex(c);
630                         enc = 1;
631                         wsi->u.hdr.ues = URIES_IDLE;
632                         break;
633                 }
634
635                 /*
636                  * PRIORITY 2
637                  * special URI processing...
638                  *  convert /.. or /... or /../ etc to /
639                  *  convert /./ to /
640                  *  convert // or /// etc to /
641                  *  leave /.dir or whatever alone
642                  */
643
644                 switch (wsi->u.hdr.ups) {
645                 case URIPS_IDLE:
646                         if (!c)
647                                 return -1;
648                         /* genuine delimiter */
649                         if ((c == '&' || c == ';') && !enc) {
650                                 if (issue_char(wsi, c) < 0)
651                                         return -1;
652                                 /* swallow the terminator */
653                                 ah->frags[ah->nfrag].len--;
654                                 /* link to next fragment */
655                                 ah->frags[ah->nfrag].nfrag = ah->nfrag + 1;
656                                 ah->nfrag++;
657                                 if (ah->nfrag >= ARRAY_SIZE(ah->frags))
658                                         goto excessive;
659                                 /* start next fragment after the & */
660                                 wsi->u.hdr.post_literal_equal = 0;
661                                 ah->frags[ah->nfrag].offset = ah->pos;
662                                 ah->frags[ah->nfrag].len = 0;
663                                 ah->frags[ah->nfrag].nfrag = 0;
664                                 goto swallow;
665                         }
666                         /* uriencoded = in the name part, disallow */
667                         if (c == '=' && enc &&
668                             ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] &&
669                             !wsi->u.hdr.post_literal_equal)
670                                 c = '_';
671
672                         /* after the real =, we don't care how many = */
673                         if (c == '=' && !enc)
674                                 wsi->u.hdr.post_literal_equal = 1;
675
676                         /* + to space */
677                         if (c == '+' && !enc)
678                                 c = ' ';
679                         /* issue the first / always */
680                         if (c == '/' && !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS])
681                                 wsi->u.hdr.ups = URIPS_SEEN_SLASH;
682                         break;
683                 case URIPS_SEEN_SLASH:
684                         /* swallow subsequent slashes */
685                         if (c == '/')
686                                 goto swallow;
687                         /* track and swallow the first . after / */
688                         if (c == '.') {
689                                 wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT;
690                                 goto swallow;
691                         }
692                         wsi->u.hdr.ups = URIPS_IDLE;
693                         break;
694                 case URIPS_SEEN_SLASH_DOT:
695                         /* swallow second . */
696                         if (c == '.') {
697                                 wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT_DOT;
698                                 goto swallow;
699                         }
700                         /* change /./ to / */
701                         if (c == '/') {
702                                 wsi->u.hdr.ups = URIPS_SEEN_SLASH;
703                                 goto swallow;
704                         }
705                         /* it was like /.dir ... regurgitate the . */
706                         wsi->u.hdr.ups = URIPS_IDLE;
707                         if (issue_char(wsi, '.') < 0)
708                                 return -1;
709                         break;
710
711                 case URIPS_SEEN_SLASH_DOT_DOT:
712
713                         /* /../ or /..[End of URI] --> backup to last / */
714                         if (c == '/' || c == '?') {
715                                 /*
716                                  * back up one dir level if possible
717                                  * safe against header fragmentation because
718                                  * the method URI can only be in 1 fragment
719                                  */
720                                 if (ah->frags[ah->nfrag].len > 2) {
721                                         ah->pos--;
722                                         ah->frags[ah->nfrag].len--;
723                                         do {
724                                                 ah->pos--;
725                                                 ah->frags[ah->nfrag].len--;
726                                         } while (ah->frags[ah->nfrag].len > 1 &&
727                                                  ah->data[ah->pos] != '/');
728                                 }
729                                 wsi->u.hdr.ups = URIPS_SEEN_SLASH;
730                                 if (ah->frags[ah->nfrag].len > 1)
731                                         break;
732                                 goto swallow;
733                         }
734
735                         /*  /..[^/] ... regurgitate and allow */
736
737                         if (issue_char(wsi, '.') < 0)
738                                 return -1;
739                         if (issue_char(wsi, '.') < 0)
740                                 return -1;
741                         wsi->u.hdr.ups = URIPS_IDLE;
742                         break;
743                 }
744
745                 if (c == '?' && !enc &&
746                     !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS]) { /* start of URI arguments */
747                         if (wsi->u.hdr.ues != URIES_IDLE)
748                                 goto forbid;
749
750                         /* seal off uri header */
751                         if (issue_char(wsi, '\0') < 0)
752                                 return -1;
753
754                         /* move to using WSI_TOKEN_HTTP_URI_ARGS */
755                         ah->nfrag++;
756                         if (ah->nfrag >= ARRAY_SIZE(ah->frags))
757                                 goto excessive;
758                         ah->frags[ah->nfrag].offset = ah->pos;
759                         ah->frags[ah->nfrag].len = 0;
760                         ah->frags[ah->nfrag].nfrag = 0;
761
762                         wsi->u.hdr.post_literal_equal = 0;
763                         ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] = ah->nfrag;
764                         wsi->u.hdr.ups = URIPS_IDLE;
765                         goto swallow;
766                 }
767
768 check_eol:
769                 /* bail at EOL */
770                 if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE &&
771                     c == '\x0d') {
772                         if (wsi->u.hdr.ues != URIES_IDLE)
773                                 goto forbid;
774
775                         c = '\0';
776                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
777                         lwsl_parser("*\n");
778                 }
779
780                 n = issue_char(wsi, c);
781                 if ((int)n < 0)
782                         return -1;
783                 if (n > 0)
784                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
785
786 swallow:
787                 /* per-protocol end of headers management */
788
789                 if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
790                         goto set_parsing_complete;
791                 break;
792
793                 /* collecting and checking a name part */
794         case WSI_TOKEN_NAME_PART:
795                 lwsl_parser("WSI_TOKEN_NAME_PART '%c' (mode=%d)\n", c, wsi->mode);
796
797                 wsi->u.hdr.lextable_pos =
798                                 lextable_decode(wsi->u.hdr.lextable_pos, c);
799                 /*
800                  * Server needs to look out for unknown methods...
801                  */
802                 if (wsi->u.hdr.lextable_pos < 0 &&
803                     wsi->mode == LWSCM_HTTP_SERVING) {
804                         /* this is not a header we know about */
805                         for (m = 0; m < ARRAY_SIZE(methods); m++)
806                                 if (ah->frag_index[methods[m]]) {
807                                         /*
808                                          * already had the method, no idea what
809                                          * this crap from the client is, ignore
810                                          */
811                                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
812                                         break;
813                                 }
814                         /*
815                          * hm it's an unknown http method from a client in fact,
816                          * it cannot be valid http
817                          */
818                         if (m == ARRAY_SIZE(methods)) {
819                                 /*
820                                  * are we set up to accept raw in these cases?
821                                  */
822                                 if (lws_check_opt(wsi->vhost->options,
823                                            LWS_SERVER_OPTION_FALLBACK_TO_RAW))
824                                         return 2; /* transition to raw */
825
826                                 lwsl_info("Unknown method - dropping\n");
827                                 goto forbid;
828                         }
829                         break;
830                 }
831                 /*
832                  * ...otherwise for a client, let him ignore unknown headers
833                  * coming from the server
834                  */
835                 if (wsi->u.hdr.lextable_pos < 0) {
836                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
837                         break;
838                 }
839
840                 if (lextable[wsi->u.hdr.lextable_pos] < FAIL_CHAR) {
841                         /* terminal state */
842
843                         n = ((unsigned int)lextable[wsi->u.hdr.lextable_pos] << 8) |
844                                         lextable[wsi->u.hdr.lextable_pos + 1];
845
846                         lwsl_parser("known hdr %d\n", n);
847                         for (m = 0; m < ARRAY_SIZE(methods); m++)
848                                 if (n == methods[m] &&
849                                     ah->frag_index[methods[m]]) {
850                                         lwsl_warn("Duplicated method\n");
851                                         return -1;
852                                 }
853
854                         /*
855                          * WSORIGIN is protocol equiv to ORIGIN,
856                          * JWebSocket likes to send it, map to ORIGIN
857                          */
858                         if (n == WSI_TOKEN_SWORIGIN)
859                                 n = WSI_TOKEN_ORIGIN;
860
861                         wsi->u.hdr.parser_state = (enum lws_token_indexes)
862                                                         (WSI_TOKEN_GET_URI + n);
863
864                         if (context->token_limits)
865                                 wsi->u.hdr.current_token_limit =
866                                         context->token_limits->token_limit[
867                                                        wsi->u.hdr.parser_state];
868                         else
869                                 wsi->u.hdr.current_token_limit =
870                                         wsi->context->max_http_header_data;
871
872                         if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
873                                 goto set_parsing_complete;
874
875                         goto start_fragment;
876                 }
877                 break;
878
879 start_fragment:
880                 ah->nfrag++;
881 excessive:
882                 if (ah->nfrag == ARRAY_SIZE(ah->frags)) {
883                         lwsl_warn("More hdr frags than we can deal with\n");
884                         return -1;
885                 }
886
887                 ah->frags[ah->nfrag].offset = ah->pos;
888                 ah->frags[ah->nfrag].len = 0;
889                 ah->frags[ah->nfrag].nfrag = 0;
890
891                 n = ah->frag_index[wsi->u.hdr.parser_state];
892                 if (!n) { /* first fragment */
893                         ah->frag_index[wsi->u.hdr.parser_state] = ah->nfrag;
894                         break;
895                 }
896                 /* continuation */
897                 while (ah->frags[n].nfrag)
898                         n = ah->frags[n].nfrag;
899                 ah->frags[n].nfrag = ah->nfrag;
900
901                 if (issue_char(wsi, ' ') < 0)
902                         return -1;
903                 break;
904
905                 /* skipping arg part of a name we didn't recognize */
906         case WSI_TOKEN_SKIPPING:
907                 lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c);
908
909                 if (c == '\x0d')
910                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
911                 break;
912
913         case WSI_TOKEN_SKIPPING_SAW_CR:
914                 lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
915                 if (wsi->u.hdr.ues != URIES_IDLE)
916                         goto forbid;
917                 if (c == '\x0a') {
918                         wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
919                         wsi->u.hdr.lextable_pos = 0;
920                 } else
921                         wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
922                 break;
923                 /* we're done, ignore anything else */
924
925         case WSI_PARSING_COMPLETE:
926                 lwsl_parser("WSI_PARSING_COMPLETE '%c'\n", c);
927                 break;
928         }
929
930         return 0;
931
932 set_parsing_complete:
933         if (wsi->u.hdr.ues != URIES_IDLE)
934                 goto forbid;
935         if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
936                 if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
937                         wsi->ietf_spec_revision =
938                                atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
939
940                 lwsl_parser("v%02d hdrs completed\n", wsi->ietf_spec_revision);
941         }
942         wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE;
943         wsi->hdr_parsing_completed = 1;
944
945         return 0;
946
947 forbid:
948         lwsl_notice(" forbidding on uri sanitation\n");
949         lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
950         return -1;
951 }
952
953 LWS_VISIBLE int lws_frame_is_binary(struct lws *wsi)
954 {
955         return wsi->u.ws.frame_is_binary;
956 }
957
958 void
959 lws_add_wsi_to_draining_ext_list(struct lws *wsi)
960 {
961         struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
962
963         if (wsi->u.ws.rx_draining_ext)
964                 return;
965
966         lwsl_ext("%s: RX EXT DRAINING: Adding to list\n", __func__);
967
968         wsi->u.ws.rx_draining_ext = 1;
969         wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
970         pt->rx_draining_ext_list = wsi;
971 }
972
973 void
974 lws_remove_wsi_from_draining_ext_list(struct lws *wsi)
975 {
976         struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
977         struct lws **w = &pt->rx_draining_ext_list;
978
979         if (!wsi->u.ws.rx_draining_ext)
980                 return;
981
982         lwsl_ext("%s: RX EXT DRAINING: Removing from list\n", __func__);
983
984         wsi->u.ws.rx_draining_ext = 0;
985
986         /* remove us from context draining ext list */
987         while (*w) {
988                 if (*w == wsi) {
989                         /* if us, point it instead to who we were pointing to */
990                         *w = wsi->u.ws.rx_draining_ext_list;
991                         break;
992                 }
993                 w = &((*w)->u.ws.rx_draining_ext_list);
994         }
995         wsi->u.ws.rx_draining_ext_list = NULL;
996 }
997
998 /*
999  * client-parser.c: lws_client_rx_sm() needs to be roughly kept in
1000  *   sync with changes here, esp related to ext draining
1001  */
1002
1003 int
1004 lws_rx_sm(struct lws *wsi, unsigned char c)
1005 {
1006         int callback_action = LWS_CALLBACK_RECEIVE;
1007         int ret = 0, n, rx_draining_ext = 0;
1008         struct lws_tokens eff_buf;
1009
1010         eff_buf.token = NULL;
1011         eff_buf.token_len = 0;
1012         if (wsi->socket_is_permanently_unusable)
1013                 return -1;
1014
1015         switch (wsi->lws_rx_parse_state) {
1016         case LWS_RXPS_NEW:
1017                 if (wsi->u.ws.rx_draining_ext) {
1018                         eff_buf.token = NULL;
1019                         eff_buf.token_len = 0;
1020                         lws_remove_wsi_from_draining_ext_list(wsi);
1021                         rx_draining_ext = 1;
1022                         lwsl_debug("%s: doing draining flow\n", __func__);
1023
1024                         goto drain_extension;
1025                 }
1026                 switch (wsi->ietf_spec_revision) {
1027                 case 13:
1028                         /*
1029                          * no prepended frame key any more
1030                          */
1031                         wsi->u.ws.all_zero_nonce = 1;
1032                         goto handle_first;
1033
1034                 default:
1035                         lwsl_warn("lws_rx_sm: unknown spec version %d\n",
1036                                                        wsi->ietf_spec_revision);
1037                         break;
1038                 }
1039                 break;
1040         case LWS_RXPS_04_mask_1:
1041                 wsi->u.ws.mask[1] = c;
1042                 if (c)
1043                         wsi->u.ws.all_zero_nonce = 0;
1044                 wsi->lws_rx_parse_state = LWS_RXPS_04_mask_2;
1045                 break;
1046         case LWS_RXPS_04_mask_2:
1047                 wsi->u.ws.mask[2] = c;
1048                 if (c)
1049                         wsi->u.ws.all_zero_nonce = 0;
1050                 wsi->lws_rx_parse_state = LWS_RXPS_04_mask_3;
1051                 break;
1052         case LWS_RXPS_04_mask_3:
1053                 wsi->u.ws.mask[3] = c;
1054                 if (c)
1055                         wsi->u.ws.all_zero_nonce = 0;
1056
1057                 /*
1058                  * start from the zero'th byte in the XOR key buffer since
1059                  * this is the start of a frame with a new key
1060                  */
1061
1062                 wsi->u.ws.mask_idx = 0;
1063
1064                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
1065                 break;
1066
1067         /*
1068          *  04 logical framing from the spec (all this is masked when incoming
1069          *  and has to be unmasked)
1070          *
1071          * We ignore the possibility of extension data because we don't
1072          * negotiate any extensions at the moment.
1073          *
1074          *    0                   1                   2                   3
1075          *    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
1076          *   +-+-+-+-+-------+-+-------------+-------------------------------+
1077          *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
1078          *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
1079          *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
1080          *   | |1|2|3|       |4|             |                               |
1081          *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
1082          *   |     Extended payload length continued, if payload len == 127  |
1083          *   + - - - - - - - - - - - - - - - +-------------------------------+
1084          *   |                               |         Extension data        |
1085          *   +-------------------------------+ - - - - - - - - - - - - - - - +
1086          *   :                                                               :
1087          *   +---------------------------------------------------------------+
1088          *   :                       Application data                        :
1089          *   +---------------------------------------------------------------+
1090          *
1091          *  We pass payload through to userland as soon as we get it, ignoring
1092          *  FIN.  It's up to userland to buffer it up if it wants to see a
1093          *  whole unfragmented block of the original size (which may be up to
1094          *  2^63 long!)
1095          */
1096
1097         case LWS_RXPS_04_FRAME_HDR_1:
1098 handle_first:
1099
1100                 wsi->u.ws.opcode = c & 0xf;
1101                 wsi->u.ws.rsv = c & 0x70;
1102                 wsi->u.ws.final = !!((c >> 7) & 1);
1103
1104                 switch (wsi->u.ws.opcode) {
1105                 case LWSWSOPC_TEXT_FRAME:
1106                 case LWSWSOPC_BINARY_FRAME:
1107                         wsi->u.ws.rsv_first_msg = (c & 0x70);
1108                         wsi->u.ws.frame_is_binary =
1109                              wsi->u.ws.opcode == LWSWSOPC_BINARY_FRAME;
1110                         break;
1111                 case 3:
1112                 case 4:
1113                 case 5:
1114                 case 6:
1115                 case 7:
1116                 case 0xb:
1117                 case 0xc:
1118                 case 0xd:
1119                 case 0xe:
1120                 case 0xf:
1121                         lwsl_info("illegal opcode\n");
1122                         return -1;
1123                 }
1124                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
1125                 break;
1126
1127         case LWS_RXPS_04_FRAME_HDR_LEN:
1128
1129                 wsi->u.ws.this_frame_masked = !!(c & 0x80);
1130
1131                 switch (c & 0x7f) {
1132                 case 126:
1133                         /* control frames are not allowed to have big lengths */
1134                         if (wsi->u.ws.opcode & 8)
1135                                 goto illegal_ctl_length;
1136
1137                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
1138                         break;
1139                 case 127:
1140                         /* control frames are not allowed to have big lengths */
1141                         if (wsi->u.ws.opcode & 8)
1142                                 goto illegal_ctl_length;
1143
1144                         wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
1145                         break;
1146                 default:
1147                         wsi->u.ws.rx_packet_length = c & 0x7f;
1148                         if (wsi->u.ws.this_frame_masked)
1149                                 wsi->lws_rx_parse_state =
1150                                                 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
1151                         else
1152                                 if (wsi->u.ws.rx_packet_length)
1153                                         wsi->lws_rx_parse_state =
1154                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
1155                                 else {
1156                                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
1157                                         goto spill;
1158                                 }
1159                         break;
1160                 }
1161                 break;
1162
1163         case LWS_RXPS_04_FRAME_HDR_LEN16_2:
1164                 wsi->u.ws.rx_packet_length = c << 8;
1165                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
1166                 break;
1167
1168         case LWS_RXPS_04_FRAME_HDR_LEN16_1:
1169                 wsi->u.ws.rx_packet_length |= c;
1170                 if (wsi->u.ws.this_frame_masked)
1171                         wsi->lws_rx_parse_state =
1172                                         LWS_RXPS_07_COLLECT_FRAME_KEY_1;
1173                 else
1174                         wsi->lws_rx_parse_state =
1175                                 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
1176                 break;
1177
1178         case LWS_RXPS_04_FRAME_HDR_LEN64_8:
1179                 if (c & 0x80) {
1180                         lwsl_warn("b63 of length must be zero\n");
1181                         /* kill the connection */
1182                         return -1;
1183                 }
1184 #if defined __LP64__
1185                 wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
1186 #else
1187                 wsi->u.ws.rx_packet_length = 0;
1188 #endif
1189                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
1190                 break;
1191
1192         case LWS_RXPS_04_FRAME_HDR_LEN64_7:
1193 #if defined __LP64__
1194                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
1195 #endif
1196                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
1197                 break;
1198
1199         case LWS_RXPS_04_FRAME_HDR_LEN64_6:
1200 #if defined __LP64__
1201                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
1202 #endif
1203                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
1204                 break;
1205
1206         case LWS_RXPS_04_FRAME_HDR_LEN64_5:
1207 #if defined __LP64__
1208                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
1209 #endif
1210                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
1211                 break;
1212
1213         case LWS_RXPS_04_FRAME_HDR_LEN64_4:
1214                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
1215                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
1216                 break;
1217
1218         case LWS_RXPS_04_FRAME_HDR_LEN64_3:
1219                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
1220                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
1221                 break;
1222
1223         case LWS_RXPS_04_FRAME_HDR_LEN64_2:
1224                 wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
1225                 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
1226                 break;
1227
1228         case LWS_RXPS_04_FRAME_HDR_LEN64_1:
1229                 wsi->u.ws.rx_packet_length |= ((size_t)c);
1230                 if (wsi->u.ws.this_frame_masked)
1231                         wsi->lws_rx_parse_state =
1232                                         LWS_RXPS_07_COLLECT_FRAME_KEY_1;
1233                 else
1234                         wsi->lws_rx_parse_state =
1235                                 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
1236                 break;
1237
1238         case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
1239                 wsi->u.ws.mask[0] = c;
1240                 if (c)
1241                         wsi->u.ws.all_zero_nonce = 0;
1242                 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
1243                 break;
1244
1245         case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
1246                 wsi->u.ws.mask[1] = c;
1247                 if (c)
1248                         wsi->u.ws.all_zero_nonce = 0;
1249                 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
1250                 break;
1251
1252         case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
1253                 wsi->u.ws.mask[2] = c;
1254                 if (c)
1255                         wsi->u.ws.all_zero_nonce = 0;
1256                 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
1257                 break;
1258
1259         case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
1260                 wsi->u.ws.mask[3] = c;
1261                 if (c)
1262                         wsi->u.ws.all_zero_nonce = 0;
1263                 wsi->lws_rx_parse_state =
1264                                         LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
1265                 wsi->u.ws.mask_idx = 0;
1266                 if (wsi->u.ws.rx_packet_length == 0) {
1267                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
1268                         goto spill;
1269                 }
1270                 break;
1271
1272
1273         case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
1274                 assert(wsi->u.ws.rx_ubuf);
1275
1276                 if (wsi->u.ws.rx_draining_ext)
1277                         goto drain_extension;
1278
1279                 if (wsi->u.ws.rx_ubuf_head + LWS_PRE >=
1280                     wsi->u.ws.rx_ubuf_alloc) {
1281                         lwsl_err("Attempted overflow \n");
1282                         return -1;
1283                 }
1284                 if (wsi->u.ws.all_zero_nonce)
1285                         wsi->u.ws.rx_ubuf[LWS_PRE +
1286                                          (wsi->u.ws.rx_ubuf_head++)] = c;
1287                 else
1288                         wsi->u.ws.rx_ubuf[LWS_PRE +
1289                                (wsi->u.ws.rx_ubuf_head++)] =
1290                                    c ^ wsi->u.ws.mask[
1291                                             (wsi->u.ws.mask_idx++) & 3];
1292
1293                 if (--wsi->u.ws.rx_packet_length == 0) {
1294                         /* spill because we have the whole frame */
1295                         wsi->lws_rx_parse_state = LWS_RXPS_NEW;
1296                         goto spill;
1297                 }
1298
1299                 /*
1300                  * if there's no protocol max frame size given, we are
1301                  * supposed to default to context->pt_serv_buf_size
1302                  */
1303
1304                 if (!wsi->protocol->rx_buffer_size &&
1305                     wsi->u.ws.rx_ubuf_head != wsi->context->pt_serv_buf_size)
1306                         break;
1307                 else
1308                         if (wsi->protocol->rx_buffer_size &&
1309                                         wsi->u.ws.rx_ubuf_head !=
1310                                                   wsi->protocol->rx_buffer_size)
1311                         break;
1312
1313                 /* spill because we filled our rx buffer */
1314 spill:
1315                 /*
1316                  * is this frame a control packet we should take care of at this
1317                  * layer?  If so service it and hide it from the user callback
1318                  */
1319
1320                 lwsl_parser("spill on %s\n", wsi->protocol->name);
1321
1322                 switch (wsi->u.ws.opcode) {
1323                 case LWSWSOPC_CLOSE:
1324
1325                         /* is this an acknowledgement of our close? */
1326                         if (wsi->state == LWSS_AWAITING_CLOSE_ACK) {
1327                                 /*
1328                                  * fine he has told us he is closing too, let's
1329                                  * finish our close
1330                                  */
1331                                 lwsl_parser("seen client close ack\n");
1332                                 return -1;
1333                         }
1334                         if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY)
1335                                 /* if he sends us 2 CLOSE, kill him */
1336                                 return -1;
1337
1338                         if (lws_partial_buffered(wsi)) {
1339                                 /*
1340                                  * if we're in the middle of something,
1341                                  * we can't do a normal close response and
1342                                  * have to just close our end.
1343                                  */
1344                                 wsi->socket_is_permanently_unusable = 1;
1345                                 lwsl_parser("Closing on peer close due to Pending tx\n");
1346                                 return -1;
1347                         }
1348
1349                         if (user_callback_handle_rxflow(
1350                                         wsi->protocol->callback, wsi,
1351                                         LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
1352                                         wsi->user_space,
1353                                         &wsi->u.ws.rx_ubuf[LWS_PRE],
1354                                         wsi->u.ws.rx_ubuf_head))
1355                                 return -1;
1356
1357                         lwsl_parser("server sees client close packet\n");
1358                         wsi->state = LWSS_RETURNED_CLOSE_ALREADY;
1359                         /* deal with the close packet contents as a PONG */
1360                         wsi->u.ws.payload_is_close = 1;
1361                         goto process_as_ping;
1362
1363                 case LWSWSOPC_PING:
1364                         lwsl_info("received %d byte ping, sending pong\n",
1365                                                  wsi->u.ws.rx_ubuf_head);
1366
1367                         if (wsi->u.ws.ping_pending_flag) {
1368                                 /*
1369                                  * there is already a pending ping payload
1370                                  * we should just log and drop
1371                                  */
1372                                 lwsl_parser("DROP PING since one pending\n");
1373                                 goto ping_drop;
1374                         }
1375 process_as_ping:
1376                         /* control packets can only be < 128 bytes long */
1377                         if (wsi->u.ws.rx_ubuf_head > 128 - 3) {
1378                                 lwsl_parser("DROP PING payload too large\n");
1379                                 goto ping_drop;
1380                         }
1381
1382                         /* stash the pong payload */
1383                         memcpy(wsi->u.ws.ping_payload_buf + LWS_PRE,
1384                                &wsi->u.ws.rx_ubuf[LWS_PRE],
1385                                 wsi->u.ws.rx_ubuf_head);
1386
1387                         wsi->u.ws.ping_payload_len = wsi->u.ws.rx_ubuf_head;
1388                         wsi->u.ws.ping_pending_flag = 1;
1389
1390                         /* get it sent as soon as possible */
1391                         lws_callback_on_writable(wsi);
1392 ping_drop:
1393                         wsi->u.ws.rx_ubuf_head = 0;
1394                         return 0;
1395
1396                 case LWSWSOPC_PONG:
1397                         lwsl_info("received pong\n");
1398                         lwsl_hexdump(&wsi->u.ws.rx_ubuf[LWS_PRE],
1399                                      wsi->u.ws.rx_ubuf_head);
1400
1401                         if (wsi->pending_timeout == PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG) {
1402                                 lwsl_info("received expected PONG on wsi %p\n", wsi);
1403                                 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1404                         }
1405
1406                         /* issue it */
1407                         callback_action = LWS_CALLBACK_RECEIVE_PONG;
1408                         break;
1409
1410                 case LWSWSOPC_TEXT_FRAME:
1411                 case LWSWSOPC_BINARY_FRAME:
1412                 case LWSWSOPC_CONTINUATION:
1413                         break;
1414
1415                 default:
1416                         lwsl_parser("passing opc %x up to exts\n",
1417                                     wsi->u.ws.opcode);
1418                         /*
1419                          * It's something special we can't understand here.
1420                          * Pass the payload up to the extension's parsing
1421                          * state machine.
1422                          */
1423
1424                         eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE];
1425                         eff_buf.token_len = wsi->u.ws.rx_ubuf_head;
1426
1427                         if (lws_ext_cb_active(wsi, LWS_EXT_CB_EXTENDED_PAYLOAD_RX,
1428                                               &eff_buf, 0) <= 0)
1429                                 /* not handle or fail */
1430                                 lwsl_ext("ext opc opcode 0x%x unknown\n",
1431                                          wsi->u.ws.opcode);
1432
1433                         wsi->u.ws.rx_ubuf_head = 0;
1434                         return 0;
1435                 }
1436
1437                 /*
1438                  * No it's real payload, pass it up to the user callback.
1439                  * It's nicely buffered with the pre-padding taken care of
1440                  * so it can be sent straight out again using lws_write
1441                  */
1442
1443                 eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE];
1444                 eff_buf.token_len = wsi->u.ws.rx_ubuf_head;
1445
1446 drain_extension:
1447                 lwsl_ext("%s: passing %d to ext\n", __func__, eff_buf.token_len);
1448
1449                 if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
1450                     wsi->state == LWSS_AWAITING_CLOSE_ACK)
1451                         goto already_done;
1452
1453                 n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &eff_buf, 0);
1454                 /* eff_buf may be pointing somewhere completely different now,
1455                  * it's the output
1456                  */
1457                 if (n < 0) {
1458                         /*
1459                          * we may rely on this to get RX, just drop connection
1460                          */
1461                         wsi->socket_is_permanently_unusable = 1;
1462                         return -1;
1463                 }
1464
1465                 if (rx_draining_ext && eff_buf.token_len == 0)
1466                         goto already_done;
1467
1468                 if (n && eff_buf.token_len) {
1469                         /* extension had more... main loop will come back */
1470                         lws_add_wsi_to_draining_ext_list(wsi);
1471                 } else
1472                         lws_remove_wsi_from_draining_ext_list(wsi);
1473
1474                 if (eff_buf.token_len > 0 ||
1475                     callback_action == LWS_CALLBACK_RECEIVE_PONG) {
1476                         eff_buf.token[eff_buf.token_len] = '\0';
1477
1478                         if (wsi->protocol->callback) {
1479
1480                                 if (callback_action == LWS_CALLBACK_RECEIVE_PONG)
1481                                         lwsl_info("Doing pong callback\n");
1482
1483                                 ret = user_callback_handle_rxflow(
1484                                                 wsi->protocol->callback,
1485                                                 wsi,
1486                                                 (enum lws_callback_reasons)callback_action,
1487                                                 wsi->user_space,
1488                                                 eff_buf.token,
1489                                                 eff_buf.token_len);
1490                         }
1491                         else
1492                                 lwsl_err("No callback on payload spill!\n");
1493                 }
1494
1495 already_done:
1496                 wsi->u.ws.rx_ubuf_head = 0;
1497                 break;
1498         }
1499
1500         return ret;
1501
1502 illegal_ctl_length:
1503
1504         lwsl_warn("Control frame with xtended length is illegal\n");
1505         /* kill the connection */
1506         return -1;
1507 }
1508
1509 LWS_VISIBLE size_t
1510 lws_remaining_packet_payload(struct lws *wsi)
1511 {
1512         return wsi->u.ws.rx_packet_length;
1513 }
1514
1515 /* Once we reach LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED, we know how much
1516  * to expect in that state and can deal with it in bulk more efficiently.
1517  */
1518
1519 int
1520 lws_payload_until_length_exhausted(struct lws *wsi, unsigned char **buf,
1521                                    size_t *len)
1522 {
1523         unsigned char *buffer = *buf, mask[4];
1524         int buffer_size, n;
1525         unsigned int avail;
1526         char *rx_ubuf;
1527
1528         if (wsi->protocol->rx_buffer_size)
1529                 buffer_size = wsi->protocol->rx_buffer_size;
1530         else
1531                 buffer_size = wsi->context->pt_serv_buf_size;
1532         avail = buffer_size - wsi->u.ws.rx_ubuf_head;
1533
1534         /* do not consume more than we should */
1535         if (avail > wsi->u.ws.rx_packet_length)
1536                 avail = wsi->u.ws.rx_packet_length;
1537
1538         /* do not consume more than what is in the buffer */
1539         if (avail > *len)
1540                 avail = *len;
1541
1542         /* we want to leave 1 byte for the parser to handle properly */
1543         if (avail <= 1)
1544                 return 0;
1545
1546         avail--;
1547         rx_ubuf = wsi->u.ws.rx_ubuf + LWS_PRE + wsi->u.ws.rx_ubuf_head;
1548         if (wsi->u.ws.all_zero_nonce)
1549                 memcpy(rx_ubuf, buffer, avail);
1550         else {
1551
1552                 for (n = 0; n < 4; n++)
1553                         mask[n] = wsi->u.ws.mask[(wsi->u.ws.mask_idx + n) & 3];
1554
1555                 /* deal with 4-byte chunks using unwrapped loop */
1556                 n = avail >> 2;
1557                 while (n--) {
1558                         *(rx_ubuf++) = *(buffer++) ^ mask[0];
1559                         *(rx_ubuf++) = *(buffer++) ^ mask[1];
1560                         *(rx_ubuf++) = *(buffer++) ^ mask[2];
1561                         *(rx_ubuf++) = *(buffer++) ^ mask[3];
1562                 }
1563                 /* and the remaining bytes bytewise */
1564                 for (n = 0; n < (int)(avail & 3); n++)
1565                         *(rx_ubuf++) = *(buffer++) ^ mask[n];
1566
1567                 wsi->u.ws.mask_idx = (wsi->u.ws.mask_idx + avail) & 3;
1568         }
1569
1570         (*buf) += avail;
1571         wsi->u.ws.rx_ubuf_head += avail;
1572         wsi->u.ws.rx_packet_length -= avail;
1573         *len -= avail;
1574
1575         return avail;
1576 }