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 - 2020 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 #include "lextable-strings.h"
27*1c60b9acSAndroid Build Coastguard Worker
28*1c60b9acSAndroid Build Coastguard Worker
29*1c60b9acSAndroid Build Coastguard Worker const unsigned char *
lws_token_to_string(enum lws_token_indexes token)30*1c60b9acSAndroid Build Coastguard Worker lws_token_to_string(enum lws_token_indexes token)
31*1c60b9acSAndroid Build Coastguard Worker {
32*1c60b9acSAndroid Build Coastguard Worker if ((unsigned int)token >= LWS_ARRAY_SIZE(set))
33*1c60b9acSAndroid Build Coastguard Worker return NULL;
34*1c60b9acSAndroid Build Coastguard Worker
35*1c60b9acSAndroid Build Coastguard Worker return (unsigned char *)set[token];
36*1c60b9acSAndroid Build Coastguard Worker }
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard Worker /*
39*1c60b9acSAndroid Build Coastguard Worker * Return http header index if one matches slen chars of s, or -1
40*1c60b9acSAndroid Build Coastguard Worker */
41*1c60b9acSAndroid Build Coastguard Worker
42*1c60b9acSAndroid Build Coastguard Worker int
lws_http_string_to_known_header(const char * s,size_t slen)43*1c60b9acSAndroid Build Coastguard Worker lws_http_string_to_known_header(const char *s, size_t slen)
44*1c60b9acSAndroid Build Coastguard Worker {
45*1c60b9acSAndroid Build Coastguard Worker int n;
46*1c60b9acSAndroid Build Coastguard Worker
47*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < (int)LWS_ARRAY_SIZE(set); n++)
48*1c60b9acSAndroid Build Coastguard Worker if (!strncmp(set[n], s, slen))
49*1c60b9acSAndroid Build Coastguard Worker return n;
50*1c60b9acSAndroid Build Coastguard Worker
51*1c60b9acSAndroid Build Coastguard Worker return LWS_HTTP_NO_KNOWN_HEADER;
52*1c60b9acSAndroid Build Coastguard Worker }
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_HTTP2
55*1c60b9acSAndroid Build Coastguard Worker int
lws_wsi_is_h2(struct lws * wsi)56*1c60b9acSAndroid Build Coastguard Worker lws_wsi_is_h2(struct lws *wsi)
57*1c60b9acSAndroid Build Coastguard Worker {
58*1c60b9acSAndroid Build Coastguard Worker return wsi->upgraded_to_http2 ||
59*1c60b9acSAndroid Build Coastguard Worker wsi->mux_substream ||
60*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
61*1c60b9acSAndroid Build Coastguard Worker wsi->client_mux_substream ||
62*1c60b9acSAndroid Build Coastguard Worker #endif
63*1c60b9acSAndroid Build Coastguard Worker lwsi_role_h2(wsi) ||
64*1c60b9acSAndroid Build Coastguard Worker lwsi_role_h2_ENCAPSULATION(wsi);
65*1c60b9acSAndroid Build Coastguard Worker }
66*1c60b9acSAndroid Build Coastguard Worker #endif
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker int
lws_add_http_header_by_name(struct lws * wsi,const unsigned char * name,const unsigned char * value,int length,unsigned char ** p,unsigned char * end)69*1c60b9acSAndroid Build Coastguard Worker lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name,
70*1c60b9acSAndroid Build Coastguard Worker const unsigned char *value, int length,
71*1c60b9acSAndroid Build Coastguard Worker unsigned char **p, unsigned char *end)
72*1c60b9acSAndroid Build Coastguard Worker {
73*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_HTTP2
74*1c60b9acSAndroid Build Coastguard Worker if (lws_wsi_is_h2(wsi))
75*1c60b9acSAndroid Build Coastguard Worker return lws_add_http2_header_by_name(wsi, name,
76*1c60b9acSAndroid Build Coastguard Worker value, length, p, end);
77*1c60b9acSAndroid Build Coastguard Worker #else
78*1c60b9acSAndroid Build Coastguard Worker (void)wsi;
79*1c60b9acSAndroid Build Coastguard Worker #endif
80*1c60b9acSAndroid Build Coastguard Worker if (name) {
81*1c60b9acSAndroid Build Coastguard Worker while (*p < end && *name)
82*1c60b9acSAndroid Build Coastguard Worker *((*p)++) = *name++;
83*1c60b9acSAndroid Build Coastguard Worker if (*p == end)
84*1c60b9acSAndroid Build Coastguard Worker return 1;
85*1c60b9acSAndroid Build Coastguard Worker *((*p)++) = ' ';
86*1c60b9acSAndroid Build Coastguard Worker }
87*1c60b9acSAndroid Build Coastguard Worker if (*p + length + 3 >= end)
88*1c60b9acSAndroid Build Coastguard Worker return 1;
89*1c60b9acSAndroid Build Coastguard Worker
90*1c60b9acSAndroid Build Coastguard Worker if (value)
91*1c60b9acSAndroid Build Coastguard Worker memcpy(*p, value, (unsigned int)length);
92*1c60b9acSAndroid Build Coastguard Worker *p += length;
93*1c60b9acSAndroid Build Coastguard Worker *((*p)++) = '\x0d';
94*1c60b9acSAndroid Build Coastguard Worker *((*p)++) = '\x0a';
95*1c60b9acSAndroid Build Coastguard Worker
96*1c60b9acSAndroid Build Coastguard Worker return 0;
97*1c60b9acSAndroid Build Coastguard Worker }
98*1c60b9acSAndroid Build Coastguard Worker
lws_finalize_http_header(struct lws * wsi,unsigned char ** p,unsigned char * end)99*1c60b9acSAndroid Build Coastguard Worker int lws_finalize_http_header(struct lws *wsi, unsigned char **p,
100*1c60b9acSAndroid Build Coastguard Worker unsigned char *end)
101*1c60b9acSAndroid Build Coastguard Worker {
102*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_HTTP2
103*1c60b9acSAndroid Build Coastguard Worker if (lws_wsi_is_h2(wsi))
104*1c60b9acSAndroid Build Coastguard Worker return 0;
105*1c60b9acSAndroid Build Coastguard Worker #else
106*1c60b9acSAndroid Build Coastguard Worker (void)wsi;
107*1c60b9acSAndroid Build Coastguard Worker #endif
108*1c60b9acSAndroid Build Coastguard Worker if ((lws_intptr_t)(end - *p) < 3)
109*1c60b9acSAndroid Build Coastguard Worker return 1;
110*1c60b9acSAndroid Build Coastguard Worker *((*p)++) = '\x0d';
111*1c60b9acSAndroid Build Coastguard Worker *((*p)++) = '\x0a';
112*1c60b9acSAndroid Build Coastguard Worker
113*1c60b9acSAndroid Build Coastguard Worker return 0;
114*1c60b9acSAndroid Build Coastguard Worker }
115*1c60b9acSAndroid Build Coastguard Worker
116*1c60b9acSAndroid Build Coastguard Worker int
lws_finalize_write_http_header(struct lws * wsi,unsigned char * start,unsigned char ** pp,unsigned char * end)117*1c60b9acSAndroid Build Coastguard Worker lws_finalize_write_http_header(struct lws *wsi, unsigned char *start,
118*1c60b9acSAndroid Build Coastguard Worker unsigned char **pp, unsigned char *end)
119*1c60b9acSAndroid Build Coastguard Worker {
120*1c60b9acSAndroid Build Coastguard Worker unsigned char *p;
121*1c60b9acSAndroid Build Coastguard Worker int len;
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker if (lws_finalize_http_header(wsi, pp, end))
124*1c60b9acSAndroid Build Coastguard Worker return 1;
125*1c60b9acSAndroid Build Coastguard Worker
126*1c60b9acSAndroid Build Coastguard Worker p = *pp;
127*1c60b9acSAndroid Build Coastguard Worker len = lws_ptr_diff(p, start);
128*1c60b9acSAndroid Build Coastguard Worker
129*1c60b9acSAndroid Build Coastguard Worker if (lws_write(wsi, start, (unsigned int)len, LWS_WRITE_HTTP_HEADERS) != len)
130*1c60b9acSAndroid Build Coastguard Worker return 1;
131*1c60b9acSAndroid Build Coastguard Worker
132*1c60b9acSAndroid Build Coastguard Worker return 0;
133*1c60b9acSAndroid Build Coastguard Worker }
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker int
lws_add_http_header_by_token(struct lws * wsi,enum lws_token_indexes token,const unsigned char * value,int length,unsigned char ** p,unsigned char * end)136*1c60b9acSAndroid Build Coastguard Worker lws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token,
137*1c60b9acSAndroid Build Coastguard Worker const unsigned char *value, int length,
138*1c60b9acSAndroid Build Coastguard Worker unsigned char **p, unsigned char *end)
139*1c60b9acSAndroid Build Coastguard Worker {
140*1c60b9acSAndroid Build Coastguard Worker const unsigned char *name;
141*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_HTTP2
142*1c60b9acSAndroid Build Coastguard Worker if (lws_wsi_is_h2(wsi))
143*1c60b9acSAndroid Build Coastguard Worker return lws_add_http2_header_by_token(wsi, token, value,
144*1c60b9acSAndroid Build Coastguard Worker length, p, end);
145*1c60b9acSAndroid Build Coastguard Worker #endif
146*1c60b9acSAndroid Build Coastguard Worker name = lws_token_to_string(token);
147*1c60b9acSAndroid Build Coastguard Worker if (!name)
148*1c60b9acSAndroid Build Coastguard Worker return 1;
149*1c60b9acSAndroid Build Coastguard Worker
150*1c60b9acSAndroid Build Coastguard Worker return lws_add_http_header_by_name(wsi, name, value, length, p, end);
151*1c60b9acSAndroid Build Coastguard Worker }
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker int
lws_add_http_header_content_length(struct lws * wsi,lws_filepos_t content_length,unsigned char ** p,unsigned char * end)154*1c60b9acSAndroid Build Coastguard Worker lws_add_http_header_content_length(struct lws *wsi,
155*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t content_length,
156*1c60b9acSAndroid Build Coastguard Worker unsigned char **p, unsigned char *end)
157*1c60b9acSAndroid Build Coastguard Worker {
158*1c60b9acSAndroid Build Coastguard Worker char b[24];
159*1c60b9acSAndroid Build Coastguard Worker int n;
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf(b, sizeof(b) - 1, "%llu", (unsigned long long)content_length);
162*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
163*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)b, n, p, end))
164*1c60b9acSAndroid Build Coastguard Worker return 1;
165*1c60b9acSAndroid Build Coastguard Worker wsi->http.tx_content_length = content_length;
166*1c60b9acSAndroid Build Coastguard Worker wsi->http.tx_content_remain = content_length;
167*1c60b9acSAndroid Build Coastguard Worker
168*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: tx_content_length/remain %llu\n", __func__,
169*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), (unsigned long long)content_length);
170*1c60b9acSAndroid Build Coastguard Worker
171*1c60b9acSAndroid Build Coastguard Worker return 0;
172*1c60b9acSAndroid Build Coastguard Worker }
173*1c60b9acSAndroid Build Coastguard Worker
174*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
175*1c60b9acSAndroid Build Coastguard Worker
176*1c60b9acSAndroid Build Coastguard Worker int
lws_add_http_common_headers(struct lws * wsi,unsigned int code,const char * content_type,lws_filepos_t content_len,unsigned char ** p,unsigned char * end)177*1c60b9acSAndroid Build Coastguard Worker lws_add_http_common_headers(struct lws *wsi, unsigned int code,
178*1c60b9acSAndroid Build Coastguard Worker const char *content_type, lws_filepos_t content_len,
179*1c60b9acSAndroid Build Coastguard Worker unsigned char **p, unsigned char *end)
180*1c60b9acSAndroid Build Coastguard Worker {
181*1c60b9acSAndroid Build Coastguard Worker const char *ka[] = { "close", "keep-alive" };
182*1c60b9acSAndroid Build Coastguard Worker int types[] = { HTTP_CONNECTION_CLOSE, HTTP_CONNECTION_KEEP_ALIVE },
183*1c60b9acSAndroid Build Coastguard Worker t = 0;
184*1c60b9acSAndroid Build Coastguard Worker
185*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_status(wsi, code, p, end))
186*1c60b9acSAndroid Build Coastguard Worker return 1;
187*1c60b9acSAndroid Build Coastguard Worker
188*1c60b9acSAndroid Build Coastguard Worker if (content_type &&
189*1c60b9acSAndroid Build Coastguard Worker lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
190*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)content_type,
191*1c60b9acSAndroid Build Coastguard Worker (int)strlen(content_type), p, end))
192*1c60b9acSAndroid Build Coastguard Worker return 1;
193*1c60b9acSAndroid Build Coastguard Worker
194*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
195*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.lcs && content_type &&
196*1c60b9acSAndroid Build Coastguard Worker (!strncmp(content_type, "text/", 5) ||
197*1c60b9acSAndroid Build Coastguard Worker !strcmp(content_type, "application/javascript") ||
198*1c60b9acSAndroid Build Coastguard Worker !strcmp(content_type, "image/svg+xml")))
199*1c60b9acSAndroid Build Coastguard Worker lws_http_compression_apply(wsi, NULL, p, end, 0);
200*1c60b9acSAndroid Build Coastguard Worker #endif
201*1c60b9acSAndroid Build Coastguard Worker
202*1c60b9acSAndroid Build Coastguard Worker /*
203*1c60b9acSAndroid Build Coastguard Worker * if we decided to compress it, we don't know the content length...
204*1c60b9acSAndroid Build Coastguard Worker * the compressed data will go out chunked on h1
205*1c60b9acSAndroid Build Coastguard Worker */
206*1c60b9acSAndroid Build Coastguard Worker if (
207*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
208*1c60b9acSAndroid Build Coastguard Worker !wsi->http.lcs &&
209*1c60b9acSAndroid Build Coastguard Worker #endif
210*1c60b9acSAndroid Build Coastguard Worker content_len != LWS_ILLEGAL_HTTP_CONTENT_LEN) {
211*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_content_length(wsi, content_len,
212*1c60b9acSAndroid Build Coastguard Worker p, end))
213*1c60b9acSAndroid Build Coastguard Worker return 1;
214*1c60b9acSAndroid Build Coastguard Worker } else {
215*1c60b9acSAndroid Build Coastguard Worker /* there was no length... it normally means CONNECTION_CLOSE */
216*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
217*1c60b9acSAndroid Build Coastguard Worker
218*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream && wsi->http.lcs) {
219*1c60b9acSAndroid Build Coastguard Worker /* so...
220*1c60b9acSAndroid Build Coastguard Worker * - h1 connection
221*1c60b9acSAndroid Build Coastguard Worker * - http compression transform active
222*1c60b9acSAndroid Build Coastguard Worker * - did not send content length
223*1c60b9acSAndroid Build Coastguard Worker *
224*1c60b9acSAndroid Build Coastguard Worker * then mark as chunked...
225*1c60b9acSAndroid Build Coastguard Worker */
226*1c60b9acSAndroid Build Coastguard Worker wsi->http.comp_ctx.chunking = 1;
227*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
228*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_TRANSFER_ENCODING,
229*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"chunked", 7, p, end))
230*1c60b9acSAndroid Build Coastguard Worker return -1;
231*1c60b9acSAndroid Build Coastguard Worker
232*1c60b9acSAndroid Build Coastguard Worker /* ... but h1 compression is chunked, if active we can
233*1c60b9acSAndroid Build Coastguard Worker * still pipeline
234*1c60b9acSAndroid Build Coastguard Worker */
235*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.lcs &&
236*1c60b9acSAndroid Build Coastguard Worker wsi->http.conn_type == HTTP_CONNECTION_KEEP_ALIVE)
237*1c60b9acSAndroid Build Coastguard Worker t = 1;
238*1c60b9acSAndroid Build Coastguard Worker }
239*1c60b9acSAndroid Build Coastguard Worker #endif
240*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream) {
241*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
242*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_CONNECTION,
243*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)ka[t],
244*1c60b9acSAndroid Build Coastguard Worker (int)strlen(ka[t]), p, end))
245*1c60b9acSAndroid Build Coastguard Worker return 1;
246*1c60b9acSAndroid Build Coastguard Worker
247*1c60b9acSAndroid Build Coastguard Worker wsi->http.conn_type = (enum http_conn_type)types[t];
248*1c60b9acSAndroid Build Coastguard Worker }
249*1c60b9acSAndroid Build Coastguard Worker }
250*1c60b9acSAndroid Build Coastguard Worker
251*1c60b9acSAndroid Build Coastguard Worker return 0;
252*1c60b9acSAndroid Build Coastguard Worker }
253*1c60b9acSAndroid Build Coastguard Worker
254*1c60b9acSAndroid Build Coastguard Worker static const char * const err400[] = {
255*1c60b9acSAndroid Build Coastguard Worker "Bad Request",
256*1c60b9acSAndroid Build Coastguard Worker "Unauthorized",
257*1c60b9acSAndroid Build Coastguard Worker "Payment Required",
258*1c60b9acSAndroid Build Coastguard Worker "Forbidden",
259*1c60b9acSAndroid Build Coastguard Worker "Not Found",
260*1c60b9acSAndroid Build Coastguard Worker "Method Not Allowed",
261*1c60b9acSAndroid Build Coastguard Worker "Not Acceptable",
262*1c60b9acSAndroid Build Coastguard Worker "Proxy Auth Required",
263*1c60b9acSAndroid Build Coastguard Worker "Request Timeout",
264*1c60b9acSAndroid Build Coastguard Worker "Conflict",
265*1c60b9acSAndroid Build Coastguard Worker "Gone",
266*1c60b9acSAndroid Build Coastguard Worker "Length Required",
267*1c60b9acSAndroid Build Coastguard Worker "Precondition Failed",
268*1c60b9acSAndroid Build Coastguard Worker "Request Entity Too Large",
269*1c60b9acSAndroid Build Coastguard Worker "Request URI too Long",
270*1c60b9acSAndroid Build Coastguard Worker "Unsupported Media Type",
271*1c60b9acSAndroid Build Coastguard Worker "Requested Range Not Satisfiable",
272*1c60b9acSAndroid Build Coastguard Worker "Expectation Failed"
273*1c60b9acSAndroid Build Coastguard Worker };
274*1c60b9acSAndroid Build Coastguard Worker
275*1c60b9acSAndroid Build Coastguard Worker static const char * const err500[] = {
276*1c60b9acSAndroid Build Coastguard Worker "Internal Server Error",
277*1c60b9acSAndroid Build Coastguard Worker "Not Implemented",
278*1c60b9acSAndroid Build Coastguard Worker "Bad Gateway",
279*1c60b9acSAndroid Build Coastguard Worker "Service Unavailable",
280*1c60b9acSAndroid Build Coastguard Worker "Gateway Timeout",
281*1c60b9acSAndroid Build Coastguard Worker "HTTP Version Not Supported"
282*1c60b9acSAndroid Build Coastguard Worker };
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker /* security best practices from Mozilla Observatory */
285*1c60b9acSAndroid Build Coastguard Worker
286*1c60b9acSAndroid Build Coastguard Worker static const
287*1c60b9acSAndroid Build Coastguard Worker struct lws_protocol_vhost_options pvo_hsbph[] = {{
288*1c60b9acSAndroid Build Coastguard Worker NULL, NULL, "referrer-policy:", "no-referrer"
289*1c60b9acSAndroid Build Coastguard Worker }, {
290*1c60b9acSAndroid Build Coastguard Worker &pvo_hsbph[0], NULL, "x-frame-options:", "deny"
291*1c60b9acSAndroid Build Coastguard Worker }, {
292*1c60b9acSAndroid Build Coastguard Worker &pvo_hsbph[1], NULL, "x-xss-protection:", "1; mode=block"
293*1c60b9acSAndroid Build Coastguard Worker }, {
294*1c60b9acSAndroid Build Coastguard Worker &pvo_hsbph[2], NULL, "x-content-type-options:", "nosniff"
295*1c60b9acSAndroid Build Coastguard Worker }, {
296*1c60b9acSAndroid Build Coastguard Worker &pvo_hsbph[3], NULL, "content-security-policy:",
297*1c60b9acSAndroid Build Coastguard Worker "default-src 'none'; img-src 'self' data: ; "
298*1c60b9acSAndroid Build Coastguard Worker "script-src 'self'; font-src 'self'; "
299*1c60b9acSAndroid Build Coastguard Worker "style-src 'self'; connect-src 'self' ws: wss:; "
300*1c60b9acSAndroid Build Coastguard Worker "frame-ancestors 'none'; base-uri 'none';"
301*1c60b9acSAndroid Build Coastguard Worker "form-action 'self';"
302*1c60b9acSAndroid Build Coastguard Worker }};
303*1c60b9acSAndroid Build Coastguard Worker
304*1c60b9acSAndroid Build Coastguard Worker int
lws_add_http_header_status(struct lws * wsi,unsigned int _code,unsigned char ** p,unsigned char * end)305*1c60b9acSAndroid Build Coastguard Worker lws_add_http_header_status(struct lws *wsi, unsigned int _code,
306*1c60b9acSAndroid Build Coastguard Worker unsigned char **p, unsigned char *end)
307*1c60b9acSAndroid Build Coastguard Worker {
308*1c60b9acSAndroid Build Coastguard Worker static const char * const hver[] = {
309*1c60b9acSAndroid Build Coastguard Worker "HTTP/1.0", "HTTP/1.1", "HTTP/2"
310*1c60b9acSAndroid Build Coastguard Worker };
311*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocol_vhost_options *headers;
312*1c60b9acSAndroid Build Coastguard Worker unsigned int code = _code & LWSAHH_CODE_MASK;
313*1c60b9acSAndroid Build Coastguard Worker const char *description = "", *p1;
314*1c60b9acSAndroid Build Coastguard Worker unsigned char code_and_desc[60];
315*1c60b9acSAndroid Build Coastguard Worker int n;
316*1c60b9acSAndroid Build Coastguard Worker
317*1c60b9acSAndroid Build Coastguard Worker wsi->http.response_code = code;
318*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_ACCESS_LOG
319*1c60b9acSAndroid Build Coastguard Worker wsi->http.access_log.response = (int)code;
320*1c60b9acSAndroid Build Coastguard Worker #endif
321*1c60b9acSAndroid Build Coastguard Worker
322*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_HTTP2
323*1c60b9acSAndroid Build Coastguard Worker if (lws_wsi_is_h2(wsi)) {
324*1c60b9acSAndroid Build Coastguard Worker n = lws_add_http2_header_status(wsi, code, p, end);
325*1c60b9acSAndroid Build Coastguard Worker if (n)
326*1c60b9acSAndroid Build Coastguard Worker return n;
327*1c60b9acSAndroid Build Coastguard Worker } else
328*1c60b9acSAndroid Build Coastguard Worker #endif
329*1c60b9acSAndroid Build Coastguard Worker {
330*1c60b9acSAndroid Build Coastguard Worker if (code >= 400 && code < (400 + LWS_ARRAY_SIZE(err400)))
331*1c60b9acSAndroid Build Coastguard Worker description = err400[code - 400];
332*1c60b9acSAndroid Build Coastguard Worker if (code >= 500 && code < (500 + LWS_ARRAY_SIZE(err500)))
333*1c60b9acSAndroid Build Coastguard Worker description = err500[code - 500];
334*1c60b9acSAndroid Build Coastguard Worker
335*1c60b9acSAndroid Build Coastguard Worker if (code == 100)
336*1c60b9acSAndroid Build Coastguard Worker description = "Continue";
337*1c60b9acSAndroid Build Coastguard Worker if (code == 200)
338*1c60b9acSAndroid Build Coastguard Worker description = "OK";
339*1c60b9acSAndroid Build Coastguard Worker if (code == 304)
340*1c60b9acSAndroid Build Coastguard Worker description = "Not Modified";
341*1c60b9acSAndroid Build Coastguard Worker else
342*1c60b9acSAndroid Build Coastguard Worker if (code >= 300 && code < 400)
343*1c60b9acSAndroid Build Coastguard Worker description = "Redirect";
344*1c60b9acSAndroid Build Coastguard Worker
345*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.request_version < LWS_ARRAY_SIZE(hver))
346*1c60b9acSAndroid Build Coastguard Worker p1 = hver[wsi->http.request_version];
347*1c60b9acSAndroid Build Coastguard Worker else
348*1c60b9acSAndroid Build Coastguard Worker p1 = hver[0];
349*1c60b9acSAndroid Build Coastguard Worker
350*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf((char *)code_and_desc,
351*1c60b9acSAndroid Build Coastguard Worker sizeof(code_and_desc) - 1, "%s %u %s",
352*1c60b9acSAndroid Build Coastguard Worker p1, code, description);
353*1c60b9acSAndroid Build Coastguard Worker
354*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_name(wsi, NULL, code_and_desc, n, p,
355*1c60b9acSAndroid Build Coastguard Worker end))
356*1c60b9acSAndroid Build Coastguard Worker return 1;
357*1c60b9acSAndroid Build Coastguard Worker }
358*1c60b9acSAndroid Build Coastguard Worker
359*1c60b9acSAndroid Build Coastguard Worker headers = wsi->a.vhost->headers;
360*1c60b9acSAndroid Build Coastguard Worker while (headers) {
361*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_name(wsi,
362*1c60b9acSAndroid Build Coastguard Worker (const unsigned char *)headers->name,
363*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)headers->value,
364*1c60b9acSAndroid Build Coastguard Worker (int)strlen(headers->value), p, end))
365*1c60b9acSAndroid Build Coastguard Worker return 1;
366*1c60b9acSAndroid Build Coastguard Worker
367*1c60b9acSAndroid Build Coastguard Worker headers = headers->next;
368*1c60b9acSAndroid Build Coastguard Worker }
369*1c60b9acSAndroid Build Coastguard Worker
370*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->options &
371*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE) {
372*1c60b9acSAndroid Build Coastguard Worker headers = &pvo_hsbph[LWS_ARRAY_SIZE(pvo_hsbph) - 1];
373*1c60b9acSAndroid Build Coastguard Worker while (headers) {
374*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_name(wsi,
375*1c60b9acSAndroid Build Coastguard Worker (const unsigned char *)headers->name,
376*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)headers->value,
377*1c60b9acSAndroid Build Coastguard Worker (int)strlen(headers->value), p, end))
378*1c60b9acSAndroid Build Coastguard Worker return 1;
379*1c60b9acSAndroid Build Coastguard Worker
380*1c60b9acSAndroid Build Coastguard Worker headers = headers->next;
381*1c60b9acSAndroid Build Coastguard Worker }
382*1c60b9acSAndroid Build Coastguard Worker }
383*1c60b9acSAndroid Build Coastguard Worker
384*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.context->server_string &&
385*1c60b9acSAndroid Build Coastguard Worker !(_code & LWSAHH_FLAG_NO_SERVER_NAME)) {
386*1c60b9acSAndroid Build Coastguard Worker assert(wsi->a.context->server_string_len > 0);
387*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,
388*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)wsi->a.context->server_string,
389*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->server_string_len, p, end))
390*1c60b9acSAndroid Build Coastguard Worker return 1;
391*1c60b9acSAndroid Build Coastguard Worker }
392*1c60b9acSAndroid Build Coastguard Worker
393*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->options & LWS_SERVER_OPTION_STS)
394*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_name(wsi, (unsigned char *)
395*1c60b9acSAndroid Build Coastguard Worker "Strict-Transport-Security:",
396*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"max-age=15768000 ; "
397*1c60b9acSAndroid Build Coastguard Worker "includeSubDomains", 36, p, end))
398*1c60b9acSAndroid Build Coastguard Worker return 1;
399*1c60b9acSAndroid Build Coastguard Worker
400*1c60b9acSAndroid Build Coastguard Worker if (*p >= (end - 2)) {
401*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: reached end of buffer\n", __func__);
402*1c60b9acSAndroid Build Coastguard Worker
403*1c60b9acSAndroid Build Coastguard Worker return 1;
404*1c60b9acSAndroid Build Coastguard Worker }
405*1c60b9acSAndroid Build Coastguard Worker
406*1c60b9acSAndroid Build Coastguard Worker return 0;
407*1c60b9acSAndroid Build Coastguard Worker }
408*1c60b9acSAndroid Build Coastguard Worker
409*1c60b9acSAndroid Build Coastguard Worker int
lws_return_http_status(struct lws * wsi,unsigned int code,const char * html_body)410*1c60b9acSAndroid Build Coastguard Worker lws_return_http_status(struct lws *wsi, unsigned int code,
411*1c60b9acSAndroid Build Coastguard Worker const char *html_body)
412*1c60b9acSAndroid Build Coastguard Worker {
413*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = lws_get_context(wsi);
414*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
415*1c60b9acSAndroid Build Coastguard Worker unsigned char *p = pt->serv_buf + LWS_PRE;
416*1c60b9acSAndroid Build Coastguard Worker unsigned char *start = p;
417*1c60b9acSAndroid Build Coastguard Worker unsigned char *end = p + context->pt_serv_buf_size - LWS_PRE;
418*1c60b9acSAndroid Build Coastguard Worker char *body = (char *)start + context->pt_serv_buf_size - 512;
419*1c60b9acSAndroid Build Coastguard Worker int n = 0, m = 0, len;
420*1c60b9acSAndroid Build Coastguard Worker char slen[20];
421*1c60b9acSAndroid Build Coastguard Worker
422*1c60b9acSAndroid Build Coastguard Worker if (!wsi->a.vhost) {
423*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: wsi not bound to vhost\n", __func__);
424*1c60b9acSAndroid Build Coastguard Worker
425*1c60b9acSAndroid Build Coastguard Worker return 1;
426*1c60b9acSAndroid Build Coastguard Worker }
427*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
428*1c60b9acSAndroid Build Coastguard Worker if (!wsi->handling_404 &&
429*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->http.error_document_404 &&
430*1c60b9acSAndroid Build Coastguard Worker code == HTTP_STATUS_NOT_FOUND)
431*1c60b9acSAndroid Build Coastguard Worker /* we should do a redirect, and do the 404 there */
432*1c60b9acSAndroid Build Coastguard Worker if (lws_http_redirect(wsi, HTTP_STATUS_FOUND,
433*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)wsi->a.vhost->http.error_document_404,
434*1c60b9acSAndroid Build Coastguard Worker (int)strlen(wsi->a.vhost->http.error_document_404),
435*1c60b9acSAndroid Build Coastguard Worker &p, end) > 0)
436*1c60b9acSAndroid Build Coastguard Worker return 0;
437*1c60b9acSAndroid Build Coastguard Worker #endif
438*1c60b9acSAndroid Build Coastguard Worker
439*1c60b9acSAndroid Build Coastguard Worker /* if the redirect failed, just do a simple status */
440*1c60b9acSAndroid Build Coastguard Worker p = start;
441*1c60b9acSAndroid Build Coastguard Worker
442*1c60b9acSAndroid Build Coastguard Worker if (!html_body)
443*1c60b9acSAndroid Build Coastguard Worker html_body = "";
444*1c60b9acSAndroid Build Coastguard Worker
445*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_status(wsi, code, &p, end))
446*1c60b9acSAndroid Build Coastguard Worker return 1;
447*1c60b9acSAndroid Build Coastguard Worker
448*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
449*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"text/html", 9,
450*1c60b9acSAndroid Build Coastguard Worker &p, end))
451*1c60b9acSAndroid Build Coastguard Worker return 1;
452*1c60b9acSAndroid Build Coastguard Worker
453*1c60b9acSAndroid Build Coastguard Worker len = lws_snprintf(body, 510, "<html><head>"
454*1c60b9acSAndroid Build Coastguard Worker "<meta charset=utf-8 http-equiv=\"Content-Language\" "
455*1c60b9acSAndroid Build Coastguard Worker "content=\"en\"/>"
456*1c60b9acSAndroid Build Coastguard Worker "<link rel=\"stylesheet\" type=\"text/css\" "
457*1c60b9acSAndroid Build Coastguard Worker "href=\"/error.css\"/>"
458*1c60b9acSAndroid Build Coastguard Worker "</head><body><h1>%u</h1>%s</body></html>", code, html_body);
459*1c60b9acSAndroid Build Coastguard Worker
460*1c60b9acSAndroid Build Coastguard Worker
461*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf(slen, 12, "%d", len);
462*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
463*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)slen, n, &p, end))
464*1c60b9acSAndroid Build Coastguard Worker return 1;
465*1c60b9acSAndroid Build Coastguard Worker
466*1c60b9acSAndroid Build Coastguard Worker if (lws_finalize_http_header(wsi, &p, end))
467*1c60b9acSAndroid Build Coastguard Worker return 1;
468*1c60b9acSAndroid Build Coastguard Worker
469*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
470*1c60b9acSAndroid Build Coastguard Worker if (wsi->mux_substream) {
471*1c60b9acSAndroid Build Coastguard Worker
472*1c60b9acSAndroid Build Coastguard Worker /*
473*1c60b9acSAndroid Build Coastguard Worker * for HTTP/2, the headers must be sent separately, since they
474*1c60b9acSAndroid Build Coastguard Worker * go out in their own frame. That puts us in a bind that
475*1c60b9acSAndroid Build Coastguard Worker * we won't always be able to get away with two lws_write()s in
476*1c60b9acSAndroid Build Coastguard Worker * sequence, since the first may use up the writability due to
477*1c60b9acSAndroid Build Coastguard Worker * the pipe being choked or SSL_WANT_.
478*1c60b9acSAndroid Build Coastguard Worker *
479*1c60b9acSAndroid Build Coastguard Worker * However we do need to send the human-readable body, and the
480*1c60b9acSAndroid Build Coastguard Worker * END_STREAM.
481*1c60b9acSAndroid Build Coastguard Worker *
482*1c60b9acSAndroid Build Coastguard Worker * Solve it by writing the headers now...
483*1c60b9acSAndroid Build Coastguard Worker */
484*1c60b9acSAndroid Build Coastguard Worker m = lws_write(wsi, start, lws_ptr_diff_size_t(p, start),
485*1c60b9acSAndroid Build Coastguard Worker LWS_WRITE_HTTP_HEADERS);
486*1c60b9acSAndroid Build Coastguard Worker if (m != lws_ptr_diff(p, start))
487*1c60b9acSAndroid Build Coastguard Worker return 1;
488*1c60b9acSAndroid Build Coastguard Worker
489*1c60b9acSAndroid Build Coastguard Worker /*
490*1c60b9acSAndroid Build Coastguard Worker * ... but stash the body and send it as a priority next
491*1c60b9acSAndroid Build Coastguard Worker * handle_POLLOUT
492*1c60b9acSAndroid Build Coastguard Worker */
493*1c60b9acSAndroid Build Coastguard Worker wsi->http.tx_content_length = (unsigned int)len;
494*1c60b9acSAndroid Build Coastguard Worker wsi->http.tx_content_remain = (unsigned int)len;
495*1c60b9acSAndroid Build Coastguard Worker
496*1c60b9acSAndroid Build Coastguard Worker wsi->h2.pending_status_body = lws_malloc((unsigned int)len + LWS_PRE + 1,
497*1c60b9acSAndroid Build Coastguard Worker "pending status body");
498*1c60b9acSAndroid Build Coastguard Worker if (!wsi->h2.pending_status_body)
499*1c60b9acSAndroid Build Coastguard Worker return -1;
500*1c60b9acSAndroid Build Coastguard Worker
501*1c60b9acSAndroid Build Coastguard Worker strcpy(wsi->h2.pending_status_body + LWS_PRE, body);
502*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
503*1c60b9acSAndroid Build Coastguard Worker
504*1c60b9acSAndroid Build Coastguard Worker return 0;
505*1c60b9acSAndroid Build Coastguard Worker } else
506*1c60b9acSAndroid Build Coastguard Worker #endif
507*1c60b9acSAndroid Build Coastguard Worker {
508*1c60b9acSAndroid Build Coastguard Worker /*
509*1c60b9acSAndroid Build Coastguard Worker * for http/1, we can just append the body after the finalized
510*1c60b9acSAndroid Build Coastguard Worker * headers and send it all in one go.
511*1c60b9acSAndroid Build Coastguard Worker */
512*1c60b9acSAndroid Build Coastguard Worker
513*1c60b9acSAndroid Build Coastguard Worker n = lws_ptr_diff(p, start) + len;
514*1c60b9acSAndroid Build Coastguard Worker memcpy(p, body, (unsigned int)len);
515*1c60b9acSAndroid Build Coastguard Worker m = lws_write(wsi, start, (unsigned int)n, LWS_WRITE_HTTP);
516*1c60b9acSAndroid Build Coastguard Worker if (m != n)
517*1c60b9acSAndroid Build Coastguard Worker return 1;
518*1c60b9acSAndroid Build Coastguard Worker }
519*1c60b9acSAndroid Build Coastguard Worker
520*1c60b9acSAndroid Build Coastguard Worker return m != n;
521*1c60b9acSAndroid Build Coastguard Worker }
522*1c60b9acSAndroid Build Coastguard Worker
523*1c60b9acSAndroid Build Coastguard Worker int
lws_http_redirect(struct lws * wsi,int code,const unsigned char * loc,int len,unsigned char ** p,unsigned char * end)524*1c60b9acSAndroid Build Coastguard Worker lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len,
525*1c60b9acSAndroid Build Coastguard Worker unsigned char **p, unsigned char *end)
526*1c60b9acSAndroid Build Coastguard Worker {
527*1c60b9acSAndroid Build Coastguard Worker unsigned char *start = *p;
528*1c60b9acSAndroid Build Coastguard Worker
529*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_status(wsi, (unsigned int)code, p, end))
530*1c60b9acSAndroid Build Coastguard Worker return -1;
531*1c60b9acSAndroid Build Coastguard Worker
532*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION, loc, len,
533*1c60b9acSAndroid Build Coastguard Worker p, end))
534*1c60b9acSAndroid Build Coastguard Worker return -1;
535*1c60b9acSAndroid Build Coastguard Worker /*
536*1c60b9acSAndroid Build Coastguard Worker * if we're going with http/1.1 and keepalive, we have to give fake
537*1c60b9acSAndroid Build Coastguard Worker * content metadata so the client knows we completed the transaction and
538*1c60b9acSAndroid Build Coastguard Worker * it can do the redirect...
539*1c60b9acSAndroid Build Coastguard Worker */
540*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
541*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"text/html", 9, p,
542*1c60b9acSAndroid Build Coastguard Worker end))
543*1c60b9acSAndroid Build Coastguard Worker return -1;
544*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
545*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"0", 1, p, end))
546*1c60b9acSAndroid Build Coastguard Worker return -1;
547*1c60b9acSAndroid Build Coastguard Worker
548*1c60b9acSAndroid Build Coastguard Worker if (lws_finalize_http_header(wsi, p, end))
549*1c60b9acSAndroid Build Coastguard Worker return -1;
550*1c60b9acSAndroid Build Coastguard Worker
551*1c60b9acSAndroid Build Coastguard Worker return lws_write(wsi, start, lws_ptr_diff_size_t(*p, start),
552*1c60b9acSAndroid Build Coastguard Worker LWS_WRITE_HTTP_HEADERS | LWS_WRITE_H2_STREAM_END);
553*1c60b9acSAndroid Build Coastguard Worker }
554*1c60b9acSAndroid Build Coastguard Worker #endif
555*1c60b9acSAndroid Build Coastguard Worker
556*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
557*1c60b9acSAndroid Build Coastguard Worker int
lws_http_compression_apply(struct lws * wsi,const char * name,unsigned char ** p,unsigned char * end,char decomp)558*1c60b9acSAndroid Build Coastguard Worker lws_http_compression_apply(struct lws *wsi, const char *name,
559*1c60b9acSAndroid Build Coastguard Worker unsigned char **p, unsigned char *end, char decomp)
560*1c60b9acSAndroid Build Coastguard Worker {
561*1c60b9acSAndroid Build Coastguard Worker (void)wsi;
562*1c60b9acSAndroid Build Coastguard Worker (void)name;
563*1c60b9acSAndroid Build Coastguard Worker (void)p;
564*1c60b9acSAndroid Build Coastguard Worker (void)end;
565*1c60b9acSAndroid Build Coastguard Worker (void)decomp;
566*1c60b9acSAndroid Build Coastguard Worker
567*1c60b9acSAndroid Build Coastguard Worker return 0;
568*1c60b9acSAndroid Build Coastguard Worker }
569*1c60b9acSAndroid Build Coastguard Worker #endif
570*1c60b9acSAndroid Build Coastguard Worker
571*1c60b9acSAndroid Build Coastguard Worker int
lws_http_headers_detach(struct lws * wsi)572*1c60b9acSAndroid Build Coastguard Worker lws_http_headers_detach(struct lws *wsi)
573*1c60b9acSAndroid Build Coastguard Worker {
574*1c60b9acSAndroid Build Coastguard Worker return lws_header_table_detach(wsi, 0);
575*1c60b9acSAndroid Build Coastguard Worker }
576*1c60b9acSAndroid Build Coastguard Worker
577*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
578*1c60b9acSAndroid Build Coastguard Worker
579*1c60b9acSAndroid Build Coastguard Worker void
lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t * sul)580*1c60b9acSAndroid Build Coastguard Worker lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul)
581*1c60b9acSAndroid Build Coastguard Worker {
582*1c60b9acSAndroid Build Coastguard Worker struct allocated_headers *ah;
583*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = lws_container_of(sul,
584*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread, sul_ah_lifecheck);
585*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi;
586*1c60b9acSAndroid Build Coastguard Worker time_t now;
587*1c60b9acSAndroid Build Coastguard Worker int m;
588*1c60b9acSAndroid Build Coastguard Worker
589*1c60b9acSAndroid Build Coastguard Worker now = time(NULL);
590*1c60b9acSAndroid Build Coastguard Worker
591*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
592*1c60b9acSAndroid Build Coastguard Worker
593*1c60b9acSAndroid Build Coastguard Worker ah = pt->http.ah_list;
594*1c60b9acSAndroid Build Coastguard Worker while (ah) {
595*1c60b9acSAndroid Build Coastguard Worker int len;
596*1c60b9acSAndroid Build Coastguard Worker char buf[256];
597*1c60b9acSAndroid Build Coastguard Worker const unsigned char *c;
598*1c60b9acSAndroid Build Coastguard Worker
599*1c60b9acSAndroid Build Coastguard Worker if (!ah->in_use || !ah->wsi || !ah->assigned ||
600*1c60b9acSAndroid Build Coastguard Worker (ah->wsi->a.vhost &&
601*1c60b9acSAndroid Build Coastguard Worker (now - ah->assigned) <
602*1c60b9acSAndroid Build Coastguard Worker ah->wsi->a.vhost->timeout_secs_ah_idle + 360)) {
603*1c60b9acSAndroid Build Coastguard Worker ah = ah->next;
604*1c60b9acSAndroid Build Coastguard Worker continue;
605*1c60b9acSAndroid Build Coastguard Worker }
606*1c60b9acSAndroid Build Coastguard Worker
607*1c60b9acSAndroid Build Coastguard Worker /*
608*1c60b9acSAndroid Build Coastguard Worker * a single ah session somehow got held for
609*1c60b9acSAndroid Build Coastguard Worker * an unreasonable amount of time.
610*1c60b9acSAndroid Build Coastguard Worker *
611*1c60b9acSAndroid Build Coastguard Worker * Dump info on the connection...
612*1c60b9acSAndroid Build Coastguard Worker */
613*1c60b9acSAndroid Build Coastguard Worker wsi = ah->wsi;
614*1c60b9acSAndroid Build Coastguard Worker buf[0] = '\0';
615*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_OPTEE)
616*1c60b9acSAndroid Build Coastguard Worker lws_get_peer_simple(wsi, buf, sizeof(buf));
617*1c60b9acSAndroid Build Coastguard Worker #else
618*1c60b9acSAndroid Build Coastguard Worker buf[0] = '\0';
619*1c60b9acSAndroid Build Coastguard Worker #endif
620*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: ah excessive hold: wsi %p\n"
621*1c60b9acSAndroid Build Coastguard Worker " peer address: %s\n"
622*1c60b9acSAndroid Build Coastguard Worker " ah pos %lu\n", __func__, lws_wsi_tag(wsi),
623*1c60b9acSAndroid Build Coastguard Worker buf, (unsigned long)ah->pos);
624*1c60b9acSAndroid Build Coastguard Worker buf[0] = '\0';
625*1c60b9acSAndroid Build Coastguard Worker m = 0;
626*1c60b9acSAndroid Build Coastguard Worker do {
627*1c60b9acSAndroid Build Coastguard Worker c = lws_token_to_string((enum lws_token_indexes)m);
628*1c60b9acSAndroid Build Coastguard Worker if (!c)
629*1c60b9acSAndroid Build Coastguard Worker break;
630*1c60b9acSAndroid Build Coastguard Worker if (!(*c))
631*1c60b9acSAndroid Build Coastguard Worker break;
632*1c60b9acSAndroid Build Coastguard Worker
633*1c60b9acSAndroid Build Coastguard Worker len = lws_hdr_total_length(wsi, (enum lws_token_indexes)m);
634*1c60b9acSAndroid Build Coastguard Worker if (!len || len > (int)sizeof(buf) - 1) {
635*1c60b9acSAndroid Build Coastguard Worker m++;
636*1c60b9acSAndroid Build Coastguard Worker continue;
637*1c60b9acSAndroid Build Coastguard Worker }
638*1c60b9acSAndroid Build Coastguard Worker
639*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_copy(wsi, buf, sizeof buf, (enum lws_token_indexes)m) > 0) {
640*1c60b9acSAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = '\0';
641*1c60b9acSAndroid Build Coastguard Worker
642*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" %s = %s\n",
643*1c60b9acSAndroid Build Coastguard Worker (const char *)c, buf);
644*1c60b9acSAndroid Build Coastguard Worker }
645*1c60b9acSAndroid Build Coastguard Worker m++;
646*1c60b9acSAndroid Build Coastguard Worker } while (1);
647*1c60b9acSAndroid Build Coastguard Worker
648*1c60b9acSAndroid Build Coastguard Worker /* explicitly detach the ah */
649*1c60b9acSAndroid Build Coastguard Worker lws_header_table_detach(wsi, 0);
650*1c60b9acSAndroid Build Coastguard Worker
651*1c60b9acSAndroid Build Coastguard Worker /* ... and then drop the connection */
652*1c60b9acSAndroid Build Coastguard Worker
653*1c60b9acSAndroid Build Coastguard Worker __lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
654*1c60b9acSAndroid Build Coastguard Worker "excessive ah");
655*1c60b9acSAndroid Build Coastguard Worker
656*1c60b9acSAndroid Build Coastguard Worker ah = pt->http.ah_list;
657*1c60b9acSAndroid Build Coastguard Worker }
658*1c60b9acSAndroid Build Coastguard Worker
659*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
660*1c60b9acSAndroid Build Coastguard Worker }
661*1c60b9acSAndroid Build Coastguard Worker #endif
662