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