1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker */
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker static const unsigned char lextable_h1[] = {
28*1c60b9acSAndroid Build Coastguard Worker #include "lextable.h"
29*1c60b9acSAndroid Build Coastguard Worker };
30*1c60b9acSAndroid Build Coastguard Worker
31*1c60b9acSAndroid Build Coastguard Worker #define FAIL_CHAR 0x08
32*1c60b9acSAndroid Build Coastguard Worker
33*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CUSTOM_HEADERS)
34*1c60b9acSAndroid Build Coastguard Worker
35*1c60b9acSAndroid Build Coastguard Worker #define UHO_NLEN 0
36*1c60b9acSAndroid Build Coastguard Worker #define UHO_VLEN 2
37*1c60b9acSAndroid Build Coastguard Worker #define UHO_LL 4
38*1c60b9acSAndroid Build Coastguard Worker #define UHO_NAME 8
39*1c60b9acSAndroid Build Coastguard Worker
40*1c60b9acSAndroid Build Coastguard Worker #endif
41*1c60b9acSAndroid Build Coastguard Worker
42*1c60b9acSAndroid Build Coastguard Worker static struct allocated_headers *
_lws_create_ah(struct lws_context_per_thread * pt,ah_data_idx_t data_size)43*1c60b9acSAndroid Build Coastguard Worker _lws_create_ah(struct lws_context_per_thread *pt, ah_data_idx_t data_size)
44*1c60b9acSAndroid Build Coastguard Worker {
45*1c60b9acSAndroid Build Coastguard Worker struct allocated_headers *ah = lws_zalloc(sizeof(*ah), "ah struct");
46*1c60b9acSAndroid Build Coastguard Worker
47*1c60b9acSAndroid Build Coastguard Worker if (!ah)
48*1c60b9acSAndroid Build Coastguard Worker return NULL;
49*1c60b9acSAndroid Build Coastguard Worker
50*1c60b9acSAndroid Build Coastguard Worker ah->data = lws_malloc(data_size, "ah data");
51*1c60b9acSAndroid Build Coastguard Worker if (!ah->data) {
52*1c60b9acSAndroid Build Coastguard Worker lws_free(ah);
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker return NULL;
55*1c60b9acSAndroid Build Coastguard Worker }
56*1c60b9acSAndroid Build Coastguard Worker ah->next = pt->http.ah_list;
57*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_list = ah;
58*1c60b9acSAndroid Build Coastguard Worker ah->data_length = data_size;
59*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_pool_length++;
60*1c60b9acSAndroid Build Coastguard Worker
61*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: created ah %p (size %d): pool length %u\n", __func__,
62*1c60b9acSAndroid Build Coastguard Worker ah, (int)data_size, (unsigned int)pt->http.ah_pool_length);
63*1c60b9acSAndroid Build Coastguard Worker
64*1c60b9acSAndroid Build Coastguard Worker return ah;
65*1c60b9acSAndroid Build Coastguard Worker }
66*1c60b9acSAndroid Build Coastguard Worker
67*1c60b9acSAndroid Build Coastguard Worker int
_lws_destroy_ah(struct lws_context_per_thread * pt,struct allocated_headers * ah)68*1c60b9acSAndroid Build Coastguard Worker _lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah)
69*1c60b9acSAndroid Build Coastguard Worker {
70*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_llp(struct allocated_headers **, a, pt->http.ah_list) {
71*1c60b9acSAndroid Build Coastguard Worker if ((*a) == ah) {
72*1c60b9acSAndroid Build Coastguard Worker *a = ah->next;
73*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_pool_length--;
74*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: freed ah %p : pool length %u\n",
75*1c60b9acSAndroid Build Coastguard Worker __func__, ah,
76*1c60b9acSAndroid Build Coastguard Worker (unsigned int)pt->http.ah_pool_length);
77*1c60b9acSAndroid Build Coastguard Worker if (ah->data)
78*1c60b9acSAndroid Build Coastguard Worker lws_free(ah->data);
79*1c60b9acSAndroid Build Coastguard Worker lws_free(ah);
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard Worker return 0;
82*1c60b9acSAndroid Build Coastguard Worker }
83*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_llp(a, next);
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker return 1;
86*1c60b9acSAndroid Build Coastguard Worker }
87*1c60b9acSAndroid Build Coastguard Worker
88*1c60b9acSAndroid Build Coastguard Worker void
_lws_header_table_reset(struct allocated_headers * ah)89*1c60b9acSAndroid Build Coastguard Worker _lws_header_table_reset(struct allocated_headers *ah)
90*1c60b9acSAndroid Build Coastguard Worker {
91*1c60b9acSAndroid Build Coastguard Worker /* init the ah to reflect no headers or data have appeared yet */
92*1c60b9acSAndroid Build Coastguard Worker memset(ah->frag_index, 0, sizeof(ah->frag_index));
93*1c60b9acSAndroid Build Coastguard Worker memset(ah->frags, 0, sizeof(ah->frags));
94*1c60b9acSAndroid Build Coastguard Worker ah->nfrag = 0;
95*1c60b9acSAndroid Build Coastguard Worker ah->pos = 0;
96*1c60b9acSAndroid Build Coastguard Worker ah->http_response = 0;
97*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_NAME_PART;
98*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos = 0;
99*1c60b9acSAndroid Build Coastguard Worker ah->unk_pos = 0;
100*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CUSTOM_HEADERS)
101*1c60b9acSAndroid Build Coastguard Worker ah->unk_ll_head = 0;
102*1c60b9acSAndroid Build Coastguard Worker ah->unk_ll_tail = 0;
103*1c60b9acSAndroid Build Coastguard Worker #endif
104*1c60b9acSAndroid Build Coastguard Worker }
105*1c60b9acSAndroid Build Coastguard Worker
106*1c60b9acSAndroid Build Coastguard Worker // doesn't scrub the ah rxbuffer by default, parent must do if needed
107*1c60b9acSAndroid Build Coastguard Worker
108*1c60b9acSAndroid Build Coastguard Worker void
__lws_header_table_reset(struct lws * wsi,int autoservice)109*1c60b9acSAndroid Build Coastguard Worker __lws_header_table_reset(struct lws *wsi, int autoservice)
110*1c60b9acSAndroid Build Coastguard Worker {
111*1c60b9acSAndroid Build Coastguard Worker struct allocated_headers *ah = wsi->http.ah;
112*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt;
113*1c60b9acSAndroid Build Coastguard Worker struct lws_pollfd *pfd;
114*1c60b9acSAndroid Build Coastguard Worker
115*1c60b9acSAndroid Build Coastguard Worker /* if we have the idea we're resetting 'our' ah, must be bound to one */
116*1c60b9acSAndroid Build Coastguard Worker assert(ah);
117*1c60b9acSAndroid Build Coastguard Worker /* ah also concurs with ownership */
118*1c60b9acSAndroid Build Coastguard Worker assert(ah->wsi == wsi);
119*1c60b9acSAndroid Build Coastguard Worker
120*1c60b9acSAndroid Build Coastguard Worker _lws_header_table_reset(ah);
121*1c60b9acSAndroid Build Coastguard Worker
122*1c60b9acSAndroid Build Coastguard Worker /* since we will restart the ah, our new headers are not completed */
123*1c60b9acSAndroid Build Coastguard Worker wsi->hdr_parsing_completed = 0;
124*1c60b9acSAndroid Build Coastguard Worker
125*1c60b9acSAndroid Build Coastguard Worker /* while we hold the ah, keep a timeout on the wsi */
126*1c60b9acSAndroid Build Coastguard Worker __lws_set_timeout(wsi, PENDING_TIMEOUT_HOLDING_AH,
127*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->timeout_secs_ah_idle);
128*1c60b9acSAndroid Build Coastguard Worker
129*1c60b9acSAndroid Build Coastguard Worker time(&ah->assigned);
130*1c60b9acSAndroid Build Coastguard Worker
131*1c60b9acSAndroid Build Coastguard Worker if (wsi->position_in_fds_table != LWS_NO_FDS_POS &&
132*1c60b9acSAndroid Build Coastguard Worker lws_buflist_next_segment_len(&wsi->buflist, NULL) &&
133*1c60b9acSAndroid Build Coastguard Worker autoservice) {
134*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: service on readbuf ah\n", __func__);
135*1c60b9acSAndroid Build Coastguard Worker
136*1c60b9acSAndroid Build Coastguard Worker pt = &wsi->a.context->pt[(int)wsi->tsi];
137*1c60b9acSAndroid Build Coastguard Worker /*
138*1c60b9acSAndroid Build Coastguard Worker * Unlike a normal connect, we have the headers already
139*1c60b9acSAndroid Build Coastguard Worker * (or the first part of them anyway)
140*1c60b9acSAndroid Build Coastguard Worker */
141*1c60b9acSAndroid Build Coastguard Worker pfd = &pt->fds[wsi->position_in_fds_table];
142*1c60b9acSAndroid Build Coastguard Worker pfd->revents |= LWS_POLLIN;
143*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: calling service\n", __func__);
144*1c60b9acSAndroid Build Coastguard Worker lws_service_fd_tsi(wsi->a.context, pfd, wsi->tsi);
145*1c60b9acSAndroid Build Coastguard Worker }
146*1c60b9acSAndroid Build Coastguard Worker }
147*1c60b9acSAndroid Build Coastguard Worker
148*1c60b9acSAndroid Build Coastguard Worker void
lws_header_table_reset(struct lws * wsi,int autoservice)149*1c60b9acSAndroid Build Coastguard Worker lws_header_table_reset(struct lws *wsi, int autoservice)
150*1c60b9acSAndroid Build Coastguard Worker {
151*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
154*1c60b9acSAndroid Build Coastguard Worker
155*1c60b9acSAndroid Build Coastguard Worker __lws_header_table_reset(wsi, autoservice);
156*1c60b9acSAndroid Build Coastguard Worker
157*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
158*1c60b9acSAndroid Build Coastguard Worker }
159*1c60b9acSAndroid Build Coastguard Worker
160*1c60b9acSAndroid Build Coastguard Worker static void
_lws_header_ensure_we_are_on_waiting_list(struct lws * wsi)161*1c60b9acSAndroid Build Coastguard Worker _lws_header_ensure_we_are_on_waiting_list(struct lws *wsi)
162*1c60b9acSAndroid Build Coastguard Worker {
163*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
164*1c60b9acSAndroid Build Coastguard Worker struct lws_pollargs pa;
165*1c60b9acSAndroid Build Coastguard Worker struct lws **pwsi = &pt->http.ah_wait_list;
166*1c60b9acSAndroid Build Coastguard Worker
167*1c60b9acSAndroid Build Coastguard Worker while (*pwsi) {
168*1c60b9acSAndroid Build Coastguard Worker if (*pwsi == wsi)
169*1c60b9acSAndroid Build Coastguard Worker return;
170*1c60b9acSAndroid Build Coastguard Worker pwsi = &(*pwsi)->http.ah_wait_list;
171*1c60b9acSAndroid Build Coastguard Worker }
172*1c60b9acSAndroid Build Coastguard Worker
173*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: wsi: %s\n", __func__, lws_wsi_tag(wsi));
174*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah_wait_list = pt->http.ah_wait_list;
175*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_wait_list = wsi;
176*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_wait_list_length++;
177*1c60b9acSAndroid Build Coastguard Worker
178*1c60b9acSAndroid Build Coastguard Worker /* we cannot accept input then */
179*1c60b9acSAndroid Build Coastguard Worker
180*1c60b9acSAndroid Build Coastguard Worker _lws_change_pollfd(wsi, LWS_POLLIN, 0, &pa);
181*1c60b9acSAndroid Build Coastguard Worker }
182*1c60b9acSAndroid Build Coastguard Worker
183*1c60b9acSAndroid Build Coastguard Worker static int
__lws_remove_from_ah_waiting_list(struct lws * wsi)184*1c60b9acSAndroid Build Coastguard Worker __lws_remove_from_ah_waiting_list(struct lws *wsi)
185*1c60b9acSAndroid Build Coastguard Worker {
186*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
187*1c60b9acSAndroid Build Coastguard Worker struct lws **pwsi =&pt->http.ah_wait_list;
188*1c60b9acSAndroid Build Coastguard Worker
189*1c60b9acSAndroid Build Coastguard Worker while (*pwsi) {
190*1c60b9acSAndroid Build Coastguard Worker if (*pwsi == wsi) {
191*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: wsi %s\n", __func__, lws_wsi_tag(wsi));
192*1c60b9acSAndroid Build Coastguard Worker /* point prev guy to our next */
193*1c60b9acSAndroid Build Coastguard Worker *pwsi = wsi->http.ah_wait_list;
194*1c60b9acSAndroid Build Coastguard Worker /* we shouldn't point anywhere now */
195*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah_wait_list = NULL;
196*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_wait_list_length--;
197*1c60b9acSAndroid Build Coastguard Worker
198*1c60b9acSAndroid Build Coastguard Worker return 1;
199*1c60b9acSAndroid Build Coastguard Worker }
200*1c60b9acSAndroid Build Coastguard Worker pwsi = &(*pwsi)->http.ah_wait_list;
201*1c60b9acSAndroid Build Coastguard Worker }
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker return 0;
204*1c60b9acSAndroid Build Coastguard Worker }
205*1c60b9acSAndroid Build Coastguard Worker
206*1c60b9acSAndroid Build Coastguard Worker int LWS_WARN_UNUSED_RESULT
lws_header_table_attach(struct lws * wsi,int autoservice)207*1c60b9acSAndroid Build Coastguard Worker lws_header_table_attach(struct lws *wsi, int autoservice)
208*1c60b9acSAndroid Build Coastguard Worker {
209*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = wsi->a.context;
210*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
211*1c60b9acSAndroid Build Coastguard Worker struct lws_pollargs pa;
212*1c60b9acSAndroid Build Coastguard Worker int n;
213*1c60b9acSAndroid Build Coastguard Worker
214*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_MQTT) && defined(LWS_WITH_CLIENT)
215*1c60b9acSAndroid Build Coastguard Worker if (lwsi_role_mqtt(wsi))
216*1c60b9acSAndroid Build Coastguard Worker goto connect_via_info2;
217*1c60b9acSAndroid Build Coastguard Worker #endif
218*1c60b9acSAndroid Build Coastguard Worker
219*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: ah %p (tsi %d, count = %d) in\n", __func__,
220*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), (void *)wsi->http.ah, wsi->tsi,
221*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_count_in_use);
222*1c60b9acSAndroid Build Coastguard Worker
223*1c60b9acSAndroid Build Coastguard Worker if (!lwsi_role_http(wsi)) {
224*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: bad role %s\n", __func__, wsi->role_ops->name);
225*1c60b9acSAndroid Build Coastguard Worker assert(0);
226*1c60b9acSAndroid Build Coastguard Worker return -1;
227*1c60b9acSAndroid Build Coastguard Worker }
228*1c60b9acSAndroid Build Coastguard Worker
229*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
230*1c60b9acSAndroid Build Coastguard Worker
231*1c60b9acSAndroid Build Coastguard Worker /* if we are already bound to one, just clear it down */
232*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.ah) {
233*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: cleardown\n", __func__);
234*1c60b9acSAndroid Build Coastguard Worker goto reset;
235*1c60b9acSAndroid Build Coastguard Worker }
236*1c60b9acSAndroid Build Coastguard Worker
237*1c60b9acSAndroid Build Coastguard Worker n = pt->http.ah_count_in_use == (int)context->max_http_header_pool;
238*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_PEER_LIMITS)
239*1c60b9acSAndroid Build Coastguard Worker if (!n)
240*1c60b9acSAndroid Build Coastguard Worker n = lws_peer_confirm_ah_attach_ok(context, wsi->peer);
241*1c60b9acSAndroid Build Coastguard Worker #endif
242*1c60b9acSAndroid Build Coastguard Worker if (n) {
243*1c60b9acSAndroid Build Coastguard Worker /*
244*1c60b9acSAndroid Build Coastguard Worker * Pool is either all busy, or we don't want to give this
245*1c60b9acSAndroid Build Coastguard Worker * particular guy an ah right now...
246*1c60b9acSAndroid Build Coastguard Worker *
247*1c60b9acSAndroid Build Coastguard Worker * Make sure we are on the waiting list, and return that we
248*1c60b9acSAndroid Build Coastguard Worker * weren't able to provide the ah
249*1c60b9acSAndroid Build Coastguard Worker */
250*1c60b9acSAndroid Build Coastguard Worker _lws_header_ensure_we_are_on_waiting_list(wsi);
251*1c60b9acSAndroid Build Coastguard Worker
252*1c60b9acSAndroid Build Coastguard Worker goto bail;
253*1c60b9acSAndroid Build Coastguard Worker }
254*1c60b9acSAndroid Build Coastguard Worker
255*1c60b9acSAndroid Build Coastguard Worker __lws_remove_from_ah_waiting_list(wsi);
256*1c60b9acSAndroid Build Coastguard Worker
257*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah = _lws_create_ah(pt, context->max_http_header_data);
258*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah) { /* we could not create an ah */
259*1c60b9acSAndroid Build Coastguard Worker _lws_header_ensure_we_are_on_waiting_list(wsi);
260*1c60b9acSAndroid Build Coastguard Worker
261*1c60b9acSAndroid Build Coastguard Worker goto bail;
262*1c60b9acSAndroid Build Coastguard Worker }
263*1c60b9acSAndroid Build Coastguard Worker
264*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->in_use = 1;
265*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->wsi = wsi; /* mark our owner */
266*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_count_in_use++;
267*1c60b9acSAndroid Build Coastguard Worker
268*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_PEER_LIMITS) && (defined(LWS_ROLE_H1) || \
269*1c60b9acSAndroid Build Coastguard Worker defined(LWS_ROLE_H2))
270*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(context, "ah attach"); /* <========================= */
271*1c60b9acSAndroid Build Coastguard Worker if (wsi->peer)
272*1c60b9acSAndroid Build Coastguard Worker wsi->peer->http.count_ah++;
273*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(context); /* ====================================> */
274*1c60b9acSAndroid Build Coastguard Worker #endif
275*1c60b9acSAndroid Build Coastguard Worker
276*1c60b9acSAndroid Build Coastguard Worker _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
277*1c60b9acSAndroid Build Coastguard Worker
278*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: did attach wsi %s: ah %p: count %d (on exit)\n", __func__,
279*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), (void *)wsi->http.ah, pt->http.ah_count_in_use);
280*1c60b9acSAndroid Build Coastguard Worker
281*1c60b9acSAndroid Build Coastguard Worker reset:
282*1c60b9acSAndroid Build Coastguard Worker __lws_header_table_reset(wsi, autoservice);
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
285*1c60b9acSAndroid Build Coastguard Worker
286*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
287*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_MQTT)
288*1c60b9acSAndroid Build Coastguard Worker connect_via_info2:
289*1c60b9acSAndroid Build Coastguard Worker #endif
290*1c60b9acSAndroid Build Coastguard Worker if (lwsi_role_client(wsi) && lwsi_state(wsi) == LRS_UNCONNECTED)
291*1c60b9acSAndroid Build Coastguard Worker if (!lws_http_client_connect_via_info2(wsi))
292*1c60b9acSAndroid Build Coastguard Worker /* our client connect has failed, the wsi
293*1c60b9acSAndroid Build Coastguard Worker * has been closed
294*1c60b9acSAndroid Build Coastguard Worker */
295*1c60b9acSAndroid Build Coastguard Worker return -1;
296*1c60b9acSAndroid Build Coastguard Worker #endif
297*1c60b9acSAndroid Build Coastguard Worker
298*1c60b9acSAndroid Build Coastguard Worker return 0;
299*1c60b9acSAndroid Build Coastguard Worker
300*1c60b9acSAndroid Build Coastguard Worker bail:
301*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
302*1c60b9acSAndroid Build Coastguard Worker
303*1c60b9acSAndroid Build Coastguard Worker return 1;
304*1c60b9acSAndroid Build Coastguard Worker }
305*1c60b9acSAndroid Build Coastguard Worker
__lws_header_table_detach(struct lws * wsi,int autoservice)306*1c60b9acSAndroid Build Coastguard Worker int __lws_header_table_detach(struct lws *wsi, int autoservice)
307*1c60b9acSAndroid Build Coastguard Worker {
308*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = wsi->a.context;
309*1c60b9acSAndroid Build Coastguard Worker struct allocated_headers *ah = wsi->http.ah;
310*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
311*1c60b9acSAndroid Build Coastguard Worker struct lws_pollargs pa;
312*1c60b9acSAndroid Build Coastguard Worker struct lws **pwsi, **pwsi_eligible;
313*1c60b9acSAndroid Build Coastguard Worker time_t now;
314*1c60b9acSAndroid Build Coastguard Worker
315*1c60b9acSAndroid Build Coastguard Worker __lws_remove_from_ah_waiting_list(wsi);
316*1c60b9acSAndroid Build Coastguard Worker
317*1c60b9acSAndroid Build Coastguard Worker if (!ah)
318*1c60b9acSAndroid Build Coastguard Worker return 0;
319*1c60b9acSAndroid Build Coastguard Worker
320*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: ah %p (tsi=%d, count = %d)\n", __func__,
321*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), (void *)ah, wsi->tsi,
322*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_count_in_use);
323*1c60b9acSAndroid Build Coastguard Worker
324*1c60b9acSAndroid Build Coastguard Worker /* we did have an ah attached */
325*1c60b9acSAndroid Build Coastguard Worker time(&now);
326*1c60b9acSAndroid Build Coastguard Worker if (ah->assigned && now - ah->assigned > 3) {
327*1c60b9acSAndroid Build Coastguard Worker /*
328*1c60b9acSAndroid Build Coastguard Worker * we're detaching the ah, but it was held an
329*1c60b9acSAndroid Build Coastguard Worker * unreasonably long time
330*1c60b9acSAndroid Build Coastguard Worker */
331*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s: ah held %ds, role/state 0x%lx 0x%x,"
332*1c60b9acSAndroid Build Coastguard Worker "\n", __func__, lws_wsi_tag(wsi),
333*1c60b9acSAndroid Build Coastguard Worker (int)(now - ah->assigned),
334*1c60b9acSAndroid Build Coastguard Worker (unsigned long)lwsi_role(wsi), lwsi_state(wsi));
335*1c60b9acSAndroid Build Coastguard Worker }
336*1c60b9acSAndroid Build Coastguard Worker
337*1c60b9acSAndroid Build Coastguard Worker ah->assigned = 0;
338*1c60b9acSAndroid Build Coastguard Worker
339*1c60b9acSAndroid Build Coastguard Worker /* if we think we're detaching one, there should be one in use */
340*1c60b9acSAndroid Build Coastguard Worker assert(pt->http.ah_count_in_use > 0);
341*1c60b9acSAndroid Build Coastguard Worker /* and this specific one should have been in use */
342*1c60b9acSAndroid Build Coastguard Worker assert(ah->in_use);
343*1c60b9acSAndroid Build Coastguard Worker memset(&wsi->http.ah, 0, sizeof(wsi->http.ah));
344*1c60b9acSAndroid Build Coastguard Worker
345*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_PEER_LIMITS)
346*1c60b9acSAndroid Build Coastguard Worker if (ah->wsi)
347*1c60b9acSAndroid Build Coastguard Worker lws_peer_track_ah_detach(context, wsi->peer);
348*1c60b9acSAndroid Build Coastguard Worker #endif
349*1c60b9acSAndroid Build Coastguard Worker ah->wsi = NULL; /* no owner */
350*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah = NULL;
351*1c60b9acSAndroid Build Coastguard Worker
352*1c60b9acSAndroid Build Coastguard Worker pwsi = &pt->http.ah_wait_list;
353*1c60b9acSAndroid Build Coastguard Worker
354*1c60b9acSAndroid Build Coastguard Worker /* oh there is nobody on the waiting list... leave the ah unattached */
355*1c60b9acSAndroid Build Coastguard Worker if (!*pwsi)
356*1c60b9acSAndroid Build Coastguard Worker goto nobody_usable_waiting;
357*1c60b9acSAndroid Build Coastguard Worker
358*1c60b9acSAndroid Build Coastguard Worker /*
359*1c60b9acSAndroid Build Coastguard Worker * at least one wsi on the same tsi is waiting, give it to oldest guy
360*1c60b9acSAndroid Build Coastguard Worker * who is allowed to take it (if any)
361*1c60b9acSAndroid Build Coastguard Worker */
362*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: pt wait list %s\n", __func__, lws_wsi_tag(*pwsi));
363*1c60b9acSAndroid Build Coastguard Worker wsi = NULL;
364*1c60b9acSAndroid Build Coastguard Worker pwsi_eligible = NULL;
365*1c60b9acSAndroid Build Coastguard Worker
366*1c60b9acSAndroid Build Coastguard Worker while (*pwsi) {
367*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_PEER_LIMITS)
368*1c60b9acSAndroid Build Coastguard Worker /* are we willing to give this guy an ah? */
369*1c60b9acSAndroid Build Coastguard Worker if (!lws_peer_confirm_ah_attach_ok(context, (*pwsi)->peer))
370*1c60b9acSAndroid Build Coastguard Worker #endif
371*1c60b9acSAndroid Build Coastguard Worker {
372*1c60b9acSAndroid Build Coastguard Worker wsi = *pwsi;
373*1c60b9acSAndroid Build Coastguard Worker pwsi_eligible = pwsi;
374*1c60b9acSAndroid Build Coastguard Worker }
375*1c60b9acSAndroid Build Coastguard Worker
376*1c60b9acSAndroid Build Coastguard Worker pwsi = &(*pwsi)->http.ah_wait_list;
377*1c60b9acSAndroid Build Coastguard Worker }
378*1c60b9acSAndroid Build Coastguard Worker
379*1c60b9acSAndroid Build Coastguard Worker if (!wsi) /* everybody waiting already has too many ah... */
380*1c60b9acSAndroid Build Coastguard Worker goto nobody_usable_waiting;
381*1c60b9acSAndroid Build Coastguard Worker
382*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: transferring ah to last eligible wsi in wait list "
383*1c60b9acSAndroid Build Coastguard Worker "%s (wsistate 0x%lx)\n", __func__, lws_wsi_tag(wsi),
384*1c60b9acSAndroid Build Coastguard Worker (unsigned long)wsi->wsistate);
385*1c60b9acSAndroid Build Coastguard Worker
386*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah = ah;
387*1c60b9acSAndroid Build Coastguard Worker ah->wsi = wsi; /* new owner */
388*1c60b9acSAndroid Build Coastguard Worker
389*1c60b9acSAndroid Build Coastguard Worker __lws_header_table_reset(wsi, autoservice);
390*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_PEER_LIMITS) && (defined(LWS_ROLE_H1) || \
391*1c60b9acSAndroid Build Coastguard Worker defined(LWS_ROLE_H2))
392*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(context, "ah detach"); /* <========================= */
393*1c60b9acSAndroid Build Coastguard Worker if (wsi->peer)
394*1c60b9acSAndroid Build Coastguard Worker wsi->peer->http.count_ah++;
395*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(context); /* ====================================> */
396*1c60b9acSAndroid Build Coastguard Worker #endif
397*1c60b9acSAndroid Build Coastguard Worker
398*1c60b9acSAndroid Build Coastguard Worker /* clients acquire the ah and then insert themselves in fds table... */
399*1c60b9acSAndroid Build Coastguard Worker if (wsi->position_in_fds_table != LWS_NO_FDS_POS) {
400*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: Enabling %s POLLIN\n", __func__, lws_wsi_tag(wsi));
401*1c60b9acSAndroid Build Coastguard Worker
402*1c60b9acSAndroid Build Coastguard Worker /* he has been stuck waiting for an ah, but now his wait is
403*1c60b9acSAndroid Build Coastguard Worker * over, let him progress */
404*1c60b9acSAndroid Build Coastguard Worker
405*1c60b9acSAndroid Build Coastguard Worker _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
406*1c60b9acSAndroid Build Coastguard Worker }
407*1c60b9acSAndroid Build Coastguard Worker
408*1c60b9acSAndroid Build Coastguard Worker /* point prev guy to next guy in list instead */
409*1c60b9acSAndroid Build Coastguard Worker *pwsi_eligible = wsi->http.ah_wait_list;
410*1c60b9acSAndroid Build Coastguard Worker /* the guy who got one is out of the list */
411*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah_wait_list = NULL;
412*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_wait_list_length--;
413*1c60b9acSAndroid Build Coastguard Worker
414*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
415*1c60b9acSAndroid Build Coastguard Worker if (lwsi_role_client(wsi) && lwsi_state(wsi) == LRS_UNCONNECTED) {
416*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
417*1c60b9acSAndroid Build Coastguard Worker
418*1c60b9acSAndroid Build Coastguard Worker if (!lws_http_client_connect_via_info2(wsi)) {
419*1c60b9acSAndroid Build Coastguard Worker /* our client connect has failed, the wsi
420*1c60b9acSAndroid Build Coastguard Worker * has been closed
421*1c60b9acSAndroid Build Coastguard Worker */
422*1c60b9acSAndroid Build Coastguard Worker
423*1c60b9acSAndroid Build Coastguard Worker return -1;
424*1c60b9acSAndroid Build Coastguard Worker }
425*1c60b9acSAndroid Build Coastguard Worker return 0;
426*1c60b9acSAndroid Build Coastguard Worker }
427*1c60b9acSAndroid Build Coastguard Worker #endif
428*1c60b9acSAndroid Build Coastguard Worker
429*1c60b9acSAndroid Build Coastguard Worker assert(!!pt->http.ah_wait_list_length ==
430*1c60b9acSAndroid Build Coastguard Worker !!(lws_intptr_t)pt->http.ah_wait_list);
431*1c60b9acSAndroid Build Coastguard Worker bail:
432*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: ah %p (tsi=%d, count = %d)\n", __func__,
433*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), (void *)ah, pt->tid, pt->http.ah_count_in_use);
434*1c60b9acSAndroid Build Coastguard Worker
435*1c60b9acSAndroid Build Coastguard Worker return 0;
436*1c60b9acSAndroid Build Coastguard Worker
437*1c60b9acSAndroid Build Coastguard Worker nobody_usable_waiting:
438*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: nobody usable waiting\n", __func__);
439*1c60b9acSAndroid Build Coastguard Worker _lws_destroy_ah(pt, ah);
440*1c60b9acSAndroid Build Coastguard Worker pt->http.ah_count_in_use--;
441*1c60b9acSAndroid Build Coastguard Worker
442*1c60b9acSAndroid Build Coastguard Worker goto bail;
443*1c60b9acSAndroid Build Coastguard Worker }
444*1c60b9acSAndroid Build Coastguard Worker
lws_header_table_detach(struct lws * wsi,int autoservice)445*1c60b9acSAndroid Build Coastguard Worker int lws_header_table_detach(struct lws *wsi, int autoservice)
446*1c60b9acSAndroid Build Coastguard Worker {
447*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = wsi->a.context;
448*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
449*1c60b9acSAndroid Build Coastguard Worker int n;
450*1c60b9acSAndroid Build Coastguard Worker
451*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
452*1c60b9acSAndroid Build Coastguard Worker n = __lws_header_table_detach(wsi, autoservice);
453*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
454*1c60b9acSAndroid Build Coastguard Worker
455*1c60b9acSAndroid Build Coastguard Worker return n;
456*1c60b9acSAndroid Build Coastguard Worker }
457*1c60b9acSAndroid Build Coastguard Worker
458*1c60b9acSAndroid Build Coastguard Worker int
lws_hdr_fragment_length(struct lws * wsi,enum lws_token_indexes h,int frag_idx)459*1c60b9acSAndroid Build Coastguard Worker lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, int frag_idx)
460*1c60b9acSAndroid Build Coastguard Worker {
461*1c60b9acSAndroid Build Coastguard Worker int n;
462*1c60b9acSAndroid Build Coastguard Worker
463*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah)
464*1c60b9acSAndroid Build Coastguard Worker return 0;
465*1c60b9acSAndroid Build Coastguard Worker
466*1c60b9acSAndroid Build Coastguard Worker n = wsi->http.ah->frag_index[h];
467*1c60b9acSAndroid Build Coastguard Worker if (!n)
468*1c60b9acSAndroid Build Coastguard Worker return 0;
469*1c60b9acSAndroid Build Coastguard Worker do {
470*1c60b9acSAndroid Build Coastguard Worker if (!frag_idx)
471*1c60b9acSAndroid Build Coastguard Worker return wsi->http.ah->frags[n].len;
472*1c60b9acSAndroid Build Coastguard Worker n = wsi->http.ah->frags[n].nfrag;
473*1c60b9acSAndroid Build Coastguard Worker } while (frag_idx-- && n);
474*1c60b9acSAndroid Build Coastguard Worker
475*1c60b9acSAndroid Build Coastguard Worker return 0;
476*1c60b9acSAndroid Build Coastguard Worker }
477*1c60b9acSAndroid Build Coastguard Worker
lws_hdr_total_length(struct lws * wsi,enum lws_token_indexes h)478*1c60b9acSAndroid Build Coastguard Worker int lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h)
479*1c60b9acSAndroid Build Coastguard Worker {
480*1c60b9acSAndroid Build Coastguard Worker int n;
481*1c60b9acSAndroid Build Coastguard Worker int len = 0;
482*1c60b9acSAndroid Build Coastguard Worker
483*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah)
484*1c60b9acSAndroid Build Coastguard Worker return 0;
485*1c60b9acSAndroid Build Coastguard Worker
486*1c60b9acSAndroid Build Coastguard Worker n = wsi->http.ah->frag_index[h];
487*1c60b9acSAndroid Build Coastguard Worker if (!n)
488*1c60b9acSAndroid Build Coastguard Worker return 0;
489*1c60b9acSAndroid Build Coastguard Worker do {
490*1c60b9acSAndroid Build Coastguard Worker len += wsi->http.ah->frags[n].len;
491*1c60b9acSAndroid Build Coastguard Worker n = wsi->http.ah->frags[n].nfrag;
492*1c60b9acSAndroid Build Coastguard Worker
493*1c60b9acSAndroid Build Coastguard Worker if (n)
494*1c60b9acSAndroid Build Coastguard Worker len++;
495*1c60b9acSAndroid Build Coastguard Worker
496*1c60b9acSAndroid Build Coastguard Worker } while (n);
497*1c60b9acSAndroid Build Coastguard Worker
498*1c60b9acSAndroid Build Coastguard Worker return len;
499*1c60b9acSAndroid Build Coastguard Worker }
500*1c60b9acSAndroid Build Coastguard Worker
lws_hdr_copy_fragment(struct lws * wsi,char * dst,int len,enum lws_token_indexes h,int frag_idx)501*1c60b9acSAndroid Build Coastguard Worker int lws_hdr_copy_fragment(struct lws *wsi, char *dst, int len,
502*1c60b9acSAndroid Build Coastguard Worker enum lws_token_indexes h, int frag_idx)
503*1c60b9acSAndroid Build Coastguard Worker {
504*1c60b9acSAndroid Build Coastguard Worker int n = 0;
505*1c60b9acSAndroid Build Coastguard Worker int f;
506*1c60b9acSAndroid Build Coastguard Worker
507*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah)
508*1c60b9acSAndroid Build Coastguard Worker return -1;
509*1c60b9acSAndroid Build Coastguard Worker
510*1c60b9acSAndroid Build Coastguard Worker f = wsi->http.ah->frag_index[h];
511*1c60b9acSAndroid Build Coastguard Worker
512*1c60b9acSAndroid Build Coastguard Worker if (!f)
513*1c60b9acSAndroid Build Coastguard Worker return -1;
514*1c60b9acSAndroid Build Coastguard Worker
515*1c60b9acSAndroid Build Coastguard Worker while (n < frag_idx) {
516*1c60b9acSAndroid Build Coastguard Worker f = wsi->http.ah->frags[f].nfrag;
517*1c60b9acSAndroid Build Coastguard Worker if (!f)
518*1c60b9acSAndroid Build Coastguard Worker return -1;
519*1c60b9acSAndroid Build Coastguard Worker n++;
520*1c60b9acSAndroid Build Coastguard Worker }
521*1c60b9acSAndroid Build Coastguard Worker
522*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.ah->frags[f].len >= len)
523*1c60b9acSAndroid Build Coastguard Worker return -1;
524*1c60b9acSAndroid Build Coastguard Worker
525*1c60b9acSAndroid Build Coastguard Worker memcpy(dst, wsi->http.ah->data + wsi->http.ah->frags[f].offset,
526*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[f].len);
527*1c60b9acSAndroid Build Coastguard Worker dst[wsi->http.ah->frags[f].len] = '\0';
528*1c60b9acSAndroid Build Coastguard Worker
529*1c60b9acSAndroid Build Coastguard Worker return wsi->http.ah->frags[f].len;
530*1c60b9acSAndroid Build Coastguard Worker }
531*1c60b9acSAndroid Build Coastguard Worker
lws_hdr_copy(struct lws * wsi,char * dst,int len,enum lws_token_indexes h)532*1c60b9acSAndroid Build Coastguard Worker int lws_hdr_copy(struct lws *wsi, char *dst, int len,
533*1c60b9acSAndroid Build Coastguard Worker enum lws_token_indexes h)
534*1c60b9acSAndroid Build Coastguard Worker {
535*1c60b9acSAndroid Build Coastguard Worker int toklen = lws_hdr_total_length(wsi, h), n, comma;
536*1c60b9acSAndroid Build Coastguard Worker
537*1c60b9acSAndroid Build Coastguard Worker *dst = '\0';
538*1c60b9acSAndroid Build Coastguard Worker if (!toklen)
539*1c60b9acSAndroid Build Coastguard Worker return 0;
540*1c60b9acSAndroid Build Coastguard Worker
541*1c60b9acSAndroid Build Coastguard Worker if (toklen >= len)
542*1c60b9acSAndroid Build Coastguard Worker return -1;
543*1c60b9acSAndroid Build Coastguard Worker
544*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah)
545*1c60b9acSAndroid Build Coastguard Worker return -1;
546*1c60b9acSAndroid Build Coastguard Worker
547*1c60b9acSAndroid Build Coastguard Worker n = wsi->http.ah->frag_index[h];
548*1c60b9acSAndroid Build Coastguard Worker if (!n)
549*1c60b9acSAndroid Build Coastguard Worker return 0;
550*1c60b9acSAndroid Build Coastguard Worker do {
551*1c60b9acSAndroid Build Coastguard Worker comma = (wsi->http.ah->frags[n].nfrag) ? 1 : 0;
552*1c60b9acSAndroid Build Coastguard Worker
553*1c60b9acSAndroid Build Coastguard Worker if (h == WSI_TOKEN_HTTP_URI_ARGS)
554*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: WSI_TOKEN_HTTP_URI_ARGS '%.*s'\n",
555*1c60b9acSAndroid Build Coastguard Worker __func__, (int)wsi->http.ah->frags[n].len,
556*1c60b9acSAndroid Build Coastguard Worker &wsi->http.ah->data[
557*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[n].offset]);
558*1c60b9acSAndroid Build Coastguard Worker
559*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.ah->frags[n].len + comma >= len) {
560*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("blowout len\n");
561*1c60b9acSAndroid Build Coastguard Worker return -1;
562*1c60b9acSAndroid Build Coastguard Worker }
563*1c60b9acSAndroid Build Coastguard Worker strncpy(dst, &wsi->http.ah->data[wsi->http.ah->frags[n].offset],
564*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[n].len);
565*1c60b9acSAndroid Build Coastguard Worker dst += wsi->http.ah->frags[n].len;
566*1c60b9acSAndroid Build Coastguard Worker len -= wsi->http.ah->frags[n].len;
567*1c60b9acSAndroid Build Coastguard Worker n = wsi->http.ah->frags[n].nfrag;
568*1c60b9acSAndroid Build Coastguard Worker
569*1c60b9acSAndroid Build Coastguard Worker /*
570*1c60b9acSAndroid Build Coastguard Worker * Note if you change this logic, take care about updating len
571*1c60b9acSAndroid Build Coastguard Worker * and make sure lws_hdr_total_length() gives the same resulting
572*1c60b9acSAndroid Build Coastguard Worker * length
573*1c60b9acSAndroid Build Coastguard Worker */
574*1c60b9acSAndroid Build Coastguard Worker
575*1c60b9acSAndroid Build Coastguard Worker if (comma) {
576*1c60b9acSAndroid Build Coastguard Worker if (h == WSI_TOKEN_HTTP_COOKIE ||
577*1c60b9acSAndroid Build Coastguard Worker h == WSI_TOKEN_HTTP_SET_COOKIE)
578*1c60b9acSAndroid Build Coastguard Worker *dst++ = ';';
579*1c60b9acSAndroid Build Coastguard Worker else
580*1c60b9acSAndroid Build Coastguard Worker if (h == WSI_TOKEN_HTTP_URI_ARGS)
581*1c60b9acSAndroid Build Coastguard Worker *dst++ = '&';
582*1c60b9acSAndroid Build Coastguard Worker else
583*1c60b9acSAndroid Build Coastguard Worker *dst++ = ',';
584*1c60b9acSAndroid Build Coastguard Worker len--;
585*1c60b9acSAndroid Build Coastguard Worker }
586*1c60b9acSAndroid Build Coastguard Worker
587*1c60b9acSAndroid Build Coastguard Worker } while (n);
588*1c60b9acSAndroid Build Coastguard Worker *dst = '\0';
589*1c60b9acSAndroid Build Coastguard Worker
590*1c60b9acSAndroid Build Coastguard Worker if (h == WSI_TOKEN_HTTP_URI_ARGS)
591*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: WSI_TOKEN_HTTP_URI_ARGS toklen %d\n", __func__, (int)toklen);
592*1c60b9acSAndroid Build Coastguard Worker
593*1c60b9acSAndroid Build Coastguard Worker return toklen;
594*1c60b9acSAndroid Build Coastguard Worker }
595*1c60b9acSAndroid Build Coastguard Worker
596*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CUSTOM_HEADERS)
597*1c60b9acSAndroid Build Coastguard Worker int
lws_hdr_custom_length(struct lws * wsi,const char * name,int nlen)598*1c60b9acSAndroid Build Coastguard Worker lws_hdr_custom_length(struct lws *wsi, const char *name, int nlen)
599*1c60b9acSAndroid Build Coastguard Worker {
600*1c60b9acSAndroid Build Coastguard Worker ah_data_idx_t ll;
601*1c60b9acSAndroid Build Coastguard Worker
602*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah || wsi->mux_substream)
603*1c60b9acSAndroid Build Coastguard Worker return -1;
604*1c60b9acSAndroid Build Coastguard Worker
605*1c60b9acSAndroid Build Coastguard Worker ll = wsi->http.ah->unk_ll_head;
606*1c60b9acSAndroid Build Coastguard Worker while (ll) {
607*1c60b9acSAndroid Build Coastguard Worker if (ll >= wsi->http.ah->data_length)
608*1c60b9acSAndroid Build Coastguard Worker return -1;
609*1c60b9acSAndroid Build Coastguard Worker if (nlen == lws_ser_ru16be(
610*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)&wsi->http.ah->data[ll + UHO_NLEN]) &&
611*1c60b9acSAndroid Build Coastguard Worker !strncmp(name, &wsi->http.ah->data[ll + UHO_NAME], (unsigned int)nlen))
612*1c60b9acSAndroid Build Coastguard Worker return lws_ser_ru16be(
613*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)&wsi->http.ah->data[ll + UHO_VLEN]);
614*1c60b9acSAndroid Build Coastguard Worker
615*1c60b9acSAndroid Build Coastguard Worker ll = lws_ser_ru32be((uint8_t *)&wsi->http.ah->data[ll + UHO_LL]);
616*1c60b9acSAndroid Build Coastguard Worker }
617*1c60b9acSAndroid Build Coastguard Worker
618*1c60b9acSAndroid Build Coastguard Worker return -1;
619*1c60b9acSAndroid Build Coastguard Worker }
620*1c60b9acSAndroid Build Coastguard Worker
621*1c60b9acSAndroid Build Coastguard Worker int
lws_hdr_custom_copy(struct lws * wsi,char * dst,int len,const char * name,int nlen)622*1c60b9acSAndroid Build Coastguard Worker lws_hdr_custom_copy(struct lws *wsi, char *dst, int len, const char *name,
623*1c60b9acSAndroid Build Coastguard Worker int nlen)
624*1c60b9acSAndroid Build Coastguard Worker {
625*1c60b9acSAndroid Build Coastguard Worker ah_data_idx_t ll;
626*1c60b9acSAndroid Build Coastguard Worker int n;
627*1c60b9acSAndroid Build Coastguard Worker
628*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah || wsi->mux_substream)
629*1c60b9acSAndroid Build Coastguard Worker return -1;
630*1c60b9acSAndroid Build Coastguard Worker
631*1c60b9acSAndroid Build Coastguard Worker *dst = '\0';
632*1c60b9acSAndroid Build Coastguard Worker
633*1c60b9acSAndroid Build Coastguard Worker ll = wsi->http.ah->unk_ll_head;
634*1c60b9acSAndroid Build Coastguard Worker while (ll) {
635*1c60b9acSAndroid Build Coastguard Worker if (ll >= wsi->http.ah->data_length)
636*1c60b9acSAndroid Build Coastguard Worker return -1;
637*1c60b9acSAndroid Build Coastguard Worker if (nlen == lws_ser_ru16be(
638*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)&wsi->http.ah->data[ll + UHO_NLEN]) &&
639*1c60b9acSAndroid Build Coastguard Worker !strncmp(name, &wsi->http.ah->data[ll + UHO_NAME], (unsigned int)nlen)) {
640*1c60b9acSAndroid Build Coastguard Worker n = lws_ser_ru16be(
641*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)&wsi->http.ah->data[ll + UHO_VLEN]);
642*1c60b9acSAndroid Build Coastguard Worker if (n + 1 > len)
643*1c60b9acSAndroid Build Coastguard Worker return -1;
644*1c60b9acSAndroid Build Coastguard Worker strncpy(dst, &wsi->http.ah->data[ll + UHO_NAME + (unsigned int)nlen], (unsigned int)n);
645*1c60b9acSAndroid Build Coastguard Worker dst[n] = '\0';
646*1c60b9acSAndroid Build Coastguard Worker
647*1c60b9acSAndroid Build Coastguard Worker return n;
648*1c60b9acSAndroid Build Coastguard Worker }
649*1c60b9acSAndroid Build Coastguard Worker ll = lws_ser_ru32be((uint8_t *)&wsi->http.ah->data[ll + UHO_LL]);
650*1c60b9acSAndroid Build Coastguard Worker }
651*1c60b9acSAndroid Build Coastguard Worker
652*1c60b9acSAndroid Build Coastguard Worker return -1;
653*1c60b9acSAndroid Build Coastguard Worker }
654*1c60b9acSAndroid Build Coastguard Worker
655*1c60b9acSAndroid Build Coastguard Worker int
lws_hdr_custom_name_foreach(struct lws * wsi,lws_hdr_custom_fe_cb_t cb,void * custom)656*1c60b9acSAndroid Build Coastguard Worker lws_hdr_custom_name_foreach(struct lws *wsi, lws_hdr_custom_fe_cb_t cb,
657*1c60b9acSAndroid Build Coastguard Worker void *custom)
658*1c60b9acSAndroid Build Coastguard Worker {
659*1c60b9acSAndroid Build Coastguard Worker ah_data_idx_t ll;
660*1c60b9acSAndroid Build Coastguard Worker
661*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah || wsi->mux_substream)
662*1c60b9acSAndroid Build Coastguard Worker return -1;
663*1c60b9acSAndroid Build Coastguard Worker
664*1c60b9acSAndroid Build Coastguard Worker ll = wsi->http.ah->unk_ll_head;
665*1c60b9acSAndroid Build Coastguard Worker
666*1c60b9acSAndroid Build Coastguard Worker while (ll) {
667*1c60b9acSAndroid Build Coastguard Worker if (ll >= wsi->http.ah->data_length)
668*1c60b9acSAndroid Build Coastguard Worker return -1;
669*1c60b9acSAndroid Build Coastguard Worker
670*1c60b9acSAndroid Build Coastguard Worker cb(&wsi->http.ah->data[ll + UHO_NAME],
671*1c60b9acSAndroid Build Coastguard Worker lws_ser_ru16be((uint8_t *)&wsi->http.ah->data[ll + UHO_NLEN]),
672*1c60b9acSAndroid Build Coastguard Worker custom);
673*1c60b9acSAndroid Build Coastguard Worker
674*1c60b9acSAndroid Build Coastguard Worker ll = lws_ser_ru32be((uint8_t *)&wsi->http.ah->data[ll + UHO_LL]);
675*1c60b9acSAndroid Build Coastguard Worker }
676*1c60b9acSAndroid Build Coastguard Worker
677*1c60b9acSAndroid Build Coastguard Worker return 0;
678*1c60b9acSAndroid Build Coastguard Worker }
679*1c60b9acSAndroid Build Coastguard Worker #endif
680*1c60b9acSAndroid Build Coastguard Worker
lws_hdr_simple_ptr(struct lws * wsi,enum lws_token_indexes h)681*1c60b9acSAndroid Build Coastguard Worker char *lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h)
682*1c60b9acSAndroid Build Coastguard Worker {
683*1c60b9acSAndroid Build Coastguard Worker int n;
684*1c60b9acSAndroid Build Coastguard Worker
685*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah)
686*1c60b9acSAndroid Build Coastguard Worker return NULL;
687*1c60b9acSAndroid Build Coastguard Worker
688*1c60b9acSAndroid Build Coastguard Worker n = wsi->http.ah->frag_index[h];
689*1c60b9acSAndroid Build Coastguard Worker if (!n)
690*1c60b9acSAndroid Build Coastguard Worker return NULL;
691*1c60b9acSAndroid Build Coastguard Worker
692*1c60b9acSAndroid Build Coastguard Worker return wsi->http.ah->data + wsi->http.ah->frags[n].offset;
693*1c60b9acSAndroid Build Coastguard Worker }
694*1c60b9acSAndroid Build Coastguard Worker
695*1c60b9acSAndroid Build Coastguard Worker static int LWS_WARN_UNUSED_RESULT
lws_pos_in_bounds(struct lws * wsi)696*1c60b9acSAndroid Build Coastguard Worker lws_pos_in_bounds(struct lws *wsi)
697*1c60b9acSAndroid Build Coastguard Worker {
698*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah)
699*1c60b9acSAndroid Build Coastguard Worker return -1;
700*1c60b9acSAndroid Build Coastguard Worker
701*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.ah->pos <
702*1c60b9acSAndroid Build Coastguard Worker (unsigned int)wsi->a.context->max_http_header_data)
703*1c60b9acSAndroid Build Coastguard Worker return 0;
704*1c60b9acSAndroid Build Coastguard Worker
705*1c60b9acSAndroid Build Coastguard Worker if ((int)wsi->http.ah->pos >= (int)wsi->a.context->max_http_header_data - 1) {
706*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Ran out of header data space\n");
707*1c60b9acSAndroid Build Coastguard Worker return 1;
708*1c60b9acSAndroid Build Coastguard Worker }
709*1c60b9acSAndroid Build Coastguard Worker
710*1c60b9acSAndroid Build Coastguard Worker /*
711*1c60b9acSAndroid Build Coastguard Worker * with these tests everywhere, it should never be able to exceed
712*1c60b9acSAndroid Build Coastguard Worker * the limit, only meet it
713*1c60b9acSAndroid Build Coastguard Worker */
714*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: pos %ld, limit %ld\n", __func__,
715*1c60b9acSAndroid Build Coastguard Worker (unsigned long)wsi->http.ah->pos,
716*1c60b9acSAndroid Build Coastguard Worker (unsigned long)wsi->a.context->max_http_header_data);
717*1c60b9acSAndroid Build Coastguard Worker assert(0);
718*1c60b9acSAndroid Build Coastguard Worker
719*1c60b9acSAndroid Build Coastguard Worker return 1;
720*1c60b9acSAndroid Build Coastguard Worker }
721*1c60b9acSAndroid Build Coastguard Worker
722*1c60b9acSAndroid Build Coastguard Worker int LWS_WARN_UNUSED_RESULT
lws_hdr_simple_create(struct lws * wsi,enum lws_token_indexes h,const char * s)723*1c60b9acSAndroid Build Coastguard Worker lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s)
724*1c60b9acSAndroid Build Coastguard Worker {
725*1c60b9acSAndroid Build Coastguard Worker if (!*s) {
726*1c60b9acSAndroid Build Coastguard Worker /*
727*1c60b9acSAndroid Build Coastguard Worker * If we get an empty string, then remove any entry for the
728*1c60b9acSAndroid Build Coastguard Worker * header
729*1c60b9acSAndroid Build Coastguard Worker */
730*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frag_index[h] = 0;
731*1c60b9acSAndroid Build Coastguard Worker
732*1c60b9acSAndroid Build Coastguard Worker return 0;
733*1c60b9acSAndroid Build Coastguard Worker }
734*1c60b9acSAndroid Build Coastguard Worker
735*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->nfrag++;
736*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.ah->nfrag == LWS_ARRAY_SIZE(wsi->http.ah->frags)) {
737*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("More hdr frags than we can deal with, dropping\n");
738*1c60b9acSAndroid Build Coastguard Worker return -1;
739*1c60b9acSAndroid Build Coastguard Worker }
740*1c60b9acSAndroid Build Coastguard Worker
741*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frag_index[h] = wsi->http.ah->nfrag;
742*1c60b9acSAndroid Build Coastguard Worker
743*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[wsi->http.ah->nfrag].offset = wsi->http.ah->pos;
744*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[wsi->http.ah->nfrag].len = 0;
745*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[wsi->http.ah->nfrag].nfrag = 0;
746*1c60b9acSAndroid Build Coastguard Worker
747*1c60b9acSAndroid Build Coastguard Worker do {
748*1c60b9acSAndroid Build Coastguard Worker if (lws_pos_in_bounds(wsi))
749*1c60b9acSAndroid Build Coastguard Worker return -1;
750*1c60b9acSAndroid Build Coastguard Worker
751*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->data[wsi->http.ah->pos++] = *s;
752*1c60b9acSAndroid Build Coastguard Worker if (*s)
753*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[wsi->http.ah->nfrag].len++;
754*1c60b9acSAndroid Build Coastguard Worker } while (*s++);
755*1c60b9acSAndroid Build Coastguard Worker
756*1c60b9acSAndroid Build Coastguard Worker return 0;
757*1c60b9acSAndroid Build Coastguard Worker }
758*1c60b9acSAndroid Build Coastguard Worker
759*1c60b9acSAndroid Build Coastguard Worker static int LWS_WARN_UNUSED_RESULT
issue_char(struct lws * wsi,unsigned char c)760*1c60b9acSAndroid Build Coastguard Worker issue_char(struct lws *wsi, unsigned char c)
761*1c60b9acSAndroid Build Coastguard Worker {
762*1c60b9acSAndroid Build Coastguard Worker unsigned short frag_len;
763*1c60b9acSAndroid Build Coastguard Worker
764*1c60b9acSAndroid Build Coastguard Worker if (lws_pos_in_bounds(wsi))
765*1c60b9acSAndroid Build Coastguard Worker return -1;
766*1c60b9acSAndroid Build Coastguard Worker
767*1c60b9acSAndroid Build Coastguard Worker frag_len = wsi->http.ah->frags[wsi->http.ah->nfrag].len;
768*1c60b9acSAndroid Build Coastguard Worker /*
769*1c60b9acSAndroid Build Coastguard Worker * If we haven't hit the token limit, just copy the character into
770*1c60b9acSAndroid Build Coastguard Worker * the header
771*1c60b9acSAndroid Build Coastguard Worker */
772*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah->current_token_limit ||
773*1c60b9acSAndroid Build Coastguard Worker frag_len < wsi->http.ah->current_token_limit) {
774*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->data[wsi->http.ah->pos++] = (char)c;
775*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[wsi->http.ah->nfrag].len++;
776*1c60b9acSAndroid Build Coastguard Worker return 0;
777*1c60b9acSAndroid Build Coastguard Worker }
778*1c60b9acSAndroid Build Coastguard Worker
779*1c60b9acSAndroid Build Coastguard Worker /* Insert a null character when we *hit* the limit: */
780*1c60b9acSAndroid Build Coastguard Worker if (frag_len == wsi->http.ah->current_token_limit) {
781*1c60b9acSAndroid Build Coastguard Worker if (lws_pos_in_bounds(wsi))
782*1c60b9acSAndroid Build Coastguard Worker return -1;
783*1c60b9acSAndroid Build Coastguard Worker
784*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->data[wsi->http.ah->pos++] = '\0';
785*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("header %li exceeds limit %ld\n",
786*1c60b9acSAndroid Build Coastguard Worker (long)wsi->http.ah->parser_state,
787*1c60b9acSAndroid Build Coastguard Worker (long)wsi->http.ah->current_token_limit);
788*1c60b9acSAndroid Build Coastguard Worker }
789*1c60b9acSAndroid Build Coastguard Worker
790*1c60b9acSAndroid Build Coastguard Worker return 1;
791*1c60b9acSAndroid Build Coastguard Worker }
792*1c60b9acSAndroid Build Coastguard Worker
793*1c60b9acSAndroid Build Coastguard Worker int
lws_parse_urldecode(struct lws * wsi,uint8_t * _c)794*1c60b9acSAndroid Build Coastguard Worker lws_parse_urldecode(struct lws *wsi, uint8_t *_c)
795*1c60b9acSAndroid Build Coastguard Worker {
796*1c60b9acSAndroid Build Coastguard Worker struct allocated_headers *ah = wsi->http.ah;
797*1c60b9acSAndroid Build Coastguard Worker unsigned int enc = 0;
798*1c60b9acSAndroid Build Coastguard Worker uint8_t c = *_c;
799*1c60b9acSAndroid Build Coastguard Worker
800*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("ah->ups %d\n", ah->ups);
801*1c60b9acSAndroid Build Coastguard Worker
802*1c60b9acSAndroid Build Coastguard Worker /*
803*1c60b9acSAndroid Build Coastguard Worker * PRIORITY 1
804*1c60b9acSAndroid Build Coastguard Worker * special URI processing... convert %xx
805*1c60b9acSAndroid Build Coastguard Worker */
806*1c60b9acSAndroid Build Coastguard Worker switch (ah->ues) {
807*1c60b9acSAndroid Build Coastguard Worker case URIES_IDLE:
808*1c60b9acSAndroid Build Coastguard Worker if (c == '%') {
809*1c60b9acSAndroid Build Coastguard Worker ah->ues = URIES_SEEN_PERCENT;
810*1c60b9acSAndroid Build Coastguard Worker goto swallow;
811*1c60b9acSAndroid Build Coastguard Worker }
812*1c60b9acSAndroid Build Coastguard Worker break;
813*1c60b9acSAndroid Build Coastguard Worker case URIES_SEEN_PERCENT:
814*1c60b9acSAndroid Build Coastguard Worker if (char_to_hex((char)c) < 0)
815*1c60b9acSAndroid Build Coastguard Worker /* illegal post-% char */
816*1c60b9acSAndroid Build Coastguard Worker goto forbid;
817*1c60b9acSAndroid Build Coastguard Worker
818*1c60b9acSAndroid Build Coastguard Worker ah->esc_stash = (char)c;
819*1c60b9acSAndroid Build Coastguard Worker ah->ues = URIES_SEEN_PERCENT_H1;
820*1c60b9acSAndroid Build Coastguard Worker goto swallow;
821*1c60b9acSAndroid Build Coastguard Worker
822*1c60b9acSAndroid Build Coastguard Worker case URIES_SEEN_PERCENT_H1:
823*1c60b9acSAndroid Build Coastguard Worker if (char_to_hex((char)c) < 0)
824*1c60b9acSAndroid Build Coastguard Worker /* illegal post-% char */
825*1c60b9acSAndroid Build Coastguard Worker goto forbid;
826*1c60b9acSAndroid Build Coastguard Worker
827*1c60b9acSAndroid Build Coastguard Worker *_c = (uint8_t)(unsigned int)((char_to_hex(ah->esc_stash) << 4) |
828*1c60b9acSAndroid Build Coastguard Worker char_to_hex((char)c));
829*1c60b9acSAndroid Build Coastguard Worker c = *_c;
830*1c60b9acSAndroid Build Coastguard Worker enc = 1;
831*1c60b9acSAndroid Build Coastguard Worker ah->ues = URIES_IDLE;
832*1c60b9acSAndroid Build Coastguard Worker break;
833*1c60b9acSAndroid Build Coastguard Worker }
834*1c60b9acSAndroid Build Coastguard Worker
835*1c60b9acSAndroid Build Coastguard Worker /*
836*1c60b9acSAndroid Build Coastguard Worker * PRIORITY 2
837*1c60b9acSAndroid Build Coastguard Worker * special URI processing...
838*1c60b9acSAndroid Build Coastguard Worker * convert /.. or /... or /../ etc to /
839*1c60b9acSAndroid Build Coastguard Worker * convert /./ to /
840*1c60b9acSAndroid Build Coastguard Worker * convert // or /// etc to /
841*1c60b9acSAndroid Build Coastguard Worker * leave /.dir or whatever alone
842*1c60b9acSAndroid Build Coastguard Worker */
843*1c60b9acSAndroid Build Coastguard Worker
844*1c60b9acSAndroid Build Coastguard Worker if (!c && (!ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] ||
845*1c60b9acSAndroid Build Coastguard Worker !ah->post_literal_equal)) {
846*1c60b9acSAndroid Build Coastguard Worker /*
847*1c60b9acSAndroid Build Coastguard Worker * Since user code is typically going to parse the path using
848*1c60b9acSAndroid Build Coastguard Worker * NUL-terminated apis, it's too dangerous to allow NUL
849*1c60b9acSAndroid Build Coastguard Worker * injection here.
850*1c60b9acSAndroid Build Coastguard Worker *
851*1c60b9acSAndroid Build Coastguard Worker * It's allowed in the urlargs, because the apis to access
852*1c60b9acSAndroid Build Coastguard Worker * those only allow retreival with explicit length.
853*1c60b9acSAndroid Build Coastguard Worker */
854*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: saw NUL outside of uri args\n", __func__);
855*1c60b9acSAndroid Build Coastguard Worker return -1;
856*1c60b9acSAndroid Build Coastguard Worker }
857*1c60b9acSAndroid Build Coastguard Worker
858*1c60b9acSAndroid Build Coastguard Worker switch (ah->ups) {
859*1c60b9acSAndroid Build Coastguard Worker case URIPS_IDLE:
860*1c60b9acSAndroid Build Coastguard Worker
861*1c60b9acSAndroid Build Coastguard Worker /* genuine delimiter */
862*1c60b9acSAndroid Build Coastguard Worker if ((c == '&' || c == ';') && !enc) {
863*1c60b9acSAndroid Build Coastguard Worker if (issue_char(wsi, '\0') < 0)
864*1c60b9acSAndroid Build Coastguard Worker return -1;
865*1c60b9acSAndroid Build Coastguard Worker /* don't account for it */
866*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[wsi->http.ah->nfrag].len--;
867*1c60b9acSAndroid Build Coastguard Worker /* link to next fragment */
868*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].nfrag = (uint8_t)(ah->nfrag + 1);
869*1c60b9acSAndroid Build Coastguard Worker ah->nfrag++;
870*1c60b9acSAndroid Build Coastguard Worker if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
871*1c60b9acSAndroid Build Coastguard Worker goto excessive;
872*1c60b9acSAndroid Build Coastguard Worker /* start next fragment after the & */
873*1c60b9acSAndroid Build Coastguard Worker ah->post_literal_equal = 0;
874*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].offset = ++ah->pos;
875*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].len = 0;
876*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].nfrag = 0;
877*1c60b9acSAndroid Build Coastguard Worker goto swallow;
878*1c60b9acSAndroid Build Coastguard Worker }
879*1c60b9acSAndroid Build Coastguard Worker /* uriencoded = in the name part, disallow */
880*1c60b9acSAndroid Build Coastguard Worker if (c == '=' && enc &&
881*1c60b9acSAndroid Build Coastguard Worker ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] &&
882*1c60b9acSAndroid Build Coastguard Worker !ah->post_literal_equal) {
883*1c60b9acSAndroid Build Coastguard Worker c = '_';
884*1c60b9acSAndroid Build Coastguard Worker *_c =c;
885*1c60b9acSAndroid Build Coastguard Worker }
886*1c60b9acSAndroid Build Coastguard Worker
887*1c60b9acSAndroid Build Coastguard Worker /* after the real =, we don't care how many = */
888*1c60b9acSAndroid Build Coastguard Worker if (c == '=' && !enc)
889*1c60b9acSAndroid Build Coastguard Worker ah->post_literal_equal = 1;
890*1c60b9acSAndroid Build Coastguard Worker
891*1c60b9acSAndroid Build Coastguard Worker /* + to space */
892*1c60b9acSAndroid Build Coastguard Worker if (c == '+' && !enc) {
893*1c60b9acSAndroid Build Coastguard Worker c = ' ';
894*1c60b9acSAndroid Build Coastguard Worker *_c = c;
895*1c60b9acSAndroid Build Coastguard Worker }
896*1c60b9acSAndroid Build Coastguard Worker /* issue the first / always */
897*1c60b9acSAndroid Build Coastguard Worker if (c == '/' && !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS])
898*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_SEEN_SLASH;
899*1c60b9acSAndroid Build Coastguard Worker break;
900*1c60b9acSAndroid Build Coastguard Worker case URIPS_SEEN_SLASH:
901*1c60b9acSAndroid Build Coastguard Worker /* swallow subsequent slashes */
902*1c60b9acSAndroid Build Coastguard Worker if (c == '/')
903*1c60b9acSAndroid Build Coastguard Worker goto swallow;
904*1c60b9acSAndroid Build Coastguard Worker /* track and swallow the first . after / */
905*1c60b9acSAndroid Build Coastguard Worker if (c == '.') {
906*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_SEEN_SLASH_DOT;
907*1c60b9acSAndroid Build Coastguard Worker goto swallow;
908*1c60b9acSAndroid Build Coastguard Worker }
909*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_IDLE;
910*1c60b9acSAndroid Build Coastguard Worker break;
911*1c60b9acSAndroid Build Coastguard Worker case URIPS_SEEN_SLASH_DOT:
912*1c60b9acSAndroid Build Coastguard Worker /* swallow second . */
913*1c60b9acSAndroid Build Coastguard Worker if (c == '.') {
914*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_SEEN_SLASH_DOT_DOT;
915*1c60b9acSAndroid Build Coastguard Worker goto swallow;
916*1c60b9acSAndroid Build Coastguard Worker }
917*1c60b9acSAndroid Build Coastguard Worker /* change /./ to / */
918*1c60b9acSAndroid Build Coastguard Worker if (c == '/') {
919*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_SEEN_SLASH;
920*1c60b9acSAndroid Build Coastguard Worker goto swallow;
921*1c60b9acSAndroid Build Coastguard Worker }
922*1c60b9acSAndroid Build Coastguard Worker /* it was like /.dir ... regurgitate the . */
923*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_IDLE;
924*1c60b9acSAndroid Build Coastguard Worker if (issue_char(wsi, '.') < 0)
925*1c60b9acSAndroid Build Coastguard Worker return -1;
926*1c60b9acSAndroid Build Coastguard Worker break;
927*1c60b9acSAndroid Build Coastguard Worker
928*1c60b9acSAndroid Build Coastguard Worker case URIPS_SEEN_SLASH_DOT_DOT:
929*1c60b9acSAndroid Build Coastguard Worker
930*1c60b9acSAndroid Build Coastguard Worker /* /../ or /..[End of URI] --> backup to last / */
931*1c60b9acSAndroid Build Coastguard Worker if (c == '/' || c == '?') {
932*1c60b9acSAndroid Build Coastguard Worker /*
933*1c60b9acSAndroid Build Coastguard Worker * back up one dir level if possible
934*1c60b9acSAndroid Build Coastguard Worker * safe against header fragmentation because
935*1c60b9acSAndroid Build Coastguard Worker * the method URI can only be in 1 fragment
936*1c60b9acSAndroid Build Coastguard Worker */
937*1c60b9acSAndroid Build Coastguard Worker if (ah->frags[ah->nfrag].len > 2) {
938*1c60b9acSAndroid Build Coastguard Worker ah->pos--;
939*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].len--;
940*1c60b9acSAndroid Build Coastguard Worker do {
941*1c60b9acSAndroid Build Coastguard Worker ah->pos--;
942*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].len--;
943*1c60b9acSAndroid Build Coastguard Worker } while (ah->frags[ah->nfrag].len > 1 &&
944*1c60b9acSAndroid Build Coastguard Worker ah->data[ah->pos] != '/');
945*1c60b9acSAndroid Build Coastguard Worker }
946*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_SEEN_SLASH;
947*1c60b9acSAndroid Build Coastguard Worker if (ah->frags[ah->nfrag].len > 1)
948*1c60b9acSAndroid Build Coastguard Worker break;
949*1c60b9acSAndroid Build Coastguard Worker goto swallow;
950*1c60b9acSAndroid Build Coastguard Worker }
951*1c60b9acSAndroid Build Coastguard Worker
952*1c60b9acSAndroid Build Coastguard Worker /* /..[^/] ... regurgitate and allow */
953*1c60b9acSAndroid Build Coastguard Worker
954*1c60b9acSAndroid Build Coastguard Worker if (issue_char(wsi, '.') < 0)
955*1c60b9acSAndroid Build Coastguard Worker return -1;
956*1c60b9acSAndroid Build Coastguard Worker if (issue_char(wsi, '.') < 0)
957*1c60b9acSAndroid Build Coastguard Worker return -1;
958*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_IDLE;
959*1c60b9acSAndroid Build Coastguard Worker break;
960*1c60b9acSAndroid Build Coastguard Worker }
961*1c60b9acSAndroid Build Coastguard Worker
962*1c60b9acSAndroid Build Coastguard Worker if (c == '?' && !enc &&
963*1c60b9acSAndroid Build Coastguard Worker !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS]) { /* start of URI args */
964*1c60b9acSAndroid Build Coastguard Worker if (ah->ues != URIES_IDLE)
965*1c60b9acSAndroid Build Coastguard Worker goto forbid;
966*1c60b9acSAndroid Build Coastguard Worker
967*1c60b9acSAndroid Build Coastguard Worker /* seal off uri header */
968*1c60b9acSAndroid Build Coastguard Worker if (issue_char(wsi, '\0') < 0)
969*1c60b9acSAndroid Build Coastguard Worker return -1;
970*1c60b9acSAndroid Build Coastguard Worker
971*1c60b9acSAndroid Build Coastguard Worker /* don't account for it */
972*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[wsi->http.ah->nfrag].len--;
973*1c60b9acSAndroid Build Coastguard Worker
974*1c60b9acSAndroid Build Coastguard Worker /* move to using WSI_TOKEN_HTTP_URI_ARGS */
975*1c60b9acSAndroid Build Coastguard Worker ah->nfrag++;
976*1c60b9acSAndroid Build Coastguard Worker if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
977*1c60b9acSAndroid Build Coastguard Worker goto excessive;
978*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].offset = ++ah->pos;
979*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].len = 0;
980*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].nfrag = 0;
981*1c60b9acSAndroid Build Coastguard Worker
982*1c60b9acSAndroid Build Coastguard Worker ah->post_literal_equal = 0;
983*1c60b9acSAndroid Build Coastguard Worker ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] = ah->nfrag;
984*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_IDLE;
985*1c60b9acSAndroid Build Coastguard Worker goto swallow;
986*1c60b9acSAndroid Build Coastguard Worker }
987*1c60b9acSAndroid Build Coastguard Worker
988*1c60b9acSAndroid Build Coastguard Worker return LPUR_CONTINUE;
989*1c60b9acSAndroid Build Coastguard Worker
990*1c60b9acSAndroid Build Coastguard Worker swallow:
991*1c60b9acSAndroid Build Coastguard Worker return LPUR_SWALLOW;
992*1c60b9acSAndroid Build Coastguard Worker
993*1c60b9acSAndroid Build Coastguard Worker forbid:
994*1c60b9acSAndroid Build Coastguard Worker return LPUR_FORBID;
995*1c60b9acSAndroid Build Coastguard Worker
996*1c60b9acSAndroid Build Coastguard Worker excessive:
997*1c60b9acSAndroid Build Coastguard Worker return LPUR_EXCESSIVE;
998*1c60b9acSAndroid Build Coastguard Worker }
999*1c60b9acSAndroid Build Coastguard Worker
1000*1c60b9acSAndroid Build Coastguard Worker static const unsigned char methods[] = {
1001*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_GET_URI,
1002*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_POST_URI,
1003*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
1004*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_OPTIONS_URI,
1005*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_PUT_URI,
1006*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_PATCH_URI,
1007*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_DELETE_URI,
1008*1c60b9acSAndroid Build Coastguard Worker #endif
1009*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_CONNECT,
1010*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HEAD_URI,
1011*1c60b9acSAndroid Build Coastguard Worker };
1012*1c60b9acSAndroid Build Coastguard Worker
1013*1c60b9acSAndroid Build Coastguard Worker /*
1014*1c60b9acSAndroid Build Coastguard Worker * possible returns:, -1 fail, 0 ok or 2, transition to raw
1015*1c60b9acSAndroid Build Coastguard Worker */
1016*1c60b9acSAndroid Build Coastguard Worker
1017*1c60b9acSAndroid Build Coastguard Worker lws_parser_return_t LWS_WARN_UNUSED_RESULT
lws_parse(struct lws * wsi,unsigned char * buf,int * len)1018*1c60b9acSAndroid Build Coastguard Worker lws_parse(struct lws *wsi, unsigned char *buf, int *len)
1019*1c60b9acSAndroid Build Coastguard Worker {
1020*1c60b9acSAndroid Build Coastguard Worker struct allocated_headers *ah = wsi->http.ah;
1021*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = wsi->a.context;
1022*1c60b9acSAndroid Build Coastguard Worker unsigned int n, m;
1023*1c60b9acSAndroid Build Coastguard Worker unsigned char c;
1024*1c60b9acSAndroid Build Coastguard Worker int r, pos;
1025*1c60b9acSAndroid Build Coastguard Worker
1026*1c60b9acSAndroid Build Coastguard Worker assert(wsi->http.ah);
1027*1c60b9acSAndroid Build Coastguard Worker
1028*1c60b9acSAndroid Build Coastguard Worker do {
1029*1c60b9acSAndroid Build Coastguard Worker (*len)--;
1030*1c60b9acSAndroid Build Coastguard Worker c = *buf++;
1031*1c60b9acSAndroid Build Coastguard Worker
1032*1c60b9acSAndroid Build Coastguard Worker switch (ah->parser_state) {
1033*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CUSTOM_HEADERS)
1034*1c60b9acSAndroid Build Coastguard Worker case WSI_TOKEN_UNKNOWN_VALUE_PART:
1035*1c60b9acSAndroid Build Coastguard Worker
1036*1c60b9acSAndroid Build Coastguard Worker if (c == '\r')
1037*1c60b9acSAndroid Build Coastguard Worker break;
1038*1c60b9acSAndroid Build Coastguard Worker if (c == '\n') {
1039*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be((uint8_t *)&ah->data[ah->unk_pos + 2],
1040*1c60b9acSAndroid Build Coastguard Worker (uint16_t)(ah->pos - ah->unk_value_pos));
1041*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_NAME_PART;
1042*1c60b9acSAndroid Build Coastguard Worker ah->unk_pos = 0;
1043*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos = 0;
1044*1c60b9acSAndroid Build Coastguard Worker break;
1045*1c60b9acSAndroid Build Coastguard Worker }
1046*1c60b9acSAndroid Build Coastguard Worker
1047*1c60b9acSAndroid Build Coastguard Worker /* trim leading whitespace */
1048*1c60b9acSAndroid Build Coastguard Worker if (ah->pos != ah->unk_value_pos ||
1049*1c60b9acSAndroid Build Coastguard Worker (c != ' ' && c != '\t')) {
1050*1c60b9acSAndroid Build Coastguard Worker
1051*1c60b9acSAndroid Build Coastguard Worker if (lws_pos_in_bounds(wsi))
1052*1c60b9acSAndroid Build Coastguard Worker return LPR_FAIL;
1053*1c60b9acSAndroid Build Coastguard Worker
1054*1c60b9acSAndroid Build Coastguard Worker ah->data[ah->pos++] = (char)c;
1055*1c60b9acSAndroid Build Coastguard Worker }
1056*1c60b9acSAndroid Build Coastguard Worker pos = ah->lextable_pos;
1057*1c60b9acSAndroid Build Coastguard Worker break;
1058*1c60b9acSAndroid Build Coastguard Worker #endif
1059*1c60b9acSAndroid Build Coastguard Worker default:
1060*1c60b9acSAndroid Build Coastguard Worker
1061*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("WSI_TOK_(%d) '%c'\n", ah->parser_state, c);
1062*1c60b9acSAndroid Build Coastguard Worker
1063*1c60b9acSAndroid Build Coastguard Worker /* collect into malloc'd buffers */
1064*1c60b9acSAndroid Build Coastguard Worker /* optional initial space swallow */
1065*1c60b9acSAndroid Build Coastguard Worker if (!ah->frags[ah->frag_index[ah->parser_state]].len &&
1066*1c60b9acSAndroid Build Coastguard Worker c == ' ')
1067*1c60b9acSAndroid Build Coastguard Worker break;
1068*1c60b9acSAndroid Build Coastguard Worker
1069*1c60b9acSAndroid Build Coastguard Worker for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
1070*1c60b9acSAndroid Build Coastguard Worker if (ah->parser_state == methods[m])
1071*1c60b9acSAndroid Build Coastguard Worker break;
1072*1c60b9acSAndroid Build Coastguard Worker if (m == LWS_ARRAY_SIZE(methods))
1073*1c60b9acSAndroid Build Coastguard Worker /* it was not any of the methods */
1074*1c60b9acSAndroid Build Coastguard Worker goto check_eol;
1075*1c60b9acSAndroid Build Coastguard Worker
1076*1c60b9acSAndroid Build Coastguard Worker /* special URI processing... end at space */
1077*1c60b9acSAndroid Build Coastguard Worker
1078*1c60b9acSAndroid Build Coastguard Worker if (c == ' ') {
1079*1c60b9acSAndroid Build Coastguard Worker /* enforce starting with / */
1080*1c60b9acSAndroid Build Coastguard Worker if (!ah->frags[ah->nfrag].len)
1081*1c60b9acSAndroid Build Coastguard Worker if (issue_char(wsi, '/') < 0)
1082*1c60b9acSAndroid Build Coastguard Worker return LPR_FAIL;
1083*1c60b9acSAndroid Build Coastguard Worker
1084*1c60b9acSAndroid Build Coastguard Worker if (ah->ups == URIPS_SEEN_SLASH_DOT_DOT) {
1085*1c60b9acSAndroid Build Coastguard Worker /*
1086*1c60b9acSAndroid Build Coastguard Worker * back up one dir level if possible
1087*1c60b9acSAndroid Build Coastguard Worker * safe against header fragmentation
1088*1c60b9acSAndroid Build Coastguard Worker * because the method URI can only be
1089*1c60b9acSAndroid Build Coastguard Worker * in 1 fragment
1090*1c60b9acSAndroid Build Coastguard Worker */
1091*1c60b9acSAndroid Build Coastguard Worker if (ah->frags[ah->nfrag].len > 2) {
1092*1c60b9acSAndroid Build Coastguard Worker ah->pos--;
1093*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].len--;
1094*1c60b9acSAndroid Build Coastguard Worker do {
1095*1c60b9acSAndroid Build Coastguard Worker ah->pos--;
1096*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].len--;
1097*1c60b9acSAndroid Build Coastguard Worker } while (ah->frags[ah->nfrag].len > 1 &&
1098*1c60b9acSAndroid Build Coastguard Worker ah->data[ah->pos] != '/');
1099*1c60b9acSAndroid Build Coastguard Worker }
1100*1c60b9acSAndroid Build Coastguard Worker }
1101*1c60b9acSAndroid Build Coastguard Worker
1102*1c60b9acSAndroid Build Coastguard Worker /* begin parsing HTTP version: */
1103*1c60b9acSAndroid Build Coastguard Worker if (issue_char(wsi, '\0') < 0)
1104*1c60b9acSAndroid Build Coastguard Worker return LPR_FAIL;
1105*1c60b9acSAndroid Build Coastguard Worker /* don't account for it */
1106*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[wsi->http.ah->nfrag].len--;
1107*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_HTTP;
1108*1c60b9acSAndroid Build Coastguard Worker goto start_fragment;
1109*1c60b9acSAndroid Build Coastguard Worker }
1110*1c60b9acSAndroid Build Coastguard Worker
1111*1c60b9acSAndroid Build Coastguard Worker r = lws_parse_urldecode(wsi, &c);
1112*1c60b9acSAndroid Build Coastguard Worker switch (r) {
1113*1c60b9acSAndroid Build Coastguard Worker case LPUR_CONTINUE:
1114*1c60b9acSAndroid Build Coastguard Worker break;
1115*1c60b9acSAndroid Build Coastguard Worker case LPUR_SWALLOW:
1116*1c60b9acSAndroid Build Coastguard Worker goto swallow;
1117*1c60b9acSAndroid Build Coastguard Worker case LPUR_FORBID:
1118*1c60b9acSAndroid Build Coastguard Worker goto forbid;
1119*1c60b9acSAndroid Build Coastguard Worker case LPUR_EXCESSIVE:
1120*1c60b9acSAndroid Build Coastguard Worker goto excessive;
1121*1c60b9acSAndroid Build Coastguard Worker default:
1122*1c60b9acSAndroid Build Coastguard Worker return LPR_FAIL;
1123*1c60b9acSAndroid Build Coastguard Worker }
1124*1c60b9acSAndroid Build Coastguard Worker check_eol:
1125*1c60b9acSAndroid Build Coastguard Worker /* bail at EOL */
1126*1c60b9acSAndroid Build Coastguard Worker if (ah->parser_state != WSI_TOKEN_CHALLENGE &&
1127*1c60b9acSAndroid Build Coastguard Worker (c == '\x0d' || c == '\x0a')) {
1128*1c60b9acSAndroid Build Coastguard Worker if (ah->ues != URIES_IDLE)
1129*1c60b9acSAndroid Build Coastguard Worker goto forbid;
1130*1c60b9acSAndroid Build Coastguard Worker
1131*1c60b9acSAndroid Build Coastguard Worker if (c == '\x0a') {
1132*1c60b9acSAndroid Build Coastguard Worker /* broken peer */
1133*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_NAME_PART;
1134*1c60b9acSAndroid Build Coastguard Worker ah->unk_pos = 0;
1135*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos = 0;
1136*1c60b9acSAndroid Build Coastguard Worker } else
1137*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
1138*1c60b9acSAndroid Build Coastguard Worker
1139*1c60b9acSAndroid Build Coastguard Worker c = '\0';
1140*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("*\n");
1141*1c60b9acSAndroid Build Coastguard Worker }
1142*1c60b9acSAndroid Build Coastguard Worker
1143*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)issue_char(wsi, c);
1144*1c60b9acSAndroid Build Coastguard Worker if ((int)n < 0)
1145*1c60b9acSAndroid Build Coastguard Worker return LPR_FAIL;
1146*1c60b9acSAndroid Build Coastguard Worker if (n > 0)
1147*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_SKIPPING;
1148*1c60b9acSAndroid Build Coastguard Worker else {
1149*1c60b9acSAndroid Build Coastguard Worker /*
1150*1c60b9acSAndroid Build Coastguard Worker * Explicit zeroes are legal in URI ARGS.
1151*1c60b9acSAndroid Build Coastguard Worker * They can only exist as a safety terminator
1152*1c60b9acSAndroid Build Coastguard Worker * after the valid part of the token contents
1153*1c60b9acSAndroid Build Coastguard Worker * for other types.
1154*1c60b9acSAndroid Build Coastguard Worker */
1155*1c60b9acSAndroid Build Coastguard Worker if (!c && ah->parser_state != WSI_TOKEN_HTTP_URI_ARGS)
1156*1c60b9acSAndroid Build Coastguard Worker /* don't account for safety terminator */
1157*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[wsi->http.ah->nfrag].len--;
1158*1c60b9acSAndroid Build Coastguard Worker }
1159*1c60b9acSAndroid Build Coastguard Worker
1160*1c60b9acSAndroid Build Coastguard Worker swallow:
1161*1c60b9acSAndroid Build Coastguard Worker /* per-protocol end of headers management */
1162*1c60b9acSAndroid Build Coastguard Worker
1163*1c60b9acSAndroid Build Coastguard Worker if (ah->parser_state == WSI_TOKEN_CHALLENGE)
1164*1c60b9acSAndroid Build Coastguard Worker goto set_parsing_complete;
1165*1c60b9acSAndroid Build Coastguard Worker break;
1166*1c60b9acSAndroid Build Coastguard Worker
1167*1c60b9acSAndroid Build Coastguard Worker /* collecting and checking a name part */
1168*1c60b9acSAndroid Build Coastguard Worker case WSI_TOKEN_NAME_PART:
1169*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("WSI_TOKEN_NAME_PART '%c' 0x%02X "
1170*1c60b9acSAndroid Build Coastguard Worker "(role=0x%lx) "
1171*1c60b9acSAndroid Build Coastguard Worker "wsi->lextable_pos=%d\n", c, c,
1172*1c60b9acSAndroid Build Coastguard Worker (unsigned long)lwsi_role(wsi),
1173*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos);
1174*1c60b9acSAndroid Build Coastguard Worker
1175*1c60b9acSAndroid Build Coastguard Worker if (!ah->unk_pos && c == '\x0a')
1176*1c60b9acSAndroid Build Coastguard Worker /* broken peer */
1177*1c60b9acSAndroid Build Coastguard Worker goto set_parsing_complete;
1178*1c60b9acSAndroid Build Coastguard Worker
1179*1c60b9acSAndroid Build Coastguard Worker if (c >= 'A' && c <= 'Z')
1180*1c60b9acSAndroid Build Coastguard Worker c = (unsigned char)(c + 'a' - 'A');
1181*1c60b9acSAndroid Build Coastguard Worker /*
1182*1c60b9acSAndroid Build Coastguard Worker * ...in case it's an unknown header, speculatively
1183*1c60b9acSAndroid Build Coastguard Worker * store it as the name comes in. If we recognize it as
1184*1c60b9acSAndroid Build Coastguard Worker * a known header, we'll snip this.
1185*1c60b9acSAndroid Build Coastguard Worker */
1186*1c60b9acSAndroid Build Coastguard Worker
1187*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream && !ah->unk_pos) {
1188*1c60b9acSAndroid Build Coastguard Worker ah->unk_pos = ah->pos;
1189*1c60b9acSAndroid Build Coastguard Worker
1190*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CUSTOM_HEADERS)
1191*1c60b9acSAndroid Build Coastguard Worker /*
1192*1c60b9acSAndroid Build Coastguard Worker * Prepare new unknown header linked-list entry
1193*1c60b9acSAndroid Build Coastguard Worker *
1194*1c60b9acSAndroid Build Coastguard Worker * - 16-bit BE: name part length
1195*1c60b9acSAndroid Build Coastguard Worker * - 16-bit BE: value part length
1196*1c60b9acSAndroid Build Coastguard Worker * - 32-bit BE: data offset of next, or 0
1197*1c60b9acSAndroid Build Coastguard Worker */
1198*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < 8; n++)
1199*1c60b9acSAndroid Build Coastguard Worker if (!lws_pos_in_bounds(wsi))
1200*1c60b9acSAndroid Build Coastguard Worker ah->data[ah->pos++] = 0;
1201*1c60b9acSAndroid Build Coastguard Worker #endif
1202*1c60b9acSAndroid Build Coastguard Worker }
1203*1c60b9acSAndroid Build Coastguard Worker
1204*1c60b9acSAndroid Build Coastguard Worker if (lws_pos_in_bounds(wsi))
1205*1c60b9acSAndroid Build Coastguard Worker return LPR_FAIL;
1206*1c60b9acSAndroid Build Coastguard Worker
1207*1c60b9acSAndroid Build Coastguard Worker ah->data[ah->pos++] = (char)c;
1208*1c60b9acSAndroid Build Coastguard Worker pos = ah->lextable_pos;
1209*1c60b9acSAndroid Build Coastguard Worker
1210*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CUSTOM_HEADERS)
1211*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream && pos < 0 && c == ':') {
1212*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
1213*1c60b9acSAndroid Build Coastguard Worker char dotstar[64];
1214*1c60b9acSAndroid Build Coastguard Worker int uhlen;
1215*1c60b9acSAndroid Build Coastguard Worker #endif
1216*1c60b9acSAndroid Build Coastguard Worker
1217*1c60b9acSAndroid Build Coastguard Worker /*
1218*1c60b9acSAndroid Build Coastguard Worker * process unknown headers
1219*1c60b9acSAndroid Build Coastguard Worker *
1220*1c60b9acSAndroid Build Coastguard Worker * register us in the unknown hdr ll
1221*1c60b9acSAndroid Build Coastguard Worker */
1222*1c60b9acSAndroid Build Coastguard Worker
1223*1c60b9acSAndroid Build Coastguard Worker if (!ah->unk_ll_head)
1224*1c60b9acSAndroid Build Coastguard Worker ah->unk_ll_head = ah->unk_pos;
1225*1c60b9acSAndroid Build Coastguard Worker
1226*1c60b9acSAndroid Build Coastguard Worker if (ah->unk_ll_tail)
1227*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(
1228*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)&ah->data[ah->unk_ll_tail + UHO_LL],
1229*1c60b9acSAndroid Build Coastguard Worker ah->unk_pos);
1230*1c60b9acSAndroid Build Coastguard Worker
1231*1c60b9acSAndroid Build Coastguard Worker ah->unk_ll_tail = ah->unk_pos;
1232*1c60b9acSAndroid Build Coastguard Worker
1233*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
1234*1c60b9acSAndroid Build Coastguard Worker uhlen = (int)(ah->pos - (ah->unk_pos + UHO_NAME));
1235*1c60b9acSAndroid Build Coastguard Worker lws_strnncpy(dotstar,
1236*1c60b9acSAndroid Build Coastguard Worker &ah->data[ah->unk_pos + UHO_NAME],
1237*1c60b9acSAndroid Build Coastguard Worker uhlen, sizeof(dotstar));
1238*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: unk header %d '%s'\n",
1239*1c60b9acSAndroid Build Coastguard Worker __func__,
1240*1c60b9acSAndroid Build Coastguard Worker ah->pos - (ah->unk_pos + UHO_NAME),
1241*1c60b9acSAndroid Build Coastguard Worker dotstar);
1242*1c60b9acSAndroid Build Coastguard Worker #endif
1243*1c60b9acSAndroid Build Coastguard Worker
1244*1c60b9acSAndroid Build Coastguard Worker /* set the unknown header name part length */
1245*1c60b9acSAndroid Build Coastguard Worker
1246*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be((uint8_t *)&ah->data[ah->unk_pos],
1247*1c60b9acSAndroid Build Coastguard Worker (uint16_t)((ah->pos - ah->unk_pos) - UHO_NAME));
1248*1c60b9acSAndroid Build Coastguard Worker
1249*1c60b9acSAndroid Build Coastguard Worker ah->unk_value_pos = ah->pos;
1250*1c60b9acSAndroid Build Coastguard Worker
1251*1c60b9acSAndroid Build Coastguard Worker /*
1252*1c60b9acSAndroid Build Coastguard Worker * collect whatever's coming for the unknown header
1253*1c60b9acSAndroid Build Coastguard Worker * argument until the next CRLF
1254*1c60b9acSAndroid Build Coastguard Worker */
1255*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_UNKNOWN_VALUE_PART;
1256*1c60b9acSAndroid Build Coastguard Worker break;
1257*1c60b9acSAndroid Build Coastguard Worker }
1258*1c60b9acSAndroid Build Coastguard Worker #endif
1259*1c60b9acSAndroid Build Coastguard Worker if (pos < 0)
1260*1c60b9acSAndroid Build Coastguard Worker break;
1261*1c60b9acSAndroid Build Coastguard Worker
1262*1c60b9acSAndroid Build Coastguard Worker while (1) {
1263*1c60b9acSAndroid Build Coastguard Worker if (lextable_h1[pos] & (1 << 7)) {
1264*1c60b9acSAndroid Build Coastguard Worker /* 1-byte, fail on mismatch */
1265*1c60b9acSAndroid Build Coastguard Worker if ((lextable_h1[pos] & 0x7f) != c) {
1266*1c60b9acSAndroid Build Coastguard Worker nope:
1267*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos = -1;
1268*1c60b9acSAndroid Build Coastguard Worker break;
1269*1c60b9acSAndroid Build Coastguard Worker }
1270*1c60b9acSAndroid Build Coastguard Worker /* fall thru */
1271*1c60b9acSAndroid Build Coastguard Worker pos++;
1272*1c60b9acSAndroid Build Coastguard Worker if (lextable_h1[pos] == FAIL_CHAR)
1273*1c60b9acSAndroid Build Coastguard Worker goto nope;
1274*1c60b9acSAndroid Build Coastguard Worker
1275*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos = (int16_t)pos;
1276*1c60b9acSAndroid Build Coastguard Worker break;
1277*1c60b9acSAndroid Build Coastguard Worker }
1278*1c60b9acSAndroid Build Coastguard Worker
1279*1c60b9acSAndroid Build Coastguard Worker if (lextable_h1[pos] == FAIL_CHAR)
1280*1c60b9acSAndroid Build Coastguard Worker goto nope;
1281*1c60b9acSAndroid Build Coastguard Worker
1282*1c60b9acSAndroid Build Coastguard Worker /* b7 = 0, end or 3-byte */
1283*1c60b9acSAndroid Build Coastguard Worker if (lextable_h1[pos] < FAIL_CHAR) {
1284*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream) {
1285*1c60b9acSAndroid Build Coastguard Worker /*
1286*1c60b9acSAndroid Build Coastguard Worker * We hit a terminal marker, so
1287*1c60b9acSAndroid Build Coastguard Worker * we recognized this header...
1288*1c60b9acSAndroid Build Coastguard Worker * drop the speculative name
1289*1c60b9acSAndroid Build Coastguard Worker * part storage
1290*1c60b9acSAndroid Build Coastguard Worker */
1291*1c60b9acSAndroid Build Coastguard Worker ah->pos = ah->unk_pos;
1292*1c60b9acSAndroid Build Coastguard Worker ah->unk_pos = 0;
1293*1c60b9acSAndroid Build Coastguard Worker }
1294*1c60b9acSAndroid Build Coastguard Worker
1295*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos = (int16_t)pos;
1296*1c60b9acSAndroid Build Coastguard Worker break;
1297*1c60b9acSAndroid Build Coastguard Worker }
1298*1c60b9acSAndroid Build Coastguard Worker
1299*1c60b9acSAndroid Build Coastguard Worker if (lextable_h1[pos] == c) { /* goto */
1300*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos = (int16_t)(pos +
1301*1c60b9acSAndroid Build Coastguard Worker (lextable_h1[pos + 1]) +
1302*1c60b9acSAndroid Build Coastguard Worker (lextable_h1[pos + 2] << 8));
1303*1c60b9acSAndroid Build Coastguard Worker break;
1304*1c60b9acSAndroid Build Coastguard Worker }
1305*1c60b9acSAndroid Build Coastguard Worker
1306*1c60b9acSAndroid Build Coastguard Worker /* fall thru goto */
1307*1c60b9acSAndroid Build Coastguard Worker pos += 3;
1308*1c60b9acSAndroid Build Coastguard Worker /* continue */
1309*1c60b9acSAndroid Build Coastguard Worker }
1310*1c60b9acSAndroid Build Coastguard Worker
1311*1c60b9acSAndroid Build Coastguard Worker /*
1312*1c60b9acSAndroid Build Coastguard Worker * If it's h1, server needs to be on the look out for
1313*1c60b9acSAndroid Build Coastguard Worker * unknown methods...
1314*1c60b9acSAndroid Build Coastguard Worker */
1315*1c60b9acSAndroid Build Coastguard Worker if (ah->lextable_pos < 0 && lwsi_role_h1(wsi) &&
1316*1c60b9acSAndroid Build Coastguard Worker lwsi_role_server(wsi)) {
1317*1c60b9acSAndroid Build Coastguard Worker /*
1318*1c60b9acSAndroid Build Coastguard Worker * this is not a header we know about... did
1319*1c60b9acSAndroid Build Coastguard Worker * we get a valid method (GET, POST etc)
1320*1c60b9acSAndroid Build Coastguard Worker * already, or is this the bogus method?
1321*1c60b9acSAndroid Build Coastguard Worker */
1322*1c60b9acSAndroid Build Coastguard Worker for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
1323*1c60b9acSAndroid Build Coastguard Worker if (ah->frag_index[methods[m]]) {
1324*1c60b9acSAndroid Build Coastguard Worker /*
1325*1c60b9acSAndroid Build Coastguard Worker * already had the method
1326*1c60b9acSAndroid Build Coastguard Worker */
1327*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITH_CUSTOM_HEADERS)
1328*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_SKIPPING;
1329*1c60b9acSAndroid Build Coastguard Worker #endif
1330*1c60b9acSAndroid Build Coastguard Worker if (wsi->mux_substream)
1331*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_SKIPPING;
1332*1c60b9acSAndroid Build Coastguard Worker break;
1333*1c60b9acSAndroid Build Coastguard Worker }
1334*1c60b9acSAndroid Build Coastguard Worker
1335*1c60b9acSAndroid Build Coastguard Worker if (m != LWS_ARRAY_SIZE(methods)) {
1336*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CUSTOM_HEADERS)
1337*1c60b9acSAndroid Build Coastguard Worker /*
1338*1c60b9acSAndroid Build Coastguard Worker * We have the method, this is just an
1339*1c60b9acSAndroid Build Coastguard Worker * unknown header then
1340*1c60b9acSAndroid Build Coastguard Worker */
1341*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream)
1342*1c60b9acSAndroid Build Coastguard Worker goto unknown_hdr;
1343*1c60b9acSAndroid Build Coastguard Worker else
1344*1c60b9acSAndroid Build Coastguard Worker break;
1345*1c60b9acSAndroid Build Coastguard Worker #else
1346*1c60b9acSAndroid Build Coastguard Worker break;
1347*1c60b9acSAndroid Build Coastguard Worker #endif
1348*1c60b9acSAndroid Build Coastguard Worker }
1349*1c60b9acSAndroid Build Coastguard Worker /*
1350*1c60b9acSAndroid Build Coastguard Worker * ...it's an unknown http method from a client
1351*1c60b9acSAndroid Build Coastguard Worker * in fact, it cannot be valid http.
1352*1c60b9acSAndroid Build Coastguard Worker *
1353*1c60b9acSAndroid Build Coastguard Worker * Are we set up to transition to another role
1354*1c60b9acSAndroid Build Coastguard Worker * in these cases?
1355*1c60b9acSAndroid Build Coastguard Worker */
1356*1c60b9acSAndroid Build Coastguard Worker if (lws_check_opt(wsi->a.vhost->options,
1357*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG)) {
1358*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: http fail fallback\n",
1359*1c60b9acSAndroid Build Coastguard Worker __func__);
1360*1c60b9acSAndroid Build Coastguard Worker /* transition to other role */
1361*1c60b9acSAndroid Build Coastguard Worker return LPR_DO_FALLBACK;
1362*1c60b9acSAndroid Build Coastguard Worker }
1363*1c60b9acSAndroid Build Coastguard Worker
1364*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Unknown method - dropping\n");
1365*1c60b9acSAndroid Build Coastguard Worker goto forbid;
1366*1c60b9acSAndroid Build Coastguard Worker }
1367*1c60b9acSAndroid Build Coastguard Worker if (ah->lextable_pos < 0) {
1368*1c60b9acSAndroid Build Coastguard Worker /*
1369*1c60b9acSAndroid Build Coastguard Worker * It's not a header that lws knows about...
1370*1c60b9acSAndroid Build Coastguard Worker */
1371*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CUSTOM_HEADERS)
1372*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream)
1373*1c60b9acSAndroid Build Coastguard Worker goto unknown_hdr;
1374*1c60b9acSAndroid Build Coastguard Worker #endif
1375*1c60b9acSAndroid Build Coastguard Worker /*
1376*1c60b9acSAndroid Build Coastguard Worker * ...otherwise for a client, let him ignore
1377*1c60b9acSAndroid Build Coastguard Worker * unknown headers coming from the server
1378*1c60b9acSAndroid Build Coastguard Worker */
1379*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_SKIPPING;
1380*1c60b9acSAndroid Build Coastguard Worker break;
1381*1c60b9acSAndroid Build Coastguard Worker }
1382*1c60b9acSAndroid Build Coastguard Worker
1383*1c60b9acSAndroid Build Coastguard Worker if (lextable_h1[ah->lextable_pos] < FAIL_CHAR) {
1384*1c60b9acSAndroid Build Coastguard Worker /* terminal state */
1385*1c60b9acSAndroid Build Coastguard Worker
1386*1c60b9acSAndroid Build Coastguard Worker n = ((unsigned int)lextable_h1[ah->lextable_pos] << 8) |
1387*1c60b9acSAndroid Build Coastguard Worker lextable_h1[ah->lextable_pos + 1];
1388*1c60b9acSAndroid Build Coastguard Worker
1389*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("known hdr %d\n", n);
1390*1c60b9acSAndroid Build Coastguard Worker for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
1391*1c60b9acSAndroid Build Coastguard Worker if (n == methods[m] &&
1392*1c60b9acSAndroid Build Coastguard Worker ah->frag_index[methods[m]]) {
1393*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("Duplicated method\n");
1394*1c60b9acSAndroid Build Coastguard Worker return LPR_FAIL;
1395*1c60b9acSAndroid Build Coastguard Worker }
1396*1c60b9acSAndroid Build Coastguard Worker
1397*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream) {
1398*1c60b9acSAndroid Build Coastguard Worker /*
1399*1c60b9acSAndroid Build Coastguard Worker * Whether we are collecting unknown names or not,
1400*1c60b9acSAndroid Build Coastguard Worker * if we matched an internal header we can dispense
1401*1c60b9acSAndroid Build Coastguard Worker * with the header name part we were keeping
1402*1c60b9acSAndroid Build Coastguard Worker */
1403*1c60b9acSAndroid Build Coastguard Worker ah->pos = ah->unk_pos;
1404*1c60b9acSAndroid Build Coastguard Worker ah->unk_pos = 0;
1405*1c60b9acSAndroid Build Coastguard Worker }
1406*1c60b9acSAndroid Build Coastguard Worker
1407*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
1408*1c60b9acSAndroid Build Coastguard Worker /*
1409*1c60b9acSAndroid Build Coastguard Worker * WSORIGIN is protocol equiv to ORIGIN,
1410*1c60b9acSAndroid Build Coastguard Worker * JWebSocket likes to send it, map to ORIGIN
1411*1c60b9acSAndroid Build Coastguard Worker */
1412*1c60b9acSAndroid Build Coastguard Worker if (n == WSI_TOKEN_SWORIGIN)
1413*1c60b9acSAndroid Build Coastguard Worker n = WSI_TOKEN_ORIGIN;
1414*1c60b9acSAndroid Build Coastguard Worker #endif
1415*1c60b9acSAndroid Build Coastguard Worker
1416*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = (uint8_t)
1417*1c60b9acSAndroid Build Coastguard Worker (WSI_TOKEN_GET_URI + n);
1418*1c60b9acSAndroid Build Coastguard Worker ah->ups = URIPS_IDLE;
1419*1c60b9acSAndroid Build Coastguard Worker
1420*1c60b9acSAndroid Build Coastguard Worker if (context->token_limits)
1421*1c60b9acSAndroid Build Coastguard Worker ah->current_token_limit = context->
1422*1c60b9acSAndroid Build Coastguard Worker token_limits->token_limit[
1423*1c60b9acSAndroid Build Coastguard Worker ah->parser_state];
1424*1c60b9acSAndroid Build Coastguard Worker else
1425*1c60b9acSAndroid Build Coastguard Worker ah->current_token_limit =
1426*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->max_http_header_data;
1427*1c60b9acSAndroid Build Coastguard Worker
1428*1c60b9acSAndroid Build Coastguard Worker if (ah->parser_state == WSI_TOKEN_CHALLENGE)
1429*1c60b9acSAndroid Build Coastguard Worker goto set_parsing_complete;
1430*1c60b9acSAndroid Build Coastguard Worker
1431*1c60b9acSAndroid Build Coastguard Worker goto start_fragment;
1432*1c60b9acSAndroid Build Coastguard Worker }
1433*1c60b9acSAndroid Build Coastguard Worker break;
1434*1c60b9acSAndroid Build Coastguard Worker
1435*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CUSTOM_HEADERS)
1436*1c60b9acSAndroid Build Coastguard Worker unknown_hdr:
1437*1c60b9acSAndroid Build Coastguard Worker //ah->parser_state = WSI_TOKEN_SKIPPING;
1438*1c60b9acSAndroid Build Coastguard Worker //break;
1439*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream)
1440*1c60b9acSAndroid Build Coastguard Worker break;
1441*1c60b9acSAndroid Build Coastguard Worker #endif
1442*1c60b9acSAndroid Build Coastguard Worker
1443*1c60b9acSAndroid Build Coastguard Worker start_fragment:
1444*1c60b9acSAndroid Build Coastguard Worker ah->nfrag++;
1445*1c60b9acSAndroid Build Coastguard Worker excessive:
1446*1c60b9acSAndroid Build Coastguard Worker if (ah->nfrag == LWS_ARRAY_SIZE(ah->frags)) {
1447*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("More hdr frags than we can deal with\n");
1448*1c60b9acSAndroid Build Coastguard Worker return LPR_FAIL;
1449*1c60b9acSAndroid Build Coastguard Worker }
1450*1c60b9acSAndroid Build Coastguard Worker
1451*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].offset = ah->pos;
1452*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].len = 0;
1453*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].nfrag = 0;
1454*1c60b9acSAndroid Build Coastguard Worker ah->frags[ah->nfrag].flags = 2;
1455*1c60b9acSAndroid Build Coastguard Worker
1456*1c60b9acSAndroid Build Coastguard Worker n = ah->frag_index[ah->parser_state];
1457*1c60b9acSAndroid Build Coastguard Worker if (!n) { /* first fragment */
1458*1c60b9acSAndroid Build Coastguard Worker ah->frag_index[ah->parser_state] = ah->nfrag;
1459*1c60b9acSAndroid Build Coastguard Worker ah->hdr_token_idx = ah->parser_state;
1460*1c60b9acSAndroid Build Coastguard Worker break;
1461*1c60b9acSAndroid Build Coastguard Worker }
1462*1c60b9acSAndroid Build Coastguard Worker /* continuation */
1463*1c60b9acSAndroid Build Coastguard Worker while (ah->frags[n].nfrag)
1464*1c60b9acSAndroid Build Coastguard Worker n = ah->frags[n].nfrag;
1465*1c60b9acSAndroid Build Coastguard Worker ah->frags[n].nfrag = ah->nfrag;
1466*1c60b9acSAndroid Build Coastguard Worker
1467*1c60b9acSAndroid Build Coastguard Worker if (issue_char(wsi, ' ') < 0)
1468*1c60b9acSAndroid Build Coastguard Worker return LPR_FAIL;
1469*1c60b9acSAndroid Build Coastguard Worker break;
1470*1c60b9acSAndroid Build Coastguard Worker
1471*1c60b9acSAndroid Build Coastguard Worker /* skipping arg part of a name we didn't recognize */
1472*1c60b9acSAndroid Build Coastguard Worker case WSI_TOKEN_SKIPPING:
1473*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c);
1474*1c60b9acSAndroid Build Coastguard Worker
1475*1c60b9acSAndroid Build Coastguard Worker if (c == '\x0a') {
1476*1c60b9acSAndroid Build Coastguard Worker /* broken peer */
1477*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_NAME_PART;
1478*1c60b9acSAndroid Build Coastguard Worker ah->unk_pos = 0;
1479*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos = 0;
1480*1c60b9acSAndroid Build Coastguard Worker }
1481*1c60b9acSAndroid Build Coastguard Worker
1482*1c60b9acSAndroid Build Coastguard Worker if (c == '\x0d')
1483*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
1484*1c60b9acSAndroid Build Coastguard Worker break;
1485*1c60b9acSAndroid Build Coastguard Worker
1486*1c60b9acSAndroid Build Coastguard Worker case WSI_TOKEN_SKIPPING_SAW_CR:
1487*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
1488*1c60b9acSAndroid Build Coastguard Worker if (ah->ues != URIES_IDLE)
1489*1c60b9acSAndroid Build Coastguard Worker goto forbid;
1490*1c60b9acSAndroid Build Coastguard Worker if (c == '\x0a') {
1491*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_NAME_PART;
1492*1c60b9acSAndroid Build Coastguard Worker ah->unk_pos = 0;
1493*1c60b9acSAndroid Build Coastguard Worker ah->lextable_pos = 0;
1494*1c60b9acSAndroid Build Coastguard Worker } else
1495*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_TOKEN_SKIPPING;
1496*1c60b9acSAndroid Build Coastguard Worker break;
1497*1c60b9acSAndroid Build Coastguard Worker /* we're done, ignore anything else */
1498*1c60b9acSAndroid Build Coastguard Worker
1499*1c60b9acSAndroid Build Coastguard Worker case WSI_PARSING_COMPLETE:
1500*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("WSI_PARSING_COMPLETE '%c'\n", c);
1501*1c60b9acSAndroid Build Coastguard Worker break;
1502*1c60b9acSAndroid Build Coastguard Worker }
1503*1c60b9acSAndroid Build Coastguard Worker
1504*1c60b9acSAndroid Build Coastguard Worker } while (*len);
1505*1c60b9acSAndroid Build Coastguard Worker
1506*1c60b9acSAndroid Build Coastguard Worker return LPR_OK;
1507*1c60b9acSAndroid Build Coastguard Worker
1508*1c60b9acSAndroid Build Coastguard Worker set_parsing_complete:
1509*1c60b9acSAndroid Build Coastguard Worker if (ah->ues != URIES_IDLE)
1510*1c60b9acSAndroid Build Coastguard Worker goto forbid;
1511*1c60b9acSAndroid Build Coastguard Worker
1512*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
1513*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
1514*1c60b9acSAndroid Build Coastguard Worker const char *pv = lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION);
1515*1c60b9acSAndroid Build Coastguard Worker if (pv)
1516*1c60b9acSAndroid Build Coastguard Worker wsi->rx_frame_type = (char)atoi(pv);
1517*1c60b9acSAndroid Build Coastguard Worker
1518*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("v%02d hdrs done\n", wsi->rx_frame_type);
1519*1c60b9acSAndroid Build Coastguard Worker #endif
1520*1c60b9acSAndroid Build Coastguard Worker }
1521*1c60b9acSAndroid Build Coastguard Worker ah->parser_state = WSI_PARSING_COMPLETE;
1522*1c60b9acSAndroid Build Coastguard Worker wsi->hdr_parsing_completed = 1;
1523*1c60b9acSAndroid Build Coastguard Worker
1524*1c60b9acSAndroid Build Coastguard Worker return LPR_OK;
1525*1c60b9acSAndroid Build Coastguard Worker
1526*1c60b9acSAndroid Build Coastguard Worker forbid:
1527*1c60b9acSAndroid Build Coastguard Worker lwsl_info(" forbidding on uri sanitation\n");
1528*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
1529*1c60b9acSAndroid Build Coastguard Worker lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
1530*1c60b9acSAndroid Build Coastguard Worker #endif
1531*1c60b9acSAndroid Build Coastguard Worker
1532*1c60b9acSAndroid Build Coastguard Worker return LPR_FORBIDDEN;
1533*1c60b9acSAndroid Build Coastguard Worker }
1534*1c60b9acSAndroid Build Coastguard Worker
1535*1c60b9acSAndroid Build Coastguard Worker int
lws_http_cookie_get(struct lws * wsi,const char * name,char * buf,size_t * max_len)1536*1c60b9acSAndroid Build Coastguard Worker lws_http_cookie_get(struct lws *wsi, const char *name, char *buf,
1537*1c60b9acSAndroid Build Coastguard Worker size_t *max_len)
1538*1c60b9acSAndroid Build Coastguard Worker {
1539*1c60b9acSAndroid Build Coastguard Worker size_t max = *max_len, bl = strlen(name);
1540*1c60b9acSAndroid Build Coastguard Worker char *p, *bo = buf;
1541*1c60b9acSAndroid Build Coastguard Worker int n;
1542*1c60b9acSAndroid Build Coastguard Worker
1543*1c60b9acSAndroid Build Coastguard Worker n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE);
1544*1c60b9acSAndroid Build Coastguard Worker if ((unsigned int)n < bl + 1)
1545*1c60b9acSAndroid Build Coastguard Worker return 1;
1546*1c60b9acSAndroid Build Coastguard Worker
1547*1c60b9acSAndroid Build Coastguard Worker /*
1548*1c60b9acSAndroid Build Coastguard Worker * This can come to us two ways, in ah fragments (h2) or as a single
1549*1c60b9acSAndroid Build Coastguard Worker * semicolon-delimited string (h1)
1550*1c60b9acSAndroid Build Coastguard Worker */
1551*1c60b9acSAndroid Build Coastguard Worker
1552*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
1553*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_METHOD)) {
1554*1c60b9acSAndroid Build Coastguard Worker
1555*1c60b9acSAndroid Build Coastguard Worker /*
1556*1c60b9acSAndroid Build Coastguard Worker * The h2 way...
1557*1c60b9acSAndroid Build Coastguard Worker */
1558*1c60b9acSAndroid Build Coastguard Worker
1559*1c60b9acSAndroid Build Coastguard Worker int f = wsi->http.ah->frag_index[WSI_TOKEN_HTTP_COOKIE];
1560*1c60b9acSAndroid Build Coastguard Worker size_t fl;
1561*1c60b9acSAndroid Build Coastguard Worker
1562*1c60b9acSAndroid Build Coastguard Worker while (f) {
1563*1c60b9acSAndroid Build Coastguard Worker p = wsi->http.ah->data + wsi->http.ah->frags[f].offset;
1564*1c60b9acSAndroid Build Coastguard Worker fl = (size_t)wsi->http.ah->frags[f].len;
1565*1c60b9acSAndroid Build Coastguard Worker if (fl >= bl + 1 &&
1566*1c60b9acSAndroid Build Coastguard Worker p[bl] == '=' &&
1567*1c60b9acSAndroid Build Coastguard Worker !memcmp(p, name, bl)) {
1568*1c60b9acSAndroid Build Coastguard Worker fl -= bl + 1;
1569*1c60b9acSAndroid Build Coastguard Worker if (max - 1 < fl)
1570*1c60b9acSAndroid Build Coastguard Worker fl = max - 1;
1571*1c60b9acSAndroid Build Coastguard Worker if (fl)
1572*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, p + bl + 1, fl);
1573*1c60b9acSAndroid Build Coastguard Worker *max_len = fl;
1574*1c60b9acSAndroid Build Coastguard Worker buf[fl] = '\0';
1575*1c60b9acSAndroid Build Coastguard Worker
1576*1c60b9acSAndroid Build Coastguard Worker return 0;
1577*1c60b9acSAndroid Build Coastguard Worker }
1578*1c60b9acSAndroid Build Coastguard Worker f = wsi->http.ah->frags[f].nfrag;
1579*1c60b9acSAndroid Build Coastguard Worker }
1580*1c60b9acSAndroid Build Coastguard Worker
1581*1c60b9acSAndroid Build Coastguard Worker return -1;
1582*1c60b9acSAndroid Build Coastguard Worker }
1583*1c60b9acSAndroid Build Coastguard Worker #endif
1584*1c60b9acSAndroid Build Coastguard Worker
1585*1c60b9acSAndroid Build Coastguard Worker /*
1586*1c60b9acSAndroid Build Coastguard Worker * The h1 way...
1587*1c60b9acSAndroid Build Coastguard Worker */
1588*1c60b9acSAndroid Build Coastguard Worker
1589*1c60b9acSAndroid Build Coastguard Worker p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COOKIE);
1590*1c60b9acSAndroid Build Coastguard Worker if (!p)
1591*1c60b9acSAndroid Build Coastguard Worker return 1;
1592*1c60b9acSAndroid Build Coastguard Worker
1593*1c60b9acSAndroid Build Coastguard Worker p += bl;
1594*1c60b9acSAndroid Build Coastguard Worker n -= (int)bl;
1595*1c60b9acSAndroid Build Coastguard Worker while (n-- > 0) {
1596*1c60b9acSAndroid Build Coastguard Worker if (*p == '=' && !memcmp(p - bl, name, (unsigned int)bl)) {
1597*1c60b9acSAndroid Build Coastguard Worker p++;
1598*1c60b9acSAndroid Build Coastguard Worker while (*p != ';' && n-- && max) {
1599*1c60b9acSAndroid Build Coastguard Worker *buf++ = *p++;
1600*1c60b9acSAndroid Build Coastguard Worker max--;
1601*1c60b9acSAndroid Build Coastguard Worker }
1602*1c60b9acSAndroid Build Coastguard Worker if (!max)
1603*1c60b9acSAndroid Build Coastguard Worker return 2;
1604*1c60b9acSAndroid Build Coastguard Worker
1605*1c60b9acSAndroid Build Coastguard Worker *buf = '\0';
1606*1c60b9acSAndroid Build Coastguard Worker *max_len = lws_ptr_diff_size_t(buf, bo);
1607*1c60b9acSAndroid Build Coastguard Worker
1608*1c60b9acSAndroid Build Coastguard Worker return 0;
1609*1c60b9acSAndroid Build Coastguard Worker }
1610*1c60b9acSAndroid Build Coastguard Worker p++;
1611*1c60b9acSAndroid Build Coastguard Worker }
1612*1c60b9acSAndroid Build Coastguard Worker
1613*1c60b9acSAndroid Build Coastguard Worker return 1;
1614*1c60b9acSAndroid Build Coastguard Worker }
1615*1c60b9acSAndroid Build Coastguard Worker
1616*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_JOSE)
1617*1c60b9acSAndroid Build Coastguard Worker
1618*1c60b9acSAndroid Build Coastguard Worker #define MAX_JWT_SIZE 1024
1619*1c60b9acSAndroid Build Coastguard Worker
1620*1c60b9acSAndroid Build Coastguard Worker int
lws_jwt_get_http_cookie_validate_jwt(struct lws * wsi,struct lws_jwt_sign_set_cookie * i,char * out,size_t * out_len)1621*1c60b9acSAndroid Build Coastguard Worker lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi,
1622*1c60b9acSAndroid Build Coastguard Worker struct lws_jwt_sign_set_cookie *i,
1623*1c60b9acSAndroid Build Coastguard Worker char *out, size_t *out_len)
1624*1c60b9acSAndroid Build Coastguard Worker {
1625*1c60b9acSAndroid Build Coastguard Worker char temp[MAX_JWT_SIZE * 2];
1626*1c60b9acSAndroid Build Coastguard Worker size_t cml = *out_len;
1627*1c60b9acSAndroid Build Coastguard Worker const char *cp;
1628*1c60b9acSAndroid Build Coastguard Worker
1629*1c60b9acSAndroid Build Coastguard Worker /* first use out to hold the encoded JWT */
1630*1c60b9acSAndroid Build Coastguard Worker
1631*1c60b9acSAndroid Build Coastguard Worker if (lws_http_cookie_get(wsi, i->cookie_name, out, out_len)) {
1632*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: cookie %s not provided\n", __func__,
1633*1c60b9acSAndroid Build Coastguard Worker i->cookie_name);
1634*1c60b9acSAndroid Build Coastguard Worker return 1;
1635*1c60b9acSAndroid Build Coastguard Worker }
1636*1c60b9acSAndroid Build Coastguard Worker
1637*1c60b9acSAndroid Build Coastguard Worker /* decode the JWT into temp */
1638*1c60b9acSAndroid Build Coastguard Worker
1639*1c60b9acSAndroid Build Coastguard Worker if (lws_jwt_signed_validate(wsi->a.context, i->jwk, i->alg, out,
1640*1c60b9acSAndroid Build Coastguard Worker *out_len, temp, sizeof(temp), out, &cml)) {
1641*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: jwt validation failed\n", __func__);
1642*1c60b9acSAndroid Build Coastguard Worker return 1;
1643*1c60b9acSAndroid Build Coastguard Worker }
1644*1c60b9acSAndroid Build Coastguard Worker
1645*1c60b9acSAndroid Build Coastguard Worker /*
1646*1c60b9acSAndroid Build Coastguard Worker * Copy out the decoded JWT payload into out, overwriting the
1647*1c60b9acSAndroid Build Coastguard Worker * original encoded JWT taken from the cookie (that has long ago been
1648*1c60b9acSAndroid Build Coastguard Worker * translated into allocated buffers in the JOSE object)
1649*1c60b9acSAndroid Build Coastguard Worker */
1650*1c60b9acSAndroid Build Coastguard Worker
1651*1c60b9acSAndroid Build Coastguard Worker if (lws_jwt_token_sanity(out, cml, i->iss, i->aud, i->csrf_in,
1652*1c60b9acSAndroid Build Coastguard Worker i->sub, sizeof(i->sub),
1653*1c60b9acSAndroid Build Coastguard Worker &i->expiry_unix_time)) {
1654*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: jwt sanity failed\n", __func__);
1655*1c60b9acSAndroid Build Coastguard Worker return 1;
1656*1c60b9acSAndroid Build Coastguard Worker }
1657*1c60b9acSAndroid Build Coastguard Worker
1658*1c60b9acSAndroid Build Coastguard Worker /*
1659*1c60b9acSAndroid Build Coastguard Worker * If he's interested in his private JSON part, point him to that in
1660*1c60b9acSAndroid Build Coastguard Worker * the args struct (it's pointing to the data in out
1661*1c60b9acSAndroid Build Coastguard Worker */
1662*1c60b9acSAndroid Build Coastguard Worker
1663*1c60b9acSAndroid Build Coastguard Worker cp = lws_json_simple_find(out, cml, "\"ext\":", &i->extra_json_len);
1664*1c60b9acSAndroid Build Coastguard Worker if (cp)
1665*1c60b9acSAndroid Build Coastguard Worker i->extra_json = cp;
1666*1c60b9acSAndroid Build Coastguard Worker
1667*1c60b9acSAndroid Build Coastguard Worker if (!cp)
1668*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: no ext JWT payload\n", __func__);
1669*1c60b9acSAndroid Build Coastguard Worker
1670*1c60b9acSAndroid Build Coastguard Worker return 0;
1671*1c60b9acSAndroid Build Coastguard Worker }
1672*1c60b9acSAndroid Build Coastguard Worker
1673*1c60b9acSAndroid Build Coastguard Worker int
lws_jwt_sign_token_set_http_cookie(struct lws * wsi,const struct lws_jwt_sign_set_cookie * i,uint8_t ** p,uint8_t * end)1674*1c60b9acSAndroid Build Coastguard Worker lws_jwt_sign_token_set_http_cookie(struct lws *wsi,
1675*1c60b9acSAndroid Build Coastguard Worker const struct lws_jwt_sign_set_cookie *i,
1676*1c60b9acSAndroid Build Coastguard Worker uint8_t **p, uint8_t *end)
1677*1c60b9acSAndroid Build Coastguard Worker {
1678*1c60b9acSAndroid Build Coastguard Worker char plain[MAX_JWT_SIZE + 1], temp[MAX_JWT_SIZE * 2], csrf[17];
1679*1c60b9acSAndroid Build Coastguard Worker size_t pl = sizeof(plain);
1680*1c60b9acSAndroid Build Coastguard Worker unsigned long long ull;
1681*1c60b9acSAndroid Build Coastguard Worker int n;
1682*1c60b9acSAndroid Build Coastguard Worker
1683*1c60b9acSAndroid Build Coastguard Worker /*
1684*1c60b9acSAndroid Build Coastguard Worker * Create a 16-char random csrf token with the same lifetime as the JWT
1685*1c60b9acSAndroid Build Coastguard Worker */
1686*1c60b9acSAndroid Build Coastguard Worker
1687*1c60b9acSAndroid Build Coastguard Worker lws_hex_random(wsi->a.context, csrf, sizeof(csrf));
1688*1c60b9acSAndroid Build Coastguard Worker ull = lws_now_secs();
1689*1c60b9acSAndroid Build Coastguard Worker if (lws_jwt_sign_compact(wsi->a.context, i->jwk, i->alg, plain, &pl,
1690*1c60b9acSAndroid Build Coastguard Worker temp, sizeof(temp),
1691*1c60b9acSAndroid Build Coastguard Worker "{\"iss\":\"%s\",\"aud\":\"%s\","
1692*1c60b9acSAndroid Build Coastguard Worker "\"iat\":%llu,\"nbf\":%llu,\"exp\":%llu,"
1693*1c60b9acSAndroid Build Coastguard Worker "\"csrf\":\"%s\",\"sub\":\"%s\"%s%s%s}",
1694*1c60b9acSAndroid Build Coastguard Worker i->iss, i->aud, ull, ull - 60,
1695*1c60b9acSAndroid Build Coastguard Worker ull + i->expiry_unix_time,
1696*1c60b9acSAndroid Build Coastguard Worker csrf, i->sub,
1697*1c60b9acSAndroid Build Coastguard Worker i->extra_json ? ",\"ext\":{" : "",
1698*1c60b9acSAndroid Build Coastguard Worker i->extra_json ? i->extra_json : "",
1699*1c60b9acSAndroid Build Coastguard Worker i->extra_json ? "}" : "")) {
1700*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed to create JWT\n", __func__);
1701*1c60b9acSAndroid Build Coastguard Worker
1702*1c60b9acSAndroid Build Coastguard Worker return 1;
1703*1c60b9acSAndroid Build Coastguard Worker }
1704*1c60b9acSAndroid Build Coastguard Worker
1705*1c60b9acSAndroid Build Coastguard Worker /*
1706*1c60b9acSAndroid Build Coastguard Worker * There's no point the browser holding on to a JWT beyond the JWT's
1707*1c60b9acSAndroid Build Coastguard Worker * expiry time, so set it to be the same.
1708*1c60b9acSAndroid Build Coastguard Worker */
1709*1c60b9acSAndroid Build Coastguard Worker
1710*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf(temp, sizeof(temp), "__Host-%s=%s;"
1711*1c60b9acSAndroid Build Coastguard Worker "HttpOnly;"
1712*1c60b9acSAndroid Build Coastguard Worker "Secure;"
1713*1c60b9acSAndroid Build Coastguard Worker "SameSite=strict;"
1714*1c60b9acSAndroid Build Coastguard Worker "Path=/;"
1715*1c60b9acSAndroid Build Coastguard Worker "Max-Age=%lu",
1716*1c60b9acSAndroid Build Coastguard Worker i->cookie_name, plain, i->expiry_unix_time);
1717*1c60b9acSAndroid Build Coastguard Worker
1718*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SET_COOKIE,
1719*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)temp, n, p, end)) {
1720*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed to add JWT cookie header\n", __func__);
1721*1c60b9acSAndroid Build Coastguard Worker return 1;
1722*1c60b9acSAndroid Build Coastguard Worker }
1723*1c60b9acSAndroid Build Coastguard Worker
1724*1c60b9acSAndroid Build Coastguard Worker return 0;
1725*1c60b9acSAndroid Build Coastguard Worker }
1726*1c60b9acSAndroid Build Coastguard Worker #endif
1727