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