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