blob: fab799ef1528d54305aee47d8218fb11ab7d05dc [file] [log] [blame]
Andy Green7c212cc2010-11-08 20:20:42 +00001/*
2 * libwebsockets - small server side websockets and web server implementation
Andy Greene77ddd82010-11-13 10:03:47 +00003 *
Andy Greena1ce6be2013-01-18 11:43:21 +08004 * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
Andy Green7c212cc2010-11-08 20:20:42 +00005 *
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
Andy Green6d1fcb72013-01-18 01:55:48 +080024unsigned char lextable[] = {
Andy Greencc13c6f2013-11-09 10:09:09 +080025 #include "lextable.h"
Andy Green6d1fcb72013-01-18 01:55:48 +080026};
27
Andy Greenbbc5c072014-03-09 11:49:21 +080028#define FAIL_CHAR 0x08
29
Andy Green8c1f6022016-01-26 20:56:56 +080030int LWS_WARN_UNUSED_RESULT
31lextable_decode(int pos, char c)
Andy Green6d1fcb72013-01-18 01:55:48 +080032{
Andy Greenf38ad332016-01-20 07:55:41 +080033 if (c >= 'A' && c <= 'Z')
34 c += 'a' - 'A';
Andy Greenbbc5c072014-03-09 11:49:21 +080035
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;
Andy Green6d1fcb72013-01-18 01:55:48 +080044 return pos;
Andy Greenbbc5c072014-03-09 11:49:21 +080045 }
Andy Greenf012f752014-08-22 19:38:17 +080046
47 if (lextable[pos] == FAIL_CHAR)
48 return -1;
49
Andy Green2c24ec02014-04-02 19:45:42 +080050 /* 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 */
Andy Green6d1fcb72013-01-18 01:55:48 +080060 }
Andy Green6d1fcb72013-01-18 01:55:48 +080061}
62
Andy Green4019aab2016-01-30 11:43:10 +080063void
Andy Greene3d141d2016-02-27 11:42:22 +080064lws_header_table_reset(struct lws *wsi, int autoservice)
Andy Green8c1f6022016-01-26 20:56:56 +080065{
Andy Green2c218e72016-02-15 12:37:04 +080066 struct allocated_headers *ah = wsi->u.hdr.ah;
Andy Greene3d141d2016-02-27 11:42:22 +080067 struct lws_context_per_thread *pt;
68 struct lws_pollfd *pfd;
Andy Green2c218e72016-02-15 12:37:04 +080069
70 /* if we have the idea we're resetting 'our' ah, must be bound to one */
71 assert(ah);
72 /* ah also concurs with ownership */
73 assert(ah->wsi == wsi);
Andy Green892f03a2016-02-09 09:15:02 +080074
Andy Green8c1f6022016-01-26 20:56:56 +080075 /* init the ah to reflect no headers or data have appeared yet */
Andy Green2c218e72016-02-15 12:37:04 +080076 memset(ah->frag_index, 0, sizeof(ah->frag_index));
77 ah->nfrag = 0;
78 ah->pos = 0;
79
80 /* and reset the rx state */
81 ah->rxpos = 0;
82 ah->rxlen = 0;
83
84 /* since we will restart the ah, our new headers are not completed */
85 wsi->hdr_parsing_completed = 0;
Andy Green51d9afa2016-02-24 11:05:56 +080086
87 /*
88 * if we inherited pending rx (from socket adoption deferred
89 * processing), apply and free it.
90 */
91 if (wsi->u.hdr.preamble_rx) {
Andy Greene3d141d2016-02-27 11:42:22 +080092 memcpy(ah->rx, wsi->u.hdr.preamble_rx,
93 wsi->u.hdr.preamble_rx_len);
Andy Green51d9afa2016-02-24 11:05:56 +080094 ah->rxlen = wsi->u.hdr.preamble_rx_len;
95 lws_free_set_NULL(wsi->u.hdr.preamble_rx);
Andy Greene3d141d2016-02-27 11:42:22 +080096
97 if (autoservice) {
98 lwsl_notice("%s: calling service on readbuf ah\n", __func__);
99
100 pt = &wsi->context->pt[(int)wsi->tsi];
101
102 /* unlike a normal connect, we have the headers already
103 * (or the first part of them anyway)
104 */
105 pfd = &pt->fds[wsi->position_in_fds_table];
106 pfd->revents |= LWS_POLLIN;
107 lwsl_err("%s: calling service\n", __func__);
108 lws_service_fd_tsi(wsi->context, pfd, wsi->tsi);
109 }
Andy Green51d9afa2016-02-24 11:05:56 +0800110 }
Andy Green8c1f6022016-01-26 20:56:56 +0800111}
112
Andy Green5a0e7862016-01-21 10:57:39 +0800113int LWS_WARN_UNUSED_RESULT
Andy Greene3d141d2016-02-27 11:42:22 +0800114lws_header_table_attach(struct lws *wsi, int autoservice)
Andy Green16ab3182013-02-10 18:02:31 +0800115{
Andy Green3df58002015-12-25 12:44:12 +0800116 struct lws_context *context = wsi->context;
Andy Green8c1f6022016-01-26 20:56:56 +0800117 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
118 struct lws_pollargs pa;
119 struct lws **pwsi;
Andy Green3df58002015-12-25 12:44:12 +0800120 int n;
121
Andy Green8c1f6022016-01-26 20:56:56 +0800122 lwsl_info("%s: wsi %p: ah %p (tsi %d)\n", __func__, (void *)wsi,
123 (void *)wsi->u.hdr.ah, wsi->tsi);
Andy Green3df58002015-12-25 12:44:12 +0800124
125 /* if we are already bound to one, just clear it down */
Andy Green8c1f6022016-01-26 20:56:56 +0800126 if (wsi->u.hdr.ah) {
Andy Green89719712016-02-25 21:39:01 +0800127 lwsl_info("cleardown\n");
Andy Green3df58002015-12-25 12:44:12 +0800128 goto reset;
Andy Green8c1f6022016-01-26 20:56:56 +0800129 }
130
131 lws_pt_lock(pt);
132 pwsi = &pt->ah_wait_list;
133 while (*pwsi) {
134 if (*pwsi == wsi) {
135 /* if already waiting on list, if no new ah just ret */
136 if (pt->ah_count_in_use ==
137 context->max_http_header_pool) {
138 lwsl_err("ah wl denied\n");
139 goto bail;
140 }
141 /* new ah.... remove ourselves from waiting list */
Andy Green89719712016-02-25 21:39:01 +0800142 *pwsi = wsi->u.hdr.ah_wait_list; /* set our prev to our next */
143 wsi->u.hdr.ah_wait_list = NULL; /* no next any more */
Andy Green8c1f6022016-01-26 20:56:56 +0800144 pt->ah_wait_list_length--;
145 break;
146 }
147 pwsi = &(*pwsi)->u.hdr.ah_wait_list;
148 }
Andy Green3df58002015-12-25 12:44:12 +0800149 /*
Andy Green8c1f6022016-01-26 20:56:56 +0800150 * pool is all busy... add us to waiting list and return that we
151 * weren't able to deliver it right now
Andy Green3df58002015-12-25 12:44:12 +0800152 */
Andy Green8c1f6022016-01-26 20:56:56 +0800153 if (pt->ah_count_in_use == context->max_http_header_pool) {
Andy Green4019aab2016-01-30 11:43:10 +0800154 lwsl_info("%s: adding %p to ah waiting list\n", __func__, wsi);
Andy Green8c1f6022016-01-26 20:56:56 +0800155 wsi->u.hdr.ah_wait_list = pt->ah_wait_list;
156 pt->ah_wait_list = wsi;
157 pt->ah_wait_list_length++;
158
159 /* we cannot accept input then */
160
161 _lws_change_pollfd(wsi, LWS_POLLIN, 0, &pa);
162 goto bail;
Andy Green16ab3182013-02-10 18:02:31 +0800163 }
Andy Green3df58002015-12-25 12:44:12 +0800164
165 for (n = 0; n < context->max_http_header_pool; n++)
Andy Green8c1f6022016-01-26 20:56:56 +0800166 if (!pt->ah_pool[n].in_use)
Andy Green3df58002015-12-25 12:44:12 +0800167 break;
168
169 /* if the count of in use said something free... */
170 assert(n != context->max_http_header_pool);
171
Andy Green8c1f6022016-01-26 20:56:56 +0800172 wsi->u.hdr.ah = &pt->ah_pool[n];
Andy Green3df58002015-12-25 12:44:12 +0800173 wsi->u.hdr.ah->in_use = 1;
Andy Green2c218e72016-02-15 12:37:04 +0800174 pt->ah_pool[n].wsi = wsi; /* mark our owner */
Andy Green8c1f6022016-01-26 20:56:56 +0800175 pt->ah_count_in_use++;
Andy Green3df58002015-12-25 12:44:12 +0800176
Andy Green8c1f6022016-01-26 20:56:56 +0800177 _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
Andy Green3df58002015-12-25 12:44:12 +0800178
Andy Green8c1f6022016-01-26 20:56:56 +0800179 lwsl_info("%s: wsi %p: ah %p: count %d (on exit)\n", __func__,
180 (void *)wsi, (void *)wsi->u.hdr.ah, pt->ah_count_in_use);
181
182 lws_pt_unlock(pt);
Andy Green3df58002015-12-25 12:44:12 +0800183
184reset:
Andy Greene3d141d2016-02-27 11:42:22 +0800185 lws_header_table_reset(wsi, autoservice);
Andy Green8c1f6022016-01-26 20:56:56 +0800186 time(&wsi->u.hdr.ah->assigned);
Andy Green6d1fcb72013-01-18 01:55:48 +0800187
Andy Green2d8d35a2016-02-29 14:19:16 +0800188#ifndef LWS_NO_CLIENT
189 if (wsi->state == LWSS_CLIENT_UNCONNECTED)
190 lws_client_connect_via_info2(wsi);
191#endif
192
Andy Green16ab3182013-02-10 18:02:31 +0800193 return 0;
Andy Green8c1f6022016-01-26 20:56:56 +0800194
195bail:
196 lws_pt_unlock(pt);
197
198 return 1;
Andy Green16ab3182013-02-10 18:02:31 +0800199}
200
Andy Greene3d141d2016-02-27 11:42:22 +0800201int lws_header_table_detach(struct lws *wsi, int autoservice)
Andrew Canaday37718812014-11-07 11:20:59 +0800202{
Andy Green3df58002015-12-25 12:44:12 +0800203 struct lws_context *context = wsi->context;
Andy Green8c1f6022016-01-26 20:56:56 +0800204 struct allocated_headers *ah = wsi->u.hdr.ah;
205 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
206 struct lws_pollargs pa;
207 struct lws **pwsi;
208 time_t now;
Andy Green3df58002015-12-25 12:44:12 +0800209
Andy Green2c218e72016-02-15 12:37:04 +0800210 lwsl_info("%s: wsi %p: ah %p (tsi=%d, count = %d)\n", __func__,
211 (void *)wsi, (void *)wsi->u.hdr.ah, wsi->tsi,
212 pt->ah_count_in_use);
213
Andy Green51d9afa2016-02-24 11:05:56 +0800214 if (wsi->u.hdr.preamble_rx)
215 lws_free_set_NULL(wsi->u.hdr.preamble_rx);
216
Andy Green2c218e72016-02-15 12:37:04 +0800217 /* may not be detached while he still has unprocessed rx */
Andy Green27966c22016-02-15 21:00:39 +0800218 if (ah && ah->rxpos != ah->rxlen) {
Andy Green2c218e72016-02-15 12:37:04 +0800219 lwsl_err("%s: %p: rxpos:%d, rxlen:%d\n", __func__, wsi,
220 ah->rxpos, ah->rxlen);
221 assert(ah->rxpos == ah->rxlen);
222 }
Andy Green3df58002015-12-25 12:44:12 +0800223
Andy Green8c1f6022016-01-26 20:56:56 +0800224 lws_pt_lock(pt);
Andy Green3df58002015-12-25 12:44:12 +0800225
Andy Green8c1f6022016-01-26 20:56:56 +0800226 pwsi = &pt->ah_wait_list;
Andy Green89719712016-02-25 21:39:01 +0800227 if (!ah) { /* remove from wait list if none attached */
Andy Green4ba798d2016-02-25 21:50:49 +0800228 while (*pwsi) {
229 if (*pwsi == wsi) {
230 lwsl_info("%s: wsi %p, remv wait\n",
231 __func__, wsi);
232 *pwsi = wsi->u.hdr.ah_wait_list;
233 wsi->u.hdr.ah_wait_list = NULL;
234 pt->ah_wait_list_length--;
235 goto bail;
Andy Green8c1f6022016-01-26 20:56:56 +0800236 }
Andy Green4ba798d2016-02-25 21:50:49 +0800237 pwsi = &(*pwsi)->u.hdr.ah_wait_list;
238 }
239 /* no ah, not on list... no more business here */
Andy Green8c1f6022016-01-26 20:56:56 +0800240 goto bail;
241 }
Andy Green89719712016-02-25 21:39:01 +0800242 /* we did have an ah attached */
Andy Green8c1f6022016-01-26 20:56:56 +0800243 time(&now);
Andy Greenc1e6e382016-02-19 11:47:52 +0800244 if (now - wsi->u.hdr.ah->assigned > 3) {
245 /*
246 * we're detaching the ah, but it was held an
247 * unreasonably long time
248 */
249 lwsl_notice("%s: wsi %p: ah held %ds, "
250 "ah.rxpos %d, ah.rxlen %d, mode/state %d %d,"
251 "wsi->more_rx_waiting %d\n", __func__, wsi,
252 (int)(now - wsi->u.hdr.ah->assigned),
253 ah->rxpos, ah->rxlen, wsi->mode, wsi->state,
Andy Green83af28a2016-02-28 10:55:31 +0800254 wsi->more_rx_waiting);
Andy Greenc1e6e382016-02-19 11:47:52 +0800255 }
Andy Green2c218e72016-02-15 12:37:04 +0800256
257 /* if we think we're detaching one, there should be one in use */
Andy Green8c1f6022016-01-26 20:56:56 +0800258 assert(pt->ah_count_in_use > 0);
Andy Green2c218e72016-02-15 12:37:04 +0800259 /* and this specific one should have been in use */
Andy Green3df58002015-12-25 12:44:12 +0800260 assert(wsi->u.hdr.ah->in_use);
Alejandro Meryac3ec392014-12-05 00:09:20 +0100261 wsi->u.hdr.ah = NULL;
Andy Green2c218e72016-02-15 12:37:04 +0800262 ah->wsi = NULL; /* no owner */
Andy Green3df58002015-12-25 12:44:12 +0800263
Andy Green89719712016-02-25 21:39:01 +0800264 /* oh there is nobody on the waiting list... leave it at that then */
Andy Green8c1f6022016-01-26 20:56:56 +0800265 if (!*pwsi) {
266 ah->in_use = 0;
267 pt->ah_count_in_use--;
268
269 goto bail;
270 }
271
Andy Green89719712016-02-25 21:39:01 +0800272 /* somebody else on same tsi is waiting, give it to oldest guy */
Andy Green8c1f6022016-01-26 20:56:56 +0800273
274 lwsl_info("pt wait list %p\n", *pwsi);
275 while ((*pwsi)->u.hdr.ah_wait_list)
276 pwsi = &(*pwsi)->u.hdr.ah_wait_list;
277
278 wsi = *pwsi;
279 lwsl_info("last wsi in wait list %p\n", wsi);
280
281 wsi->u.hdr.ah = ah;
Andy Green2c218e72016-02-15 12:37:04 +0800282 ah->wsi = wsi; /* new owner */
Andy Greene3d141d2016-02-27 11:42:22 +0800283 lws_header_table_reset(wsi, autoservice);
Andy Green8c1f6022016-01-26 20:56:56 +0800284 time(&wsi->u.hdr.ah->assigned);
285
286 assert(wsi->position_in_fds_table != -1);
287
288 lwsl_info("%s: Enabling %p POLLIN\n", __func__, wsi);
Andy Green2c218e72016-02-15 12:37:04 +0800289
290 /* he has been stuck waiting for an ah, but now his wait is over,
291 * let him progress
292 */
Andy Green8c1f6022016-01-26 20:56:56 +0800293 _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
294
295 /* point prev guy to next guy in list instead */
296 *pwsi = wsi->u.hdr.ah_wait_list;
Andy Green89719712016-02-25 21:39:01 +0800297 /* the guy who got one is out of the list */
Andy Green8c1f6022016-01-26 20:56:56 +0800298 wsi->u.hdr.ah_wait_list = NULL;
299 pt->ah_wait_list_length--;
300
Andy Green2d8d35a2016-02-29 14:19:16 +0800301#ifndef LWS_NO_CLIENT
302 if (wsi->state == LWSS_CLIENT_UNCONNECTED)
303 lws_client_connect_via_info2(wsi);
304#endif
305
Andy Green8c1f6022016-01-26 20:56:56 +0800306 assert(!!pt->ah_wait_list_length == !!(int)(long)pt->ah_wait_list);
307bail:
308 lws_pt_unlock(pt);
309
Alejandro Mery6ff28242014-12-04 23:59:35 +0100310 return 0;
Andy Green3df58002015-12-25 12:44:12 +0800311}
Andrew Canaday37718812014-11-07 11:20:59 +0800312
Andy Green0c7e5a92015-12-30 14:53:50 +0800313/**
314 * lws_hdr_fragment_length: report length of a single fragment of a header
315 * The returned length does not include the space for a
316 * terminating '\0'
317 *
318 * @wsi: websocket connection
319 * @h: which header index we are interested in
320 * @frag_idx: which fragment of @h we want to get the length of
321 */
322
Andy Greene974f0c2015-12-19 07:35:23 +0800323LWS_VISIBLE int
324lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, int frag_idx)
325{
326 int n;
327
328 n = wsi->u.hdr.ah->frag_index[h];
329 if (!n)
330 return 0;
331 do {
332 if (!frag_idx)
333 return wsi->u.hdr.ah->frags[n].len;
334 n = wsi->u.hdr.ah->frags[n].nfrag;
335 } while (frag_idx-- && n);
336
337 return 0;
338}
339
Andy Green0c7e5a92015-12-30 14:53:50 +0800340/**
341 * lws_hdr_total_length: report length of all fragments of a header totalled up
342 * The returned length does not include the space for a
343 * terminating '\0'
344 *
345 * @wsi: websocket connection
346 * @h: which header index we are interested in
347 */
348
Andy Green4b85c1d2015-12-04 11:08:32 +0800349LWS_VISIBLE int lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h)
Andy Green16ab3182013-02-10 18:02:31 +0800350{
351 int n;
352 int len = 0;
353
354 n = wsi->u.hdr.ah->frag_index[h];
Andy Green2c24ec02014-04-02 19:45:42 +0800355 if (!n)
Andy Green16ab3182013-02-10 18:02:31 +0800356 return 0;
Andy Green16ab3182013-02-10 18:02:31 +0800357 do {
358 len += wsi->u.hdr.ah->frags[n].len;
Andy Green6b5de702015-12-15 21:15:58 +0800359 n = wsi->u.hdr.ah->frags[n].nfrag;
Andy Green16ab3182013-02-10 18:02:31 +0800360 } while (n);
361
362 return len;
363}
364
Andy Green0c7e5a92015-12-30 14:53:50 +0800365/**
366 * lws_hdr_copy_fragment: copy a single fragment of the given header to a buffer
367 * The buffer length @len must include space for an additional
368 * terminating '\0', or it will fail returning -1.
369 * If the requested fragment index is not present, it fails
370 * returning -1.
371 *
372 * @wsi: websocket connection
373 * @dst: destination buffer
374 * @len: length of destination buffer
375 * @h: which header index we are interested in
376 * @frag_index: which fragment of @h we want to copy
377 */
378
Andy Green566eb432015-12-15 22:59:23 +0800379LWS_VISIBLE int lws_hdr_copy_fragment(struct lws *wsi, char *dst, int len,
380 enum lws_token_indexes h, int frag_idx)
381{
382 int n = 0;
383 int f = wsi->u.hdr.ah->frag_index[h];
384
Andy Greenaf607da2016-01-20 09:44:04 +0800385 if (!f)
386 return -1;
387
Andy Green566eb432015-12-15 22:59:23 +0800388 while (n < frag_idx) {
389 f = wsi->u.hdr.ah->frags[f].nfrag;
390 if (!f)
391 return -1;
392 n++;
393 }
394
Andy Green9f54c1f2015-12-18 16:40:02 +0800395 if (wsi->u.hdr.ah->frags[f].len >= len)
Andy Green566eb432015-12-15 22:59:23 +0800396 return -1;
397
Andy Green3df58002015-12-25 12:44:12 +0800398 memcpy(dst, wsi->u.hdr.ah->data + wsi->u.hdr.ah->frags[f].offset,
Andy Green566eb432015-12-15 22:59:23 +0800399 wsi->u.hdr.ah->frags[f].len);
400 dst[wsi->u.hdr.ah->frags[f].len] = '\0';
401
402 return wsi->u.hdr.ah->frags[f].len;
403}
404
Andy Green0c7e5a92015-12-30 14:53:50 +0800405/**
406 * lws_hdr_copy: copy a single fragment of the given header to a buffer
407 * The buffer length @len must include space for an additional
408 * terminating '\0', or it will fail returning -1.
409 *
410 * @wsi: websocket connection
411 * @dst: destination buffer
412 * @len: length of destination buffer
413 * @h: which header index we are interested in
414 */
415
Andy Green6b5de702015-12-15 21:15:58 +0800416LWS_VISIBLE int lws_hdr_copy(struct lws *wsi, char *dst, int len,
Andy Green5c9660d2015-12-04 11:30:53 +0800417 enum lws_token_indexes h)
Andy Green16ab3182013-02-10 18:02:31 +0800418{
419 int toklen = lws_hdr_total_length(wsi, h);
420 int n;
421
422 if (toklen >= len)
423 return -1;
424
425 n = wsi->u.hdr.ah->frag_index[h];
Andy Green2c24ec02014-04-02 19:45:42 +0800426 if (!n)
Andy Green16ab3182013-02-10 18:02:31 +0800427 return 0;
428
429 do {
Andy Green6b5de702015-12-15 21:15:58 +0800430 strcpy(dst, &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset]);
431 dst += wsi->u.hdr.ah->frags[n].len;
432 n = wsi->u.hdr.ah->frags[n].nfrag;
Andy Green16ab3182013-02-10 18:02:31 +0800433 } while (n);
434
435 return toklen;
436}
437
Andy Green4b85c1d2015-12-04 11:08:32 +0800438char *lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h)
Andy Green16ab3182013-02-10 18:02:31 +0800439{
440 int n;
441
442 n = wsi->u.hdr.ah->frag_index[h];
443 if (!n)
444 return NULL;
445
Andy Green3df58002015-12-25 12:44:12 +0800446 return wsi->u.hdr.ah->data + wsi->u.hdr.ah->frags[n].offset;
Andy Green16ab3182013-02-10 18:02:31 +0800447}
Andy Green6d1fcb72013-01-18 01:55:48 +0800448
Andy Green5a0e7862016-01-21 10:57:39 +0800449int LWS_WARN_UNUSED_RESULT
450lws_pos_in_bounds(struct lws *wsi)
451{
452 if (wsi->u.hdr.ah->pos < wsi->context->max_http_header_data)
453 return 0;
454
455 if (wsi->u.hdr.ah->pos == wsi->context->max_http_header_data) {
456 lwsl_err("Ran out of header data space\n");
457 return 1;
458 }
459
460 /*
461 * with these tests everywhere, it should never be able to exceed
462 * the limit, only meet the limit
463 */
464
465 lwsl_err("%s: pos %d, limit %d\n", __func__, wsi->u.hdr.ah->pos,
466 wsi->context->max_http_header_data);
467 assert(0);
468
469 return 1;
470}
471
472int LWS_WARN_UNUSED_RESULT
473lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s)
Andy Greene77fb802013-02-11 13:04:45 +0800474{
Andy Green6b5de702015-12-15 21:15:58 +0800475 wsi->u.hdr.ah->nfrag++;
476 if (wsi->u.hdr.ah->nfrag == ARRAY_SIZE(wsi->u.hdr.ah->frags)) {
Andy Greenb5b23192013-02-11 17:13:32 +0800477 lwsl_warn("More hdr frags than we can deal with, dropping\n");
Andy Greene77fb802013-02-11 13:04:45 +0800478 return -1;
479 }
480
Andy Green6b5de702015-12-15 21:15:58 +0800481 wsi->u.hdr.ah->frag_index[h] = wsi->u.hdr.ah->nfrag;
Andy Greene77fb802013-02-11 13:04:45 +0800482
Andy Green6b5de702015-12-15 21:15:58 +0800483 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].offset = wsi->u.hdr.ah->pos;
484 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len = 0;
485 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].nfrag = 0;
Andy Greene77fb802013-02-11 13:04:45 +0800486
487 do {
Andy Green5a0e7862016-01-21 10:57:39 +0800488 if (lws_pos_in_bounds(wsi))
Andy Greene77fb802013-02-11 13:04:45 +0800489 return -1;
Andy Green5a0e7862016-01-21 10:57:39 +0800490
Andy Greene77fb802013-02-11 13:04:45 +0800491 wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = *s;
492 if (*s)
Andy Green6b5de702015-12-15 21:15:58 +0800493 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len++;
Andy Greene77fb802013-02-11 13:04:45 +0800494 } while (*s++);
495
496 return 0;
497}
498
Andy Green2a5774e2015-03-30 18:56:52 +0800499static signed char char_to_hex(const char c)
Andy Greenb1a9e502013-11-10 15:15:21 +0800500{
501 if (c >= '0' && c <= '9')
502 return c - '0';
503
504 if (c >= 'a' && c <= 'f')
505 return c - 'a' + 10;
506
507 if (c >= 'A' && c <= 'F')
508 return c - 'A' + 10;
509
510 return -1;
511}
512
Andy Greene99a83c2016-01-20 16:56:06 +0800513static int LWS_WARN_UNUSED_RESULT
514issue_char(struct lws *wsi, unsigned char c)
Andy Greenb1a9e502013-11-10 15:15:21 +0800515{
Andrew Canadayffe64562015-11-29 19:26:01 +0800516 unsigned short frag_len;
Andy Green6b5de702015-12-15 21:15:58 +0800517
Andy Green5a0e7862016-01-21 10:57:39 +0800518 if (lws_pos_in_bounds(wsi))
Andy Greenb1a9e502013-11-10 15:15:21 +0800519 return -1;
Andrew Canaday74b4a652014-06-29 00:25:19 -0400520
Andy Green6b5de702015-12-15 21:15:58 +0800521 frag_len = wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len;
522 /*
523 * If we haven't hit the token limit, just copy the character into
524 * the header
525 */
526 if (frag_len < wsi->u.hdr.current_token_limit) {
Andrew Canaday4cfc42c2015-11-29 19:24:04 +0800527 wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = c;
528 if (c)
Andy Green6b5de702015-12-15 21:15:58 +0800529 wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len++;
Andrew Canaday4cfc42c2015-11-29 19:24:04 +0800530 return 0;
531 }
Andy Green6b5de702015-12-15 21:15:58 +0800532
533 /* Insert a null character when we *hit* the limit: */
534 if (frag_len == wsi->u.hdr.current_token_limit) {
Andy Green5a0e7862016-01-21 10:57:39 +0800535 if (lws_pos_in_bounds(wsi))
Andy Greenbc401292016-01-20 07:40:13 +0800536 return -1;
Andy Green6b5de702015-12-15 21:15:58 +0800537 wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = '\0';
Andy Green3df58002015-12-25 12:44:12 +0800538 lwsl_warn("header %i exceeds limit %d\n",
Andy Green2c218e72016-02-15 12:37:04 +0800539 wsi->u.hdr.parser_state,
540 wsi->u.hdr.current_token_limit);
Andy Green6b5de702015-12-15 21:15:58 +0800541 }
542
Andrew Canaday4cfc42c2015-11-29 19:24:04 +0800543 return 1;
Andy Greenb1a9e502013-11-10 15:15:21 +0800544}
545
Andy Greene99a83c2016-01-20 16:56:06 +0800546int LWS_WARN_UNUSED_RESULT
547lws_parse(struct lws *wsi, unsigned char c)
Andy Green7c212cc2010-11-08 20:20:42 +0000548{
Quinlan Pfiffer49f72aa2015-01-10 19:01:52 -0800549 static const unsigned char methods[] = {
550 WSI_TOKEN_GET_URI,
551 WSI_TOKEN_POST_URI,
552 WSI_TOKEN_OPTIONS_URI,
553 WSI_TOKEN_PUT_URI,
554 WSI_TOKEN_PATCH_URI,
555 WSI_TOKEN_DELETE_URI,
556 };
Andy Green6b5de702015-12-15 21:15:58 +0800557 struct allocated_headers *ah = wsi->u.hdr.ah;
558 struct lws_context *context = wsi->context;
Andy Green38f32252015-12-14 19:42:26 +0800559 unsigned int n, m, enc = 0;
Andy Green7c212cc2010-11-08 20:20:42 +0000560
Andy Green8c1f6022016-01-26 20:56:56 +0800561 assert(wsi->u.hdr.ah);
562
Andy Green623a98d2013-01-21 11:04:23 +0800563 switch (wsi->u.hdr.parser_state) {
Andy Greenb08cb502014-09-30 16:33:56 +0800564 default:
Andy Greena41314f2011-05-23 10:00:03 +0100565
Andy Greenb5b23192013-02-11 17:13:32 +0800566 lwsl_parser("WSI_TOK_(%d) '%c'\n", wsi->u.hdr.parser_state, c);
Andy Green7c212cc2010-11-08 20:20:42 +0000567
568 /* collect into malloc'd buffers */
Andy Green16ab3182013-02-10 18:02:31 +0800569 /* optional initial space swallow */
Andy Green5a0e7862016-01-21 10:57:39 +0800570 if (!ah->frags[ah->frag_index[wsi->u.hdr.parser_state]].len &&
571 c == ' ')
Andy Green7c212cc2010-11-08 20:20:42 +0000572 break;
Andy Greene77ddd82010-11-13 10:03:47 +0000573
Quinlan Pfiffer49f72aa2015-01-10 19:01:52 -0800574 for (m = 0; m < ARRAY_SIZE(methods); m++)
575 if (wsi->u.hdr.parser_state == methods[m])
576 break;
577 if (m == ARRAY_SIZE(methods))
578 /* it was not any of the methods */
Andy Greenb1a9e502013-11-10 15:15:21 +0800579 goto check_eol;
580
581 /* special URI processing... end at space */
582
583 if (c == ' ') {
584 /* enforce starting with / */
Andy Green6b5de702015-12-15 21:15:58 +0800585 if (!ah->frags[ah->nfrag].len)
Andrew Canaday18fd4f62014-06-29 01:34:24 -0400586 if (issue_char(wsi, '/') < 0)
Andy Greenb1a9e502013-11-10 15:15:21 +0800587 return -1;
Andrew Canadayafe26cf2014-07-13 01:07:36 -0400588
589 /* begin parsing HTTP version: */
590 if (issue_char(wsi, '\0') < 0)
591 return -1;
592 wsi->u.hdr.parser_state = WSI_TOKEN_HTTP;
593 goto start_fragment;
Andy Green7c212cc2010-11-08 20:20:42 +0000594 }
595
Andy Greenb1a9e502013-11-10 15:15:21 +0800596 /* special URI processing... convert %xx */
597
598 switch (wsi->u.hdr.ues) {
599 case URIES_IDLE:
600 if (c == '%') {
601 wsi->u.hdr.ues = URIES_SEEN_PERCENT;
602 goto swallow;
603 }
604 break;
605 case URIES_SEEN_PERCENT:
606 if (char_to_hex(c) < 0) {
607 /* regurgitate */
Andrew Canaday18fd4f62014-06-29 01:34:24 -0400608 if (issue_char(wsi, '%') < 0)
Andy Greenb1a9e502013-11-10 15:15:21 +0800609 return -1;
610 wsi->u.hdr.ues = URIES_IDLE;
611 /* continue on to assess c */
612 break;
613 }
614 wsi->u.hdr.esc_stash = c;
615 wsi->u.hdr.ues = URIES_SEEN_PERCENT_H1;
Andy Green6f429102013-11-11 06:14:52 +0800616 goto swallow;
Andy Green40110e82015-12-14 08:52:03 +0800617
Andy Greenb1a9e502013-11-10 15:15:21 +0800618 case URIES_SEEN_PERCENT_H1:
619 if (char_to_hex(c) < 0) {
620 /* regurgitate */
Andy Greene99a83c2016-01-20 16:56:06 +0800621 if (issue_char(wsi, '%') < 0)
622 return -1;
Andy Greenb1a9e502013-11-10 15:15:21 +0800623 wsi->u.hdr.ues = URIES_IDLE;
624 /* regurgitate + assess */
Andy Green6b5de702015-12-15 21:15:58 +0800625 if (lws_parse(wsi, wsi->u.hdr.esc_stash) < 0)
Andy Greenb1a9e502013-11-10 15:15:21 +0800626 return -1;
627 /* continue on to assess c */
628 break;
629 }
630 c = (char_to_hex(wsi->u.hdr.esc_stash) << 4) |
631 char_to_hex(c);
Andy Green38f32252015-12-14 19:42:26 +0800632 enc = 1;
Andy Green6f429102013-11-11 06:14:52 +0800633 wsi->u.hdr.ues = URIES_IDLE;
Andy Greenb1a9e502013-11-10 15:15:21 +0800634 break;
635 }
636
637 /*
Andy Green40110e82015-12-14 08:52:03 +0800638 * special URI processing...
Andy Green6f429102013-11-11 06:14:52 +0800639 * convert /.. or /... or /../ etc to /
640 * convert /./ to /
Andy Greenb1a9e502013-11-10 15:15:21 +0800641 * convert // or /// etc to /
642 * leave /.dir or whatever alone
643 */
644
645 switch (wsi->u.hdr.ups) {
646 case URIPS_IDLE:
Andy Greenbc401292016-01-20 07:40:13 +0800647 if (!c)
648 return -1;
Andy Green4eb36372015-12-15 22:57:19 +0800649 /* genuine delimiter */
Andy Green03d7e9d2015-12-18 15:20:09 +0800650 if ((c == '&' || c == ';') && !enc) {
Andy Greenbc401292016-01-20 07:40:13 +0800651 if (issue_char(wsi, c) < 0)
652 return -1;
Andy Green4eb36372015-12-15 22:57:19 +0800653 /* swallow the terminator */
654 ah->frags[ah->nfrag].len--;
655 /* link to next fragment */
656 ah->frags[ah->nfrag].nfrag = ah->nfrag + 1;
657 ah->nfrag++;
658 if (ah->nfrag >= ARRAY_SIZE(ah->frags))
659 goto excessive;
660 /* start next fragment after the & */
Andy Green3ba035d2015-12-18 15:40:03 +0800661 wsi->u.hdr.post_literal_equal = 0;
Andy Green4eb36372015-12-15 22:57:19 +0800662 ah->frags[ah->nfrag].offset = ah->pos;
663 ah->frags[ah->nfrag].len = 0;
664 ah->frags[ah->nfrag].nfrag = 0;
665 goto swallow;
666 }
Andy Green3ba035d2015-12-18 15:40:03 +0800667 /* uriencoded = in the name part, disallow */
668 if (c == '=' && enc && !wsi->u.hdr.post_literal_equal)
669 c = '_';
670
671 /* after the real =, we don't care how many = */
672 if (c == '=' && !enc)
673 wsi->u.hdr.post_literal_equal = 1;
674
Andy Green8b9fe992015-12-18 15:23:31 +0800675 /* + to space */
676 if (c == '+' && !enc)
677 c = ' ';
Andy Greenb1a9e502013-11-10 15:15:21 +0800678 /* issue the first / always */
Andy Green4eb36372015-12-15 22:57:19 +0800679 if (c == '/' && !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS])
Andy Greenb1a9e502013-11-10 15:15:21 +0800680 wsi->u.hdr.ups = URIPS_SEEN_SLASH;
681 break;
682 case URIPS_SEEN_SLASH:
683 /* swallow subsequent slashes */
684 if (c == '/')
685 goto swallow;
686 /* track and swallow the first . after / */
687 if (c == '.') {
688 wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT;
689 goto swallow;
Andy Green4b812fe2014-08-19 18:34:31 +0800690 }
691 wsi->u.hdr.ups = URIPS_IDLE;
Andy Greenb1a9e502013-11-10 15:15:21 +0800692 break;
693 case URIPS_SEEN_SLASH_DOT:
694 /* swallow second . */
695 if (c == '.') {
Andy Green40110e82015-12-14 08:52:03 +0800696 /*
Andy Greend3f68732013-11-13 06:53:21 +0800697 * back up one dir level if possible
698 * safe against header fragmentation because
699 * the method URI can only be in 1 fragment
700 */
Andy Green6b5de702015-12-15 21:15:58 +0800701 if (ah->frags[ah->nfrag].len > 2) {
702 ah->pos--;
703 ah->frags[ah->nfrag].len--;
Andy Greend3f68732013-11-13 06:53:21 +0800704 do {
Andy Green6b5de702015-12-15 21:15:58 +0800705 ah->pos--;
706 ah->frags[ah->nfrag].len--;
707 } while (ah->frags[ah->nfrag].len > 1 &&
708 ah->data[ah->pos] != '/');
Andy Greend3f68732013-11-13 06:53:21 +0800709 }
Andy Greenb1a9e502013-11-10 15:15:21 +0800710 wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT_DOT;
711 goto swallow;
712 }
Andy Green6f429102013-11-11 06:14:52 +0800713 /* change /./ to / */
714 if (c == '/') {
715 wsi->u.hdr.ups = URIPS_SEEN_SLASH;
716 goto swallow;
717 }
Andy Greenb1a9e502013-11-10 15:15:21 +0800718 /* it was like /.dir ... regurgitate the . */
719 wsi->u.hdr.ups = URIPS_IDLE;
Andy Green4eb36372015-12-15 22:57:19 +0800720 if (issue_char(wsi, '.') < 0)
721 return -1;
Andy Greenb1a9e502013-11-10 15:15:21 +0800722 break;
Andy Green40110e82015-12-14 08:52:03 +0800723
Andy Greenb1a9e502013-11-10 15:15:21 +0800724 case URIPS_SEEN_SLASH_DOT_DOT:
725 /* swallow prior .. chars and any subsequent . */
726 if (c == '.')
727 goto swallow;
Andy Green6f429102013-11-11 06:14:52 +0800728 /* last issued was /, so another / == // */
729 if (c == '/')
730 goto swallow;
Andy Green4b812fe2014-08-19 18:34:31 +0800731 /* last we issued was / so SEEN_SLASH */
732 wsi->u.hdr.ups = URIPS_SEEN_SLASH;
Andy Greenb1a9e502013-11-10 15:15:21 +0800733 break;
734 }
735
Andy Green4eb36372015-12-15 22:57:19 +0800736 if (c == '?' && !enc &&
737 !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS]) { /* start of URI arguments */
Andy Green1e3f7b82013-11-13 07:45:17 +0800738 /* seal off uri header */
Andy Greenbc401292016-01-20 07:40:13 +0800739 if (issue_char(wsi, '\0') < 0)
740 return -1;
Andy Green1e3f7b82013-11-13 07:45:17 +0800741
742 /* move to using WSI_TOKEN_HTTP_URI_ARGS */
Andy Green6b5de702015-12-15 21:15:58 +0800743 ah->nfrag++;
Andy Green4eb36372015-12-15 22:57:19 +0800744 if (ah->nfrag >= ARRAY_SIZE(ah->frags))
745 goto excessive;
Andy Green6b5de702015-12-15 21:15:58 +0800746 ah->frags[ah->nfrag].offset = ah->pos;
747 ah->frags[ah->nfrag].len = 0;
748 ah->frags[ah->nfrag].nfrag = 0;
Andy Green1e3f7b82013-11-13 07:45:17 +0800749
Andy Green3ba035d2015-12-18 15:40:03 +0800750 wsi->u.hdr.post_literal_equal = 0;
Andy Green6b5de702015-12-15 21:15:58 +0800751 ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] = ah->nfrag;
Andy Greenf35801b2015-12-15 23:05:23 +0800752 wsi->u.hdr.ups = URIPS_IDLE;
Andy Green1e3f7b82013-11-13 07:45:17 +0800753 goto swallow;
754 }
755
Andrew Canaday991f1cd2014-07-19 06:58:53 +0800756check_eol:
757
758 /* bail at EOL */
759 if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE &&
Andy Green2c218e72016-02-15 12:37:04 +0800760 c == '\x0d') {
Andrew Canaday991f1cd2014-07-19 06:58:53 +0800761 c = '\0';
762 wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
763 lwsl_parser("*\n");
764 }
765
Andy Green4b812fe2014-08-19 18:34:31 +0800766 n = issue_char(wsi, c);
Andy Green2cd30742015-11-02 13:10:33 +0800767 if ((int)n < 0)
Andy Green4b812fe2014-08-19 18:34:31 +0800768 return -1;
769 if (n > 0)
770 wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
771
Andy Greenb1a9e502013-11-10 15:15:21 +0800772swallow:
Andy Greend1b11e32011-01-18 15:39:02 +0000773 /* per-protocol end of headers management */
Andy Greene77ddd82010-11-13 10:03:47 +0000774
Andy Green16ab3182013-02-10 18:02:31 +0800775 if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
776 goto set_parsing_complete;
Andy Greena41314f2011-05-23 10:00:03 +0100777 break;
778
Andy Green7c212cc2010-11-08 20:20:42 +0000779 /* collecting and checking a name part */
780 case WSI_TOKEN_NAME_PART:
Andy Green8fb338f2015-04-07 08:19:30 +0800781 lwsl_parser("WSI_TOKEN_NAME_PART '%c' (mode=%d)\n", c, wsi->mode);
Andy Green7c212cc2010-11-08 20:20:42 +0000782
Andy Greenb5b23192013-02-11 17:13:32 +0800783 wsi->u.hdr.lextable_pos =
784 lextable_decode(wsi->u.hdr.lextable_pos, c);
Andy Green8fb338f2015-04-07 08:19:30 +0800785 /*
786 * Server needs to look out for unknown methods...
787 */
788 if (wsi->u.hdr.lextable_pos < 0 &&
Andy Green54806b12015-12-17 17:03:59 +0800789 wsi->mode == LWSCM_HTTP_SERVING) {
Andy Greene4dffc92013-02-04 09:24:18 +0800790 /* this is not a header we know about */
Quinlan Pfiffer49f72aa2015-01-10 19:01:52 -0800791 for (m = 0; m < ARRAY_SIZE(methods); m++)
Andy Green6b5de702015-12-15 21:15:58 +0800792 if (ah->frag_index[methods[m]]) {
Quinlan Pfiffer49f72aa2015-01-10 19:01:52 -0800793 /*
794 * already had the method, no idea what
Andy Green8fb338f2015-04-07 08:19:30 +0800795 * this crap from the client is, ignore
Quinlan Pfiffer49f72aa2015-01-10 19:01:52 -0800796 */
797 wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
798 break;
799 }
Andy Green3ee9b312013-02-12 12:52:39 +0800800 /*
Andy Green8fb338f2015-04-07 08:19:30 +0800801 * hm it's an unknown http method from a client in fact,
Andy Green3ee9b312013-02-12 12:52:39 +0800802 * treat as dangerous
803 */
Drew Noakes2121e8a2015-01-30 12:04:43 +0000804 if (m == ARRAY_SIZE(methods)) {
805 lwsl_info("Unknown method - dropping\n");
806 return -1;
807 }
808 break;
Andy Greene4dffc92013-02-04 09:24:18 +0800809 }
Andy Green8fb338f2015-04-07 08:19:30 +0800810 /*
811 * ...otherwise for a client, let him ignore unknown headers
812 * coming from the server
813 */
814 if (wsi->u.hdr.lextable_pos < 0) {
815 wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
816 break;
817 }
818
Andy Greenbbc5c072014-03-09 11:49:21 +0800819 if (lextable[wsi->u.hdr.lextable_pos] < FAIL_CHAR) {
Andy Greene4dffc92013-02-04 09:24:18 +0800820 /* terminal state */
821
Andy Green59800b72014-11-30 12:36:09 +0800822 n = ((unsigned int)lextable[wsi->u.hdr.lextable_pos] << 8) |
823 lextable[wsi->u.hdr.lextable_pos + 1];
Andy Green6d1fcb72013-01-18 01:55:48 +0800824
Andy Greencc7cb682013-02-18 10:22:42 +0800825 lwsl_parser("known hdr %d\n", n);
Quinlan Pfiffer49f72aa2015-01-10 19:01:52 -0800826 for (m = 0; m < ARRAY_SIZE(methods); m++)
827 if (n == methods[m] &&
Andy Green8c1f6022016-01-26 20:56:56 +0800828 ah->frag_index[methods[m]]) {
Quinlan Pfiffer49f72aa2015-01-10 19:01:52 -0800829 lwsl_warn("Duplicated method\n");
830 return -1;
831 }
Andy Green94f94652013-02-12 13:10:19 +0800832
Andy Greenfd963302012-04-03 17:02:20 +0200833 /*
834 * WSORIGIN is protocol equiv to ORIGIN,
835 * JWebSocket likes to send it, map to ORIGIN
836 */
837 if (n == WSI_TOKEN_SWORIGIN)
838 n = WSI_TOKEN_ORIGIN;
839
Andy Green16ab3182013-02-10 18:02:31 +0800840 wsi->u.hdr.parser_state = (enum lws_token_indexes)
841 (WSI_TOKEN_GET_URI + n);
Andrew Canaday18fd4f62014-06-29 01:34:24 -0400842
Andy Greenf012f752014-08-22 19:38:17 +0800843 if (context->token_limits)
844 wsi->u.hdr.current_token_limit =
Andy Green6b5de702015-12-15 21:15:58 +0800845 context->token_limits->token_limit[
846 wsi->u.hdr.parser_state];
Andy Greenf012f752014-08-22 19:38:17 +0800847 else
Andy Green3df58002015-12-25 12:44:12 +0800848 wsi->u.hdr.current_token_limit =
849 wsi->context->max_http_header_data;
Andrew Canaday18fd4f62014-06-29 01:34:24 -0400850
Andy Green16ab3182013-02-10 18:02:31 +0800851 if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
852 goto set_parsing_complete;
Andy Green6964bb52011-01-23 16:50:33 +0000853
Andy Green16ab3182013-02-10 18:02:31 +0800854 goto start_fragment;
855 }
856 break;
Nick Dowell30592632012-04-05 10:31:48 +0800857
Andy Green16ab3182013-02-10 18:02:31 +0800858start_fragment:
Andy Green6b5de702015-12-15 21:15:58 +0800859 ah->nfrag++;
Andy Green4eb36372015-12-15 22:57:19 +0800860excessive:
Andy Green6b5de702015-12-15 21:15:58 +0800861 if (ah->nfrag == ARRAY_SIZE(ah->frags)) {
Andy Greenb5b23192013-02-11 17:13:32 +0800862 lwsl_warn("More hdr frags than we can deal with\n");
Andy Green16ab3182013-02-10 18:02:31 +0800863 return -1;
Andy Green7c212cc2010-11-08 20:20:42 +0000864 }
865
Andy Green6b5de702015-12-15 21:15:58 +0800866 ah->frags[ah->nfrag].offset = ah->pos;
867 ah->frags[ah->nfrag].len = 0;
Andy Green5a0e7862016-01-21 10:57:39 +0800868 ah->frags[ah->nfrag].nfrag = 0;
Andy Green16ab3182013-02-10 18:02:31 +0800869
Andy Green6b5de702015-12-15 21:15:58 +0800870 n = ah->frag_index[wsi->u.hdr.parser_state];
Andy Green16ab3182013-02-10 18:02:31 +0800871 if (!n) { /* first fragment */
Andy Green6b5de702015-12-15 21:15:58 +0800872 ah->frag_index[wsi->u.hdr.parser_state] = ah->nfrag;
Andy Greencc13c6f2013-11-09 10:09:09 +0800873 break;
874 }
875 /* continuation */
Andy Green6b5de702015-12-15 21:15:58 +0800876 while (ah->frags[n].nfrag)
Andy Green5a0e7862016-01-21 10:57:39 +0800877 n = ah->frags[n].nfrag;
Andy Green6b5de702015-12-15 21:15:58 +0800878 ah->frags[n].nfrag = ah->nfrag;
Andy Green16ab3182013-02-10 18:02:31 +0800879
Andy Greenbc401292016-01-20 07:40:13 +0800880 if (issue_char(wsi, ' ') < 0)
Andy Greencc13c6f2013-11-09 10:09:09 +0800881 return -1;
Andy Greene4dffc92013-02-04 09:24:18 +0800882 break;
Andy Greene77ddd82010-11-13 10:03:47 +0000883
Andy Green7c212cc2010-11-08 20:20:42 +0000884 /* skipping arg part of a name we didn't recognize */
885 case WSI_TOKEN_SKIPPING:
Andy Green43db0452013-01-10 19:50:35 +0800886 lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c);
kapejodce64fb02013-11-19 13:38:16 +0100887
Andy Green7c212cc2010-11-08 20:20:42 +0000888 if (c == '\x0d')
Andy Green623a98d2013-01-21 11:04:23 +0800889 wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
Andy Green7c212cc2010-11-08 20:20:42 +0000890 break;
Andy Green177ca782013-02-04 09:09:19 +0800891
Andy Green7c212cc2010-11-08 20:20:42 +0000892 case WSI_TOKEN_SKIPPING_SAW_CR:
Andy Green43db0452013-01-10 19:50:35 +0800893 lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
Andy Green6d1fcb72013-01-18 01:55:48 +0800894 if (c == '\x0a') {
Andy Green623a98d2013-01-21 11:04:23 +0800895 wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
896 wsi->u.hdr.lextable_pos = 0;
Andy Green6d1fcb72013-01-18 01:55:48 +0800897 } else
Andy Green623a98d2013-01-21 11:04:23 +0800898 wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
Andy Green7c212cc2010-11-08 20:20:42 +0000899 break;
900 /* we're done, ignore anything else */
kapejodce64fb02013-11-19 13:38:16 +0100901
Andy Green7c212cc2010-11-08 20:20:42 +0000902 case WSI_PARSING_COMPLETE:
Andy Green43db0452013-01-10 19:50:35 +0800903 lwsl_parser("WSI_PARSING_COMPLETE '%c'\n", c);
Andy Green7c212cc2010-11-08 20:20:42 +0000904 break;
Andy Green7c212cc2010-11-08 20:20:42 +0000905 }
Andy Greene77ddd82010-11-13 10:03:47 +0000906
Andy Green7c212cc2010-11-08 20:20:42 +0000907 return 0;
Andy Green177ca782013-02-04 09:09:19 +0800908
909set_parsing_complete:
910
Andy Green16ab3182013-02-10 18:02:31 +0800911 if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
Andy Greenb5b23192013-02-11 17:13:32 +0800912 if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
Andy Green2b57a342013-02-06 15:15:25 +0900913 wsi->ietf_spec_revision =
Andy Green16ab3182013-02-10 18:02:31 +0800914 atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
Andy Green177ca782013-02-04 09:09:19 +0800915
Andy Greenb5b23192013-02-11 17:13:32 +0800916 lwsl_parser("v%02d hdrs completed\n", wsi->ietf_spec_revision);
Andy Green2b57a342013-02-06 15:15:25 +0900917 }
Andy Green177ca782013-02-04 09:09:19 +0800918 wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE;
Andy Green224149a2013-02-11 21:43:41 +0800919 wsi->hdr_parsing_completed = 1;
Andy Green177ca782013-02-04 09:09:19 +0800920
921 return 0;
Andy Green7c212cc2010-11-08 20:20:42 +0000922}
923
Andy Greenbfb051f2011-02-09 08:49:14 +0000924
Andy Green2fd3f2f2013-01-18 09:49:20 +0800925/**
926 * lws_frame_is_binary: true if the current frame was sent in binary mode
927 *
928 * @wsi: the connection we are inquiring about
929 *
930 * This is intended to be called from the LWS_CALLBACK_RECEIVE callback if
931 * it's interested to see if the frame it's dealing with was sent in binary
932 * mode.
933 */
934
Andy Green4b85c1d2015-12-04 11:08:32 +0800935LWS_VISIBLE int lws_frame_is_binary(struct lws *wsi)
Andy Green2fd3f2f2013-01-18 09:49:20 +0800936{
Andy Green623a98d2013-01-21 11:04:23 +0800937 return wsi->u.ws.frame_is_binary;
Andy Green2fd3f2f2013-01-18 09:49:20 +0800938}
Andy Greenbfb051f2011-02-09 08:49:14 +0000939
Andy Greena41314f2011-05-23 10:00:03 +0100940int
Andy Green4b85c1d2015-12-04 11:08:32 +0800941lws_rx_sm(struct lws *wsi, unsigned char c)
Andy Green7c212cc2010-11-08 20:20:42 +0000942{
Andy Greend3a55052016-01-19 03:34:24 +0800943 struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
John Tarlton05fc6ba2015-10-05 11:35:52 +0100944 int callback_action = LWS_CALLBACK_RECEIVE;
Andy Green1b2c9a22016-01-29 21:18:54 +0800945 int ret = 0, n, rx_draining_ext = 0;
946 struct lws_tokens eff_buf;
947
Andy Green67112662016-01-11 11:34:01 +0800948 if (wsi->socket_is_permanently_unusable)
949 return -1;
Andy Green7c212cc2010-11-08 20:20:42 +0000950
951 switch (wsi->lws_rx_parse_state) {
952 case LWS_RXPS_NEW:
Andy Green67112662016-01-11 11:34:01 +0800953 if (wsi->u.ws.rx_draining_ext) {
Andy Greend3a55052016-01-19 03:34:24 +0800954 struct lws **w = &pt->rx_draining_ext_list;
Andy Greene77ddd82010-11-13 10:03:47 +0000955
Andy Green67112662016-01-11 11:34:01 +0800956 eff_buf.token = NULL;
957 eff_buf.token_len = 0;
958 wsi->u.ws.rx_draining_ext = 0;
959 /* remove us from context draining ext list */
960 while (*w) {
961 if (*w == wsi) {
962 *w = wsi->u.ws.rx_draining_ext_list;
963 break;
964 }
965 w = &((*w)->u.ws.rx_draining_ext_list);
966 }
967 wsi->u.ws.rx_draining_ext_list = NULL;
968 rx_draining_ext = 1;
969 lwsl_err("%s: doing draining flow\n", __func__);
970
971 goto drain_extension;
972 }
Andy Green7c212cc2010-11-08 20:20:42 +0000973 switch (wsi->ietf_spec_revision) {
Andy Greend85cb202011-09-25 09:32:54 +0100974 case 13:
Andy Green283d0a22011-04-24 05:46:23 +0100975 /*
976 * no prepended frame key any more
977 */
Andy Green623a98d2013-01-21 11:04:23 +0800978 wsi->u.ws.all_zero_nonce = 1;
Andy Green283d0a22011-04-24 05:46:23 +0100979 goto handle_first;
980
Andy Greenbfb051f2011-02-09 08:49:14 +0000981 default:
Andy Greenb5b23192013-02-11 17:13:32 +0800982 lwsl_warn("lws_rx_sm: unknown spec version %d\n",
983 wsi->ietf_spec_revision);
Andy Greenbfb051f2011-02-09 08:49:14 +0000984 break;
Andy Green7c212cc2010-11-08 20:20:42 +0000985 }
Andy Green6452f1e2010-11-11 09:22:22 +0000986 break;
Andy Green67112662016-01-11 11:34:01 +0800987 case LWS_RXPS_04_mask_1:
988 wsi->u.ws.mask[1] = c;
Andy Green92970ba2011-02-10 09:22:35 +0000989 if (c)
Andy Green623a98d2013-01-21 11:04:23 +0800990 wsi->u.ws.all_zero_nonce = 0;
Andy Green67112662016-01-11 11:34:01 +0800991 wsi->lws_rx_parse_state = LWS_RXPS_04_mask_2;
Andy Green3e5eb782011-01-18 18:14:26 +0000992 break;
Andy Green67112662016-01-11 11:34:01 +0800993 case LWS_RXPS_04_mask_2:
994 wsi->u.ws.mask[2] = c;
Andy Green92970ba2011-02-10 09:22:35 +0000995 if (c)
Andy Green623a98d2013-01-21 11:04:23 +0800996 wsi->u.ws.all_zero_nonce = 0;
Andy Green67112662016-01-11 11:34:01 +0800997 wsi->lws_rx_parse_state = LWS_RXPS_04_mask_3;
Andy Green3e5eb782011-01-18 18:14:26 +0000998 break;
Andy Green67112662016-01-11 11:34:01 +0800999 case LWS_RXPS_04_mask_3:
1000 wsi->u.ws.mask[3] = c;
Andy Green92970ba2011-02-10 09:22:35 +00001001 if (c)
Andy Green623a98d2013-01-21 11:04:23 +08001002 wsi->u.ws.all_zero_nonce = 0;
Andy Green3e5eb782011-01-18 18:14:26 +00001003
Andy Green3e5eb782011-01-18 18:14:26 +00001004 /*
1005 * start from the zero'th byte in the XOR key buffer since
1006 * this is the start of a frame with a new key
1007 */
1008
Andy Green67112662016-01-11 11:34:01 +08001009 wsi->u.ws.mask_idx = 0;
Andy Green6964bb52011-01-23 16:50:33 +00001010
Andy Green3e5eb782011-01-18 18:14:26 +00001011 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
1012 break;
Andy Green38e57bb2011-01-19 12:20:27 +00001013
1014 /*
1015 * 04 logical framing from the spec (all this is masked when incoming
1016 * and has to be unmasked)
1017 *
1018 * We ignore the possibility of extension data because we don't
1019 * negotiate any extensions at the moment.
Andy Green6964bb52011-01-23 16:50:33 +00001020 *
Andy Green38e57bb2011-01-19 12:20:27 +00001021 * 0 1 2 3
1022 * 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
1023 * +-+-+-+-+-------+-+-------------+-------------------------------+
1024 * |F|R|R|R| opcode|R| Payload len | Extended payload length |
1025 * |I|S|S|S| (4) |S| (7) | (16/63) |
1026 * |N|V|V|V| |V| | (if payload len==126/127) |
1027 * | |1|2|3| |4| | |
1028 * +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
1029 * | Extended payload length continued, if payload len == 127 |
1030 * + - - - - - - - - - - - - - - - +-------------------------------+
1031 * | | Extension data |
1032 * +-------------------------------+ - - - - - - - - - - - - - - - +
1033 * : :
1034 * +---------------------------------------------------------------+
1035 * : Application data :
1036 * +---------------------------------------------------------------+
1037 *
1038 * We pass payload through to userland as soon as we get it, ignoring
1039 * FIN. It's up to userland to buffer it up if it wants to see a
1040 * whole unfragmented block of the original size (which may be up to
1041 * 2^63 long!)
1042 */
1043
1044 case LWS_RXPS_04_FRAME_HDR_1:
Andy Green283d0a22011-04-24 05:46:23 +01001045handle_first:
1046
Andy Green623a98d2013-01-21 11:04:23 +08001047 wsi->u.ws.opcode = c & 0xf;
1048 wsi->u.ws.rsv = c & 0x70;
1049 wsi->u.ws.final = !!((c >> 7) & 1);
Andy Green1bc12f92013-02-28 17:11:29 +08001050
Andy Green623a98d2013-01-21 11:04:23 +08001051 switch (wsi->u.ws.opcode) {
Andy Green54806b12015-12-17 17:03:59 +08001052 case LWSWSOPC_TEXT_FRAME:
1053 case LWSWSOPC_BINARY_FRAME:
Andy Green67112662016-01-11 11:34:01 +08001054 wsi->u.ws.rsv_first_msg = (c & 0x70);
Andy Greenb5b23192013-02-11 17:13:32 +08001055 wsi->u.ws.frame_is_binary =
Andy Green54806b12015-12-17 17:03:59 +08001056 wsi->u.ws.opcode == LWSWSOPC_BINARY_FRAME;
Andy Green10601c12013-01-19 10:39:35 +08001057 break;
Andy Green67112662016-01-11 11:34:01 +08001058 case 3:
1059 case 4:
1060 case 5:
1061 case 6:
1062 case 7:
1063 case 0xb:
1064 case 0xc:
1065 case 0xd:
1066 case 0xe:
1067 case 0xf:
1068 lwsl_info("illegal opcode\n");
1069 return -1;
Andy Green10601c12013-01-19 10:39:35 +08001070 }
Andy Green38e57bb2011-01-19 12:20:27 +00001071 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
1072 break;
1073
1074 case LWS_RXPS_04_FRAME_HDR_LEN:
Andy Green38e57bb2011-01-19 12:20:27 +00001075
Andy Green623a98d2013-01-21 11:04:23 +08001076 wsi->u.ws.this_frame_masked = !!(c & 0x80);
Andy Green283d0a22011-04-24 05:46:23 +01001077
Andy Green5bf65782011-09-25 10:46:31 +01001078 switch (c & 0x7f) {
Andy Green38e57bb2011-01-19 12:20:27 +00001079 case 126:
1080 /* control frames are not allowed to have big lengths */
Andy Green623a98d2013-01-21 11:04:23 +08001081 if (wsi->u.ws.opcode & 8)
Andy Green23545db2011-04-24 06:19:22 +01001082 goto illegal_ctl_length;
1083
Andy Green38e57bb2011-01-19 12:20:27 +00001084 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
1085 break;
1086 case 127:
1087 /* control frames are not allowed to have big lengths */
Andy Green623a98d2013-01-21 11:04:23 +08001088 if (wsi->u.ws.opcode & 8)
Andy Green23545db2011-04-24 06:19:22 +01001089 goto illegal_ctl_length;
1090
Andy Green38e57bb2011-01-19 12:20:27 +00001091 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
1092 break;
1093 default:
Andy Green623a98d2013-01-21 11:04:23 +08001094 wsi->u.ws.rx_packet_length = c & 0x7f;
1095 if (wsi->u.ws.this_frame_masked)
Andy Green283d0a22011-04-24 05:46:23 +01001096 wsi->lws_rx_parse_state =
1097 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
1098 else
Andy Green8ea19552014-02-15 16:00:37 +08001099 if (wsi->u.ws.rx_packet_length)
1100 wsi->lws_rx_parse_state =
Andy Green38e57bb2011-01-19 12:20:27 +00001101 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
Andy Green8ea19552014-02-15 16:00:37 +08001102 else {
1103 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
1104 goto spill;
1105 }
Andy Green38e57bb2011-01-19 12:20:27 +00001106 break;
1107 }
1108 break;
1109
1110 case LWS_RXPS_04_FRAME_HDR_LEN16_2:
Andy Green623a98d2013-01-21 11:04:23 +08001111 wsi->u.ws.rx_packet_length = c << 8;
Andy Green38e57bb2011-01-19 12:20:27 +00001112 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
1113 break;
1114
1115 case LWS_RXPS_04_FRAME_HDR_LEN16_1:
Andy Green623a98d2013-01-21 11:04:23 +08001116 wsi->u.ws.rx_packet_length |= c;
1117 if (wsi->u.ws.this_frame_masked)
Andy Green283d0a22011-04-24 05:46:23 +01001118 wsi->lws_rx_parse_state =
1119 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
1120 else
1121 wsi->lws_rx_parse_state =
1122 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
Andy Green38e57bb2011-01-19 12:20:27 +00001123 break;
1124
1125 case LWS_RXPS_04_FRAME_HDR_LEN64_8:
Andy Green38e57bb2011-01-19 12:20:27 +00001126 if (c & 0x80) {
Andy Green43db0452013-01-10 19:50:35 +08001127 lwsl_warn("b63 of length must be zero\n");
Andy Green38e57bb2011-01-19 12:20:27 +00001128 /* kill the connection */
1129 return -1;
1130 }
Andy Greenf55830d2011-01-27 06:45:53 +00001131#if defined __LP64__
Andy Green623a98d2013-01-21 11:04:23 +08001132 wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
Andy Greenf55830d2011-01-27 06:45:53 +00001133#else
Andy Green623a98d2013-01-21 11:04:23 +08001134 wsi->u.ws.rx_packet_length = 0;
Andy Greenf55830d2011-01-27 06:45:53 +00001135#endif
Andy Green38e57bb2011-01-19 12:20:27 +00001136 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
1137 break;
1138
1139 case LWS_RXPS_04_FRAME_HDR_LEN64_7:
Andy Greenf55830d2011-01-27 06:45:53 +00001140#if defined __LP64__
Andy Green623a98d2013-01-21 11:04:23 +08001141 wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
Andy Greenf55830d2011-01-27 06:45:53 +00001142#endif
Andy Green38e57bb2011-01-19 12:20:27 +00001143 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
1144 break;
1145
1146 case LWS_RXPS_04_FRAME_HDR_LEN64_6:
Andy Greenf55830d2011-01-27 06:45:53 +00001147#if defined __LP64__
Andy Green623a98d2013-01-21 11:04:23 +08001148 wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
Andy Greenf55830d2011-01-27 06:45:53 +00001149#endif
Andy Green38e57bb2011-01-19 12:20:27 +00001150 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
1151 break;
1152
1153 case LWS_RXPS_04_FRAME_HDR_LEN64_5:
Andy Greenf55830d2011-01-27 06:45:53 +00001154#if defined __LP64__
Andy Green623a98d2013-01-21 11:04:23 +08001155 wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
Andy Greenf55830d2011-01-27 06:45:53 +00001156#endif
Andy Green38e57bb2011-01-19 12:20:27 +00001157 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
1158 break;
1159
1160 case LWS_RXPS_04_FRAME_HDR_LEN64_4:
Andy Green623a98d2013-01-21 11:04:23 +08001161 wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
Andy Green38e57bb2011-01-19 12:20:27 +00001162 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
1163 break;
1164
1165 case LWS_RXPS_04_FRAME_HDR_LEN64_3:
Andy Green623a98d2013-01-21 11:04:23 +08001166 wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
Andy Green38e57bb2011-01-19 12:20:27 +00001167 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
1168 break;
1169
1170 case LWS_RXPS_04_FRAME_HDR_LEN64_2:
Andy Green623a98d2013-01-21 11:04:23 +08001171 wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
Andy Green38e57bb2011-01-19 12:20:27 +00001172 wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
1173 break;
1174
1175 case LWS_RXPS_04_FRAME_HDR_LEN64_1:
Andy Green623a98d2013-01-21 11:04:23 +08001176 wsi->u.ws.rx_packet_length |= ((size_t)c);
1177 if (wsi->u.ws.this_frame_masked)
Andy Green283d0a22011-04-24 05:46:23 +01001178 wsi->lws_rx_parse_state =
1179 LWS_RXPS_07_COLLECT_FRAME_KEY_1;
1180 else
1181 wsi->lws_rx_parse_state =
1182 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
Andy Green38e57bb2011-01-19 12:20:27 +00001183 break;
1184
Andy Green283d0a22011-04-24 05:46:23 +01001185 case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
Andy Green67112662016-01-11 11:34:01 +08001186 wsi->u.ws.mask[0] = c;
Andy Green283d0a22011-04-24 05:46:23 +01001187 if (c)
Andy Green623a98d2013-01-21 11:04:23 +08001188 wsi->u.ws.all_zero_nonce = 0;
Andy Green283d0a22011-04-24 05:46:23 +01001189 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
1190 break;
1191
1192 case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
Andy Green67112662016-01-11 11:34:01 +08001193 wsi->u.ws.mask[1] = c;
Andy Green283d0a22011-04-24 05:46:23 +01001194 if (c)
Andy Green623a98d2013-01-21 11:04:23 +08001195 wsi->u.ws.all_zero_nonce = 0;
Andy Green283d0a22011-04-24 05:46:23 +01001196 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
1197 break;
1198
1199 case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
Andy Green67112662016-01-11 11:34:01 +08001200 wsi->u.ws.mask[2] = c;
Andy Green283d0a22011-04-24 05:46:23 +01001201 if (c)
Andy Green623a98d2013-01-21 11:04:23 +08001202 wsi->u.ws.all_zero_nonce = 0;
Andy Green283d0a22011-04-24 05:46:23 +01001203 wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
1204 break;
1205
1206 case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
Andy Green67112662016-01-11 11:34:01 +08001207 wsi->u.ws.mask[3] = c;
Andy Green283d0a22011-04-24 05:46:23 +01001208 if (c)
Andy Green623a98d2013-01-21 11:04:23 +08001209 wsi->u.ws.all_zero_nonce = 0;
Andy Green283d0a22011-04-24 05:46:23 +01001210 wsi->lws_rx_parse_state =
1211 LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
Andy Green67112662016-01-11 11:34:01 +08001212 wsi->u.ws.mask_idx = 0;
Andy Green8ea19552014-02-15 16:00:37 +08001213 if (wsi->u.ws.rx_packet_length == 0) {
1214 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
Andy Green1bc12f92013-02-28 17:11:29 +08001215 goto spill;
Andy Green8ea19552014-02-15 16:00:37 +08001216 }
Andy Green283d0a22011-04-24 05:46:23 +01001217 break;
1218
1219
Andy Green7c212cc2010-11-08 20:20:42 +00001220 case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
Andy Green67112662016-01-11 11:34:01 +08001221 assert(wsi->u.ws.rx_ubuf);
Andy Green54495112013-02-06 21:10:16 +09001222
Andy Greend3a55052016-01-19 03:34:24 +08001223 if (wsi->u.ws.rx_ubuf_head + LWS_PRE >=
1224 wsi->u.ws.rx_ubuf_alloc) {
1225 lwsl_err("Attempted overflow \n");
1226 return -1;
1227 }
Andy Green623a98d2013-01-21 11:04:23 +08001228 if (wsi->u.ws.all_zero_nonce)
Andy Green67112662016-01-11 11:34:01 +08001229 wsi->u.ws.rx_ubuf[LWS_PRE +
Andy Greend3a55052016-01-19 03:34:24 +08001230 (wsi->u.ws.rx_ubuf_head++)] = c;
Andy Green92970ba2011-02-10 09:22:35 +00001231 else
Andy Green67112662016-01-11 11:34:01 +08001232 wsi->u.ws.rx_ubuf[LWS_PRE +
1233 (wsi->u.ws.rx_ubuf_head++)] =
1234 c ^ wsi->u.ws.mask[
1235 (wsi->u.ws.mask_idx++) & 3];
Andy Green4739e5c2011-01-22 12:51:57 +00001236
Andy Green623a98d2013-01-21 11:04:23 +08001237 if (--wsi->u.ws.rx_packet_length == 0) {
Andy Greenc2bb3dc2013-02-14 11:25:44 +08001238 /* spill because we have the whole frame */
Andy Green4739e5c2011-01-22 12:51:57 +00001239 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
1240 goto spill;
1241 }
Andy Greenc2bb3dc2013-02-14 11:25:44 +08001242
1243 /*
1244 * if there's no protocol max frame size given, we are
1245 * supposed to default to LWS_MAX_SOCKET_IO_BUF
1246 */
1247
1248 if (!wsi->protocol->rx_buffer_size &&
Andy Green67112662016-01-11 11:34:01 +08001249 wsi->u.ws.rx_ubuf_head !=
Andy Greenc2bb3dc2013-02-14 11:25:44 +08001250 LWS_MAX_SOCKET_IO_BUF)
Andy Green4739e5c2011-01-22 12:51:57 +00001251 break;
Andy Greenc2bb3dc2013-02-14 11:25:44 +08001252 else
1253 if (wsi->protocol->rx_buffer_size &&
Andy Green67112662016-01-11 11:34:01 +08001254 wsi->u.ws.rx_ubuf_head !=
Andy Greenc2bb3dc2013-02-14 11:25:44 +08001255 wsi->protocol->rx_buffer_size)
1256 break;
1257
1258 /* spill because we filled our rx buffer */
Andy Green4739e5c2011-01-22 12:51:57 +00001259spill:
1260 /*
1261 * is this frame a control packet we should take care of at this
1262 * layer? If so service it and hide it from the user callback
1263 */
1264
Andy Green43db0452013-01-10 19:50:35 +08001265 lwsl_parser("spill on %s\n", wsi->protocol->name);
Andy Greena41314f2011-05-23 10:00:03 +01001266
Andy Green623a98d2013-01-21 11:04:23 +08001267 switch (wsi->u.ws.opcode) {
Andy Green54806b12015-12-17 17:03:59 +08001268 case LWSWSOPC_CLOSE:
Andy Green066a7a12015-12-26 15:47:06 +08001269
Andy Greenda527df2011-03-07 07:08:12 +00001270 /* is this an acknowledgement of our close? */
Andy Green54806b12015-12-17 17:03:59 +08001271 if (wsi->state == LWSS_AWAITING_CLOSE_ACK) {
Andy Greenda527df2011-03-07 07:08:12 +00001272 /*
1273 * fine he has told us he is closing too, let's
1274 * finish our close
1275 */
Andy Green43db0452013-01-10 19:50:35 +08001276 lwsl_parser("seen client close ack\n");
Andy Greenda527df2011-03-07 07:08:12 +00001277 return -1;
1278 }
Andy Green54806b12015-12-17 17:03:59 +08001279 if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY)
Andy Green40d5abc2015-04-17 20:29:58 +08001280 /* if he sends us 2 CLOSE, kill him */
1281 return -1;
1282
Andy Green066a7a12015-12-26 15:47:06 +08001283 if (user_callback_handle_rxflow(
1284 wsi->protocol->callback, wsi,
1285 LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
1286 wsi->user_space,
Andy Greend3a55052016-01-19 03:34:24 +08001287 &wsi->u.ws.rx_ubuf[LWS_PRE],
Andy Green67112662016-01-11 11:34:01 +08001288 wsi->u.ws.rx_ubuf_head))
Andy Green066a7a12015-12-26 15:47:06 +08001289 return -1;
1290
Andy Green43db0452013-01-10 19:50:35 +08001291 lwsl_parser("server sees client close packet\n");
Andy Green54806b12015-12-17 17:03:59 +08001292 wsi->state = LWSS_RETURNED_CLOSE_ALREADY;
Andy Green40d5abc2015-04-17 20:29:58 +08001293 /* deal with the close packet contents as a PONG */
1294 wsi->u.ws.payload_is_close = 1;
1295 goto process_as_ping;
Andy Green4739e5c2011-01-22 12:51:57 +00001296
Andy Green54806b12015-12-17 17:03:59 +08001297 case LWSWSOPC_PING:
Andy Greenb5b23192013-02-11 17:13:32 +08001298 lwsl_info("received %d byte ping, sending pong\n",
Andy Green67112662016-01-11 11:34:01 +08001299 wsi->u.ws.rx_ubuf_head);
Andy Green82bac6b2014-08-24 14:39:19 +08001300
Andy Green2fd6e6f2015-03-24 21:07:01 +08001301 if (wsi->u.ws.ping_pending_flag) {
Andy Green40110e82015-12-14 08:52:03 +08001302 /*
Andy Green82bac6b2014-08-24 14:39:19 +08001303 * there is already a pending ping payload
1304 * we should just log and drop
1305 */
1306 lwsl_parser("DROP PING since one pending\n");
1307 goto ping_drop;
1308 }
Andy Green40d5abc2015-04-17 20:29:58 +08001309process_as_ping:
Andy Green82bac6b2014-08-24 14:39:19 +08001310 /* control packets can only be < 128 bytes long */
Andy Green67112662016-01-11 11:34:01 +08001311 if (wsi->u.ws.rx_ubuf_head > 128 - 3) {
Andy Green82bac6b2014-08-24 14:39:19 +08001312 lwsl_parser("DROP PING payload too large\n");
1313 goto ping_drop;
1314 }
Andy Green40110e82015-12-14 08:52:03 +08001315
Andy Green82bac6b2014-08-24 14:39:19 +08001316 /* stash the pong payload */
Andy Green67112662016-01-11 11:34:01 +08001317 memcpy(wsi->u.ws.ping_payload_buf + LWS_PRE,
1318 &wsi->u.ws.rx_ubuf[LWS_PRE],
1319 wsi->u.ws.rx_ubuf_head);
Andy Green40110e82015-12-14 08:52:03 +08001320
Andy Green67112662016-01-11 11:34:01 +08001321 wsi->u.ws.ping_payload_len = wsi->u.ws.rx_ubuf_head;
Andy Green2fd6e6f2015-03-24 21:07:01 +08001322 wsi->u.ws.ping_pending_flag = 1;
Andy Green40110e82015-12-14 08:52:03 +08001323
Andy Green82bac6b2014-08-24 14:39:19 +08001324 /* get it sent as soon as possible */
Andy Green11c05bf2015-12-16 18:19:08 +08001325 lws_callback_on_writable(wsi);
Andy Green82bac6b2014-08-24 14:39:19 +08001326ping_drop:
Andy Green67112662016-01-11 11:34:01 +08001327 wsi->u.ws.rx_ubuf_head = 0;
Andy Greena6cbece2011-01-27 20:06:03 +00001328 return 0;
Andy Green4739e5c2011-01-22 12:51:57 +00001329
Andy Green54806b12015-12-17 17:03:59 +08001330 case LWSWSOPC_PONG:
John Tarlton05fc6ba2015-10-05 11:35:52 +01001331 lwsl_info("received pong\n");
Andy Green67112662016-01-11 11:34:01 +08001332 lwsl_hexdump(&wsi->u.ws.rx_ubuf[LWS_PRE],
1333 wsi->u.ws.rx_ubuf_head);
John Tarlton05fc6ba2015-10-05 11:35:52 +01001334
1335 /* issue it */
1336 callback_action = LWS_CALLBACK_RECEIVE_PONG;
1337 break;
Andy Green4739e5c2011-01-22 12:51:57 +00001338
Andy Green54806b12015-12-17 17:03:59 +08001339 case LWSWSOPC_TEXT_FRAME:
1340 case LWSWSOPC_BINARY_FRAME:
1341 case LWSWSOPC_CONTINUATION:
Andy Green4739e5c2011-01-22 12:51:57 +00001342 break;
Andy Greena41314f2011-05-23 10:00:03 +01001343
1344 default:
Andy Greenb5b23192013-02-11 17:13:32 +08001345 lwsl_parser("passing opc %x up to exts\n",
Andy Greend3a55052016-01-19 03:34:24 +08001346 wsi->u.ws.opcode);
Andy Greena41314f2011-05-23 10:00:03 +01001347 /*
1348 * It's something special we can't understand here.
1349 * Pass the payload up to the extension's parsing
1350 * state machine.
1351 */
1352
Andy Green67112662016-01-11 11:34:01 +08001353 eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE];
1354 eff_buf.token_len = wsi->u.ws.rx_ubuf_head;
Andy Greena41314f2011-05-23 10:00:03 +01001355
Andy Green67112662016-01-11 11:34:01 +08001356 if (lws_ext_cb_active(wsi, LWS_EXT_CB_EXTENDED_PAYLOAD_RX,
Andy Green2c24ec02014-04-02 19:45:42 +08001357 &eff_buf, 0) <= 0) /* not handle or fail */
Andy Greenb5b23192013-02-11 17:13:32 +08001358 lwsl_ext("ext opc opcode 0x%x unknown\n",
1359 wsi->u.ws.opcode);
Andy Greena41314f2011-05-23 10:00:03 +01001360
Andy Green67112662016-01-11 11:34:01 +08001361 wsi->u.ws.rx_ubuf_head = 0;
Andy Greena41314f2011-05-23 10:00:03 +01001362 return 0;
Andy Green4739e5c2011-01-22 12:51:57 +00001363 }
1364
1365 /*
1366 * No it's real payload, pass it up to the user callback.
1367 * It's nicely buffered with the pre-padding taken care of
Andy Green62304762015-12-04 08:43:54 +08001368 * so it can be sent straight out again using lws_write
Andy Green4739e5c2011-01-22 12:51:57 +00001369 */
1370
Andy Green67112662016-01-11 11:34:01 +08001371 eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE];
1372 eff_buf.token_len = wsi->u.ws.rx_ubuf_head;
Andy Green40110e82015-12-14 08:52:03 +08001373
Andy Green67112662016-01-11 11:34:01 +08001374drain_extension:
1375 lwsl_ext("%s: passing %d to ext\n", __func__, eff_buf.token_len);
1376
1377 if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
1378 wsi->state == LWSS_AWAITING_CLOSE_ACK)
1379 goto already_done;
1380
1381 n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &eff_buf, 0);
1382 if (n < 0) {
1383 /*
1384 * we may rely on this to get RX, just drop connection
1385 */
1386 wsi->socket_is_permanently_unusable = 1;
Andy Green2c24ec02014-04-02 19:45:42 +08001387 return -1;
Andy Green67112662016-01-11 11:34:01 +08001388 }
1389
1390 if (rx_draining_ext && eff_buf.token_len == 0)
1391 goto already_done;
1392
1393 if (n && eff_buf.token_len) {
1394 /* extension had more... main loop will come back */
1395 wsi->u.ws.rx_draining_ext = 1;
Andy Greend3a55052016-01-19 03:34:24 +08001396 wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
1397 pt->rx_draining_ext_list = wsi;
Andy Green67112662016-01-11 11:34:01 +08001398 }
Andy Green2c24ec02014-04-02 19:45:42 +08001399
Andrejs Hanins765914c2015-12-01 14:44:33 +02001400 if (eff_buf.token_len > 0 ||
1401 callback_action == LWS_CALLBACK_RECEIVE_PONG) {
Andy Greenaedc9532013-02-10 21:21:24 +08001402 eff_buf.token[eff_buf.token_len] = '\0';
David Galeanoe2cf9922013-01-09 18:06:55 +08001403
John Tarlton05fc6ba2015-10-05 11:35:52 +01001404 if (wsi->protocol->callback) {
1405
1406 if (callback_action == LWS_CALLBACK_RECEIVE_PONG)
Andy Green67112662016-01-11 11:34:01 +08001407 lwsl_info("Doing pong callback\n");
John Tarlton05fc6ba2015-10-05 11:35:52 +01001408
Andy Greenb5b23192013-02-11 17:13:32 +08001409 ret = user_callback_handle_rxflow(
1410 wsi->protocol->callback,
John Tarlton05fc6ba2015-10-05 11:35:52 +01001411 wsi,
Andy Green4b85c1d2015-12-04 11:08:32 +08001412 (enum lws_callback_reasons)callback_action,
Andy Greenb5b23192013-02-11 17:13:32 +08001413 wsi->user_space,
1414 eff_buf.token,
1415 eff_buf.token_len);
John Tarlton05fc6ba2015-10-05 11:35:52 +01001416 }
1417 else
1418 lwsl_err("No callback on payload spill!\n");
David Galeanoe2cf9922013-01-09 18:06:55 +08001419 }
Andy Greena41314f2011-05-23 10:00:03 +01001420
Andy Green67112662016-01-11 11:34:01 +08001421already_done:
1422 wsi->u.ws.rx_ubuf_head = 0;
Andy Green4739e5c2011-01-22 12:51:57 +00001423 break;
1424 }
1425
Andy Greenaedc9532013-02-10 21:21:24 +08001426 return ret;
Andy Green23545db2011-04-24 06:19:22 +01001427
1428illegal_ctl_length:
1429
Andy Greenb5b23192013-02-11 17:13:32 +08001430 lwsl_warn("Control frame with xtended length is illegal\n");
Andy Green23545db2011-04-24 06:19:22 +01001431 /* kill the connection */
1432 return -1;
Andy Green4739e5c2011-01-22 12:51:57 +00001433}
1434
1435
Andy Green38e57bb2011-01-19 12:20:27 +00001436/**
Andy Green62304762015-12-04 08:43:54 +08001437 * lws_remaining_packet_payload() - Bytes to come before "overall"
Andy Green6964bb52011-01-23 16:50:33 +00001438 * rx packet is complete
Andy Green38e57bb2011-01-19 12:20:27 +00001439 * @wsi: Websocket instance (available from user callback)
1440 *
1441 * This function is intended to be called from the callback if the
1442 * user code is interested in "complete packets" from the client.
1443 * libwebsockets just passes through payload as it comes and issues a buffer
1444 * additionally when it hits a built-in limit. The LWS_CALLBACK_RECEIVE
1445 * callback handler can use this API to find out if the buffer it has just
1446 * been given is the last piece of a "complete packet" from the client --
Andy Green62304762015-12-04 08:43:54 +08001447 * when that is the case lws_remaining_packet_payload() will return
Andy Green38e57bb2011-01-19 12:20:27 +00001448 * 0.
1449 *
1450 * Many protocols won't care becuse their packets are always small.
1451 */
1452
Peter Pentchev9a4fef72013-03-30 09:52:21 +08001453LWS_VISIBLE size_t
Andy Green4b85c1d2015-12-04 11:08:32 +08001454lws_remaining_packet_payload(struct lws *wsi)
Andy Green38e57bb2011-01-19 12:20:27 +00001455{
Andy Green623a98d2013-01-21 11:04:23 +08001456 return wsi->u.ws.rx_packet_length;
Andy Green38e57bb2011-01-19 12:20:27 +00001457}