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 #if !defined(SOL_TCP) && defined(IPPROTO_TCP)
28*1c60b9acSAndroid Build Coastguard Worker #define SOL_TCP IPPROTO_TCP
29*1c60b9acSAndroid Build Coastguard Worker #endif
30*1c60b9acSAndroid Build Coastguard Worker
31*1c60b9acSAndroid Build Coastguard Worker const char * const method_names[] = {
32*1c60b9acSAndroid Build Coastguard Worker "GET", "POST",
33*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
34*1c60b9acSAndroid Build Coastguard Worker "OPTIONS", "PUT", "PATCH", "DELETE",
35*1c60b9acSAndroid Build Coastguard Worker #endif
36*1c60b9acSAndroid Build Coastguard Worker "CONNECT", "HEAD",
37*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_HTTP2
38*1c60b9acSAndroid Build Coastguard Worker ":path",
39*1c60b9acSAndroid Build Coastguard Worker #endif
40*1c60b9acSAndroid Build Coastguard Worker };
41*1c60b9acSAndroid Build Coastguard Worker
42*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
43*1c60b9acSAndroid Build Coastguard Worker static const char * const intermediates[] = { "private", "public" };
44*1c60b9acSAndroid Build Coastguard Worker #endif
45*1c60b9acSAndroid Build Coastguard Worker
46*1c60b9acSAndroid Build Coastguard Worker /*
47*1c60b9acSAndroid Build Coastguard Worker * return 0: all done
48*1c60b9acSAndroid Build Coastguard Worker * 1: nonfatal error
49*1c60b9acSAndroid Build Coastguard Worker * <0: fatal error
50*1c60b9acSAndroid Build Coastguard Worker *
51*1c60b9acSAndroid Build Coastguard Worker * REQUIRES CONTEXT LOCK HELD
52*1c60b9acSAndroid Build Coastguard Worker */
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
55*1c60b9acSAndroid Build Coastguard Worker
56*1c60b9acSAndroid Build Coastguard Worker struct vh_sock_args {
57*1c60b9acSAndroid Build Coastguard Worker const struct lws_context_creation_info *info;
58*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost *vhost;
59*1c60b9acSAndroid Build Coastguard Worker int af;
60*1c60b9acSAndroid Build Coastguard Worker };
61*1c60b9acSAndroid Build Coastguard Worker
62*1c60b9acSAndroid Build Coastguard Worker
63*1c60b9acSAndroid Build Coastguard Worker static int
check_extant(struct lws_dll2 * d,void * user)64*1c60b9acSAndroid Build Coastguard Worker check_extant(struct lws_dll2 *d, void *user)
65*1c60b9acSAndroid Build Coastguard Worker {
66*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi = lws_container_of(d, struct lws, listen_list);
67*1c60b9acSAndroid Build Coastguard Worker struct vh_sock_args *a = (struct vh_sock_args *)user;
68*1c60b9acSAndroid Build Coastguard Worker
69*1c60b9acSAndroid Build Coastguard Worker if (!lws_vhost_compare_listen(wsi->a.vhost, a->vhost))
70*1c60b9acSAndroid Build Coastguard Worker return 0;
71*1c60b9acSAndroid Build Coastguard Worker
72*1c60b9acSAndroid Build Coastguard Worker if (wsi->af != a ->af)
73*1c60b9acSAndroid Build Coastguard Worker return 0;
74*1c60b9acSAndroid Build Coastguard Worker
75*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" using listen skt from vhost %s\n", wsi->a.vhost->name);
76*1c60b9acSAndroid Build Coastguard Worker
77*1c60b9acSAndroid Build Coastguard Worker return 1;
78*1c60b9acSAndroid Build Coastguard Worker }
79*1c60b9acSAndroid Build Coastguard Worker
80*1c60b9acSAndroid Build Coastguard Worker /*
81*1c60b9acSAndroid Build Coastguard Worker * Creates a single listen socket of a specific AF
82*1c60b9acSAndroid Build Coastguard Worker */
83*1c60b9acSAndroid Build Coastguard Worker
84*1c60b9acSAndroid Build Coastguard Worker int
_lws_vhost_init_server_af(struct vh_sock_args * a)85*1c60b9acSAndroid Build Coastguard Worker _lws_vhost_init_server_af(struct vh_sock_args *a)
86*1c60b9acSAndroid Build Coastguard Worker {
87*1c60b9acSAndroid Build Coastguard Worker struct lws_context *cx = a->vhost->context;
88*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt;
89*1c60b9acSAndroid Build Coastguard Worker int n, opt = 1, limit = 1;
90*1c60b9acSAndroid Build Coastguard Worker lws_sockfd_type sockfd;
91*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi;
92*1c60b9acSAndroid Build Coastguard Worker int m = 0, is;
93*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_IPV6)
94*1c60b9acSAndroid Build Coastguard Worker int value = 1;
95*1c60b9acSAndroid Build Coastguard Worker #endif
96*1c60b9acSAndroid Build Coastguard Worker
97*1c60b9acSAndroid Build Coastguard Worker (void)method_names;
98*1c60b9acSAndroid Build Coastguard Worker (void)opt;
99*1c60b9acSAndroid Build Coastguard Worker
100*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: af %d\n", __func__, (int)a->af);
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard Worker if (lws_vhost_foreach_listen_wsi(a->vhost->context, a, check_extant))
103*1c60b9acSAndroid Build Coastguard Worker return 0;
104*1c60b9acSAndroid Build Coastguard Worker
105*1c60b9acSAndroid Build Coastguard Worker deal:
106*1c60b9acSAndroid Build Coastguard Worker
107*1c60b9acSAndroid Build Coastguard Worker if (a->vhost->iface) {
108*1c60b9acSAndroid Build Coastguard Worker
109*1c60b9acSAndroid Build Coastguard Worker /*
110*1c60b9acSAndroid Build Coastguard Worker * let's check before we do anything else about the disposition
111*1c60b9acSAndroid Build Coastguard Worker * of the interface he wants to bind to...
112*1c60b9acSAndroid Build Coastguard Worker */
113*1c60b9acSAndroid Build Coastguard Worker is = lws_socket_bind(a->vhost, NULL, LWS_SOCK_INVALID,
114*1c60b9acSAndroid Build Coastguard Worker a->vhost->listen_port, a->vhost->iface,
115*1c60b9acSAndroid Build Coastguard Worker a->af);
116*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("initial if check says %d\n", is);
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker if (is == LWS_ITOSA_BUSY)
119*1c60b9acSAndroid Build Coastguard Worker /* treat as fatal */
120*1c60b9acSAndroid Build Coastguard Worker return -1;
121*1c60b9acSAndroid Build Coastguard Worker
122*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_llp(struct lws_vhost **, pv,
123*1c60b9acSAndroid Build Coastguard Worker cx->no_listener_vhost_list) {
124*1c60b9acSAndroid Build Coastguard Worker if (is >= LWS_ITOSA_USABLE && *pv == a->vhost) {
125*1c60b9acSAndroid Build Coastguard Worker /* on the list and shouldn't be: remove it */
126*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("deferred iface: removing vh %s\n",
127*1c60b9acSAndroid Build Coastguard Worker (*pv)->name);
128*1c60b9acSAndroid Build Coastguard Worker *pv = a->vhost->no_listener_vhost_list;
129*1c60b9acSAndroid Build Coastguard Worker a->vhost->no_listener_vhost_list = NULL;
130*1c60b9acSAndroid Build Coastguard Worker goto done_list;
131*1c60b9acSAndroid Build Coastguard Worker }
132*1c60b9acSAndroid Build Coastguard Worker if (is < LWS_ITOSA_USABLE && *pv == a->vhost)
133*1c60b9acSAndroid Build Coastguard Worker goto done_list;
134*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_llp(pv, no_listener_vhost_list);
135*1c60b9acSAndroid Build Coastguard Worker
136*1c60b9acSAndroid Build Coastguard Worker /* not on the list... */
137*1c60b9acSAndroid Build Coastguard Worker
138*1c60b9acSAndroid Build Coastguard Worker if (is < LWS_ITOSA_USABLE) {
139*1c60b9acSAndroid Build Coastguard Worker
140*1c60b9acSAndroid Build Coastguard Worker /* ... but needs to be: so add it */
141*1c60b9acSAndroid Build Coastguard Worker
142*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("deferred iface: adding vh %s\n",
143*1c60b9acSAndroid Build Coastguard Worker a->vhost->name);
144*1c60b9acSAndroid Build Coastguard Worker a->vhost->no_listener_vhost_list =
145*1c60b9acSAndroid Build Coastguard Worker cx->no_listener_vhost_list;
146*1c60b9acSAndroid Build Coastguard Worker cx->no_listener_vhost_list = a->vhost;
147*1c60b9acSAndroid Build Coastguard Worker }
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker done_list:
150*1c60b9acSAndroid Build Coastguard Worker
151*1c60b9acSAndroid Build Coastguard Worker switch (is) {
152*1c60b9acSAndroid Build Coastguard Worker default:
153*1c60b9acSAndroid Build Coastguard Worker break;
154*1c60b9acSAndroid Build Coastguard Worker case LWS_ITOSA_NOT_EXIST:
155*1c60b9acSAndroid Build Coastguard Worker /* can't add it */
156*1c60b9acSAndroid Build Coastguard Worker if (!a->info)
157*1c60b9acSAndroid Build Coastguard Worker return -1;
158*1c60b9acSAndroid Build Coastguard Worker
159*1c60b9acSAndroid Build Coastguard Worker /* first time */
160*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: VH %s: iface %s port %d DOESN'T EXIST\n",
161*1c60b9acSAndroid Build Coastguard Worker __func__, a->vhost->name, a->vhost->iface,
162*1c60b9acSAndroid Build Coastguard Worker a->vhost->listen_port);
163*1c60b9acSAndroid Build Coastguard Worker
164*1c60b9acSAndroid Build Coastguard Worker return (a->info->options &
165*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND) ==
166*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND ?
167*1c60b9acSAndroid Build Coastguard Worker -1 : 1;
168*1c60b9acSAndroid Build Coastguard Worker
169*1c60b9acSAndroid Build Coastguard Worker case LWS_ITOSA_NOT_USABLE:
170*1c60b9acSAndroid Build Coastguard Worker /* can't add it */
171*1c60b9acSAndroid Build Coastguard Worker if (!a->info) /* first time */
172*1c60b9acSAndroid Build Coastguard Worker return -1;
173*1c60b9acSAndroid Build Coastguard Worker
174*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: VH %s: iface %s port %d NOT USABLE\n",
175*1c60b9acSAndroid Build Coastguard Worker __func__, a->vhost->name, a->vhost->iface,
176*1c60b9acSAndroid Build Coastguard Worker a->vhost->listen_port);
177*1c60b9acSAndroid Build Coastguard Worker
178*1c60b9acSAndroid Build Coastguard Worker return (a->info->options &
179*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND) ==
180*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND ?
181*1c60b9acSAndroid Build Coastguard Worker -1 : 1;
182*1c60b9acSAndroid Build Coastguard Worker }
183*1c60b9acSAndroid Build Coastguard Worker }
184*1c60b9acSAndroid Build Coastguard Worker
185*1c60b9acSAndroid Build Coastguard Worker (void)n;
186*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
187*1c60b9acSAndroid Build Coastguard Worker /*
188*1c60b9acSAndroid Build Coastguard Worker * A Unix domain sockets cannot be bound multiple times, even if we
189*1c60b9acSAndroid Build Coastguard Worker * set the SO_REUSE* options on.
190*1c60b9acSAndroid Build Coastguard Worker *
191*1c60b9acSAndroid Build Coastguard Worker * However on recent linux, each thread is able to independently listen.
192*1c60b9acSAndroid Build Coastguard Worker *
193*1c60b9acSAndroid Build Coastguard Worker * So we can assume creating just one listening socket for a multi-
194*1c60b9acSAndroid Build Coastguard Worker * threaded environment will typically work.
195*1c60b9acSAndroid Build Coastguard Worker */
196*1c60b9acSAndroid Build Coastguard Worker if (a->af != AF_UNIX)
197*1c60b9acSAndroid Build Coastguard Worker limit = cx->count_threads;
198*1c60b9acSAndroid Build Coastguard Worker #endif
199*1c60b9acSAndroid Build Coastguard Worker
200*1c60b9acSAndroid Build Coastguard Worker for (m = 0; m < limit; m++) {
201*1c60b9acSAndroid Build Coastguard Worker
202*1c60b9acSAndroid Build Coastguard Worker sockfd = lws_fi(&a->vhost->fic, "listenskt") ?
203*1c60b9acSAndroid Build Coastguard Worker LWS_SOCK_INVALID :
204*1c60b9acSAndroid Build Coastguard Worker socket(a->af, SOCK_STREAM, 0);
205*1c60b9acSAndroid Build Coastguard Worker
206*1c60b9acSAndroid Build Coastguard Worker if (sockfd == LWS_SOCK_INVALID) {
207*1c60b9acSAndroid Build Coastguard Worker lwsl_err("ERROR opening socket\n");
208*1c60b9acSAndroid Build Coastguard Worker return 1;
209*1c60b9acSAndroid Build Coastguard Worker }
210*1c60b9acSAndroid Build Coastguard Worker
211*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_FREERTOS)
212*1c60b9acSAndroid Build Coastguard Worker #if (defined(WIN32) || defined(_WIN32)) && defined(SO_EXCLUSIVEADDRUSE)
213*1c60b9acSAndroid Build Coastguard Worker /*
214*1c60b9acSAndroid Build Coastguard Worker * only accept that we are the only listener on the port
215*1c60b9acSAndroid Build Coastguard Worker * https://msdn.microsoft.com/zh-tw/library/
216*1c60b9acSAndroid Build Coastguard Worker * windows/desktop/ms740621(v=vs.85).aspx
217*1c60b9acSAndroid Build Coastguard Worker *
218*1c60b9acSAndroid Build Coastguard Worker * for lws, to match Linux, we default to exclusive listen
219*1c60b9acSAndroid Build Coastguard Worker */
220*1c60b9acSAndroid Build Coastguard Worker if (!lws_check_opt(a->vhost->options,
221*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE)) {
222*1c60b9acSAndroid Build Coastguard Worker if (setsockopt(sockfd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
223*1c60b9acSAndroid Build Coastguard Worker (const void *)&opt, sizeof(opt)) < 0) {
224*1c60b9acSAndroid Build Coastguard Worker lwsl_err("reuseaddr failed\n");
225*1c60b9acSAndroid Build Coastguard Worker compatible_close(sockfd);
226*1c60b9acSAndroid Build Coastguard Worker return -1;
227*1c60b9acSAndroid Build Coastguard Worker }
228*1c60b9acSAndroid Build Coastguard Worker } else
229*1c60b9acSAndroid Build Coastguard Worker #endif
230*1c60b9acSAndroid Build Coastguard Worker
231*1c60b9acSAndroid Build Coastguard Worker /*
232*1c60b9acSAndroid Build Coastguard Worker * allow us to restart even if old sockets in TIME_WAIT
233*1c60b9acSAndroid Build Coastguard Worker */
234*1c60b9acSAndroid Build Coastguard Worker if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
235*1c60b9acSAndroid Build Coastguard Worker (const void *)&opt, sizeof(opt)) < 0) {
236*1c60b9acSAndroid Build Coastguard Worker lwsl_err("reuseaddr failed\n");
237*1c60b9acSAndroid Build Coastguard Worker compatible_close(sockfd);
238*1c60b9acSAndroid Build Coastguard Worker return -1;
239*1c60b9acSAndroid Build Coastguard Worker }
240*1c60b9acSAndroid Build Coastguard Worker
241*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_IPV6) && defined(IPV6_V6ONLY)
242*1c60b9acSAndroid Build Coastguard Worker /*
243*1c60b9acSAndroid Build Coastguard Worker * If we have an ipv6 listen socket, it only accepts ipv6.
244*1c60b9acSAndroid Build Coastguard Worker *
245*1c60b9acSAndroid Build Coastguard Worker * There will be a separate ipv4 listen socket if that's
246*1c60b9acSAndroid Build Coastguard Worker * enabled.
247*1c60b9acSAndroid Build Coastguard Worker */
248*1c60b9acSAndroid Build Coastguard Worker if (a->af == AF_INET6 &&
249*1c60b9acSAndroid Build Coastguard Worker setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
250*1c60b9acSAndroid Build Coastguard Worker (const void*)&value, sizeof(value)) < 0) {
251*1c60b9acSAndroid Build Coastguard Worker compatible_close(sockfd);
252*1c60b9acSAndroid Build Coastguard Worker return -1;
253*1c60b9acSAndroid Build Coastguard Worker }
254*1c60b9acSAndroid Build Coastguard Worker #endif
255*1c60b9acSAndroid Build Coastguard Worker
256*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__) && defined(SO_REUSEPORT)
257*1c60b9acSAndroid Build Coastguard Worker /* keep coverity happy */
258*1c60b9acSAndroid Build Coastguard Worker #if LWS_MAX_SMP > 1
259*1c60b9acSAndroid Build Coastguard Worker n = 1;
260*1c60b9acSAndroid Build Coastguard Worker #else
261*1c60b9acSAndroid Build Coastguard Worker n = lws_check_opt(a->vhost->options,
262*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE);
263*1c60b9acSAndroid Build Coastguard Worker #endif
264*1c60b9acSAndroid Build Coastguard Worker if (n || cx->count_threads > 1) /* ... also implied by threads > 1 */
265*1c60b9acSAndroid Build Coastguard Worker if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
266*1c60b9acSAndroid Build Coastguard Worker (const void *)&opt, sizeof(opt)) < 0) {
267*1c60b9acSAndroid Build Coastguard Worker compatible_close(sockfd);
268*1c60b9acSAndroid Build Coastguard Worker return -1;
269*1c60b9acSAndroid Build Coastguard Worker }
270*1c60b9acSAndroid Build Coastguard Worker #endif
271*1c60b9acSAndroid Build Coastguard Worker #endif
272*1c60b9acSAndroid Build Coastguard Worker lws_plat_set_socket_options(a->vhost, sockfd, 0);
273*1c60b9acSAndroid Build Coastguard Worker
274*1c60b9acSAndroid Build Coastguard Worker is = lws_socket_bind(a->vhost, NULL, sockfd,
275*1c60b9acSAndroid Build Coastguard Worker a->vhost->listen_port,
276*1c60b9acSAndroid Build Coastguard Worker a->vhost->iface, a->af);
277*1c60b9acSAndroid Build Coastguard Worker
278*1c60b9acSAndroid Build Coastguard Worker if (is == LWS_ITOSA_BUSY) {
279*1c60b9acSAndroid Build Coastguard Worker /* treat as fatal */
280*1c60b9acSAndroid Build Coastguard Worker compatible_close(sockfd);
281*1c60b9acSAndroid Build Coastguard Worker
282*1c60b9acSAndroid Build Coastguard Worker return -1;
283*1c60b9acSAndroid Build Coastguard Worker }
284*1c60b9acSAndroid Build Coastguard Worker
285*1c60b9acSAndroid Build Coastguard Worker /*
286*1c60b9acSAndroid Build Coastguard Worker * There is a race where the network device may come up and then
287*1c60b9acSAndroid Build Coastguard Worker * go away and fail here. So correctly handle unexpected failure
288*1c60b9acSAndroid Build Coastguard Worker * here despite we earlier confirmed it.
289*1c60b9acSAndroid Build Coastguard Worker */
290*1c60b9acSAndroid Build Coastguard Worker if (is < 0) {
291*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: lws_socket_bind says %d\n", __func__, is);
292*1c60b9acSAndroid Build Coastguard Worker compatible_close(sockfd);
293*1c60b9acSAndroid Build Coastguard Worker if (a->vhost->iface)
294*1c60b9acSAndroid Build Coastguard Worker goto deal;
295*1c60b9acSAndroid Build Coastguard Worker return -1;
296*1c60b9acSAndroid Build Coastguard Worker }
297*1c60b9acSAndroid Build Coastguard Worker
298*1c60b9acSAndroid Build Coastguard Worker /*
299*1c60b9acSAndroid Build Coastguard Worker * Create the listen wsi and customize it
300*1c60b9acSAndroid Build Coastguard Worker */
301*1c60b9acSAndroid Build Coastguard Worker
302*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(cx, __func__);
303*1c60b9acSAndroid Build Coastguard Worker wsi = __lws_wsi_create_with_role(cx, m, &role_ops_listen, NULL);
304*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(cx);
305*1c60b9acSAndroid Build Coastguard Worker if (wsi == NULL) {
306*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Out of mem\n");
307*1c60b9acSAndroid Build Coastguard Worker goto bail;
308*1c60b9acSAndroid Build Coastguard Worker }
309*1c60b9acSAndroid Build Coastguard Worker
310*1c60b9acSAndroid Build Coastguard Worker wsi->af = (uint8_t)a->af;
311*1c60b9acSAndroid Build Coastguard Worker
312*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_UNIX_SOCK
313*1c60b9acSAndroid Build Coastguard Worker if (!LWS_UNIX_SOCK_ENABLED(a->vhost))
314*1c60b9acSAndroid Build Coastguard Worker #endif
315*1c60b9acSAndroid Build Coastguard Worker {
316*1c60b9acSAndroid Build Coastguard Worker wsi->unix_skt = 1;
317*1c60b9acSAndroid Build Coastguard Worker a->vhost->listen_port = is;
318*1c60b9acSAndroid Build Coastguard Worker
319*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: lws_socket_bind says %d\n", __func__, is);
320*1c60b9acSAndroid Build Coastguard Worker }
321*1c60b9acSAndroid Build Coastguard Worker
322*1c60b9acSAndroid Build Coastguard Worker wsi->desc.sockfd = sockfd;
323*1c60b9acSAndroid Build Coastguard Worker wsi->a.protocol = a->vhost->protocols;
324*1c60b9acSAndroid Build Coastguard Worker lws_vhost_bind_wsi(a->vhost, wsi);
325*1c60b9acSAndroid Build Coastguard Worker wsi->listener = 1;
326*1c60b9acSAndroid Build Coastguard Worker
327*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.context->event_loop_ops->init_vhost_listen_wsi)
328*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->event_loop_ops->init_vhost_listen_wsi(wsi);
329*1c60b9acSAndroid Build Coastguard Worker
330*1c60b9acSAndroid Build Coastguard Worker pt = &cx->pt[m];
331*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
332*1c60b9acSAndroid Build Coastguard Worker
333*1c60b9acSAndroid Build Coastguard Worker if (__insert_wsi_socket_into_fds(cx, wsi)) {
334*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("inserting wsi socket into fds failed\n");
335*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
336*1c60b9acSAndroid Build Coastguard Worker goto bail;
337*1c60b9acSAndroid Build Coastguard Worker }
338*1c60b9acSAndroid Build Coastguard Worker
339*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&wsi->listen_list, &a->vhost->listen_wsi);
340*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
341*1c60b9acSAndroid Build Coastguard Worker
342*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32) && defined(TCP_FASTOPEN)
343*1c60b9acSAndroid Build Coastguard Worker if (a->vhost->fo_listen_queue) {
344*1c60b9acSAndroid Build Coastguard Worker int optval = 1;
345*1c60b9acSAndroid Build Coastguard Worker if (setsockopt(wsi->desc.sockfd, IPPROTO_TCP,
346*1c60b9acSAndroid Build Coastguard Worker TCP_FASTOPEN,
347*1c60b9acSAndroid Build Coastguard Worker (const char*)&optval, sizeof(optval)) < 0) {
348*1c60b9acSAndroid Build Coastguard Worker int error = LWS_ERRNO;
349*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: TCP_NODELAY failed with error %d\n",
350*1c60b9acSAndroid Build Coastguard Worker __func__, error);
351*1c60b9acSAndroid Build Coastguard Worker }
352*1c60b9acSAndroid Build Coastguard Worker }
353*1c60b9acSAndroid Build Coastguard Worker #else
354*1c60b9acSAndroid Build Coastguard Worker #if defined(TCP_FASTOPEN)
355*1c60b9acSAndroid Build Coastguard Worker if (a->vhost->fo_listen_queue) {
356*1c60b9acSAndroid Build Coastguard Worker int qlen = a->vhost->fo_listen_queue;
357*1c60b9acSAndroid Build Coastguard Worker
358*1c60b9acSAndroid Build Coastguard Worker if (setsockopt(wsi->desc.sockfd, SOL_TCP, TCP_FASTOPEN,
359*1c60b9acSAndroid Build Coastguard Worker &qlen, sizeof(qlen)))
360*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: TCP_FASTOPEN failed\n", __func__);
361*1c60b9acSAndroid Build Coastguard Worker }
362*1c60b9acSAndroid Build Coastguard Worker #endif
363*1c60b9acSAndroid Build Coastguard Worker #endif
364*1c60b9acSAndroid Build Coastguard Worker
365*1c60b9acSAndroid Build Coastguard Worker n = listen(wsi->desc.sockfd, LWS_SOMAXCONN);
366*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
367*1c60b9acSAndroid Build Coastguard Worker lwsl_err("listen failed with error %d\n", LWS_ERRNO);
368*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&wsi->listen_list);
369*1c60b9acSAndroid Build Coastguard Worker __remove_wsi_socket_from_fds(wsi);
370*1c60b9acSAndroid Build Coastguard Worker goto bail;
371*1c60b9acSAndroid Build Coastguard Worker }
372*1c60b9acSAndroid Build Coastguard Worker
373*1c60b9acSAndroid Build Coastguard Worker if (wsi)
374*1c60b9acSAndroid Build Coastguard Worker __lws_lc_tag(a->vhost->context,
375*1c60b9acSAndroid Build Coastguard Worker &a->vhost->context->lcg[LWSLCG_WSI],
376*1c60b9acSAndroid Build Coastguard Worker &wsi->lc, "listen|%s|%s|%d",
377*1c60b9acSAndroid Build Coastguard Worker a->vhost->name,
378*1c60b9acSAndroid Build Coastguard Worker a->vhost->iface ? a->vhost->iface : "",
379*1c60b9acSAndroid Build Coastguard Worker (int)a->vhost->listen_port);
380*1c60b9acSAndroid Build Coastguard Worker
381*1c60b9acSAndroid Build Coastguard Worker } /* for each thread able to independently listen */
382*1c60b9acSAndroid Build Coastguard Worker
383*1c60b9acSAndroid Build Coastguard Worker if (!lws_check_opt(cx->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) {
384*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_UNIX_SOCK
385*1c60b9acSAndroid Build Coastguard Worker if (a->af == AF_UNIX)
386*1c60b9acSAndroid Build Coastguard Worker lwsl_info(" Listening on \"%s\"\n", a->vhost->iface);
387*1c60b9acSAndroid Build Coastguard Worker else
388*1c60b9acSAndroid Build Coastguard Worker #endif
389*1c60b9acSAndroid Build Coastguard Worker lwsl_info(" Listening on %s:%d\n",
390*1c60b9acSAndroid Build Coastguard Worker a->vhost->iface,
391*1c60b9acSAndroid Build Coastguard Worker a->vhost->listen_port);
392*1c60b9acSAndroid Build Coastguard Worker }
393*1c60b9acSAndroid Build Coastguard Worker
394*1c60b9acSAndroid Build Coastguard Worker // info->port = vhost->listen_port;
395*1c60b9acSAndroid Build Coastguard Worker
396*1c60b9acSAndroid Build Coastguard Worker return 0;
397*1c60b9acSAndroid Build Coastguard Worker
398*1c60b9acSAndroid Build Coastguard Worker bail:
399*1c60b9acSAndroid Build Coastguard Worker compatible_close(sockfd);
400*1c60b9acSAndroid Build Coastguard Worker
401*1c60b9acSAndroid Build Coastguard Worker return -1;
402*1c60b9acSAndroid Build Coastguard Worker }
403*1c60b9acSAndroid Build Coastguard Worker
404*1c60b9acSAndroid Build Coastguard Worker
405*1c60b9acSAndroid Build Coastguard Worker int
_lws_vhost_init_server(const struct lws_context_creation_info * info,struct lws_vhost * vhost)406*1c60b9acSAndroid Build Coastguard Worker _lws_vhost_init_server(const struct lws_context_creation_info *info,
407*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost *vhost)
408*1c60b9acSAndroid Build Coastguard Worker {
409*1c60b9acSAndroid Build Coastguard Worker struct vh_sock_args a;
410*1c60b9acSAndroid Build Coastguard Worker
411*1c60b9acSAndroid Build Coastguard Worker a.info = info;
412*1c60b9acSAndroid Build Coastguard Worker a.vhost = vhost;
413*1c60b9acSAndroid Build Coastguard Worker
414*1c60b9acSAndroid Build Coastguard Worker if (info) {
415*1c60b9acSAndroid Build Coastguard Worker vhost->iface = info->iface;
416*1c60b9acSAndroid Build Coastguard Worker vhost->listen_port = info->port;
417*1c60b9acSAndroid Build Coastguard Worker }
418*1c60b9acSAndroid Build Coastguard Worker
419*1c60b9acSAndroid Build Coastguard Worker /* set up our external listening socket we serve on */
420*1c60b9acSAndroid Build Coastguard Worker
421*1c60b9acSAndroid Build Coastguard Worker if (vhost->listen_port == CONTEXT_PORT_NO_LISTEN ||
422*1c60b9acSAndroid Build Coastguard Worker vhost->listen_port == CONTEXT_PORT_NO_LISTEN_SERVER)
423*1c60b9acSAndroid Build Coastguard Worker return 0;
424*1c60b9acSAndroid Build Coastguard Worker
425*1c60b9acSAndroid Build Coastguard Worker /*
426*1c60b9acSAndroid Build Coastguard Worker * Let's figure out what AF(s) we want this vhost to listen on.
427*1c60b9acSAndroid Build Coastguard Worker *
428*1c60b9acSAndroid Build Coastguard Worker * We want AF_UNIX alone if that's what's told
429*1c60b9acSAndroid Build Coastguard Worker */
430*1c60b9acSAndroid Build Coastguard Worker
431*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_UNIX_SOCK)
432*1c60b9acSAndroid Build Coastguard Worker /*
433*1c60b9acSAndroid Build Coastguard Worker * If unix socket, ask for that and we are done
434*1c60b9acSAndroid Build Coastguard Worker */
435*1c60b9acSAndroid Build Coastguard Worker if (LWS_UNIX_SOCK_ENABLED(vhost)) {
436*1c60b9acSAndroid Build Coastguard Worker a.af = AF_UNIX;
437*1c60b9acSAndroid Build Coastguard Worker goto single;
438*1c60b9acSAndroid Build Coastguard Worker }
439*1c60b9acSAndroid Build Coastguard Worker #endif
440*1c60b9acSAndroid Build Coastguard Worker
441*1c60b9acSAndroid Build Coastguard Worker /*
442*1c60b9acSAndroid Build Coastguard Worker * We may support both ipv4 and ipv6, but get a numeric vhost listen
443*1c60b9acSAndroid Build Coastguard Worker * iface that is unambiguously ipv4 or ipv6, meaning we can only listen
444*1c60b9acSAndroid Build Coastguard Worker * for the related AF then.
445*1c60b9acSAndroid Build Coastguard Worker */
446*1c60b9acSAndroid Build Coastguard Worker
447*1c60b9acSAndroid Build Coastguard Worker if (vhost->iface) {
448*1c60b9acSAndroid Build Coastguard Worker uint8_t buf[16];
449*1c60b9acSAndroid Build Coastguard Worker int q;
450*1c60b9acSAndroid Build Coastguard Worker
451*1c60b9acSAndroid Build Coastguard Worker q = lws_parse_numeric_address(vhost->iface, buf, sizeof(buf));
452*1c60b9acSAndroid Build Coastguard Worker
453*1c60b9acSAndroid Build Coastguard Worker if (q == 4) {
454*1c60b9acSAndroid Build Coastguard Worker a.af = AF_INET;
455*1c60b9acSAndroid Build Coastguard Worker goto single;
456*1c60b9acSAndroid Build Coastguard Worker }
457*1c60b9acSAndroid Build Coastguard Worker
458*1c60b9acSAndroid Build Coastguard Worker if (q == 16) {
459*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_IPV6)
460*1c60b9acSAndroid Build Coastguard Worker if (LWS_IPV6_ENABLED(vhost)) {
461*1c60b9acSAndroid Build Coastguard Worker a.af = AF_INET6;
462*1c60b9acSAndroid Build Coastguard Worker goto single;
463*1c60b9acSAndroid Build Coastguard Worker }
464*1c60b9acSAndroid Build Coastguard Worker #endif
465*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: ipv6 not supported on %s\n", __func__,
466*1c60b9acSAndroid Build Coastguard Worker vhost->name);
467*1c60b9acSAndroid Build Coastguard Worker return 1;
468*1c60b9acSAndroid Build Coastguard Worker }
469*1c60b9acSAndroid Build Coastguard Worker }
470*1c60b9acSAndroid Build Coastguard Worker
471*1c60b9acSAndroid Build Coastguard Worker /*
472*1c60b9acSAndroid Build Coastguard Worker * ... if we make it here, we would want to listen on AF_INET and
473*1c60b9acSAndroid Build Coastguard Worker * AF_INET6 unless one or the other is forbidden
474*1c60b9acSAndroid Build Coastguard Worker */
475*1c60b9acSAndroid Build Coastguard Worker
476*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_IPV6)
477*1c60b9acSAndroid Build Coastguard Worker if (!(LWS_IPV6_ENABLED(vhost) &&
478*1c60b9acSAndroid Build Coastguard Worker (vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY) &&
479*1c60b9acSAndroid Build Coastguard Worker (vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE))) {
480*1c60b9acSAndroid Build Coastguard Worker #endif
481*1c60b9acSAndroid Build Coastguard Worker a.af = AF_INET;
482*1c60b9acSAndroid Build Coastguard Worker if (_lws_vhost_init_server_af(&a))
483*1c60b9acSAndroid Build Coastguard Worker return 1;
484*1c60b9acSAndroid Build Coastguard Worker
485*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_IPV6)
486*1c60b9acSAndroid Build Coastguard Worker }
487*1c60b9acSAndroid Build Coastguard Worker if (LWS_IPV6_ENABLED(vhost)) {
488*1c60b9acSAndroid Build Coastguard Worker a.af = AF_INET6;
489*1c60b9acSAndroid Build Coastguard Worker goto single;
490*1c60b9acSAndroid Build Coastguard Worker }
491*1c60b9acSAndroid Build Coastguard Worker #endif
492*1c60b9acSAndroid Build Coastguard Worker
493*1c60b9acSAndroid Build Coastguard Worker return 0;
494*1c60b9acSAndroid Build Coastguard Worker
495*1c60b9acSAndroid Build Coastguard Worker single:
496*1c60b9acSAndroid Build Coastguard Worker return _lws_vhost_init_server_af(&a);
497*1c60b9acSAndroid Build Coastguard Worker }
498*1c60b9acSAndroid Build Coastguard Worker
499*1c60b9acSAndroid Build Coastguard Worker #endif
500*1c60b9acSAndroid Build Coastguard Worker
501*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost *
lws_select_vhost(struct lws_context * context,int port,const char * servername)502*1c60b9acSAndroid Build Coastguard Worker lws_select_vhost(struct lws_context *context, int port, const char *servername)
503*1c60b9acSAndroid Build Coastguard Worker {
504*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost *vhost = context->vhost_list;
505*1c60b9acSAndroid Build Coastguard Worker const char *p;
506*1c60b9acSAndroid Build Coastguard Worker int n, colon;
507*1c60b9acSAndroid Build Coastguard Worker
508*1c60b9acSAndroid Build Coastguard Worker n = (int)strlen(servername);
509*1c60b9acSAndroid Build Coastguard Worker colon = n;
510*1c60b9acSAndroid Build Coastguard Worker p = strchr(servername, ':');
511*1c60b9acSAndroid Build Coastguard Worker if (p)
512*1c60b9acSAndroid Build Coastguard Worker colon = lws_ptr_diff(p, servername);
513*1c60b9acSAndroid Build Coastguard Worker
514*1c60b9acSAndroid Build Coastguard Worker /* Priotity 1: first try exact matches */
515*1c60b9acSAndroid Build Coastguard Worker
516*1c60b9acSAndroid Build Coastguard Worker while (vhost) {
517*1c60b9acSAndroid Build Coastguard Worker if (port == vhost->listen_port &&
518*1c60b9acSAndroid Build Coastguard Worker !strncmp(vhost->name, servername, (unsigned int)colon)) {
519*1c60b9acSAndroid Build Coastguard Worker lwsl_info("SNI: Found: %s\n", servername);
520*1c60b9acSAndroid Build Coastguard Worker return vhost;
521*1c60b9acSAndroid Build Coastguard Worker }
522*1c60b9acSAndroid Build Coastguard Worker vhost = vhost->vhost_next;
523*1c60b9acSAndroid Build Coastguard Worker }
524*1c60b9acSAndroid Build Coastguard Worker
525*1c60b9acSAndroid Build Coastguard Worker /*
526*1c60b9acSAndroid Build Coastguard Worker * Priority 2: if no exact matches, try matching *.vhost-name
527*1c60b9acSAndroid Build Coastguard Worker * unintentional matches are possible but resolve to x.com for *.x.com
528*1c60b9acSAndroid Build Coastguard Worker * which is reasonable. If exact match exists we already chose it and
529*1c60b9acSAndroid Build Coastguard Worker * never reach here. SSL will still fail it if the cert doesn't allow
530*1c60b9acSAndroid Build Coastguard Worker * *.x.com.
531*1c60b9acSAndroid Build Coastguard Worker */
532*1c60b9acSAndroid Build Coastguard Worker vhost = context->vhost_list;
533*1c60b9acSAndroid Build Coastguard Worker while (vhost) {
534*1c60b9acSAndroid Build Coastguard Worker int m = (int)strlen(vhost->name);
535*1c60b9acSAndroid Build Coastguard Worker if (port && port == vhost->listen_port &&
536*1c60b9acSAndroid Build Coastguard Worker m <= (colon - 2) &&
537*1c60b9acSAndroid Build Coastguard Worker servername[colon - m - 1] == '.' &&
538*1c60b9acSAndroid Build Coastguard Worker !strncmp(vhost->name, servername + colon - m, (unsigned int)m)) {
539*1c60b9acSAndroid Build Coastguard Worker lwsl_info("SNI: Found %s on wildcard: %s\n",
540*1c60b9acSAndroid Build Coastguard Worker servername, vhost->name);
541*1c60b9acSAndroid Build Coastguard Worker return vhost;
542*1c60b9acSAndroid Build Coastguard Worker }
543*1c60b9acSAndroid Build Coastguard Worker vhost = vhost->vhost_next;
544*1c60b9acSAndroid Build Coastguard Worker }
545*1c60b9acSAndroid Build Coastguard Worker
546*1c60b9acSAndroid Build Coastguard Worker /* Priority 3: match the first vhost on our port */
547*1c60b9acSAndroid Build Coastguard Worker
548*1c60b9acSAndroid Build Coastguard Worker vhost = context->vhost_list;
549*1c60b9acSAndroid Build Coastguard Worker while (vhost) {
550*1c60b9acSAndroid Build Coastguard Worker if (port && port == vhost->listen_port) {
551*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: vhost match to %s based on port %d\n",
552*1c60b9acSAndroid Build Coastguard Worker __func__, vhost->name, port);
553*1c60b9acSAndroid Build Coastguard Worker return vhost;
554*1c60b9acSAndroid Build Coastguard Worker }
555*1c60b9acSAndroid Build Coastguard Worker vhost = vhost->vhost_next;
556*1c60b9acSAndroid Build Coastguard Worker }
557*1c60b9acSAndroid Build Coastguard Worker
558*1c60b9acSAndroid Build Coastguard Worker /* no match */
559*1c60b9acSAndroid Build Coastguard Worker
560*1c60b9acSAndroid Build Coastguard Worker return NULL;
561*1c60b9acSAndroid Build Coastguard Worker }
562*1c60b9acSAndroid Build Coastguard Worker
563*1c60b9acSAndroid Build Coastguard Worker static const struct lws_mimetype {
564*1c60b9acSAndroid Build Coastguard Worker const char *extension;
565*1c60b9acSAndroid Build Coastguard Worker const char *mimetype;
566*1c60b9acSAndroid Build Coastguard Worker } server_mimetypes[] = {
567*1c60b9acSAndroid Build Coastguard Worker { ".html", "text/html" },
568*1c60b9acSAndroid Build Coastguard Worker { ".htm", "text/html" },
569*1c60b9acSAndroid Build Coastguard Worker { ".js", "text/javascript" },
570*1c60b9acSAndroid Build Coastguard Worker { ".css", "text/css" },
571*1c60b9acSAndroid Build Coastguard Worker { ".png", "image/png" },
572*1c60b9acSAndroid Build Coastguard Worker { ".jpg", "image/jpeg" },
573*1c60b9acSAndroid Build Coastguard Worker { ".jpeg", "image/jpeg" },
574*1c60b9acSAndroid Build Coastguard Worker { ".ico", "image/x-icon" },
575*1c60b9acSAndroid Build Coastguard Worker { ".gif", "image/gif" },
576*1c60b9acSAndroid Build Coastguard Worker { ".svg", "image/svg+xml" },
577*1c60b9acSAndroid Build Coastguard Worker { ".ttf", "application/x-font-ttf" },
578*1c60b9acSAndroid Build Coastguard Worker { ".otf", "application/font-woff" },
579*1c60b9acSAndroid Build Coastguard Worker { ".woff", "application/font-woff" },
580*1c60b9acSAndroid Build Coastguard Worker { ".woff2", "application/font-woff2" },
581*1c60b9acSAndroid Build Coastguard Worker { ".gz", "application/gzip" },
582*1c60b9acSAndroid Build Coastguard Worker { ".txt", "text/plain" },
583*1c60b9acSAndroid Build Coastguard Worker { ".xml", "application/xml" },
584*1c60b9acSAndroid Build Coastguard Worker { ".json", "application/json" },
585*1c60b9acSAndroid Build Coastguard Worker { ".mjs", "text/javascript" },
586*1c60b9acSAndroid Build Coastguard Worker };
587*1c60b9acSAndroid Build Coastguard Worker
588*1c60b9acSAndroid Build Coastguard Worker const char *
lws_get_mimetype(const char * file,const struct lws_http_mount * m)589*1c60b9acSAndroid Build Coastguard Worker lws_get_mimetype(const char *file, const struct lws_http_mount *m)
590*1c60b9acSAndroid Build Coastguard Worker {
591*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocol_vhost_options *pvo;
592*1c60b9acSAndroid Build Coastguard Worker size_t n = strlen(file), len, i;
593*1c60b9acSAndroid Build Coastguard Worker const char *fallback_mimetype = NULL;
594*1c60b9acSAndroid Build Coastguard Worker const struct lws_mimetype *mt;
595*1c60b9acSAndroid Build Coastguard Worker
596*1c60b9acSAndroid Build Coastguard Worker /* prioritize user-defined mimetypes */
597*1c60b9acSAndroid Build Coastguard Worker for (pvo = m ? m->extra_mimetypes : NULL; pvo; pvo = pvo->next) {
598*1c60b9acSAndroid Build Coastguard Worker /* ie, match anything */
599*1c60b9acSAndroid Build Coastguard Worker if (!fallback_mimetype && pvo->name[0] == '*') {
600*1c60b9acSAndroid Build Coastguard Worker fallback_mimetype = pvo->value;
601*1c60b9acSAndroid Build Coastguard Worker continue;
602*1c60b9acSAndroid Build Coastguard Worker }
603*1c60b9acSAndroid Build Coastguard Worker
604*1c60b9acSAndroid Build Coastguard Worker len = strlen(pvo->name);
605*1c60b9acSAndroid Build Coastguard Worker if (n > len && !strcasecmp(&file[n - len], pvo->name)) {
606*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: match to user mimetype: %s\n", __func__,
607*1c60b9acSAndroid Build Coastguard Worker pvo->value);
608*1c60b9acSAndroid Build Coastguard Worker return pvo->value;
609*1c60b9acSAndroid Build Coastguard Worker }
610*1c60b9acSAndroid Build Coastguard Worker }
611*1c60b9acSAndroid Build Coastguard Worker
612*1c60b9acSAndroid Build Coastguard Worker /* fallback to server-defined mimetypes */
613*1c60b9acSAndroid Build Coastguard Worker for (i = 0; i < LWS_ARRAY_SIZE(server_mimetypes); ++i) {
614*1c60b9acSAndroid Build Coastguard Worker mt = &server_mimetypes[i];
615*1c60b9acSAndroid Build Coastguard Worker
616*1c60b9acSAndroid Build Coastguard Worker len = strlen(mt->extension);
617*1c60b9acSAndroid Build Coastguard Worker if (n > len && !strcasecmp(&file[n - len], mt->extension)) {
618*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: match to server mimetype: %s\n", __func__,
619*1c60b9acSAndroid Build Coastguard Worker mt->mimetype);
620*1c60b9acSAndroid Build Coastguard Worker return mt->mimetype;
621*1c60b9acSAndroid Build Coastguard Worker }
622*1c60b9acSAndroid Build Coastguard Worker }
623*1c60b9acSAndroid Build Coastguard Worker
624*1c60b9acSAndroid Build Coastguard Worker /* fallback to '*' if defined */
625*1c60b9acSAndroid Build Coastguard Worker if (fallback_mimetype) {
626*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: match to any mimetype: %s\n", __func__,
627*1c60b9acSAndroid Build Coastguard Worker fallback_mimetype);
628*1c60b9acSAndroid Build Coastguard Worker return fallback_mimetype;
629*1c60b9acSAndroid Build Coastguard Worker }
630*1c60b9acSAndroid Build Coastguard Worker
631*1c60b9acSAndroid Build Coastguard Worker return NULL;
632*1c60b9acSAndroid Build Coastguard Worker }
633*1c60b9acSAndroid Build Coastguard Worker
634*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
635*1c60b9acSAndroid Build Coastguard Worker static lws_fop_flags_t
lws_vfs_prepare_flags(struct lws * wsi)636*1c60b9acSAndroid Build Coastguard Worker lws_vfs_prepare_flags(struct lws *wsi)
637*1c60b9acSAndroid Build Coastguard Worker {
638*1c60b9acSAndroid Build Coastguard Worker lws_fop_flags_t f = 0;
639*1c60b9acSAndroid Build Coastguard Worker
640*1c60b9acSAndroid Build Coastguard Worker if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING))
641*1c60b9acSAndroid Build Coastguard Worker return f;
642*1c60b9acSAndroid Build Coastguard Worker
643*1c60b9acSAndroid Build Coastguard Worker if (strstr(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING),
644*1c60b9acSAndroid Build Coastguard Worker "gzip")) {
645*1c60b9acSAndroid Build Coastguard Worker lwsl_info("client indicates GZIP is acceptable\n");
646*1c60b9acSAndroid Build Coastguard Worker f |= LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP;
647*1c60b9acSAndroid Build Coastguard Worker }
648*1c60b9acSAndroid Build Coastguard Worker
649*1c60b9acSAndroid Build Coastguard Worker return f;
650*1c60b9acSAndroid Build Coastguard Worker }
651*1c60b9acSAndroid Build Coastguard Worker
652*1c60b9acSAndroid Build Coastguard Worker static int
lws_http_serve(struct lws * wsi,char * uri,const char * origin,const struct lws_http_mount * m)653*1c60b9acSAndroid Build Coastguard Worker lws_http_serve(struct lws *wsi, char *uri, const char *origin,
654*1c60b9acSAndroid Build Coastguard Worker const struct lws_http_mount *m)
655*1c60b9acSAndroid Build Coastguard Worker {
656*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocol_vhost_options *pvo = m->interpret;
657*1c60b9acSAndroid Build Coastguard Worker struct lws_process_html_args args;
658*1c60b9acSAndroid Build Coastguard Worker const char *mimetype;
659*1c60b9acSAndroid Build Coastguard Worker #if !defined(_WIN32_WCE)
660*1c60b9acSAndroid Build Coastguard Worker const struct lws_plat_file_ops *fops;
661*1c60b9acSAndroid Build Coastguard Worker const char *vpath;
662*1c60b9acSAndroid Build Coastguard Worker lws_fop_flags_t fflags = LWS_O_RDONLY;
663*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32) && defined(LWS_HAVE__STAT32I64)
664*1c60b9acSAndroid Build Coastguard Worker struct _stat32i64 st;
665*1c60b9acSAndroid Build Coastguard Worker #else
666*1c60b9acSAndroid Build Coastguard Worker struct stat st;
667*1c60b9acSAndroid Build Coastguard Worker #endif
668*1c60b9acSAndroid Build Coastguard Worker int spin = 0;
669*1c60b9acSAndroid Build Coastguard Worker #endif
670*1c60b9acSAndroid Build Coastguard Worker char path[256], sym[2048];
671*1c60b9acSAndroid Build Coastguard Worker unsigned char *p = (unsigned char *)sym + 32 + LWS_PRE, *start = p;
672*1c60b9acSAndroid Build Coastguard Worker unsigned char *end = p + sizeof(sym) - 32 - LWS_PRE;
673*1c60b9acSAndroid Build Coastguard Worker #if !defined(WIN32) && !defined(LWS_PLAT_FREERTOS)
674*1c60b9acSAndroid Build Coastguard Worker size_t len;
675*1c60b9acSAndroid Build Coastguard Worker #endif
676*1c60b9acSAndroid Build Coastguard Worker int n;
677*1c60b9acSAndroid Build Coastguard Worker
678*1c60b9acSAndroid Build Coastguard Worker wsi->handling_404 = 0;
679*1c60b9acSAndroid Build Coastguard Worker if (!wsi->a.vhost)
680*1c60b9acSAndroid Build Coastguard Worker return -1;
681*1c60b9acSAndroid Build Coastguard Worker
682*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
683*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->http.error_document_404 &&
684*1c60b9acSAndroid Build Coastguard Worker !strcmp(uri, wsi->a.vhost->http.error_document_404))
685*1c60b9acSAndroid Build Coastguard Worker wsi->handling_404 = 1;
686*1c60b9acSAndroid Build Coastguard Worker #endif
687*1c60b9acSAndroid Build Coastguard Worker
688*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(path, sizeof(path) - 1, "%s/%s", origin, uri);
689*1c60b9acSAndroid Build Coastguard Worker
690*1c60b9acSAndroid Build Coastguard Worker #if !defined(_WIN32_WCE)
691*1c60b9acSAndroid Build Coastguard Worker
692*1c60b9acSAndroid Build Coastguard Worker fflags |= lws_vfs_prepare_flags(wsi);
693*1c60b9acSAndroid Build Coastguard Worker
694*1c60b9acSAndroid Build Coastguard Worker do {
695*1c60b9acSAndroid Build Coastguard Worker spin++;
696*1c60b9acSAndroid Build Coastguard Worker fops = lws_vfs_select_fops(wsi->a.context->fops, path, &vpath);
697*1c60b9acSAndroid Build Coastguard Worker
698*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.fop_fd)
699*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&wsi->http.fop_fd);
700*1c60b9acSAndroid Build Coastguard Worker
701*1c60b9acSAndroid Build Coastguard Worker wsi->http.fop_fd = fops->LWS_FOP_OPEN(wsi->a.context->fops,
702*1c60b9acSAndroid Build Coastguard Worker path, vpath, &fflags);
703*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.fop_fd) {
704*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: Unable to open '%s': errno %d\n",
705*1c60b9acSAndroid Build Coastguard Worker __func__, path, errno);
706*1c60b9acSAndroid Build Coastguard Worker
707*1c60b9acSAndroid Build Coastguard Worker return 1;
708*1c60b9acSAndroid Build Coastguard Worker }
709*1c60b9acSAndroid Build Coastguard Worker
710*1c60b9acSAndroid Build Coastguard Worker /* if it can't be statted, don't try */
711*1c60b9acSAndroid Build Coastguard Worker if (fflags & LWS_FOP_FLAG_VIRTUAL)
712*1c60b9acSAndroid Build Coastguard Worker break;
713*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_PLAT_FREERTOS)
714*1c60b9acSAndroid Build Coastguard Worker break;
715*1c60b9acSAndroid Build Coastguard Worker #endif
716*1c60b9acSAndroid Build Coastguard Worker #if !defined(WIN32)
717*1c60b9acSAndroid Build Coastguard Worker if (fstat(wsi->http.fop_fd->fd, &st)) {
718*1c60b9acSAndroid Build Coastguard Worker lwsl_info("unable to stat %s\n", path);
719*1c60b9acSAndroid Build Coastguard Worker goto notfound;
720*1c60b9acSAndroid Build Coastguard Worker }
721*1c60b9acSAndroid Build Coastguard Worker #else
722*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE__STAT32I64)
723*1c60b9acSAndroid Build Coastguard Worker {
724*1c60b9acSAndroid Build Coastguard Worker WCHAR buf[MAX_PATH];
725*1c60b9acSAndroid Build Coastguard Worker MultiByteToWideChar(CP_UTF8, 0, path, -1, buf, LWS_ARRAY_SIZE(buf));
726*1c60b9acSAndroid Build Coastguard Worker if (_wstat32i64(buf, &st)) {
727*1c60b9acSAndroid Build Coastguard Worker lwsl_info("unable to stat %s\n", path);
728*1c60b9acSAndroid Build Coastguard Worker goto notfound;
729*1c60b9acSAndroid Build Coastguard Worker }
730*1c60b9acSAndroid Build Coastguard Worker }
731*1c60b9acSAndroid Build Coastguard Worker #else
732*1c60b9acSAndroid Build Coastguard Worker if (stat(path, &st)) {
733*1c60b9acSAndroid Build Coastguard Worker lwsl_info("unable to stat %s\n", path);
734*1c60b9acSAndroid Build Coastguard Worker goto notfound;
735*1c60b9acSAndroid Build Coastguard Worker }
736*1c60b9acSAndroid Build Coastguard Worker #endif
737*1c60b9acSAndroid Build Coastguard Worker #endif
738*1c60b9acSAndroid Build Coastguard Worker
739*1c60b9acSAndroid Build Coastguard Worker wsi->http.fop_fd->mod_time = (uint32_t)st.st_mtime;
740*1c60b9acSAndroid Build Coastguard Worker fflags |= LWS_FOP_FLAG_MOD_TIME_VALID;
741*1c60b9acSAndroid Build Coastguard Worker
742*1c60b9acSAndroid Build Coastguard Worker #if !defined(WIN32) && !defined(LWS_PLAT_FREERTOS)
743*1c60b9acSAndroid Build Coastguard Worker if ((S_IFMT & st.st_mode) == S_IFLNK) {
744*1c60b9acSAndroid Build Coastguard Worker len = (size_t)readlink(path, sym, sizeof(sym) - 1);
745*1c60b9acSAndroid Build Coastguard Worker if (len) {
746*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Failed to read link %s\n", path);
747*1c60b9acSAndroid Build Coastguard Worker goto notfound;
748*1c60b9acSAndroid Build Coastguard Worker }
749*1c60b9acSAndroid Build Coastguard Worker sym[len] = '\0';
750*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("symlink %s -> %s\n", path, sym);
751*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(path, sizeof(path) - 1, "%s", sym);
752*1c60b9acSAndroid Build Coastguard Worker }
753*1c60b9acSAndroid Build Coastguard Worker #endif
754*1c60b9acSAndroid Build Coastguard Worker if ((S_IFMT & st.st_mode) == S_IFDIR) {
755*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("default filename append to dir\n");
756*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(path, sizeof(path) - 1, "%s/%s/%s",
757*1c60b9acSAndroid Build Coastguard Worker origin, uri, m->def ? m->def : "index.html");
758*1c60b9acSAndroid Build Coastguard Worker }
759*1c60b9acSAndroid Build Coastguard Worker
760*1c60b9acSAndroid Build Coastguard Worker } while ((S_IFMT & st.st_mode) != S_IFREG && spin < 5);
761*1c60b9acSAndroid Build Coastguard Worker
762*1c60b9acSAndroid Build Coastguard Worker if (spin == 5)
763*1c60b9acSAndroid Build Coastguard Worker lwsl_err("symlink loop %s \n", path);
764*1c60b9acSAndroid Build Coastguard Worker
765*1c60b9acSAndroid Build Coastguard Worker n = sprintf(sym, "%08llX%08lX",
766*1c60b9acSAndroid Build Coastguard Worker (unsigned long long)lws_vfs_get_length(wsi->http.fop_fd),
767*1c60b9acSAndroid Build Coastguard Worker (unsigned long)lws_vfs_get_mod_time(wsi->http.fop_fd));
768*1c60b9acSAndroid Build Coastguard Worker
769*1c60b9acSAndroid Build Coastguard Worker /* disable ranges if IF_RANGE token invalid */
770*1c60b9acSAndroid Build Coastguard Worker
771*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_IF_RANGE))
772*1c60b9acSAndroid Build Coastguard Worker if (strcmp(sym, lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_IF_RANGE)))
773*1c60b9acSAndroid Build Coastguard Worker /* differs - defeat Range: */
774*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frag_index[WSI_TOKEN_HTTP_RANGE] = 0;
775*1c60b9acSAndroid Build Coastguard Worker
776*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_IF_NONE_MATCH)) {
777*1c60b9acSAndroid Build Coastguard Worker /*
778*1c60b9acSAndroid Build Coastguard Worker * he thinks he has some version of it already,
779*1c60b9acSAndroid Build Coastguard Worker * check if the tag matches
780*1c60b9acSAndroid Build Coastguard Worker */
781*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(sym, lws_hdr_simple_ptr(wsi,
782*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_IF_NONE_MATCH))) {
783*1c60b9acSAndroid Build Coastguard Worker
784*1c60b9acSAndroid Build Coastguard Worker char cache_control[50], *cc = "no-store";
785*1c60b9acSAndroid Build Coastguard Worker int cclen = 8;
786*1c60b9acSAndroid Build Coastguard Worker
787*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: ETAG match %s %s\n", __func__,
788*1c60b9acSAndroid Build Coastguard Worker uri, origin);
789*1c60b9acSAndroid Build Coastguard Worker
790*1c60b9acSAndroid Build Coastguard Worker /* we don't need to send the payload */
791*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_status(wsi,
792*1c60b9acSAndroid Build Coastguard Worker HTTP_STATUS_NOT_MODIFIED, &p, end)) {
793*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed adding not modified\n",
794*1c60b9acSAndroid Build Coastguard Worker __func__);
795*1c60b9acSAndroid Build Coastguard Worker return -1;
796*1c60b9acSAndroid Build Coastguard Worker }
797*1c60b9acSAndroid Build Coastguard Worker
798*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
799*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_ETAG,
800*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)sym, n, &p, end))
801*1c60b9acSAndroid Build Coastguard Worker return -1;
802*1c60b9acSAndroid Build Coastguard Worker
803*1c60b9acSAndroid Build Coastguard Worker /* but we still need to send cache control... */
804*1c60b9acSAndroid Build Coastguard Worker
805*1c60b9acSAndroid Build Coastguard Worker if (m->cache_max_age && m->cache_reusable) {
806*1c60b9acSAndroid Build Coastguard Worker if (!m->cache_revalidate) {
807*1c60b9acSAndroid Build Coastguard Worker cc = cache_control;
808*1c60b9acSAndroid Build Coastguard Worker cclen = sprintf(cache_control,
809*1c60b9acSAndroid Build Coastguard Worker "%s, max-age=%u",
810*1c60b9acSAndroid Build Coastguard Worker intermediates[wsi->cache_intermediaries],
811*1c60b9acSAndroid Build Coastguard Worker m->cache_max_age);
812*1c60b9acSAndroid Build Coastguard Worker } else {
813*1c60b9acSAndroid Build Coastguard Worker cc = cache_control;
814*1c60b9acSAndroid Build Coastguard Worker cclen = sprintf(cache_control,
815*1c60b9acSAndroid Build Coastguard Worker "must-revalidate, %s, max-age=%u",
816*1c60b9acSAndroid Build Coastguard Worker intermediates[wsi->cache_intermediaries],
817*1c60b9acSAndroid Build Coastguard Worker m->cache_max_age);
818*1c60b9acSAndroid Build Coastguard Worker }
819*1c60b9acSAndroid Build Coastguard Worker }
820*1c60b9acSAndroid Build Coastguard Worker
821*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
822*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CACHE_CONTROL,
823*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)cc, cclen, &p, end))
824*1c60b9acSAndroid Build Coastguard Worker return -1;
825*1c60b9acSAndroid Build Coastguard Worker
826*1c60b9acSAndroid Build Coastguard Worker if (lws_finalize_http_header(wsi, &p, end))
827*1c60b9acSAndroid Build Coastguard Worker return -1;
828*1c60b9acSAndroid Build Coastguard Worker
829*1c60b9acSAndroid Build Coastguard Worker n = lws_write(wsi, start, lws_ptr_diff_size_t(p, start),
830*1c60b9acSAndroid Build Coastguard Worker LWS_WRITE_HTTP_HEADERS |
831*1c60b9acSAndroid Build Coastguard Worker LWS_WRITE_H2_STREAM_END);
832*1c60b9acSAndroid Build Coastguard Worker if (n != lws_ptr_diff(p, start)) {
833*1c60b9acSAndroid Build Coastguard Worker lwsl_err("_write returned %d from %ld\n", n,
834*1c60b9acSAndroid Build Coastguard Worker (long)(p - start));
835*1c60b9acSAndroid Build Coastguard Worker return -1;
836*1c60b9acSAndroid Build Coastguard Worker }
837*1c60b9acSAndroid Build Coastguard Worker
838*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&wsi->http.fop_fd);
839*1c60b9acSAndroid Build Coastguard Worker
840*1c60b9acSAndroid Build Coastguard Worker if (lws_http_transaction_completed(wsi))
841*1c60b9acSAndroid Build Coastguard Worker return -1;
842*1c60b9acSAndroid Build Coastguard Worker
843*1c60b9acSAndroid Build Coastguard Worker return 0;
844*1c60b9acSAndroid Build Coastguard Worker }
845*1c60b9acSAndroid Build Coastguard Worker }
846*1c60b9acSAndroid Build Coastguard Worker
847*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ETAG,
848*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)sym, n, &p, end))
849*1c60b9acSAndroid Build Coastguard Worker return -1;
850*1c60b9acSAndroid Build Coastguard Worker #endif
851*1c60b9acSAndroid Build Coastguard Worker
852*1c60b9acSAndroid Build Coastguard Worker mimetype = lws_get_mimetype(path, m);
853*1c60b9acSAndroid Build Coastguard Worker if (!mimetype) {
854*1c60b9acSAndroid Build Coastguard Worker lwsl_info("unknown mimetype for %s\n", path);
855*1c60b9acSAndroid Build Coastguard Worker if (lws_return_http_status(wsi,
856*1c60b9acSAndroid Build Coastguard Worker HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, NULL) ||
857*1c60b9acSAndroid Build Coastguard Worker lws_http_transaction_completed(wsi))
858*1c60b9acSAndroid Build Coastguard Worker return -1;
859*1c60b9acSAndroid Build Coastguard Worker
860*1c60b9acSAndroid Build Coastguard Worker return 0;
861*1c60b9acSAndroid Build Coastguard Worker }
862*1c60b9acSAndroid Build Coastguard Worker if (!mimetype[0])
863*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("sending no mimetype for %s\n", path);
864*1c60b9acSAndroid Build Coastguard Worker
865*1c60b9acSAndroid Build Coastguard Worker wsi->sending_chunked = 0;
866*1c60b9acSAndroid Build Coastguard Worker wsi->interpreting = 0;
867*1c60b9acSAndroid Build Coastguard Worker
868*1c60b9acSAndroid Build Coastguard Worker /*
869*1c60b9acSAndroid Build Coastguard Worker * check if this is in the list of file suffixes to be interpreted by
870*1c60b9acSAndroid Build Coastguard Worker * a protocol
871*1c60b9acSAndroid Build Coastguard Worker */
872*1c60b9acSAndroid Build Coastguard Worker while (pvo) {
873*1c60b9acSAndroid Build Coastguard Worker n = (int)strlen(path);
874*1c60b9acSAndroid Build Coastguard Worker if (n > (int)strlen(pvo->name) &&
875*1c60b9acSAndroid Build Coastguard Worker !strcmp(&path[(unsigned int)n - strlen(pvo->name)], pvo->name)) {
876*1c60b9acSAndroid Build Coastguard Worker wsi->interpreting = 1;
877*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream)
878*1c60b9acSAndroid Build Coastguard Worker wsi->sending_chunked = 1;
879*1c60b9acSAndroid Build Coastguard Worker
880*1c60b9acSAndroid Build Coastguard Worker wsi->protocol_interpret_idx = (char)(
881*1c60b9acSAndroid Build Coastguard Worker lws_vhost_name_to_protocol(wsi->a.vhost,
882*1c60b9acSAndroid Build Coastguard Worker pvo->value) -
883*1c60b9acSAndroid Build Coastguard Worker &lws_get_vhost(wsi)->protocols[0]);
884*1c60b9acSAndroid Build Coastguard Worker
885*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("want %s interpreted by %s (pcol is %s)\n", path,
886*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->protocols[
887*1c60b9acSAndroid Build Coastguard Worker (int)wsi->protocol_interpret_idx].name,
888*1c60b9acSAndroid Build Coastguard Worker wsi->a.protocol->name);
889*1c60b9acSAndroid Build Coastguard Worker if (lws_bind_protocol(wsi, &wsi->a.vhost->protocols[
890*1c60b9acSAndroid Build Coastguard Worker (int)wsi->protocol_interpret_idx], __func__))
891*1c60b9acSAndroid Build Coastguard Worker return -1;
892*1c60b9acSAndroid Build Coastguard Worker
893*1c60b9acSAndroid Build Coastguard Worker if (lws_ensure_user_space(wsi))
894*1c60b9acSAndroid Build Coastguard Worker return -1;
895*1c60b9acSAndroid Build Coastguard Worker break;
896*1c60b9acSAndroid Build Coastguard Worker }
897*1c60b9acSAndroid Build Coastguard Worker pvo = pvo->next;
898*1c60b9acSAndroid Build Coastguard Worker }
899*1c60b9acSAndroid Build Coastguard Worker
900*1c60b9acSAndroid Build Coastguard Worker if (wsi->sending_chunked) {
901*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
902*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_TRANSFER_ENCODING,
903*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"chunked", 7,
904*1c60b9acSAndroid Build Coastguard Worker &p, end))
905*1c60b9acSAndroid Build Coastguard Worker return -1;
906*1c60b9acSAndroid Build Coastguard Worker }
907*1c60b9acSAndroid Build Coastguard Worker
908*1c60b9acSAndroid Build Coastguard Worker if (m->protocol) {
909*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocols *pp = lws_vhost_name_to_protocol(
910*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost, m->protocol);
911*1c60b9acSAndroid Build Coastguard Worker
912*1c60b9acSAndroid Build Coastguard Worker if (lws_bind_protocol(wsi, pp, __func__))
913*1c60b9acSAndroid Build Coastguard Worker return -1;
914*1c60b9acSAndroid Build Coastguard Worker args.p = (char *)p;
915*1c60b9acSAndroid Build Coastguard Worker args.max_len = lws_ptr_diff(end, p);
916*1c60b9acSAndroid Build Coastguard Worker if (pp->callback(wsi, LWS_CALLBACK_ADD_HEADERS,
917*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, &args, 0))
918*1c60b9acSAndroid Build Coastguard Worker return -1;
919*1c60b9acSAndroid Build Coastguard Worker p = (unsigned char *)args.p;
920*1c60b9acSAndroid Build Coastguard Worker }
921*1c60b9acSAndroid Build Coastguard Worker
922*1c60b9acSAndroid Build Coastguard Worker *p = '\0';
923*1c60b9acSAndroid Build Coastguard Worker n = lws_serve_http_file(wsi, path, mimetype, (char *)start,
924*1c60b9acSAndroid Build Coastguard Worker lws_ptr_diff(p, start));
925*1c60b9acSAndroid Build Coastguard Worker
926*1c60b9acSAndroid Build Coastguard Worker if (n < 0 || ((n > 0) && lws_http_transaction_completed(wsi)))
927*1c60b9acSAndroid Build Coastguard Worker return -1; /* error or can't reuse connection: close the socket */
928*1c60b9acSAndroid Build Coastguard Worker
929*1c60b9acSAndroid Build Coastguard Worker return 0;
930*1c60b9acSAndroid Build Coastguard Worker
931*1c60b9acSAndroid Build Coastguard Worker notfound:
932*1c60b9acSAndroid Build Coastguard Worker
933*1c60b9acSAndroid Build Coastguard Worker return 1;
934*1c60b9acSAndroid Build Coastguard Worker }
935*1c60b9acSAndroid Build Coastguard Worker #endif
936*1c60b9acSAndroid Build Coastguard Worker
937*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
938*1c60b9acSAndroid Build Coastguard Worker const struct lws_http_mount *
lws_find_mount(struct lws * wsi,const char * uri_ptr,int uri_len)939*1c60b9acSAndroid Build Coastguard Worker lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len)
940*1c60b9acSAndroid Build Coastguard Worker {
941*1c60b9acSAndroid Build Coastguard Worker const struct lws_http_mount *hm, *hit = NULL;
942*1c60b9acSAndroid Build Coastguard Worker int best = 0;
943*1c60b9acSAndroid Build Coastguard Worker
944*1c60b9acSAndroid Build Coastguard Worker hm = wsi->a.vhost->http.mount_list;
945*1c60b9acSAndroid Build Coastguard Worker while (hm) {
946*1c60b9acSAndroid Build Coastguard Worker if (uri_len >= hm->mountpoint_len &&
947*1c60b9acSAndroid Build Coastguard Worker !strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len) &&
948*1c60b9acSAndroid Build Coastguard Worker (uri_ptr[hm->mountpoint_len] == '\0' ||
949*1c60b9acSAndroid Build Coastguard Worker uri_ptr[hm->mountpoint_len] == '/' ||
950*1c60b9acSAndroid Build Coastguard Worker hm->mountpoint_len == 1)
951*1c60b9acSAndroid Build Coastguard Worker ) {
952*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
953*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_wsi_add(wsi, "mnt", hm->mountpoint);
954*1c60b9acSAndroid Build Coastguard Worker #endif
955*1c60b9acSAndroid Build Coastguard Worker
956*1c60b9acSAndroid Build Coastguard Worker if (hm->origin_protocol == LWSMPRO_CALLBACK ||
957*1c60b9acSAndroid Build Coastguard Worker ((hm->origin_protocol == LWSMPRO_CGI ||
958*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) ||
959*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) ||
960*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
961*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI) ||
962*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI) ||
963*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_DELETE_URI) ||
964*1c60b9acSAndroid Build Coastguard Worker #endif
965*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_HEAD_URI) ||
966*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
967*1c60b9acSAndroid Build Coastguard Worker (wsi->mux_substream &&
968*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi,
969*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_PATH)) ||
970*1c60b9acSAndroid Build Coastguard Worker #endif
971*1c60b9acSAndroid Build Coastguard Worker hm->protocol) &&
972*1c60b9acSAndroid Build Coastguard Worker hm->mountpoint_len > best)) {
973*1c60b9acSAndroid Build Coastguard Worker best = hm->mountpoint_len;
974*1c60b9acSAndroid Build Coastguard Worker hit = hm;
975*1c60b9acSAndroid Build Coastguard Worker }
976*1c60b9acSAndroid Build Coastguard Worker }
977*1c60b9acSAndroid Build Coastguard Worker hm = hm->mount_next;
978*1c60b9acSAndroid Build Coastguard Worker }
979*1c60b9acSAndroid Build Coastguard Worker
980*1c60b9acSAndroid Build Coastguard Worker return hit;
981*1c60b9acSAndroid Build Coastguard Worker }
982*1c60b9acSAndroid Build Coastguard Worker #endif
983*1c60b9acSAndroid Build Coastguard Worker
984*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_BASIC_AUTH) && !defined(LWS_PLAT_FREERTOS) && defined(LWS_WITH_FILE_OPS)
985*1c60b9acSAndroid Build Coastguard Worker static int
lws_find_string_in_file(const char * filename,const char * string,int stringlen)986*1c60b9acSAndroid Build Coastguard Worker lws_find_string_in_file(const char *filename, const char *string, int stringlen)
987*1c60b9acSAndroid Build Coastguard Worker {
988*1c60b9acSAndroid Build Coastguard Worker char buf[128];
989*1c60b9acSAndroid Build Coastguard Worker int fd, match = 0, pos = 0, n = 0, hit = 0;
990*1c60b9acSAndroid Build Coastguard Worker
991*1c60b9acSAndroid Build Coastguard Worker fd = lws_open(filename, O_RDONLY);
992*1c60b9acSAndroid Build Coastguard Worker if (fd < 0) {
993*1c60b9acSAndroid Build Coastguard Worker lwsl_err("can't open auth file: %s\n", filename);
994*1c60b9acSAndroid Build Coastguard Worker return 0;
995*1c60b9acSAndroid Build Coastguard Worker }
996*1c60b9acSAndroid Build Coastguard Worker
997*1c60b9acSAndroid Build Coastguard Worker while (1) {
998*1c60b9acSAndroid Build Coastguard Worker if (pos == n) {
999*1c60b9acSAndroid Build Coastguard Worker n = (int)read(fd, buf, sizeof(buf));
1000*1c60b9acSAndroid Build Coastguard Worker if (n <= 0) {
1001*1c60b9acSAndroid Build Coastguard Worker if (match == stringlen)
1002*1c60b9acSAndroid Build Coastguard Worker hit = 1;
1003*1c60b9acSAndroid Build Coastguard Worker break;
1004*1c60b9acSAndroid Build Coastguard Worker }
1005*1c60b9acSAndroid Build Coastguard Worker pos = 0;
1006*1c60b9acSAndroid Build Coastguard Worker }
1007*1c60b9acSAndroid Build Coastguard Worker
1008*1c60b9acSAndroid Build Coastguard Worker if (match == stringlen) {
1009*1c60b9acSAndroid Build Coastguard Worker if (buf[pos] == '\r' || buf[pos] == '\n') {
1010*1c60b9acSAndroid Build Coastguard Worker hit = 1;
1011*1c60b9acSAndroid Build Coastguard Worker break;
1012*1c60b9acSAndroid Build Coastguard Worker }
1013*1c60b9acSAndroid Build Coastguard Worker match = 0;
1014*1c60b9acSAndroid Build Coastguard Worker }
1015*1c60b9acSAndroid Build Coastguard Worker
1016*1c60b9acSAndroid Build Coastguard Worker if (buf[pos] == string[match])
1017*1c60b9acSAndroid Build Coastguard Worker match++;
1018*1c60b9acSAndroid Build Coastguard Worker else
1019*1c60b9acSAndroid Build Coastguard Worker match = 0;
1020*1c60b9acSAndroid Build Coastguard Worker
1021*1c60b9acSAndroid Build Coastguard Worker pos++;
1022*1c60b9acSAndroid Build Coastguard Worker }
1023*1c60b9acSAndroid Build Coastguard Worker
1024*1c60b9acSAndroid Build Coastguard Worker close(fd);
1025*1c60b9acSAndroid Build Coastguard Worker
1026*1c60b9acSAndroid Build Coastguard Worker return hit;
1027*1c60b9acSAndroid Build Coastguard Worker }
1028*1c60b9acSAndroid Build Coastguard Worker #endif
1029*1c60b9acSAndroid Build Coastguard Worker
1030*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_BASIC_AUTH)
1031*1c60b9acSAndroid Build Coastguard Worker
1032*1c60b9acSAndroid Build Coastguard Worker int
lws_unauthorised_basic_auth(struct lws * wsi)1033*1c60b9acSAndroid Build Coastguard Worker lws_unauthorised_basic_auth(struct lws *wsi)
1034*1c60b9acSAndroid Build Coastguard Worker {
1035*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
1036*1c60b9acSAndroid Build Coastguard Worker unsigned char *start = pt->serv_buf + LWS_PRE,
1037*1c60b9acSAndroid Build Coastguard Worker *p = start, *end = p + 2048;
1038*1c60b9acSAndroid Build Coastguard Worker char buf[64];
1039*1c60b9acSAndroid Build Coastguard Worker int n;
1040*1c60b9acSAndroid Build Coastguard Worker
1041*1c60b9acSAndroid Build Coastguard Worker /* no auth... tell him it is required */
1042*1c60b9acSAndroid Build Coastguard Worker
1043*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_status(wsi, HTTP_STATUS_UNAUTHORIZED, &p, end))
1044*1c60b9acSAndroid Build Coastguard Worker return -1;
1045*1c60b9acSAndroid Build Coastguard Worker
1046*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf(buf, sizeof(buf), "Basic realm=\"lwsws\"");
1047*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
1048*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
1049*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)buf, n, &p, end))
1050*1c60b9acSAndroid Build Coastguard Worker return -1;
1051*1c60b9acSAndroid Build Coastguard Worker
1052*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_content_length(wsi, 0, &p, end))
1053*1c60b9acSAndroid Build Coastguard Worker return -1;
1054*1c60b9acSAndroid Build Coastguard Worker
1055*1c60b9acSAndroid Build Coastguard Worker if (lws_finalize_http_header(wsi, &p, end))
1056*1c60b9acSAndroid Build Coastguard Worker return -1;
1057*1c60b9acSAndroid Build Coastguard Worker
1058*1c60b9acSAndroid Build Coastguard Worker n = lws_write(wsi, start, lws_ptr_diff_size_t(p, start), LWS_WRITE_HTTP_HEADERS |
1059*1c60b9acSAndroid Build Coastguard Worker LWS_WRITE_H2_STREAM_END);
1060*1c60b9acSAndroid Build Coastguard Worker if (n < 0)
1061*1c60b9acSAndroid Build Coastguard Worker return -1;
1062*1c60b9acSAndroid Build Coastguard Worker
1063*1c60b9acSAndroid Build Coastguard Worker return lws_http_transaction_completed(wsi);
1064*1c60b9acSAndroid Build Coastguard Worker
1065*1c60b9acSAndroid Build Coastguard Worker }
1066*1c60b9acSAndroid Build Coastguard Worker
1067*1c60b9acSAndroid Build Coastguard Worker #endif
1068*1c60b9acSAndroid Build Coastguard Worker
lws_clean_url(char * p)1069*1c60b9acSAndroid Build Coastguard Worker int lws_clean_url(char *p)
1070*1c60b9acSAndroid Build Coastguard Worker {
1071*1c60b9acSAndroid Build Coastguard Worker if (p[0] == 'h' && p[1] == 't' && p[2] == 't' && p[3] == 'p') {
1072*1c60b9acSAndroid Build Coastguard Worker p += 4;
1073*1c60b9acSAndroid Build Coastguard Worker if (*p == 's')
1074*1c60b9acSAndroid Build Coastguard Worker p++;
1075*1c60b9acSAndroid Build Coastguard Worker if (*p == ':') {
1076*1c60b9acSAndroid Build Coastguard Worker p++;
1077*1c60b9acSAndroid Build Coastguard Worker if (*p == '/')
1078*1c60b9acSAndroid Build Coastguard Worker p++;
1079*1c60b9acSAndroid Build Coastguard Worker }
1080*1c60b9acSAndroid Build Coastguard Worker }
1081*1c60b9acSAndroid Build Coastguard Worker
1082*1c60b9acSAndroid Build Coastguard Worker while (*p) {
1083*1c60b9acSAndroid Build Coastguard Worker if (p[0] == '/' && p[1] == '/') {
1084*1c60b9acSAndroid Build Coastguard Worker char *p1 = p;
1085*1c60b9acSAndroid Build Coastguard Worker while (*p1) {
1086*1c60b9acSAndroid Build Coastguard Worker *p1 = p1[1];
1087*1c60b9acSAndroid Build Coastguard Worker p1++;
1088*1c60b9acSAndroid Build Coastguard Worker }
1089*1c60b9acSAndroid Build Coastguard Worker continue;
1090*1c60b9acSAndroid Build Coastguard Worker }
1091*1c60b9acSAndroid Build Coastguard Worker p++;
1092*1c60b9acSAndroid Build Coastguard Worker }
1093*1c60b9acSAndroid Build Coastguard Worker
1094*1c60b9acSAndroid Build Coastguard Worker return 0;
1095*1c60b9acSAndroid Build Coastguard Worker }
1096*1c60b9acSAndroid Build Coastguard Worker
1097*1c60b9acSAndroid Build Coastguard Worker static const unsigned char methods[] = {
1098*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_GET_URI,
1099*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_POST_URI,
1100*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
1101*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_OPTIONS_URI,
1102*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_PUT_URI,
1103*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_PATCH_URI,
1104*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_DELETE_URI,
1105*1c60b9acSAndroid Build Coastguard Worker #endif
1106*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_CONNECT,
1107*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HEAD_URI,
1108*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_HTTP2
1109*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_PATH,
1110*1c60b9acSAndroid Build Coastguard Worker #endif
1111*1c60b9acSAndroid Build Coastguard Worker };
1112*1c60b9acSAndroid Build Coastguard Worker
1113*1c60b9acSAndroid Build Coastguard Worker int
lws_http_get_uri_and_method(struct lws * wsi,char ** puri_ptr,int * puri_len)1114*1c60b9acSAndroid Build Coastguard Worker lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len)
1115*1c60b9acSAndroid Build Coastguard Worker {
1116*1c60b9acSAndroid Build Coastguard Worker int n, count = 0;
1117*1c60b9acSAndroid Build Coastguard Worker
1118*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < (int)LWS_ARRAY_SIZE(methods); n++)
1119*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, methods[n]))
1120*1c60b9acSAndroid Build Coastguard Worker count++;
1121*1c60b9acSAndroid Build Coastguard Worker if (!count) {
1122*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("Missing URI in HTTP request\n");
1123*1c60b9acSAndroid Build Coastguard Worker return -1;
1124*1c60b9acSAndroid Build Coastguard Worker }
1125*1c60b9acSAndroid Build Coastguard Worker
1126*1c60b9acSAndroid Build Coastguard Worker if (count != 1 &&
1127*1c60b9acSAndroid Build Coastguard Worker !((wsi->mux_substream || wsi->h2_stream_carries_ws)
1128*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
1129*1c60b9acSAndroid Build Coastguard Worker &&
1130*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH)
1131*1c60b9acSAndroid Build Coastguard Worker #endif
1132*1c60b9acSAndroid Build Coastguard Worker )) {
1133*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("multiple methods?\n");
1134*1c60b9acSAndroid Build Coastguard Worker return -1;
1135*1c60b9acSAndroid Build Coastguard Worker }
1136*1c60b9acSAndroid Build Coastguard Worker
1137*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < (int)LWS_ARRAY_SIZE(methods); n++)
1138*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, methods[n])) {
1139*1c60b9acSAndroid Build Coastguard Worker *puri_ptr = lws_hdr_simple_ptr(wsi, methods[n]);
1140*1c60b9acSAndroid Build Coastguard Worker *puri_len = lws_hdr_total_length(wsi, methods[n]);
1141*1c60b9acSAndroid Build Coastguard Worker return n;
1142*1c60b9acSAndroid Build Coastguard Worker }
1143*1c60b9acSAndroid Build Coastguard Worker
1144*1c60b9acSAndroid Build Coastguard Worker return -1;
1145*1c60b9acSAndroid Build Coastguard Worker }
1146*1c60b9acSAndroid Build Coastguard Worker
1147*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_BASIC_AUTH)
1148*1c60b9acSAndroid Build Coastguard Worker
1149*1c60b9acSAndroid Build Coastguard Worker enum lws_check_basic_auth_results
lws_check_basic_auth(struct lws * wsi,const char * basic_auth_login_file,unsigned int auth_mode)1150*1c60b9acSAndroid Build Coastguard Worker lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file,
1151*1c60b9acSAndroid Build Coastguard Worker unsigned int auth_mode)
1152*1c60b9acSAndroid Build Coastguard Worker {
1153*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
1154*1c60b9acSAndroid Build Coastguard Worker char b64[160], plain[(sizeof(b64) * 3) / 4], *pcolon;
1155*1c60b9acSAndroid Build Coastguard Worker int m, ml, fi, bar;
1156*1c60b9acSAndroid Build Coastguard Worker
1157*1c60b9acSAndroid Build Coastguard Worker if (!basic_auth_login_file && auth_mode == LWSAUTHM_DEFAULT)
1158*1c60b9acSAndroid Build Coastguard Worker return LCBA_CONTINUE;
1159*1c60b9acSAndroid Build Coastguard Worker
1160*1c60b9acSAndroid Build Coastguard Worker /* Did he send auth? */
1161*1c60b9acSAndroid Build Coastguard Worker ml = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_AUTHORIZATION);
1162*1c60b9acSAndroid Build Coastguard Worker if (!ml)
1163*1c60b9acSAndroid Build Coastguard Worker return LCBA_FAILED_AUTH;
1164*1c60b9acSAndroid Build Coastguard Worker
1165*1c60b9acSAndroid Build Coastguard Worker /* Disallow fragmentation monkey business */
1166*1c60b9acSAndroid Build Coastguard Worker
1167*1c60b9acSAndroid Build Coastguard Worker fi = wsi->http.ah->frag_index[WSI_TOKEN_HTTP_AUTHORIZATION];
1168*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.ah->frags[fi].nfrag) {
1169*1c60b9acSAndroid Build Coastguard Worker lwsl_err("fragmented basic auth header not allowed\n");
1170*1c60b9acSAndroid Build Coastguard Worker return LCBA_FAILED_AUTH;
1171*1c60b9acSAndroid Build Coastguard Worker }
1172*1c60b9acSAndroid Build Coastguard Worker
1173*1c60b9acSAndroid Build Coastguard Worker m = lws_hdr_copy(wsi, b64, sizeof(b64),
1174*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_AUTHORIZATION);
1175*1c60b9acSAndroid Build Coastguard Worker if (m < 7) {
1176*1c60b9acSAndroid Build Coastguard Worker lwsl_err("b64 auth too long\n");
1177*1c60b9acSAndroid Build Coastguard Worker return LCBA_END_TRANSACTION;
1178*1c60b9acSAndroid Build Coastguard Worker }
1179*1c60b9acSAndroid Build Coastguard Worker
1180*1c60b9acSAndroid Build Coastguard Worker b64[5] = '\0';
1181*1c60b9acSAndroid Build Coastguard Worker if (strcasecmp(b64, "Basic")) {
1182*1c60b9acSAndroid Build Coastguard Worker lwsl_err("auth missing basic: %s\n", b64);
1183*1c60b9acSAndroid Build Coastguard Worker return LCBA_END_TRANSACTION;
1184*1c60b9acSAndroid Build Coastguard Worker }
1185*1c60b9acSAndroid Build Coastguard Worker
1186*1c60b9acSAndroid Build Coastguard Worker /* It'll be like Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l */
1187*1c60b9acSAndroid Build Coastguard Worker
1188*1c60b9acSAndroid Build Coastguard Worker m = lws_b64_decode_string(b64 + 6, plain, sizeof(plain) - 1);
1189*1c60b9acSAndroid Build Coastguard Worker if (m < 0) {
1190*1c60b9acSAndroid Build Coastguard Worker lwsl_err("plain auth too long\n");
1191*1c60b9acSAndroid Build Coastguard Worker return LCBA_END_TRANSACTION;
1192*1c60b9acSAndroid Build Coastguard Worker }
1193*1c60b9acSAndroid Build Coastguard Worker
1194*1c60b9acSAndroid Build Coastguard Worker plain[m] = '\0';
1195*1c60b9acSAndroid Build Coastguard Worker pcolon = strchr(plain, ':');
1196*1c60b9acSAndroid Build Coastguard Worker if (!pcolon) {
1197*1c60b9acSAndroid Build Coastguard Worker lwsl_err("basic auth format broken\n");
1198*1c60b9acSAndroid Build Coastguard Worker return LCBA_END_TRANSACTION;
1199*1c60b9acSAndroid Build Coastguard Worker }
1200*1c60b9acSAndroid Build Coastguard Worker
1201*1c60b9acSAndroid Build Coastguard Worker switch (auth_mode) {
1202*1c60b9acSAndroid Build Coastguard Worker case LWSAUTHM_DEFAULT:
1203*1c60b9acSAndroid Build Coastguard Worker if (lws_find_string_in_file(basic_auth_login_file, plain, m))
1204*1c60b9acSAndroid Build Coastguard Worker break;
1205*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: basic auth lookup failed\n", __func__);
1206*1c60b9acSAndroid Build Coastguard Worker return LCBA_FAILED_AUTH;
1207*1c60b9acSAndroid Build Coastguard Worker
1208*1c60b9acSAndroid Build Coastguard Worker case LWSAUTHM_BASIC_AUTH_CALLBACK:
1209*1c60b9acSAndroid Build Coastguard Worker bar = wsi->a.protocol->callback(wsi,
1210*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_VERIFY_BASIC_AUTHORIZATION,
1211*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, plain, (unsigned int)m);
1212*1c60b9acSAndroid Build Coastguard Worker if (!bar)
1213*1c60b9acSAndroid Build Coastguard Worker return LCBA_FAILED_AUTH;
1214*1c60b9acSAndroid Build Coastguard Worker break;
1215*1c60b9acSAndroid Build Coastguard Worker default:
1216*1c60b9acSAndroid Build Coastguard Worker /* Invalid auth mode so lets fail all authentication attempts */
1217*1c60b9acSAndroid Build Coastguard Worker return LCBA_FAILED_AUTH;
1218*1c60b9acSAndroid Build Coastguard Worker }
1219*1c60b9acSAndroid Build Coastguard Worker
1220*1c60b9acSAndroid Build Coastguard Worker /*
1221*1c60b9acSAndroid Build Coastguard Worker * Rewrite WSI_TOKEN_HTTP_AUTHORIZATION so it is just the
1222*1c60b9acSAndroid Build Coastguard Worker * authorized username
1223*1c60b9acSAndroid Build Coastguard Worker */
1224*1c60b9acSAndroid Build Coastguard Worker
1225*1c60b9acSAndroid Build Coastguard Worker *pcolon = '\0';
1226*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->frags[fi].len = (uint16_t)lws_ptr_diff_size_t(pcolon, &plain[0]);
1227*1c60b9acSAndroid Build Coastguard Worker pcolon = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_AUTHORIZATION);
1228*1c60b9acSAndroid Build Coastguard Worker strncpy(pcolon, plain, (unsigned int)(ml - 1));
1229*1c60b9acSAndroid Build Coastguard Worker pcolon[ml - 1] = '\0';
1230*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: basic auth accepted for %s\n", __func__,
1231*1c60b9acSAndroid Build Coastguard Worker lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_AUTHORIZATION));
1232*1c60b9acSAndroid Build Coastguard Worker
1233*1c60b9acSAndroid Build Coastguard Worker return LCBA_CONTINUE;
1234*1c60b9acSAndroid Build Coastguard Worker #else
1235*1c60b9acSAndroid Build Coastguard Worker return LCBA_FAILED_AUTH;
1236*1c60b9acSAndroid Build Coastguard Worker #endif
1237*1c60b9acSAndroid Build Coastguard Worker }
1238*1c60b9acSAndroid Build Coastguard Worker
1239*1c60b9acSAndroid Build Coastguard Worker #endif
1240*1c60b9acSAndroid Build Coastguard Worker
1241*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_PROXY)
1242*1c60b9acSAndroid Build Coastguard Worker /*
1243*1c60b9acSAndroid Build Coastguard Worker * Set up an onward http proxy connection according to the mount this
1244*1c60b9acSAndroid Build Coastguard Worker * uri falls under. Notice this can also be starting the proxying of what was
1245*1c60b9acSAndroid Build Coastguard Worker * originally an incoming h1 upgrade, or an h2 ws "upgrade".
1246*1c60b9acSAndroid Build Coastguard Worker */
1247*1c60b9acSAndroid Build Coastguard Worker int
lws_http_proxy_start(struct lws * wsi,const struct lws_http_mount * hit,char * uri_ptr,char ws)1248*1c60b9acSAndroid Build Coastguard Worker lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit,
1249*1c60b9acSAndroid Build Coastguard Worker char *uri_ptr, char ws)
1250*1c60b9acSAndroid Build Coastguard Worker {
1251*1c60b9acSAndroid Build Coastguard Worker char ads[96], host[96], *pcolon, *pslash, unix_skt = 0;
1252*1c60b9acSAndroid Build Coastguard Worker struct lws_client_connect_info i;
1253*1c60b9acSAndroid Build Coastguard Worker struct lws *cwsi;
1254*1c60b9acSAndroid Build Coastguard Worker int n, na;
1255*1c60b9acSAndroid Build Coastguard Worker unsigned int max_http_header_data = wsi->a.context->max_http_header_data > 256 ? wsi->a.context->max_http_header_data : 256;
1256*1c60b9acSAndroid Build Coastguard Worker char rpath[max_http_header_data];
1257*1c60b9acSAndroid Build Coastguard Worker
1258*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
1259*1c60b9acSAndroid Build Coastguard Worker if (ws)
1260*1c60b9acSAndroid Build Coastguard Worker /*
1261*1c60b9acSAndroid Build Coastguard Worker * Neither our inbound ws upgrade request side, nor our onward
1262*1c60b9acSAndroid Build Coastguard Worker * ws client connection on our side can bind to the actual
1263*1c60b9acSAndroid Build Coastguard Worker * protocol that only the remote inbound side and the remote
1264*1c60b9acSAndroid Build Coastguard Worker * onward side understand.
1265*1c60b9acSAndroid Build Coastguard Worker *
1266*1c60b9acSAndroid Build Coastguard Worker * Instead these are both bound to our built-in "lws-ws-proxy"
1267*1c60b9acSAndroid Build Coastguard Worker * protocol, which understands how to proxy between the two
1268*1c60b9acSAndroid Build Coastguard Worker * sides.
1269*1c60b9acSAndroid Build Coastguard Worker *
1270*1c60b9acSAndroid Build Coastguard Worker * We bind the parent, inbound part here and our side of the
1271*1c60b9acSAndroid Build Coastguard Worker * onward client connection is bound to the same handler using
1272*1c60b9acSAndroid Build Coastguard Worker * the .local_protocol_name.
1273*1c60b9acSAndroid Build Coastguard Worker */
1274*1c60b9acSAndroid Build Coastguard Worker lws_bind_protocol(wsi, &lws_ws_proxy, __func__);
1275*1c60b9acSAndroid Build Coastguard Worker #endif
1276*1c60b9acSAndroid Build Coastguard Worker memset(&i, 0, sizeof(i));
1277*1c60b9acSAndroid Build Coastguard Worker i.context = lws_get_context(wsi);
1278*1c60b9acSAndroid Build Coastguard Worker
1279*1c60b9acSAndroid Build Coastguard Worker if (hit->origin[0] == '+')
1280*1c60b9acSAndroid Build Coastguard Worker unix_skt = 1;
1281*1c60b9acSAndroid Build Coastguard Worker
1282*1c60b9acSAndroid Build Coastguard Worker pcolon = strchr(hit->origin, ':');
1283*1c60b9acSAndroid Build Coastguard Worker pslash = strchr(hit->origin, '/');
1284*1c60b9acSAndroid Build Coastguard Worker if (!pslash) {
1285*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Proxy mount origin '%s' must have /\n", hit->origin);
1286*1c60b9acSAndroid Build Coastguard Worker return -1;
1287*1c60b9acSAndroid Build Coastguard Worker }
1288*1c60b9acSAndroid Build Coastguard Worker
1289*1c60b9acSAndroid Build Coastguard Worker if (unix_skt) {
1290*1c60b9acSAndroid Build Coastguard Worker if (!pcolon) {
1291*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Proxy mount origin for unix skt must "
1292*1c60b9acSAndroid Build Coastguard Worker "have address delimited by :\n");
1293*1c60b9acSAndroid Build Coastguard Worker
1294*1c60b9acSAndroid Build Coastguard Worker return -1;
1295*1c60b9acSAndroid Build Coastguard Worker }
1296*1c60b9acSAndroid Build Coastguard Worker n = lws_ptr_diff(pcolon, hit->origin);
1297*1c60b9acSAndroid Build Coastguard Worker pslash = pcolon;
1298*1c60b9acSAndroid Build Coastguard Worker } else {
1299*1c60b9acSAndroid Build Coastguard Worker if (pcolon > pslash)
1300*1c60b9acSAndroid Build Coastguard Worker pcolon = NULL;
1301*1c60b9acSAndroid Build Coastguard Worker
1302*1c60b9acSAndroid Build Coastguard Worker if (pcolon)
1303*1c60b9acSAndroid Build Coastguard Worker n = (int)(pcolon - hit->origin);
1304*1c60b9acSAndroid Build Coastguard Worker else
1305*1c60b9acSAndroid Build Coastguard Worker n = (int)(pslash - hit->origin);
1306*1c60b9acSAndroid Build Coastguard Worker
1307*1c60b9acSAndroid Build Coastguard Worker if (n >= (int)sizeof(ads) - 2)
1308*1c60b9acSAndroid Build Coastguard Worker n = sizeof(ads) - 2;
1309*1c60b9acSAndroid Build Coastguard Worker }
1310*1c60b9acSAndroid Build Coastguard Worker
1311*1c60b9acSAndroid Build Coastguard Worker memcpy(ads, hit->origin, (unsigned int)n);
1312*1c60b9acSAndroid Build Coastguard Worker ads[n] = '\0';
1313*1c60b9acSAndroid Build Coastguard Worker
1314*1c60b9acSAndroid Build Coastguard Worker i.address = ads;
1315*1c60b9acSAndroid Build Coastguard Worker i.port = 80;
1316*1c60b9acSAndroid Build Coastguard Worker if (hit->origin_protocol == LWSMPRO_HTTPS) {
1317*1c60b9acSAndroid Build Coastguard Worker i.port = 443;
1318*1c60b9acSAndroid Build Coastguard Worker i.ssl_connection = 1;
1319*1c60b9acSAndroid Build Coastguard Worker }
1320*1c60b9acSAndroid Build Coastguard Worker if (pcolon)
1321*1c60b9acSAndroid Build Coastguard Worker i.port = atoi(pcolon + 1);
1322*1c60b9acSAndroid Build Coastguard Worker
1323*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf(rpath, max_http_header_data - 1, "/%s/%s",
1324*1c60b9acSAndroid Build Coastguard Worker pslash + 1, uri_ptr + hit->mountpoint_len) - 1;
1325*1c60b9acSAndroid Build Coastguard Worker lws_clean_url(rpath);
1326*1c60b9acSAndroid Build Coastguard Worker n = (int)strlen(rpath);
1327*1c60b9acSAndroid Build Coastguard Worker if (n && rpath[n - 1] == '/')
1328*1c60b9acSAndroid Build Coastguard Worker n--;
1329*1c60b9acSAndroid Build Coastguard Worker
1330*1c60b9acSAndroid Build Coastguard Worker na = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_URI_ARGS);
1331*1c60b9acSAndroid Build Coastguard Worker if (na) {
1332*1c60b9acSAndroid Build Coastguard Worker char *p;
1333*1c60b9acSAndroid Build Coastguard Worker int budg;
1334*1c60b9acSAndroid Build Coastguard Worker
1335*1c60b9acSAndroid Build Coastguard Worker if (!n) /* don't start with the ?... use the first / if so */
1336*1c60b9acSAndroid Build Coastguard Worker n++;
1337*1c60b9acSAndroid Build Coastguard Worker
1338*1c60b9acSAndroid Build Coastguard Worker p = rpath + n;
1339*1c60b9acSAndroid Build Coastguard Worker
1340*1c60b9acSAndroid Build Coastguard Worker if (na >= (int)max_http_header_data - n - 2) {
1341*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: query string %d longer "
1342*1c60b9acSAndroid Build Coastguard Worker "than we can handle\n", __func__,
1343*1c60b9acSAndroid Build Coastguard Worker na);
1344*1c60b9acSAndroid Build Coastguard Worker
1345*1c60b9acSAndroid Build Coastguard Worker return -1;
1346*1c60b9acSAndroid Build Coastguard Worker }
1347*1c60b9acSAndroid Build Coastguard Worker
1348*1c60b9acSAndroid Build Coastguard Worker *p++ = '?';
1349*1c60b9acSAndroid Build Coastguard Worker budg = lws_hdr_copy(wsi, p,
1350*1c60b9acSAndroid Build Coastguard Worker (int)(&rpath[max_http_header_data - 1] - p),
1351*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_URI_ARGS);
1352*1c60b9acSAndroid Build Coastguard Worker if (budg > 0)
1353*1c60b9acSAndroid Build Coastguard Worker p += budg;
1354*1c60b9acSAndroid Build Coastguard Worker
1355*1c60b9acSAndroid Build Coastguard Worker *p = '\0';
1356*1c60b9acSAndroid Build Coastguard Worker }
1357*1c60b9acSAndroid Build Coastguard Worker
1358*1c60b9acSAndroid Build Coastguard Worker i.path = rpath;
1359*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: proxied path '%s'\n", __func__, i.path);
1360*1c60b9acSAndroid Build Coastguard Worker
1361*1c60b9acSAndroid Build Coastguard Worker /* incoming may be h1 or h2... if he sends h1 HOST, use that
1362*1c60b9acSAndroid Build Coastguard Worker * directly, otherwise we must convert h2 :authority to h1
1363*1c60b9acSAndroid Build Coastguard Worker * host */
1364*1c60b9acSAndroid Build Coastguard Worker
1365*1c60b9acSAndroid Build Coastguard Worker i.host = NULL;
1366*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
1367*1c60b9acSAndroid Build Coastguard Worker n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_AUTHORITY);
1368*1c60b9acSAndroid Build Coastguard Worker if (n > 0)
1369*1c60b9acSAndroid Build Coastguard Worker i.host = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_AUTHORITY);
1370*1c60b9acSAndroid Build Coastguard Worker else
1371*1c60b9acSAndroid Build Coastguard Worker #endif
1372*1c60b9acSAndroid Build Coastguard Worker {
1373*1c60b9acSAndroid Build Coastguard Worker n = lws_hdr_total_length(wsi, WSI_TOKEN_HOST);
1374*1c60b9acSAndroid Build Coastguard Worker if (n > 0) {
1375*1c60b9acSAndroid Build Coastguard Worker i.host = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST);
1376*1c60b9acSAndroid Build Coastguard Worker }
1377*1c60b9acSAndroid Build Coastguard Worker }
1378*1c60b9acSAndroid Build Coastguard Worker
1379*1c60b9acSAndroid Build Coastguard Worker #if 0
1380*1c60b9acSAndroid Build Coastguard Worker if (i.address[0] != '+' ||
1381*1c60b9acSAndroid Build Coastguard Worker !lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST))
1382*1c60b9acSAndroid Build Coastguard Worker i.host = i.address;
1383*1c60b9acSAndroid Build Coastguard Worker else
1384*1c60b9acSAndroid Build Coastguard Worker i.host = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST);
1385*1c60b9acSAndroid Build Coastguard Worker #endif
1386*1c60b9acSAndroid Build Coastguard Worker i.origin = NULL;
1387*1c60b9acSAndroid Build Coastguard Worker if (!ws) {
1388*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI)
1389*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
1390*1c60b9acSAndroid Build Coastguard Worker || (
1391*1c60b9acSAndroid Build Coastguard Worker lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) &&
1392*1c60b9acSAndroid Build Coastguard Worker !strcmp(lws_hdr_simple_ptr(wsi,
1393*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_METHOD), "post")
1394*1c60b9acSAndroid Build Coastguard Worker )
1395*1c60b9acSAndroid Build Coastguard Worker #endif
1396*1c60b9acSAndroid Build Coastguard Worker )
1397*1c60b9acSAndroid Build Coastguard Worker i.method = "POST";
1398*1c60b9acSAndroid Build Coastguard Worker else if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PUT_URI)
1399*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
1400*1c60b9acSAndroid Build Coastguard Worker || (
1401*1c60b9acSAndroid Build Coastguard Worker lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) &&
1402*1c60b9acSAndroid Build Coastguard Worker !strcmp(lws_hdr_simple_ptr(wsi,
1403*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_METHOD), "put")
1404*1c60b9acSAndroid Build Coastguard Worker )
1405*1c60b9acSAndroid Build Coastguard Worker #endif
1406*1c60b9acSAndroid Build Coastguard Worker )
1407*1c60b9acSAndroid Build Coastguard Worker i.method = "PUT";
1408*1c60b9acSAndroid Build Coastguard Worker else if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PATCH_URI)
1409*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
1410*1c60b9acSAndroid Build Coastguard Worker || (
1411*1c60b9acSAndroid Build Coastguard Worker lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) &&
1412*1c60b9acSAndroid Build Coastguard Worker !strcmp(lws_hdr_simple_ptr(wsi,
1413*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_METHOD), "patch")
1414*1c60b9acSAndroid Build Coastguard Worker )
1415*1c60b9acSAndroid Build Coastguard Worker #endif
1416*1c60b9acSAndroid Build Coastguard Worker )
1417*1c60b9acSAndroid Build Coastguard Worker i.method = "PATCH";
1418*1c60b9acSAndroid Build Coastguard Worker else if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_DELETE_URI)
1419*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
1420*1c60b9acSAndroid Build Coastguard Worker || (
1421*1c60b9acSAndroid Build Coastguard Worker lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) &&
1422*1c60b9acSAndroid Build Coastguard Worker !strcmp(lws_hdr_simple_ptr(wsi,
1423*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_METHOD), "delete")
1424*1c60b9acSAndroid Build Coastguard Worker )
1425*1c60b9acSAndroid Build Coastguard Worker #endif
1426*1c60b9acSAndroid Build Coastguard Worker )
1427*1c60b9acSAndroid Build Coastguard Worker i.method = "DELETE";
1428*1c60b9acSAndroid Build Coastguard Worker else
1429*1c60b9acSAndroid Build Coastguard Worker i.method = "GET";
1430*1c60b9acSAndroid Build Coastguard Worker }
1431*1c60b9acSAndroid Build Coastguard Worker
1432*1c60b9acSAndroid Build Coastguard Worker if (i.host)
1433*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(host, sizeof(host), "%s:%u", i.host,
1434*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->listen_port);
1435*1c60b9acSAndroid Build Coastguard Worker else
1436*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(host, sizeof(host), "%s:%d", i.address, i.port);
1437*1c60b9acSAndroid Build Coastguard Worker
1438*1c60b9acSAndroid Build Coastguard Worker i.host = host;
1439*1c60b9acSAndroid Build Coastguard Worker
1440*1c60b9acSAndroid Build Coastguard Worker i.alpn = "http/1.1";
1441*1c60b9acSAndroid Build Coastguard Worker i.parent_wsi = wsi;
1442*1c60b9acSAndroid Build Coastguard Worker i.pwsi = &cwsi;
1443*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
1444*1c60b9acSAndroid Build Coastguard Worker i.protocol = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
1445*1c60b9acSAndroid Build Coastguard Worker if (ws)
1446*1c60b9acSAndroid Build Coastguard Worker i.local_protocol_name = "lws-ws-proxy";
1447*1c60b9acSAndroid Build Coastguard Worker #endif
1448*1c60b9acSAndroid Build Coastguard Worker
1449*1c60b9acSAndroid Build Coastguard Worker // i.uri_replace_from = hit->origin;
1450*1c60b9acSAndroid Build Coastguard Worker // i.uri_replace_to = hit->mountpoint;
1451*1c60b9acSAndroid Build Coastguard Worker
1452*1c60b9acSAndroid Build Coastguard Worker lwsl_info("proxying to %s port %d url %s, ssl %d, from %s, to %s\n",
1453*1c60b9acSAndroid Build Coastguard Worker i.address, i.port, i.path, i.ssl_connection,
1454*1c60b9acSAndroid Build Coastguard Worker i.uri_replace_from, i.uri_replace_to);
1455*1c60b9acSAndroid Build Coastguard Worker
1456*1c60b9acSAndroid Build Coastguard Worker if (!lws_client_connect_via_info(&i)) {
1457*1c60b9acSAndroid Build Coastguard Worker lwsl_err("proxy connect fail\n");
1458*1c60b9acSAndroid Build Coastguard Worker
1459*1c60b9acSAndroid Build Coastguard Worker /*
1460*1c60b9acSAndroid Build Coastguard Worker * ... we can't do the proxy action, but we can
1461*1c60b9acSAndroid Build Coastguard Worker * cleanly return him a 503 and a description
1462*1c60b9acSAndroid Build Coastguard Worker */
1463*1c60b9acSAndroid Build Coastguard Worker
1464*1c60b9acSAndroid Build Coastguard Worker lws_return_http_status(wsi,
1465*1c60b9acSAndroid Build Coastguard Worker HTTP_STATUS_SERVICE_UNAVAILABLE,
1466*1c60b9acSAndroid Build Coastguard Worker "<h1>Service Temporarily Unavailable</h1>"
1467*1c60b9acSAndroid Build Coastguard Worker "The server is temporarily unable to service "
1468*1c60b9acSAndroid Build Coastguard Worker "your request due to maintenance downtime or "
1469*1c60b9acSAndroid Build Coastguard Worker "capacity problems. Please try again later.");
1470*1c60b9acSAndroid Build Coastguard Worker
1471*1c60b9acSAndroid Build Coastguard Worker return 1;
1472*1c60b9acSAndroid Build Coastguard Worker }
1473*1c60b9acSAndroid Build Coastguard Worker
1474*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: setting proxy clientside on %s (parent %s)\n",
1475*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(cwsi), lws_wsi_tag(lws_get_parent(cwsi)));
1476*1c60b9acSAndroid Build Coastguard Worker
1477*1c60b9acSAndroid Build Coastguard Worker cwsi->http.proxy_clientside = 1;
1478*1c60b9acSAndroid Build Coastguard Worker if (ws) {
1479*1c60b9acSAndroid Build Coastguard Worker wsi->proxied_ws_parent = 1;
1480*1c60b9acSAndroid Build Coastguard Worker cwsi->h1_ws_proxied = 1;
1481*1c60b9acSAndroid Build Coastguard Worker if (i.protocol) {
1482*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: (requesting '%s')\n",
1483*1c60b9acSAndroid Build Coastguard Worker __func__, i.protocol);
1484*1c60b9acSAndroid Build Coastguard Worker }
1485*1c60b9acSAndroid Build Coastguard Worker }
1486*1c60b9acSAndroid Build Coastguard Worker
1487*1c60b9acSAndroid Build Coastguard Worker return 0;
1488*1c60b9acSAndroid Build Coastguard Worker }
1489*1c60b9acSAndroid Build Coastguard Worker #endif
1490*1c60b9acSAndroid Build Coastguard Worker
1491*1c60b9acSAndroid Build Coastguard Worker
1492*1c60b9acSAndroid Build Coastguard Worker static const char * const oprot[] = {
1493*1c60b9acSAndroid Build Coastguard Worker "http://", "https://"
1494*1c60b9acSAndroid Build Coastguard Worker };
1495*1c60b9acSAndroid Build Coastguard Worker
1496*1c60b9acSAndroid Build Coastguard Worker
1497*1c60b9acSAndroid Build Coastguard Worker static int
lws_http_redirect_hit(struct lws_context_per_thread * pt,struct lws * wsi,const struct lws_http_mount * hit,char * uri_ptr,int uri_len,int * h)1498*1c60b9acSAndroid Build Coastguard Worker lws_http_redirect_hit(struct lws_context_per_thread *pt, struct lws *wsi,
1499*1c60b9acSAndroid Build Coastguard Worker const struct lws_http_mount *hit, char *uri_ptr,
1500*1c60b9acSAndroid Build Coastguard Worker int uri_len, int *h)
1501*1c60b9acSAndroid Build Coastguard Worker {
1502*1c60b9acSAndroid Build Coastguard Worker char *s;
1503*1c60b9acSAndroid Build Coastguard Worker int n;
1504*1c60b9acSAndroid Build Coastguard Worker
1505*1c60b9acSAndroid Build Coastguard Worker *h = 0;
1506*1c60b9acSAndroid Build Coastguard Worker s = uri_ptr + hit->mountpoint_len;
1507*1c60b9acSAndroid Build Coastguard Worker
1508*1c60b9acSAndroid Build Coastguard Worker /*
1509*1c60b9acSAndroid Build Coastguard Worker * if we have a mountpoint like https://xxx.com/yyy
1510*1c60b9acSAndroid Build Coastguard Worker * there is an implied / at the end for our purposes since
1511*1c60b9acSAndroid Build Coastguard Worker * we can only mount on a "directory".
1512*1c60b9acSAndroid Build Coastguard Worker *
1513*1c60b9acSAndroid Build Coastguard Worker * But if we just go with that, the browser cannot understand
1514*1c60b9acSAndroid Build Coastguard Worker * that he is actually looking down one "directory level", so
1515*1c60b9acSAndroid Build Coastguard Worker * even though we give him /yyy/abc.html he acts like the
1516*1c60b9acSAndroid Build Coastguard Worker * current directory level is /. So relative urls like "x.png"
1517*1c60b9acSAndroid Build Coastguard Worker * wrongly look outside the mountpoint.
1518*1c60b9acSAndroid Build Coastguard Worker *
1519*1c60b9acSAndroid Build Coastguard Worker * Therefore if we didn't come in on a url with an explicit
1520*1c60b9acSAndroid Build Coastguard Worker * / at the end, we must redirect to add it so the browser
1521*1c60b9acSAndroid Build Coastguard Worker * understands he is one "directory level" down.
1522*1c60b9acSAndroid Build Coastguard Worker */
1523*1c60b9acSAndroid Build Coastguard Worker if ((hit->mountpoint_len > 1 ||
1524*1c60b9acSAndroid Build Coastguard Worker (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
1525*1c60b9acSAndroid Build Coastguard Worker hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
1526*1c60b9acSAndroid Build Coastguard Worker (*s != '/' ||
1527*1c60b9acSAndroid Build Coastguard Worker (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
1528*1c60b9acSAndroid Build Coastguard Worker hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
1529*1c60b9acSAndroid Build Coastguard Worker (hit->origin_protocol != LWSMPRO_CGI &&
1530*1c60b9acSAndroid Build Coastguard Worker hit->origin_protocol != LWSMPRO_CALLBACK)) {
1531*1c60b9acSAndroid Build Coastguard Worker unsigned char *start = pt->serv_buf + LWS_PRE, *p = start,
1532*1c60b9acSAndroid Build Coastguard Worker *end = p + wsi->a.context->pt_serv_buf_size -
1533*1c60b9acSAndroid Build Coastguard Worker LWS_PRE - 512;
1534*1c60b9acSAndroid Build Coastguard Worker
1535*1c60b9acSAndroid Build Coastguard Worker *h = 1;
1536*1c60b9acSAndroid Build Coastguard Worker
1537*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Doing 301 '%s' org %s\n", s, hit->origin);
1538*1c60b9acSAndroid Build Coastguard Worker
1539*1c60b9acSAndroid Build Coastguard Worker /* > at start indicates deal with by redirect */
1540*1c60b9acSAndroid Build Coastguard Worker if (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
1541*1c60b9acSAndroid Build Coastguard Worker hit->origin_protocol == LWSMPRO_REDIR_HTTPS)
1542*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf((char *)end, 256, "%s%s",
1543*1c60b9acSAndroid Build Coastguard Worker oprot[hit->origin_protocol & 1],
1544*1c60b9acSAndroid Build Coastguard Worker hit->origin);
1545*1c60b9acSAndroid Build Coastguard Worker else {
1546*1c60b9acSAndroid Build Coastguard Worker if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
1547*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
1548*1c60b9acSAndroid Build Coastguard Worker if (!lws_hdr_total_length(wsi,
1549*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_AUTHORITY))
1550*1c60b9acSAndroid Build Coastguard Worker #endif
1551*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1552*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
1553*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf((char *)end, 256,
1554*1c60b9acSAndroid Build Coastguard Worker "%s%s%s/", oprot[!!lws_is_ssl(wsi)],
1555*1c60b9acSAndroid Build Coastguard Worker lws_hdr_simple_ptr(wsi,
1556*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_COLON_AUTHORITY),
1557*1c60b9acSAndroid Build Coastguard Worker uri_ptr);
1558*1c60b9acSAndroid Build Coastguard Worker #else
1559*1c60b9acSAndroid Build Coastguard Worker ;
1560*1c60b9acSAndroid Build Coastguard Worker #endif
1561*1c60b9acSAndroid Build Coastguard Worker } else
1562*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf((char *)end, 256,
1563*1c60b9acSAndroid Build Coastguard Worker "%s%s%s/", oprot[!!lws_is_ssl(wsi)],
1564*1c60b9acSAndroid Build Coastguard Worker lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
1565*1c60b9acSAndroid Build Coastguard Worker uri_ptr);
1566*1c60b9acSAndroid Build Coastguard Worker }
1567*1c60b9acSAndroid Build Coastguard Worker
1568*1c60b9acSAndroid Build Coastguard Worker lws_clean_url((char *)end);
1569*1c60b9acSAndroid Build Coastguard Worker n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
1570*1c60b9acSAndroid Build Coastguard Worker end, n, &p, end);
1571*1c60b9acSAndroid Build Coastguard Worker if ((int)n < 0)
1572*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1573*1c60b9acSAndroid Build Coastguard Worker
1574*1c60b9acSAndroid Build Coastguard Worker return lws_http_transaction_completed(wsi);
1575*1c60b9acSAndroid Build Coastguard Worker }
1576*1c60b9acSAndroid Build Coastguard Worker
1577*1c60b9acSAndroid Build Coastguard Worker return 0;
1578*1c60b9acSAndroid Build Coastguard Worker
1579*1c60b9acSAndroid Build Coastguard Worker bail_nuke_ah:
1580*1c60b9acSAndroid Build Coastguard Worker lws_header_table_detach(wsi, 1);
1581*1c60b9acSAndroid Build Coastguard Worker
1582*1c60b9acSAndroid Build Coastguard Worker return 1;
1583*1c60b9acSAndroid Build Coastguard Worker }
1584*1c60b9acSAndroid Build Coastguard Worker
1585*1c60b9acSAndroid Build Coastguard Worker int
lws_http_action(struct lws * wsi)1586*1c60b9acSAndroid Build Coastguard Worker lws_http_action(struct lws *wsi)
1587*1c60b9acSAndroid Build Coastguard Worker {
1588*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
1589*1c60b9acSAndroid Build Coastguard Worker int uri_len = 0, meth, m, http_version_len, ha;
1590*1c60b9acSAndroid Build Coastguard Worker const struct lws_http_mount *hit = NULL;
1591*1c60b9acSAndroid Build Coastguard Worker enum http_version request_version;
1592*1c60b9acSAndroid Build Coastguard Worker struct lws_process_html_args args;
1593*1c60b9acSAndroid Build Coastguard Worker enum http_conn_type conn_type;
1594*1c60b9acSAndroid Build Coastguard Worker char content_length_str[32];
1595*1c60b9acSAndroid Build Coastguard Worker char http_version_str[12];
1596*1c60b9acSAndroid Build Coastguard Worker char http_conn_str[25];
1597*1c60b9acSAndroid Build Coastguard Worker char *uri_ptr = NULL;
1598*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
1599*1c60b9acSAndroid Build Coastguard Worker char *s;
1600*1c60b9acSAndroid Build Coastguard Worker #endif
1601*1c60b9acSAndroid Build Coastguard Worker unsigned int n;
1602*1c60b9acSAndroid Build Coastguard Worker
1603*1c60b9acSAndroid Build Coastguard Worker meth = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
1604*1c60b9acSAndroid Build Coastguard Worker if (meth < 0 || meth >= (int)LWS_ARRAY_SIZE(method_names))
1605*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1606*1c60b9acSAndroid Build Coastguard Worker
1607*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_wsi_add(wsi, "vh", wsi->a.vhost->name);
1608*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_wsi_add(wsi, "meth", method_names[meth]);
1609*1c60b9acSAndroid Build Coastguard Worker
1610*1c60b9acSAndroid Build Coastguard Worker /* we insist on absolute paths */
1611*1c60b9acSAndroid Build Coastguard Worker
1612*1c60b9acSAndroid Build Coastguard Worker if (!uri_ptr || uri_ptr[0] != '/') {
1613*1c60b9acSAndroid Build Coastguard Worker lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
1614*1c60b9acSAndroid Build Coastguard Worker
1615*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1616*1c60b9acSAndroid Build Coastguard Worker }
1617*1c60b9acSAndroid Build Coastguard Worker
1618*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Method: '%s' (%d), request for '%s'\n", method_names[meth],
1619*1c60b9acSAndroid Build Coastguard Worker meth, uri_ptr);
1620*1c60b9acSAndroid Build Coastguard Worker
1621*1c60b9acSAndroid Build Coastguard Worker if (wsi->role_ops &&
1622*1c60b9acSAndroid Build Coastguard Worker lws_rops_fidx(wsi->role_ops, LWS_ROPS_check_upgrades))
1623*1c60b9acSAndroid Build Coastguard Worker switch (lws_rops_func_fidx(wsi->role_ops,
1624*1c60b9acSAndroid Build Coastguard Worker LWS_ROPS_check_upgrades).
1625*1c60b9acSAndroid Build Coastguard Worker check_upgrades(wsi)) {
1626*1c60b9acSAndroid Build Coastguard Worker case LWS_UPG_RET_DONE:
1627*1c60b9acSAndroid Build Coastguard Worker return 0;
1628*1c60b9acSAndroid Build Coastguard Worker case LWS_UPG_RET_CONTINUE:
1629*1c60b9acSAndroid Build Coastguard Worker break;
1630*1c60b9acSAndroid Build Coastguard Worker case LWS_UPG_RET_BAIL:
1631*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1632*1c60b9acSAndroid Build Coastguard Worker }
1633*1c60b9acSAndroid Build Coastguard Worker
1634*1c60b9acSAndroid Build Coastguard Worker if (lws_ensure_user_space(wsi))
1635*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1636*1c60b9acSAndroid Build Coastguard Worker
1637*1c60b9acSAndroid Build Coastguard Worker /* HTTP header had a content length? */
1638*1c60b9acSAndroid Build Coastguard Worker
1639*1c60b9acSAndroid Build Coastguard Worker wsi->http.rx_content_length = 0;
1640*1c60b9acSAndroid Build Coastguard Worker wsi->http.content_length_explicitly_zero = 0;
1641*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)
1642*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
1643*1c60b9acSAndroid Build Coastguard Worker ||
1644*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI) ||
1645*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI)
1646*1c60b9acSAndroid Build Coastguard Worker #endif
1647*1c60b9acSAndroid Build Coastguard Worker )
1648*1c60b9acSAndroid Build Coastguard Worker wsi->http.rx_content_length = 100 * 1024 * 1024;
1649*1c60b9acSAndroid Build Coastguard Worker
1650*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH) &&
1651*1c60b9acSAndroid Build Coastguard Worker lws_hdr_copy(wsi, content_length_str,
1652*1c60b9acSAndroid Build Coastguard Worker sizeof(content_length_str) - 1,
1653*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_LENGTH) > 0) {
1654*1c60b9acSAndroid Build Coastguard Worker wsi->http.rx_content_remain = wsi->http.rx_content_length =
1655*1c60b9acSAndroid Build Coastguard Worker (lws_filepos_t)atoll(content_length_str);
1656*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.rx_content_length) {
1657*1c60b9acSAndroid Build Coastguard Worker wsi->http.content_length_explicitly_zero = 1;
1658*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: explicit 0 content-length\n", __func__);
1659*1c60b9acSAndroid Build Coastguard Worker }
1660*1c60b9acSAndroid Build Coastguard Worker }
1661*1c60b9acSAndroid Build Coastguard Worker
1662*1c60b9acSAndroid Build Coastguard Worker if (wsi->mux_substream) {
1663*1c60b9acSAndroid Build Coastguard Worker wsi->http.request_version = HTTP_VERSION_2;
1664*1c60b9acSAndroid Build Coastguard Worker } else {
1665*1c60b9acSAndroid Build Coastguard Worker /* http_version? Default to 1.0, override with token: */
1666*1c60b9acSAndroid Build Coastguard Worker request_version = HTTP_VERSION_1_0;
1667*1c60b9acSAndroid Build Coastguard Worker
1668*1c60b9acSAndroid Build Coastguard Worker /* Works for single digit HTTP versions. : */
1669*1c60b9acSAndroid Build Coastguard Worker http_version_len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP);
1670*1c60b9acSAndroid Build Coastguard Worker if (http_version_len > 7 &&
1671*1c60b9acSAndroid Build Coastguard Worker lws_hdr_copy(wsi, http_version_str,
1672*1c60b9acSAndroid Build Coastguard Worker sizeof(http_version_str) - 1,
1673*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP) > 0 &&
1674*1c60b9acSAndroid Build Coastguard Worker http_version_str[5] == '1' && http_version_str[7] == '1')
1675*1c60b9acSAndroid Build Coastguard Worker request_version = HTTP_VERSION_1_1;
1676*1c60b9acSAndroid Build Coastguard Worker
1677*1c60b9acSAndroid Build Coastguard Worker wsi->http.request_version = request_version;
1678*1c60b9acSAndroid Build Coastguard Worker
1679*1c60b9acSAndroid Build Coastguard Worker /* HTTP/1.1 defaults to "keep-alive", 1.0 to "close" */
1680*1c60b9acSAndroid Build Coastguard Worker if (request_version == HTTP_VERSION_1_1)
1681*1c60b9acSAndroid Build Coastguard Worker conn_type = HTTP_CONNECTION_KEEP_ALIVE;
1682*1c60b9acSAndroid Build Coastguard Worker else
1683*1c60b9acSAndroid Build Coastguard Worker conn_type = HTTP_CONNECTION_CLOSE;
1684*1c60b9acSAndroid Build Coastguard Worker
1685*1c60b9acSAndroid Build Coastguard Worker /* Override default if http "Connection:" header: */
1686*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION) &&
1687*1c60b9acSAndroid Build Coastguard Worker lws_hdr_copy(wsi, http_conn_str, sizeof(http_conn_str) - 1,
1688*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_CONNECTION) > 0) {
1689*1c60b9acSAndroid Build Coastguard Worker http_conn_str[sizeof(http_conn_str) - 1] = '\0';
1690*1c60b9acSAndroid Build Coastguard Worker if (!strcasecmp(http_conn_str, "keep-alive"))
1691*1c60b9acSAndroid Build Coastguard Worker conn_type = HTTP_CONNECTION_KEEP_ALIVE;
1692*1c60b9acSAndroid Build Coastguard Worker else
1693*1c60b9acSAndroid Build Coastguard Worker if (!strcasecmp(http_conn_str, "close"))
1694*1c60b9acSAndroid Build Coastguard Worker conn_type = HTTP_CONNECTION_CLOSE;
1695*1c60b9acSAndroid Build Coastguard Worker }
1696*1c60b9acSAndroid Build Coastguard Worker wsi->http.conn_type = conn_type;
1697*1c60b9acSAndroid Build Coastguard Worker }
1698*1c60b9acSAndroid Build Coastguard Worker
1699*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)wsi->a.protocol->callback(wsi, LWS_CALLBACK_FILTER_HTTP_CONNECTION,
1700*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, uri_ptr, (unsigned int)uri_len);
1701*1c60b9acSAndroid Build Coastguard Worker if (n) {
1702*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_CALLBACK_HTTP closing\n");
1703*1c60b9acSAndroid Build Coastguard Worker
1704*1c60b9acSAndroid Build Coastguard Worker return 1;
1705*1c60b9acSAndroid Build Coastguard Worker }
1706*1c60b9acSAndroid Build Coastguard Worker /*
1707*1c60b9acSAndroid Build Coastguard Worker * if there is content supposed to be coming,
1708*1c60b9acSAndroid Build Coastguard Worker * put a timeout on it having arrived
1709*1c60b9acSAndroid Build Coastguard Worker */
1710*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_stream_immortal)
1711*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
1712*1c60b9acSAndroid Build Coastguard Worker (int)wsi->a.context->timeout_secs);
1713*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS)
1714*1c60b9acSAndroid Build Coastguard Worker if (wsi->tls.redirect_to_https) {
1715*1c60b9acSAndroid Build Coastguard Worker /*
1716*1c60b9acSAndroid Build Coastguard Worker * We accepted http:// only so we could redirect to
1717*1c60b9acSAndroid Build Coastguard Worker * https://, so issue the redirect. Create the redirection
1718*1c60b9acSAndroid Build Coastguard Worker * URI from the host: header, and regenerate the path part from
1719*1c60b9acSAndroid Build Coastguard Worker * the parsed pieces
1720*1c60b9acSAndroid Build Coastguard Worker */
1721*1c60b9acSAndroid Build Coastguard Worker unsigned char *start = pt->serv_buf + LWS_PRE, *p = start,
1722*1c60b9acSAndroid Build Coastguard Worker *end = p + wsi->a.context->pt_serv_buf_size -
1723*1c60b9acSAndroid Build Coastguard Worker LWS_PRE;
1724*1c60b9acSAndroid Build Coastguard Worker
1725*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)lws_hdr_total_length(wsi, WSI_TOKEN_HOST);
1726*1c60b9acSAndroid Build Coastguard Worker if (!n || n > 128)
1727*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1728*1c60b9acSAndroid Build Coastguard Worker
1729*1c60b9acSAndroid Build Coastguard Worker if (!lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST))
1730*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1731*1c60b9acSAndroid Build Coastguard Worker
1732*1c60b9acSAndroid Build Coastguard Worker p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "https://");
1733*1c60b9acSAndroid Build Coastguard Worker memcpy(p, lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST), n);
1734*1c60b9acSAndroid Build Coastguard Worker p += n;
1735*1c60b9acSAndroid Build Coastguard Worker *p++ = '/';
1736*1c60b9acSAndroid Build Coastguard Worker if (uri_len >= lws_ptr_diff(end, p))
1737*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1738*1c60b9acSAndroid Build Coastguard Worker
1739*1c60b9acSAndroid Build Coastguard Worker if (uri_ptr[0])
1740*1c60b9acSAndroid Build Coastguard Worker p--;
1741*1c60b9acSAndroid Build Coastguard Worker memcpy(p, uri_ptr, (unsigned int)uri_len);
1742*1c60b9acSAndroid Build Coastguard Worker p += uri_len;
1743*1c60b9acSAndroid Build Coastguard Worker
1744*1c60b9acSAndroid Build Coastguard Worker n = 0;
1745*1c60b9acSAndroid Build Coastguard Worker while (lws_hdr_copy_fragment(wsi, (char *)p + 1,
1746*1c60b9acSAndroid Build Coastguard Worker lws_ptr_diff(end, p) - 2,
1747*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_URI_ARGS, (int)n) > 0) {
1748*1c60b9acSAndroid Build Coastguard Worker *p = n ? '&' : '?';
1749*1c60b9acSAndroid Build Coastguard Worker p += strlen((char *)p);
1750*1c60b9acSAndroid Build Coastguard Worker if (p >= end - 2)
1751*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1752*1c60b9acSAndroid Build Coastguard Worker n++;
1753*1c60b9acSAndroid Build Coastguard Worker }
1754*1c60b9acSAndroid Build Coastguard Worker
1755*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)lws_ptr_diff(p, start);
1756*1c60b9acSAndroid Build Coastguard Worker
1757*1c60b9acSAndroid Build Coastguard Worker p += LWS_PRE;
1758*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
1759*1c60b9acSAndroid Build Coastguard Worker start, (int)n, &p, end);
1760*1c60b9acSAndroid Build Coastguard Worker if ((int)n < 0)
1761*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1762*1c60b9acSAndroid Build Coastguard Worker
1763*1c60b9acSAndroid Build Coastguard Worker return lws_http_transaction_completed(wsi);
1764*1c60b9acSAndroid Build Coastguard Worker }
1765*1c60b9acSAndroid Build Coastguard Worker #endif
1766*1c60b9acSAndroid Build Coastguard Worker
1767*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_ACCESS_LOG
1768*1c60b9acSAndroid Build Coastguard Worker lws_prepare_access_log_info(wsi, uri_ptr, uri_len, meth);
1769*1c60b9acSAndroid Build Coastguard Worker #endif
1770*1c60b9acSAndroid Build Coastguard Worker
1771*1c60b9acSAndroid Build Coastguard Worker /* can we serve it from the mount list? */
1772*1c60b9acSAndroid Build Coastguard Worker
1773*1c60b9acSAndroid Build Coastguard Worker hit = lws_find_mount(wsi, uri_ptr, uri_len);
1774*1c60b9acSAndroid Build Coastguard Worker if (!hit) {
1775*1c60b9acSAndroid Build Coastguard Worker /* deferred cleanup and reset to protocols[0] */
1776*1c60b9acSAndroid Build Coastguard Worker
1777*1c60b9acSAndroid Build Coastguard Worker lwsl_info("no hit\n");
1778*1c60b9acSAndroid Build Coastguard Worker
1779*1c60b9acSAndroid Build Coastguard Worker if (lws_bind_protocol(wsi, &wsi->a.vhost->protocols[0],
1780*1c60b9acSAndroid Build Coastguard Worker "no mount hit"))
1781*1c60b9acSAndroid Build Coastguard Worker return 1;
1782*1c60b9acSAndroid Build Coastguard Worker
1783*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_DOING_TRANSACTION);
1784*1c60b9acSAndroid Build Coastguard Worker
1785*1c60b9acSAndroid Build Coastguard Worker m = wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP,
1786*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, uri_ptr, (unsigned int)uri_len);
1787*1c60b9acSAndroid Build Coastguard Worker
1788*1c60b9acSAndroid Build Coastguard Worker goto after;
1789*1c60b9acSAndroid Build Coastguard Worker }
1790*1c60b9acSAndroid Build Coastguard Worker
1791*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
1792*1c60b9acSAndroid Build Coastguard Worker s = uri_ptr + hit->mountpoint_len;
1793*1c60b9acSAndroid Build Coastguard Worker #endif
1794*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)lws_http_redirect_hit(pt, wsi, hit, uri_ptr, uri_len, &ha);
1795*1c60b9acSAndroid Build Coastguard Worker if (ha)
1796*1c60b9acSAndroid Build Coastguard Worker return (int)n;
1797*1c60b9acSAndroid Build Coastguard Worker
1798*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_BASIC_AUTH)
1799*1c60b9acSAndroid Build Coastguard Worker
1800*1c60b9acSAndroid Build Coastguard Worker /* basic auth? */
1801*1c60b9acSAndroid Build Coastguard Worker
1802*1c60b9acSAndroid Build Coastguard Worker switch (lws_check_basic_auth(wsi, hit->basic_auth_login_file,
1803*1c60b9acSAndroid Build Coastguard Worker hit->auth_mask & AUTH_MODE_MASK)) {
1804*1c60b9acSAndroid Build Coastguard Worker case LCBA_CONTINUE:
1805*1c60b9acSAndroid Build Coastguard Worker break;
1806*1c60b9acSAndroid Build Coastguard Worker case LCBA_FAILED_AUTH:
1807*1c60b9acSAndroid Build Coastguard Worker return lws_unauthorised_basic_auth(wsi);
1808*1c60b9acSAndroid Build Coastguard Worker case LCBA_END_TRANSACTION:
1809*1c60b9acSAndroid Build Coastguard Worker lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
1810*1c60b9acSAndroid Build Coastguard Worker return lws_http_transaction_completed(wsi);
1811*1c60b9acSAndroid Build Coastguard Worker }
1812*1c60b9acSAndroid Build Coastguard Worker #endif
1813*1c60b9acSAndroid Build Coastguard Worker
1814*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_PROXY)
1815*1c60b9acSAndroid Build Coastguard Worker /*
1816*1c60b9acSAndroid Build Coastguard Worker * The mount is a reverse proxy?
1817*1c60b9acSAndroid Build Coastguard Worker */
1818*1c60b9acSAndroid Build Coastguard Worker
1819*1c60b9acSAndroid Build Coastguard Worker // if (hit)
1820*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("%s: origin_protocol: %d\n", __func__, hit->origin_protocol);
1821*1c60b9acSAndroid Build Coastguard Worker //else
1822*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("%s: no hit\n", __func__);
1823*1c60b9acSAndroid Build Coastguard Worker
1824*1c60b9acSAndroid Build Coastguard Worker if (hit->origin_protocol == LWSMPRO_HTTPS ||
1825*1c60b9acSAndroid Build Coastguard Worker hit->origin_protocol == LWSMPRO_HTTP) {
1826*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)lws_http_proxy_start(wsi, hit, uri_ptr, 0);
1827*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("proxy start says %d\n", n);
1828*1c60b9acSAndroid Build Coastguard Worker if (n)
1829*1c60b9acSAndroid Build Coastguard Worker return (int)n;
1830*1c60b9acSAndroid Build Coastguard Worker
1831*1c60b9acSAndroid Build Coastguard Worker goto deal_body;
1832*1c60b9acSAndroid Build Coastguard Worker }
1833*1c60b9acSAndroid Build Coastguard Worker #endif
1834*1c60b9acSAndroid Build Coastguard Worker
1835*1c60b9acSAndroid Build Coastguard Worker /*
1836*1c60b9acSAndroid Build Coastguard Worker * A particular protocol callback is mounted here?
1837*1c60b9acSAndroid Build Coastguard Worker *
1838*1c60b9acSAndroid Build Coastguard Worker * For the duration of this http transaction, bind us to the
1839*1c60b9acSAndroid Build Coastguard Worker * associated protocol
1840*1c60b9acSAndroid Build Coastguard Worker */
1841*1c60b9acSAndroid Build Coastguard Worker if (hit->origin_protocol == LWSMPRO_CALLBACK || hit->protocol) {
1842*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocols *pp;
1843*1c60b9acSAndroid Build Coastguard Worker const char *name = hit->origin;
1844*1c60b9acSAndroid Build Coastguard Worker if (hit->protocol)
1845*1c60b9acSAndroid Build Coastguard Worker name = hit->protocol;
1846*1c60b9acSAndroid Build Coastguard Worker
1847*1c60b9acSAndroid Build Coastguard Worker pp = lws_vhost_name_to_protocol(wsi->a.vhost, name);
1848*1c60b9acSAndroid Build Coastguard Worker if (!pp) {
1849*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Unable to find plugin '%s'\n",
1850*1c60b9acSAndroid Build Coastguard Worker hit->origin);
1851*1c60b9acSAndroid Build Coastguard Worker return 1;
1852*1c60b9acSAndroid Build Coastguard Worker }
1853*1c60b9acSAndroid Build Coastguard Worker
1854*1c60b9acSAndroid Build Coastguard Worker if (lws_bind_protocol(wsi, pp, "http action CALLBACK bind"))
1855*1c60b9acSAndroid Build Coastguard Worker return 1;
1856*1c60b9acSAndroid Build Coastguard Worker
1857*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s, checking access rights for mask 0x%x\n",
1858*1c60b9acSAndroid Build Coastguard Worker __func__, hit->origin, hit->auth_mask);
1859*1c60b9acSAndroid Build Coastguard Worker
1860*1c60b9acSAndroid Build Coastguard Worker args.p = uri_ptr;
1861*1c60b9acSAndroid Build Coastguard Worker args.len = uri_len;
1862*1c60b9acSAndroid Build Coastguard Worker args.max_len = hit->auth_mask & ~AUTH_MODE_MASK;
1863*1c60b9acSAndroid Build Coastguard Worker args.final = 0; /* used to signal callback dealt with it */
1864*1c60b9acSAndroid Build Coastguard Worker args.chunked = 0;
1865*1c60b9acSAndroid Build Coastguard Worker
1866*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)wsi->a.protocol->callback(wsi,
1867*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_CHECK_ACCESS_RIGHTS,
1868*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, &args, 0);
1869*1c60b9acSAndroid Build Coastguard Worker if (n) {
1870*1c60b9acSAndroid Build Coastguard Worker lws_return_http_status(wsi, HTTP_STATUS_UNAUTHORIZED,
1871*1c60b9acSAndroid Build Coastguard Worker NULL);
1872*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
1873*1c60b9acSAndroid Build Coastguard Worker }
1874*1c60b9acSAndroid Build Coastguard Worker if (args.final) /* callback completely handled it well */
1875*1c60b9acSAndroid Build Coastguard Worker return 0;
1876*1c60b9acSAndroid Build Coastguard Worker
1877*1c60b9acSAndroid Build Coastguard Worker if (hit->cgienv && wsi->a.protocol->callback(wsi,
1878*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_HTTP_PMO,
1879*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, (void *)hit->cgienv, 0))
1880*1c60b9acSAndroid Build Coastguard Worker return 1;
1881*1c60b9acSAndroid Build Coastguard Worker
1882*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
1883*1c60b9acSAndroid Build Coastguard Worker m = wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP,
1884*1c60b9acSAndroid Build Coastguard Worker wsi->user_space,
1885*1c60b9acSAndroid Build Coastguard Worker uri_ptr + hit->mountpoint_len,
1886*1c60b9acSAndroid Build Coastguard Worker (unsigned int)uri_len - hit->mountpoint_len);
1887*1c60b9acSAndroid Build Coastguard Worker goto after;
1888*1c60b9acSAndroid Build Coastguard Worker }
1889*1c60b9acSAndroid Build Coastguard Worker }
1890*1c60b9acSAndroid Build Coastguard Worker
1891*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_CGI
1892*1c60b9acSAndroid Build Coastguard Worker /* did we hit something with a cgi:// origin? */
1893*1c60b9acSAndroid Build Coastguard Worker if (hit->origin_protocol == LWSMPRO_CGI) {
1894*1c60b9acSAndroid Build Coastguard Worker const char *cmd[] = {
1895*1c60b9acSAndroid Build Coastguard Worker NULL, /* replace with cgi path */
1896*1c60b9acSAndroid Build Coastguard Worker NULL
1897*1c60b9acSAndroid Build Coastguard Worker };
1898*1c60b9acSAndroid Build Coastguard Worker
1899*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: cgi\n", __func__);
1900*1c60b9acSAndroid Build Coastguard Worker cmd[0] = hit->origin;
1901*1c60b9acSAndroid Build Coastguard Worker
1902*1c60b9acSAndroid Build Coastguard Worker n = 5;
1903*1c60b9acSAndroid Build Coastguard Worker if (hit->cgi_timeout)
1904*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)hit->cgi_timeout;
1905*1c60b9acSAndroid Build Coastguard Worker
1906*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)lws_cgi(wsi, cmd, hit->mountpoint_len, (int)n,
1907*1c60b9acSAndroid Build Coastguard Worker hit->cgienv);
1908*1c60b9acSAndroid Build Coastguard Worker if (n) {
1909*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: cgi failed\n", __func__);
1910*1c60b9acSAndroid Build Coastguard Worker return -1;
1911*1c60b9acSAndroid Build Coastguard Worker }
1912*1c60b9acSAndroid Build Coastguard Worker
1913*1c60b9acSAndroid Build Coastguard Worker goto deal_body;
1914*1c60b9acSAndroid Build Coastguard Worker }
1915*1c60b9acSAndroid Build Coastguard Worker #endif
1916*1c60b9acSAndroid Build Coastguard Worker
1917*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
1918*1c60b9acSAndroid Build Coastguard Worker n = (unsigned int)(uri_len - lws_ptr_diff(s, uri_ptr));
1919*1c60b9acSAndroid Build Coastguard Worker if (s[0] == '\0' || (n == 1 && s[n - 1] == '/'))
1920*1c60b9acSAndroid Build Coastguard Worker s = (char *)hit->def;
1921*1c60b9acSAndroid Build Coastguard Worker if (!s)
1922*1c60b9acSAndroid Build Coastguard Worker s = "index.html";
1923*1c60b9acSAndroid Build Coastguard Worker #endif
1924*1c60b9acSAndroid Build Coastguard Worker
1925*1c60b9acSAndroid Build Coastguard Worker wsi->cache_secs = (unsigned int)hit->cache_max_age;
1926*1c60b9acSAndroid Build Coastguard Worker wsi->cache_reuse = hit->cache_reusable;
1927*1c60b9acSAndroid Build Coastguard Worker wsi->cache_revalidate = hit->cache_revalidate;
1928*1c60b9acSAndroid Build Coastguard Worker wsi->cache_intermediaries = hit->cache_intermediaries;
1929*1c60b9acSAndroid Build Coastguard Worker
1930*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
1931*1c60b9acSAndroid Build Coastguard Worker m = 1;
1932*1c60b9acSAndroid Build Coastguard Worker if (hit->origin_protocol == LWSMPRO_FILE)
1933*1c60b9acSAndroid Build Coastguard Worker m = lws_http_serve(wsi, s, hit->origin, hit);
1934*1c60b9acSAndroid Build Coastguard Worker
1935*1c60b9acSAndroid Build Coastguard Worker if (m > 0)
1936*1c60b9acSAndroid Build Coastguard Worker #endif
1937*1c60b9acSAndroid Build Coastguard Worker {
1938*1c60b9acSAndroid Build Coastguard Worker /*
1939*1c60b9acSAndroid Build Coastguard Worker * lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
1940*1c60b9acSAndroid Build Coastguard Worker */
1941*1c60b9acSAndroid Build Coastguard Worker if (hit->protocol) {
1942*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocols *pp =
1943*1c60b9acSAndroid Build Coastguard Worker lws_vhost_name_to_protocol(
1944*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost, hit->protocol);
1945*1c60b9acSAndroid Build Coastguard Worker
1946*1c60b9acSAndroid Build Coastguard Worker /* coverity */
1947*1c60b9acSAndroid Build Coastguard Worker if (!pp)
1948*1c60b9acSAndroid Build Coastguard Worker return 1;
1949*1c60b9acSAndroid Build Coastguard Worker
1950*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_DOING_TRANSACTION);
1951*1c60b9acSAndroid Build Coastguard Worker
1952*1c60b9acSAndroid Build Coastguard Worker if (lws_bind_protocol(wsi, pp, "http_action HTTP"))
1953*1c60b9acSAndroid Build Coastguard Worker return 1;
1954*1c60b9acSAndroid Build Coastguard Worker
1955*1c60b9acSAndroid Build Coastguard Worker m = pp->callback(wsi, LWS_CALLBACK_HTTP,
1956*1c60b9acSAndroid Build Coastguard Worker wsi->user_space,
1957*1c60b9acSAndroid Build Coastguard Worker uri_ptr + hit->mountpoint_len,
1958*1c60b9acSAndroid Build Coastguard Worker (size_t)(uri_len - hit->mountpoint_len));
1959*1c60b9acSAndroid Build Coastguard Worker } else
1960*1c60b9acSAndroid Build Coastguard Worker m = wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP,
1961*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, uri_ptr, (size_t)uri_len);
1962*1c60b9acSAndroid Build Coastguard Worker }
1963*1c60b9acSAndroid Build Coastguard Worker
1964*1c60b9acSAndroid Build Coastguard Worker after:
1965*1c60b9acSAndroid Build Coastguard Worker if (m) {
1966*1c60b9acSAndroid Build Coastguard Worker lwsl_info("LWS_CALLBACK_HTTP closing\n");
1967*1c60b9acSAndroid Build Coastguard Worker
1968*1c60b9acSAndroid Build Coastguard Worker return 1;
1969*1c60b9acSAndroid Build Coastguard Worker }
1970*1c60b9acSAndroid Build Coastguard Worker
1971*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CGI) || defined(LWS_WITH_HTTP_PROXY)
1972*1c60b9acSAndroid Build Coastguard Worker deal_body:
1973*1c60b9acSAndroid Build Coastguard Worker #endif
1974*1c60b9acSAndroid Build Coastguard Worker /*
1975*1c60b9acSAndroid Build Coastguard Worker * If we're not issuing a file, check for content_length or
1976*1c60b9acSAndroid Build Coastguard Worker * HTTP keep-alive. No keep-alive header allocation for
1977*1c60b9acSAndroid Build Coastguard Worker * ISSUING_FILE, as this uses HTTP/1.0.
1978*1c60b9acSAndroid Build Coastguard Worker *
1979*1c60b9acSAndroid Build Coastguard Worker * In any case, return 0 and let lws_read decide how to
1980*1c60b9acSAndroid Build Coastguard Worker * proceed based on state
1981*1c60b9acSAndroid Build Coastguard Worker */
1982*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) == LRS_ISSUING_FILE)
1983*1c60b9acSAndroid Build Coastguard Worker return 0;
1984*1c60b9acSAndroid Build Coastguard Worker
1985*1c60b9acSAndroid Build Coastguard Worker /* Prepare to read body if we have a content length: */
1986*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("wsi->http.rx_content_length %lld %d %d\n",
1987*1c60b9acSAndroid Build Coastguard Worker (long long)wsi->http.rx_content_length,
1988*1c60b9acSAndroid Build Coastguard Worker wsi->upgraded_to_http2, wsi->mux_substream);
1989*1c60b9acSAndroid Build Coastguard Worker
1990*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.content_length_explicitly_zero &&
1991*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
1992*1c60b9acSAndroid Build Coastguard Worker
1993*1c60b9acSAndroid Build Coastguard Worker /*
1994*1c60b9acSAndroid Build Coastguard Worker * POST with an explicit content-length of zero
1995*1c60b9acSAndroid Build Coastguard Worker *
1996*1c60b9acSAndroid Build Coastguard Worker * If we don't give the user code the empty HTTP_BODY callback,
1997*1c60b9acSAndroid Build Coastguard Worker * he may become confused to hear the HTTP_BODY_COMPLETION (due
1998*1c60b9acSAndroid Build Coastguard Worker * to, eg, instantiation of lws_spa never happened).
1999*1c60b9acSAndroid Build Coastguard Worker *
2000*1c60b9acSAndroid Build Coastguard Worker * HTTP_BODY_COMPLETION is responsible for sending the result
2001*1c60b9acSAndroid Build Coastguard Worker * status code and result body if any, and to do the transaction
2002*1c60b9acSAndroid Build Coastguard Worker * complete processing.
2003*1c60b9acSAndroid Build Coastguard Worker */
2004*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY,
2005*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, NULL, 0))
2006*1c60b9acSAndroid Build Coastguard Worker return 1;
2007*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_BODY_COMPLETION,
2008*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, NULL, 0))
2009*1c60b9acSAndroid Build Coastguard Worker return 1;
2010*1c60b9acSAndroid Build Coastguard Worker
2011*1c60b9acSAndroid Build Coastguard Worker return 0;
2012*1c60b9acSAndroid Build Coastguard Worker }
2013*1c60b9acSAndroid Build Coastguard Worker
2014*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.rx_content_length <= 0)
2015*1c60b9acSAndroid Build Coastguard Worker return 0;
2016*1c60b9acSAndroid Build Coastguard Worker
2017*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) != LRS_DISCARD_BODY) {
2018*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_BODY);
2019*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: LRS_BODY state set (0x%x)\n", __func__,
2020*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), (int)wsi->wsistate);
2021*1c60b9acSAndroid Build Coastguard Worker }
2022*1c60b9acSAndroid Build Coastguard Worker wsi->http.rx_content_remain = wsi->http.rx_content_length;
2023*1c60b9acSAndroid Build Coastguard Worker
2024*1c60b9acSAndroid Build Coastguard Worker /*
2025*1c60b9acSAndroid Build Coastguard Worker * At this point we have transitioned from deferred
2026*1c60b9acSAndroid Build Coastguard Worker * action to expecting BODY on the stream wsi, if it's
2027*1c60b9acSAndroid Build Coastguard Worker * in a bundle like h2. So if the stream wsi has its
2028*1c60b9acSAndroid Build Coastguard Worker * own buflist, we need to deal with that first.
2029*1c60b9acSAndroid Build Coastguard Worker */
2030*1c60b9acSAndroid Build Coastguard Worker
2031*1c60b9acSAndroid Build Coastguard Worker while (1) {
2032*1c60b9acSAndroid Build Coastguard Worker struct lws_tokens ebuf;
2033*1c60b9acSAndroid Build Coastguard Worker int m;
2034*1c60b9acSAndroid Build Coastguard Worker
2035*1c60b9acSAndroid Build Coastguard Worker ebuf.len = (int)lws_buflist_next_segment_len(&wsi->buflist,
2036*1c60b9acSAndroid Build Coastguard Worker &ebuf.token);
2037*1c60b9acSAndroid Build Coastguard Worker if (!ebuf.len)
2038*1c60b9acSAndroid Build Coastguard Worker break;
2039*1c60b9acSAndroid Build Coastguard Worker
2040*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: consuming %d\n", __func__, (int)ebuf.len);
2041*1c60b9acSAndroid Build Coastguard Worker m = lws_read_h1(wsi, ebuf.token, (lws_filepos_t)ebuf.len);
2042*1c60b9acSAndroid Build Coastguard Worker if (m < 0)
2043*1c60b9acSAndroid Build Coastguard Worker return -1;
2044*1c60b9acSAndroid Build Coastguard Worker
2045*1c60b9acSAndroid Build Coastguard Worker if (lws_buflist_aware_finished_consuming(wsi, &ebuf, m, 1,
2046*1c60b9acSAndroid Build Coastguard Worker __func__))
2047*1c60b9acSAndroid Build Coastguard Worker return -1;
2048*1c60b9acSAndroid Build Coastguard Worker }
2049*1c60b9acSAndroid Build Coastguard Worker
2050*1c60b9acSAndroid Build Coastguard Worker return 0;
2051*1c60b9acSAndroid Build Coastguard Worker
2052*1c60b9acSAndroid Build Coastguard Worker bail_nuke_ah:
2053*1c60b9acSAndroid Build Coastguard Worker lws_header_table_detach(wsi, 1);
2054*1c60b9acSAndroid Build Coastguard Worker
2055*1c60b9acSAndroid Build Coastguard Worker return 1;
2056*1c60b9acSAndroid Build Coastguard Worker }
2057*1c60b9acSAndroid Build Coastguard Worker
2058*1c60b9acSAndroid Build Coastguard Worker int
lws_confirm_host_header(struct lws * wsi)2059*1c60b9acSAndroid Build Coastguard Worker lws_confirm_host_header(struct lws *wsi)
2060*1c60b9acSAndroid Build Coastguard Worker {
2061*1c60b9acSAndroid Build Coastguard Worker struct lws_tokenize ts;
2062*1c60b9acSAndroid Build Coastguard Worker lws_tokenize_elem e;
2063*1c60b9acSAndroid Build Coastguard Worker int port = 80, n;
2064*1c60b9acSAndroid Build Coastguard Worker char buf[128];
2065*1c60b9acSAndroid Build Coastguard Worker
2066*1c60b9acSAndroid Build Coastguard Worker /*
2067*1c60b9acSAndroid Build Coastguard Worker * this vhost wants us to validate what the
2068*1c60b9acSAndroid Build Coastguard Worker * client sent against our vhost name
2069*1c60b9acSAndroid Build Coastguard Worker */
2070*1c60b9acSAndroid Build Coastguard Worker
2071*1c60b9acSAndroid Build Coastguard Worker if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
2072*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: missing host on upgrade\n", __func__);
2073*1c60b9acSAndroid Build Coastguard Worker
2074*1c60b9acSAndroid Build Coastguard Worker return 1;
2075*1c60b9acSAndroid Build Coastguard Worker }
2076*1c60b9acSAndroid Build Coastguard Worker
2077*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS)
2078*1c60b9acSAndroid Build Coastguard Worker if (wsi->tls.ssl)
2079*1c60b9acSAndroid Build Coastguard Worker port = 443;
2080*1c60b9acSAndroid Build Coastguard Worker #endif
2081*1c60b9acSAndroid Build Coastguard Worker
2082*1c60b9acSAndroid Build Coastguard Worker n = lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_HOST);
2083*1c60b9acSAndroid Build Coastguard Worker if (n <= 0) {
2084*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: missing or oversize host header\n", __func__);
2085*1c60b9acSAndroid Build Coastguard Worker return 1;
2086*1c60b9acSAndroid Build Coastguard Worker }
2087*1c60b9acSAndroid Build Coastguard Worker ts.len = (size_t)n;
2088*1c60b9acSAndroid Build Coastguard Worker lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_DOT_NONTERM /* server.com */|
2089*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_NO_FLOATS /* 1.server.com */|
2090*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_MINUS_NONTERM /* a-b.com */);
2091*1c60b9acSAndroid Build Coastguard Worker
2092*1c60b9acSAndroid Build Coastguard Worker if (lws_tokenize(&ts) != LWS_TOKZE_TOKEN)
2093*1c60b9acSAndroid Build Coastguard Worker goto bad_format;
2094*1c60b9acSAndroid Build Coastguard Worker
2095*1c60b9acSAndroid Build Coastguard Worker if (strncmp(ts.token, wsi->a.vhost->name, ts.token_len)) {
2096*1c60b9acSAndroid Build Coastguard Worker buf[(size_t)(ts.token - buf) + ts.token_len] = '\0';
2097*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: '%s' in host hdr but vhost name %s\n",
2098*1c60b9acSAndroid Build Coastguard Worker __func__, ts.token, wsi->a.vhost->name);
2099*1c60b9acSAndroid Build Coastguard Worker return 1;
2100*1c60b9acSAndroid Build Coastguard Worker }
2101*1c60b9acSAndroid Build Coastguard Worker
2102*1c60b9acSAndroid Build Coastguard Worker e = lws_tokenize(&ts);
2103*1c60b9acSAndroid Build Coastguard Worker if (e == LWS_TOKZE_DELIMITER && ts.token[0] == ':') {
2104*1c60b9acSAndroid Build Coastguard Worker if (lws_tokenize(&ts) != LWS_TOKZE_INTEGER)
2105*1c60b9acSAndroid Build Coastguard Worker goto bad_format;
2106*1c60b9acSAndroid Build Coastguard Worker else
2107*1c60b9acSAndroid Build Coastguard Worker port = atoi(ts.token);
2108*1c60b9acSAndroid Build Coastguard Worker } else
2109*1c60b9acSAndroid Build Coastguard Worker if (e != LWS_TOKZE_ENDED)
2110*1c60b9acSAndroid Build Coastguard Worker goto bad_format;
2111*1c60b9acSAndroid Build Coastguard Worker
2112*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->listen_port != port) {
2113*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: host port %d mismatches vhost port %d\n",
2114*1c60b9acSAndroid Build Coastguard Worker __func__, port, wsi->a.vhost->listen_port);
2115*1c60b9acSAndroid Build Coastguard Worker return 1;
2116*1c60b9acSAndroid Build Coastguard Worker }
2117*1c60b9acSAndroid Build Coastguard Worker
2118*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: host header OK\n", __func__);
2119*1c60b9acSAndroid Build Coastguard Worker
2120*1c60b9acSAndroid Build Coastguard Worker return 0;
2121*1c60b9acSAndroid Build Coastguard Worker
2122*1c60b9acSAndroid Build Coastguard Worker bad_format:
2123*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: bad host header format\n", __func__);
2124*1c60b9acSAndroid Build Coastguard Worker
2125*1c60b9acSAndroid Build Coastguard Worker return 1;
2126*1c60b9acSAndroid Build Coastguard Worker }
2127*1c60b9acSAndroid Build Coastguard Worker
2128*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
2129*1c60b9acSAndroid Build Coastguard Worker int
lws_http_to_fallback(struct lws * wsi,unsigned char * obuf,size_t olen)2130*1c60b9acSAndroid Build Coastguard Worker lws_http_to_fallback(struct lws *wsi, unsigned char *obuf, size_t olen)
2131*1c60b9acSAndroid Build Coastguard Worker {
2132*1c60b9acSAndroid Build Coastguard Worker const struct lws_role_ops *role = &role_ops_raw_skt;
2133*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocols *p1, *protocol =
2134*1c60b9acSAndroid Build Coastguard Worker &wsi->a.vhost->protocols[wsi->a.vhost->raw_protocol_index];
2135*1c60b9acSAndroid Build Coastguard Worker char ipbuf[64];
2136*1c60b9acSAndroid Build Coastguard Worker int n;
2137*1c60b9acSAndroid Build Coastguard Worker
2138*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->listen_accept_role &&
2139*1c60b9acSAndroid Build Coastguard Worker lws_role_by_name(wsi->a.vhost->listen_accept_role))
2140*1c60b9acSAndroid Build Coastguard Worker role = lws_role_by_name(wsi->a.vhost->listen_accept_role);
2141*1c60b9acSAndroid Build Coastguard Worker
2142*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->listen_accept_protocol) {
2143*1c60b9acSAndroid Build Coastguard Worker p1 = lws_vhost_name_to_protocol(wsi->a.vhost,
2144*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->listen_accept_protocol);
2145*1c60b9acSAndroid Build Coastguard Worker if (p1)
2146*1c60b9acSAndroid Build Coastguard Worker protocol = p1;
2147*1c60b9acSAndroid Build Coastguard Worker }
2148*1c60b9acSAndroid Build Coastguard Worker
2149*1c60b9acSAndroid Build Coastguard Worker lws_bind_protocol(wsi, protocol, __func__);
2150*1c60b9acSAndroid Build Coastguard Worker
2151*1c60b9acSAndroid Build Coastguard Worker lws_role_transition(wsi, LWSIFR_SERVER, LRS_ESTABLISHED, role);
2152*1c60b9acSAndroid Build Coastguard Worker
2153*1c60b9acSAndroid Build Coastguard Worker lws_header_table_detach(wsi, 0);
2154*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
2155*1c60b9acSAndroid Build Coastguard Worker
2156*1c60b9acSAndroid Build Coastguard Worker n = LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED;
2157*1c60b9acSAndroid Build Coastguard Worker if (wsi->role_ops->adoption_cb[1])
2158*1c60b9acSAndroid Build Coastguard Worker n = wsi->role_ops->adoption_cb[1];
2159*1c60b9acSAndroid Build Coastguard Worker
2160*1c60b9acSAndroid Build Coastguard Worker ipbuf[0] = '\0';
2161*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_OPTEE)
2162*1c60b9acSAndroid Build Coastguard Worker lws_get_peer_simple(wsi, ipbuf, sizeof(ipbuf));
2163*1c60b9acSAndroid Build Coastguard Worker #endif
2164*1c60b9acSAndroid Build Coastguard Worker
2165*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: vh %s, peer: %s, role %s, "
2166*1c60b9acSAndroid Build Coastguard Worker "protocol %s, cb %d, ah %p\n", __func__, wsi->a.vhost->name,
2167*1c60b9acSAndroid Build Coastguard Worker ipbuf, role ? role->name : "null", protocol->name, n,
2168*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah);
2169*1c60b9acSAndroid Build Coastguard Worker
2170*1c60b9acSAndroid Build Coastguard Worker if ((wsi->a.protocol->callback)(wsi, (enum lws_callback_reasons)n, wsi->user_space, NULL, 0))
2171*1c60b9acSAndroid Build Coastguard Worker return 1;
2172*1c60b9acSAndroid Build Coastguard Worker
2173*1c60b9acSAndroid Build Coastguard Worker n = LWS_CALLBACK_RAW_RX;
2174*1c60b9acSAndroid Build Coastguard Worker if (wsi->role_ops->rx_cb[lwsi_role_server(wsi)])
2175*1c60b9acSAndroid Build Coastguard Worker n = wsi->role_ops->rx_cb[lwsi_role_server(wsi)];
2176*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.protocol->callback(wsi, (enum lws_callback_reasons)n, wsi->user_space, obuf, olen))
2177*1c60b9acSAndroid Build Coastguard Worker return 1;
2178*1c60b9acSAndroid Build Coastguard Worker
2179*1c60b9acSAndroid Build Coastguard Worker return 0;
2180*1c60b9acSAndroid Build Coastguard Worker }
2181*1c60b9acSAndroid Build Coastguard Worker
2182*1c60b9acSAndroid Build Coastguard Worker int
lws_handshake_server(struct lws * wsi,unsigned char ** buf,size_t len)2183*1c60b9acSAndroid Build Coastguard Worker lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
2184*1c60b9acSAndroid Build Coastguard Worker {
2185*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = lws_get_context(wsi);
2186*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
2187*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
2188*1c60b9acSAndroid Build Coastguard Worker struct allocated_headers *ah;
2189*1c60b9acSAndroid Build Coastguard Worker #endif
2190*1c60b9acSAndroid Build Coastguard Worker unsigned char *obuf = *buf;
2191*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
2192*1c60b9acSAndroid Build Coastguard Worker char tbuf[128], *p;
2193*1c60b9acSAndroid Build Coastguard Worker #endif
2194*1c60b9acSAndroid Build Coastguard Worker size_t olen = len;
2195*1c60b9acSAndroid Build Coastguard Worker int n = 0, m, i;
2196*1c60b9acSAndroid Build Coastguard Worker
2197*1c60b9acSAndroid Build Coastguard Worker if (len >= 10000000) {
2198*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: assert: len %ld\n", __func__, (long)len);
2199*1c60b9acSAndroid Build Coastguard Worker assert(0);
2200*1c60b9acSAndroid Build Coastguard Worker }
2201*1c60b9acSAndroid Build Coastguard Worker
2202*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah) {
2203*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: assert: NULL ah\n", __func__);
2204*1c60b9acSAndroid Build Coastguard Worker assert(0);
2205*1c60b9acSAndroid Build Coastguard Worker }
2206*1c60b9acSAndroid Build Coastguard Worker
2207*1c60b9acSAndroid Build Coastguard Worker while (len) {
2208*1c60b9acSAndroid Build Coastguard Worker if (!lwsi_role_server(wsi) || !lwsi_role_http(wsi)) {
2209*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: bad wsi role 0x%x\n", __func__,
2210*1c60b9acSAndroid Build Coastguard Worker (int)lwsi_role(wsi));
2211*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2212*1c60b9acSAndroid Build Coastguard Worker }
2213*1c60b9acSAndroid Build Coastguard Worker
2214*1c60b9acSAndroid Build Coastguard Worker i = (int)len;
2215*1c60b9acSAndroid Build Coastguard Worker m = lws_parse(wsi, *buf, &i);
2216*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: parsed count %d\n", __func__, (int)len - i);
2217*1c60b9acSAndroid Build Coastguard Worker (*buf) += (int)len - i;
2218*1c60b9acSAndroid Build Coastguard Worker len = (unsigned int)i;
2219*1c60b9acSAndroid Build Coastguard Worker
2220*1c60b9acSAndroid Build Coastguard Worker if (m == LPR_DO_FALLBACK) {
2221*1c60b9acSAndroid Build Coastguard Worker
2222*1c60b9acSAndroid Build Coastguard Worker /*
2223*1c60b9acSAndroid Build Coastguard Worker * http parser went off the rails and
2224*1c60b9acSAndroid Build Coastguard Worker * LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_
2225*1c60b9acSAndroid Build Coastguard Worker * ACCEPT_CONFIG is set on this vhost.
2226*1c60b9acSAndroid Build Coastguard Worker *
2227*1c60b9acSAndroid Build Coastguard Worker * We are transitioning from http with an AH, to
2228*1c60b9acSAndroid Build Coastguard Worker * a backup role (raw-skt, by default). Drop
2229*1c60b9acSAndroid Build Coastguard Worker * the ah, bind to the role with mode as
2230*1c60b9acSAndroid Build Coastguard Worker * ESTABLISHED.
2231*1c60b9acSAndroid Build Coastguard Worker */
2232*1c60b9acSAndroid Build Coastguard Worker raw_transition:
2233*1c60b9acSAndroid Build Coastguard Worker
2234*1c60b9acSAndroid Build Coastguard Worker if (lws_http_to_fallback(wsi, obuf, olen)) {
2235*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: fallback -> close\n", __func__);
2236*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2237*1c60b9acSAndroid Build Coastguard Worker }
2238*1c60b9acSAndroid Build Coastguard Worker
2239*1c60b9acSAndroid Build Coastguard Worker (*buf) = obuf + olen;
2240*1c60b9acSAndroid Build Coastguard Worker
2241*1c60b9acSAndroid Build Coastguard Worker return 0;
2242*1c60b9acSAndroid Build Coastguard Worker }
2243*1c60b9acSAndroid Build Coastguard Worker if (m) {
2244*1c60b9acSAndroid Build Coastguard Worker lwsl_info("lws_parse failed\n");
2245*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2246*1c60b9acSAndroid Build Coastguard Worker }
2247*1c60b9acSAndroid Build Coastguard Worker
2248*1c60b9acSAndroid Build Coastguard Worker /* coverity... */
2249*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.ah)
2250*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2251*1c60b9acSAndroid Build Coastguard Worker
2252*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE)
2253*1c60b9acSAndroid Build Coastguard Worker continue;
2254*1c60b9acSAndroid Build Coastguard Worker
2255*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("%s: lws_parse sees parsing complete\n", __func__);
2256*1c60b9acSAndroid Build Coastguard Worker
2257*1c60b9acSAndroid Build Coastguard Worker /* select vhost */
2258*1c60b9acSAndroid Build Coastguard Worker
2259*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->listen_port &&
2260*1c60b9acSAndroid Build Coastguard Worker lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
2261*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost *vhost = lws_select_vhost(
2262*1c60b9acSAndroid Build Coastguard Worker context, wsi->a.vhost->listen_port,
2263*1c60b9acSAndroid Build Coastguard Worker lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
2264*1c60b9acSAndroid Build Coastguard Worker
2265*1c60b9acSAndroid Build Coastguard Worker if (vhost)
2266*1c60b9acSAndroid Build Coastguard Worker lws_vhost_bind_wsi(vhost, wsi);
2267*1c60b9acSAndroid Build Coastguard Worker } else
2268*1c60b9acSAndroid Build Coastguard Worker lwsl_info("no host\n");
2269*1c60b9acSAndroid Build Coastguard Worker
2270*1c60b9acSAndroid Build Coastguard Worker if ((!lwsi_role_h2(wsi) || !lwsi_role_server(wsi)) &&
2271*1c60b9acSAndroid Build Coastguard Worker (!wsi->conn_stat_done))
2272*1c60b9acSAndroid Build Coastguard Worker wsi->conn_stat_done = 1;
2273*1c60b9acSAndroid Build Coastguard Worker
2274*1c60b9acSAndroid Build Coastguard Worker /* check for unwelcome guests */
2275*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
2276*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.context->reject_service_keywords) {
2277*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocol_vhost_options *rej =
2278*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->reject_service_keywords;
2279*1c60b9acSAndroid Build Coastguard Worker char ua[384], *msg = NULL;
2280*1c60b9acSAndroid Build Coastguard Worker
2281*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_copy(wsi, ua, sizeof(ua) - 1,
2282*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_USER_AGENT) > 0) {
2283*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_ACCESS_LOG
2284*1c60b9acSAndroid Build Coastguard Worker char *uri_ptr = NULL;
2285*1c60b9acSAndroid Build Coastguard Worker int meth, uri_len;
2286*1c60b9acSAndroid Build Coastguard Worker #endif
2287*1c60b9acSAndroid Build Coastguard Worker ua[sizeof(ua) - 1] = '\0';
2288*1c60b9acSAndroid Build Coastguard Worker while (rej) {
2289*1c60b9acSAndroid Build Coastguard Worker if (!strstr(ua, rej->name)) {
2290*1c60b9acSAndroid Build Coastguard Worker rej = rej->next;
2291*1c60b9acSAndroid Build Coastguard Worker continue;
2292*1c60b9acSAndroid Build Coastguard Worker }
2293*1c60b9acSAndroid Build Coastguard Worker
2294*1c60b9acSAndroid Build Coastguard Worker msg = strchr(rej->value, ' ');
2295*1c60b9acSAndroid Build Coastguard Worker if (msg)
2296*1c60b9acSAndroid Build Coastguard Worker msg++;
2297*1c60b9acSAndroid Build Coastguard Worker lws_return_http_status(wsi,
2298*1c60b9acSAndroid Build Coastguard Worker (unsigned int)atoi(rej->value), msg);
2299*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_ACCESS_LOG
2300*1c60b9acSAndroid Build Coastguard Worker meth = lws_http_get_uri_and_method(wsi,
2301*1c60b9acSAndroid Build Coastguard Worker &uri_ptr, &uri_len);
2302*1c60b9acSAndroid Build Coastguard Worker if (meth >= 0)
2303*1c60b9acSAndroid Build Coastguard Worker lws_prepare_access_log_info(wsi,
2304*1c60b9acSAndroid Build Coastguard Worker uri_ptr, uri_len, meth);
2305*1c60b9acSAndroid Build Coastguard Worker
2306*1c60b9acSAndroid Build Coastguard Worker /* wsi close will do the log */
2307*1c60b9acSAndroid Build Coastguard Worker #endif
2308*1c60b9acSAndroid Build Coastguard Worker /*
2309*1c60b9acSAndroid Build Coastguard Worker * We don't want anything from
2310*1c60b9acSAndroid Build Coastguard Worker * this rejected guy. Follow
2311*1c60b9acSAndroid Build Coastguard Worker * the close flow, not the
2312*1c60b9acSAndroid Build Coastguard Worker * transaction complete flow.
2313*1c60b9acSAndroid Build Coastguard Worker */
2314*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2315*1c60b9acSAndroid Build Coastguard Worker }
2316*1c60b9acSAndroid Build Coastguard Worker }
2317*1c60b9acSAndroid Build Coastguard Worker }
2318*1c60b9acSAndroid Build Coastguard Worker #endif
2319*1c60b9acSAndroid Build Coastguard Worker /*
2320*1c60b9acSAndroid Build Coastguard Worker * So he may have come to us requesting one or another kind
2321*1c60b9acSAndroid Build Coastguard Worker * of upgrade from http... but we may want to redirect him at
2322*1c60b9acSAndroid Build Coastguard Worker * http level. In that case, we need to check the redirect
2323*1c60b9acSAndroid Build Coastguard Worker * situation even though he's not actually wanting http and
2324*1c60b9acSAndroid Build Coastguard Worker * prioritize returning that if there is one.
2325*1c60b9acSAndroid Build Coastguard Worker */
2326*1c60b9acSAndroid Build Coastguard Worker
2327*1c60b9acSAndroid Build Coastguard Worker {
2328*1c60b9acSAndroid Build Coastguard Worker const struct lws_http_mount *hit = NULL;
2329*1c60b9acSAndroid Build Coastguard Worker int uri_len = 0, ha, n;
2330*1c60b9acSAndroid Build Coastguard Worker char *uri_ptr = NULL;
2331*1c60b9acSAndroid Build Coastguard Worker
2332*1c60b9acSAndroid Build Coastguard Worker n = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
2333*1c60b9acSAndroid Build Coastguard Worker if (n >= 0) {
2334*1c60b9acSAndroid Build Coastguard Worker hit = lws_find_mount(wsi, uri_ptr, uri_len);
2335*1c60b9acSAndroid Build Coastguard Worker if (hit) {
2336*1c60b9acSAndroid Build Coastguard Worker n = lws_http_redirect_hit(pt, wsi, hit, uri_ptr,
2337*1c60b9acSAndroid Build Coastguard Worker uri_len, &ha);
2338*1c60b9acSAndroid Build Coastguard Worker if (ha)
2339*1c60b9acSAndroid Build Coastguard Worker return n;
2340*1c60b9acSAndroid Build Coastguard Worker }
2341*1c60b9acSAndroid Build Coastguard Worker }
2342*1c60b9acSAndroid Build Coastguard Worker }
2343*1c60b9acSAndroid Build Coastguard Worker
2344*1c60b9acSAndroid Build Coastguard Worker
2345*1c60b9acSAndroid Build Coastguard Worker
2346*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECT)) {
2347*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Changing to RAW mode\n");
2348*1c60b9acSAndroid Build Coastguard Worker goto raw_transition;
2349*1c60b9acSAndroid Build Coastguard Worker }
2350*1c60b9acSAndroid Build Coastguard Worker
2351*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_PRE_WS_SERVING_ACCEPT);
2352*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
2353*1c60b9acSAndroid Build Coastguard Worker
2354*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
2355*1c60b9acSAndroid Build Coastguard Worker
2356*1c60b9acSAndroid Build Coastguard Worker const char *up = lws_hdr_simple_ptr(wsi,
2357*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_UPGRADE);
2358*1c60b9acSAndroid Build Coastguard Worker
2359*1c60b9acSAndroid Build Coastguard Worker if (strcasecmp(up, "websocket") &&
2360*1c60b9acSAndroid Build Coastguard Worker strcasecmp(up, "h2c")) {
2361*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Unknown upgrade '%s'\n", up);
2362*1c60b9acSAndroid Build Coastguard Worker
2363*1c60b9acSAndroid Build Coastguard Worker if (lws_return_http_status(wsi,
2364*1c60b9acSAndroid Build Coastguard Worker HTTP_STATUS_FORBIDDEN, NULL) ||
2365*1c60b9acSAndroid Build Coastguard Worker lws_http_transaction_completed(wsi))
2366*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2367*1c60b9acSAndroid Build Coastguard Worker }
2368*1c60b9acSAndroid Build Coastguard Worker
2369*1c60b9acSAndroid Build Coastguard Worker n = user_callback_handle_rxflow(wsi->a.protocol->callback,
2370*1c60b9acSAndroid Build Coastguard Worker wsi, LWS_CALLBACK_HTTP_CONFIRM_UPGRADE,
2371*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, (char *)up, 0);
2372*1c60b9acSAndroid Build Coastguard Worker
2373*1c60b9acSAndroid Build Coastguard Worker /* just hang up? */
2374*1c60b9acSAndroid Build Coastguard Worker
2375*1c60b9acSAndroid Build Coastguard Worker if (n < 0)
2376*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2377*1c60b9acSAndroid Build Coastguard Worker
2378*1c60b9acSAndroid Build Coastguard Worker /* callback returned headers already, do t_c? */
2379*1c60b9acSAndroid Build Coastguard Worker
2380*1c60b9acSAndroid Build Coastguard Worker if (n > 0) {
2381*1c60b9acSAndroid Build Coastguard Worker if (lws_http_transaction_completed(wsi))
2382*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2383*1c60b9acSAndroid Build Coastguard Worker
2384*1c60b9acSAndroid Build Coastguard Worker /* continue on */
2385*1c60b9acSAndroid Build Coastguard Worker
2386*1c60b9acSAndroid Build Coastguard Worker return 0;
2387*1c60b9acSAndroid Build Coastguard Worker }
2388*1c60b9acSAndroid Build Coastguard Worker
2389*1c60b9acSAndroid Build Coastguard Worker /* callback said 0, it was allowed */
2390*1c60b9acSAndroid Build Coastguard Worker
2391*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->options &
2392*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK &&
2393*1c60b9acSAndroid Build Coastguard Worker lws_confirm_host_header(wsi))
2394*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2395*1c60b9acSAndroid Build Coastguard Worker
2396*1c60b9acSAndroid Build Coastguard Worker if (!strcasecmp(up, "websocket")) {
2397*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
2398*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_wsi_add(wsi, "upg", "ws");
2399*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Upgrade to ws\n");
2400*1c60b9acSAndroid Build Coastguard Worker goto upgrade_ws;
2401*1c60b9acSAndroid Build Coastguard Worker #endif
2402*1c60b9acSAndroid Build Coastguard Worker }
2403*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
2404*1c60b9acSAndroid Build Coastguard Worker if (!strcasecmp(up, "h2c")) {
2405*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_wsi_add(wsi, "upg", "h2c");
2406*1c60b9acSAndroid Build Coastguard Worker lwsl_info("Upgrade to h2c\n");
2407*1c60b9acSAndroid Build Coastguard Worker goto upgrade_h2c;
2408*1c60b9acSAndroid Build Coastguard Worker }
2409*1c60b9acSAndroid Build Coastguard Worker #endif
2410*1c60b9acSAndroid Build Coastguard Worker }
2411*1c60b9acSAndroid Build Coastguard Worker
2412*1c60b9acSAndroid Build Coastguard Worker /* no upgrade ack... he remained as HTTP */
2413*1c60b9acSAndroid Build Coastguard Worker
2414*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: No upgrade\n", __func__, lws_wsi_tag(wsi));
2415*1c60b9acSAndroid Build Coastguard Worker
2416*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_ESTABLISHED);
2417*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
2418*1c60b9acSAndroid Build Coastguard Worker wsi->http.fop_fd = NULL;
2419*1c60b9acSAndroid Build Coastguard Worker #endif
2420*1c60b9acSAndroid Build Coastguard Worker
2421*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
2422*1c60b9acSAndroid Build Coastguard Worker lws_http_compression_validate(wsi);
2423*1c60b9acSAndroid Build Coastguard Worker #endif
2424*1c60b9acSAndroid Build Coastguard Worker
2425*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s: ah %p\n", __func__, lws_wsi_tag(wsi),
2426*1c60b9acSAndroid Build Coastguard Worker (void *)wsi->http.ah);
2427*1c60b9acSAndroid Build Coastguard Worker
2428*1c60b9acSAndroid Build Coastguard Worker n = lws_http_action(wsi);
2429*1c60b9acSAndroid Build Coastguard Worker
2430*1c60b9acSAndroid Build Coastguard Worker return n;
2431*1c60b9acSAndroid Build Coastguard Worker
2432*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
2433*1c60b9acSAndroid Build Coastguard Worker upgrade_h2c:
2434*1c60b9acSAndroid Build Coastguard Worker if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP2_SETTINGS)) {
2435*1c60b9acSAndroid Build Coastguard Worker lwsl_info("missing http2_settings\n");
2436*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2437*1c60b9acSAndroid Build Coastguard Worker }
2438*1c60b9acSAndroid Build Coastguard Worker
2439*1c60b9acSAndroid Build Coastguard Worker lwsl_info("h2c upgrade...\n");
2440*1c60b9acSAndroid Build Coastguard Worker
2441*1c60b9acSAndroid Build Coastguard Worker p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP2_SETTINGS);
2442*1c60b9acSAndroid Build Coastguard Worker /* convert the peer's HTTP-Settings */
2443*1c60b9acSAndroid Build Coastguard Worker n = lws_b64_decode_string(p, tbuf, sizeof(tbuf));
2444*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
2445*1c60b9acSAndroid Build Coastguard Worker lwsl_parser("HTTP2_SETTINGS too long\n");
2446*1c60b9acSAndroid Build Coastguard Worker return 1;
2447*1c60b9acSAndroid Build Coastguard Worker }
2448*1c60b9acSAndroid Build Coastguard Worker
2449*1c60b9acSAndroid Build Coastguard Worker wsi->upgraded_to_http2 = 1;
2450*1c60b9acSAndroid Build Coastguard Worker
2451*1c60b9acSAndroid Build Coastguard Worker /* adopt the header info */
2452*1c60b9acSAndroid Build Coastguard Worker
2453*1c60b9acSAndroid Build Coastguard Worker ah = wsi->http.ah;
2454*1c60b9acSAndroid Build Coastguard Worker lws_role_transition(wsi, LWSIFR_SERVER, LRS_H2_AWAIT_PREFACE,
2455*1c60b9acSAndroid Build Coastguard Worker &role_ops_h2);
2456*1c60b9acSAndroid Build Coastguard Worker
2457*1c60b9acSAndroid Build Coastguard Worker /* http2 union member has http union struct at start */
2458*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah = ah;
2459*1c60b9acSAndroid Build Coastguard Worker
2460*1c60b9acSAndroid Build Coastguard Worker if (!wsi->h2.h2n) {
2461*1c60b9acSAndroid Build Coastguard Worker wsi->h2.h2n = lws_zalloc(sizeof(*wsi->h2.h2n), "h2n");
2462*1c60b9acSAndroid Build Coastguard Worker if (!wsi->h2.h2n)
2463*1c60b9acSAndroid Build Coastguard Worker return 1;
2464*1c60b9acSAndroid Build Coastguard Worker }
2465*1c60b9acSAndroid Build Coastguard Worker
2466*1c60b9acSAndroid Build Coastguard Worker lws_h2_init(wsi);
2467*1c60b9acSAndroid Build Coastguard Worker
2468*1c60b9acSAndroid Build Coastguard Worker /* HTTP2 union */
2469*1c60b9acSAndroid Build Coastguard Worker
2470*1c60b9acSAndroid Build Coastguard Worker lws_h2_settings(wsi, &wsi->h2.h2n->peer_set, (uint8_t *)tbuf, n);
2471*1c60b9acSAndroid Build Coastguard Worker
2472*1c60b9acSAndroid Build Coastguard Worker if (lws_hpack_dynamic_size(wsi, (int)wsi->h2.h2n->peer_set.s[
2473*1c60b9acSAndroid Build Coastguard Worker H2SET_HEADER_TABLE_SIZE]))
2474*1c60b9acSAndroid Build Coastguard Worker return 1;
2475*1c60b9acSAndroid Build Coastguard Worker
2476*1c60b9acSAndroid Build Coastguard Worker strcpy(tbuf, "HTTP/1.1 101 Switching Protocols\x0d\x0a"
2477*1c60b9acSAndroid Build Coastguard Worker "Connection: Upgrade\x0d\x0a"
2478*1c60b9acSAndroid Build Coastguard Worker "Upgrade: h2c\x0d\x0a\x0d\x0a");
2479*1c60b9acSAndroid Build Coastguard Worker m = (int)strlen(tbuf);
2480*1c60b9acSAndroid Build Coastguard Worker n = lws_issue_raw(wsi, (unsigned char *)tbuf, (unsigned int)m);
2481*1c60b9acSAndroid Build Coastguard Worker if (n != m) {
2482*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("http2 switch: ERROR writing to socket\n");
2483*1c60b9acSAndroid Build Coastguard Worker return 1;
2484*1c60b9acSAndroid Build Coastguard Worker }
2485*1c60b9acSAndroid Build Coastguard Worker
2486*1c60b9acSAndroid Build Coastguard Worker return 0;
2487*1c60b9acSAndroid Build Coastguard Worker #endif
2488*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_WS)
2489*1c60b9acSAndroid Build Coastguard Worker upgrade_ws:
2490*1c60b9acSAndroid Build Coastguard Worker if (lws_process_ws_upgrade(wsi))
2491*1c60b9acSAndroid Build Coastguard Worker goto bail_nuke_ah;
2492*1c60b9acSAndroid Build Coastguard Worker
2493*1c60b9acSAndroid Build Coastguard Worker return 0;
2494*1c60b9acSAndroid Build Coastguard Worker #endif
2495*1c60b9acSAndroid Build Coastguard Worker } /* while all chars are handled */
2496*1c60b9acSAndroid Build Coastguard Worker
2497*1c60b9acSAndroid Build Coastguard Worker return 0;
2498*1c60b9acSAndroid Build Coastguard Worker
2499*1c60b9acSAndroid Build Coastguard Worker bail_nuke_ah:
2500*1c60b9acSAndroid Build Coastguard Worker /* drop the header info */
2501*1c60b9acSAndroid Build Coastguard Worker lws_header_table_detach(wsi, 1);
2502*1c60b9acSAndroid Build Coastguard Worker
2503*1c60b9acSAndroid Build Coastguard Worker return 1;
2504*1c60b9acSAndroid Build Coastguard Worker }
2505*1c60b9acSAndroid Build Coastguard Worker #endif
2506*1c60b9acSAndroid Build Coastguard Worker
2507*1c60b9acSAndroid Build Coastguard Worker int LWS_WARN_UNUSED_RESULT
lws_http_transaction_completed(struct lws * wsi)2508*1c60b9acSAndroid Build Coastguard Worker lws_http_transaction_completed(struct lws *wsi)
2509*1c60b9acSAndroid Build Coastguard Worker {
2510*1c60b9acSAndroid Build Coastguard Worker int n;
2511*1c60b9acSAndroid Build Coastguard Worker
2512*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.cgi_transaction_complete)
2513*1c60b9acSAndroid Build Coastguard Worker return 0;
2514*1c60b9acSAndroid Build Coastguard Worker
2515*1c60b9acSAndroid Build Coastguard Worker if (lws_has_buffered_out(wsi)
2516*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
2517*1c60b9acSAndroid Build Coastguard Worker || wsi->http.comp_ctx.buflist_comp ||
2518*1c60b9acSAndroid Build Coastguard Worker wsi->http.comp_ctx.may_have_more
2519*1c60b9acSAndroid Build Coastguard Worker #endif
2520*1c60b9acSAndroid Build Coastguard Worker ) {
2521*1c60b9acSAndroid Build Coastguard Worker /*
2522*1c60b9acSAndroid Build Coastguard Worker * ...so he tried to send something large as the http reply,
2523*1c60b9acSAndroid Build Coastguard Worker * it went as a partial, but he immediately said the
2524*1c60b9acSAndroid Build Coastguard Worker * transaction was completed.
2525*1c60b9acSAndroid Build Coastguard Worker *
2526*1c60b9acSAndroid Build Coastguard Worker * Defer the transaction completed until the last part of the
2527*1c60b9acSAndroid Build Coastguard Worker * partial is sent.
2528*1c60b9acSAndroid Build Coastguard Worker */
2529*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s: deferring due to partial\n", __func__,
2530*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi));
2531*1c60b9acSAndroid Build Coastguard Worker wsi->http.deferred_transaction_completed = 1;
2532*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
2533*1c60b9acSAndroid Build Coastguard Worker
2534*1c60b9acSAndroid Build Coastguard Worker return 0;
2535*1c60b9acSAndroid Build Coastguard Worker }
2536*1c60b9acSAndroid Build Coastguard Worker /*
2537*1c60b9acSAndroid Build Coastguard Worker * Are we finishing the transaction before we have consumed any body?
2538*1c60b9acSAndroid Build Coastguard Worker *
2539*1c60b9acSAndroid Build Coastguard Worker * For h1 this would kill keepalive pipelining, and for h2, considering
2540*1c60b9acSAndroid Build Coastguard Worker * it can extend over multiple DATA frames, it would kill the network
2541*1c60b9acSAndroid Build Coastguard Worker * connection.
2542*1c60b9acSAndroid Build Coastguard Worker */
2543*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.rx_content_length && wsi->http.rx_content_remain) {
2544*1c60b9acSAndroid Build Coastguard Worker /*
2545*1c60b9acSAndroid Build Coastguard Worker * are we already in LRS_DISCARD_BODY and didn't clear the
2546*1c60b9acSAndroid Build Coastguard Worker * remaining before trying to complete the transaction again?
2547*1c60b9acSAndroid Build Coastguard Worker */
2548*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) == LRS_DISCARD_BODY)
2549*1c60b9acSAndroid Build Coastguard Worker return -1;
2550*1c60b9acSAndroid Build Coastguard Worker /*
2551*1c60b9acSAndroid Build Coastguard Worker * let's defer transaction completed processing until we
2552*1c60b9acSAndroid Build Coastguard Worker * discarded the remaining body
2553*1c60b9acSAndroid Build Coastguard Worker */
2554*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_DISCARD_BODY);
2555*1c60b9acSAndroid Build Coastguard Worker
2556*1c60b9acSAndroid Build Coastguard Worker return 0;
2557*1c60b9acSAndroid Build Coastguard Worker }
2558*1c60b9acSAndroid Build Coastguard Worker
2559*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
2560*1c60b9acSAndroid Build Coastguard Worker {
2561*1c60b9acSAndroid Build Coastguard Worker char tmp[10];
2562*1c60b9acSAndroid Build Coastguard Worker
2563*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(tmp, sizeof(tmp), "%u", wsi->http.response_code);
2564*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_wsi_add(wsi, "status", tmp);
2565*1c60b9acSAndroid Build Coastguard Worker }
2566*1c60b9acSAndroid Build Coastguard Worker #endif
2567*1c60b9acSAndroid Build Coastguard Worker
2568*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s\n", __func__, lws_wsi_tag(wsi));
2569*1c60b9acSAndroid Build Coastguard Worker
2570*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
2571*1c60b9acSAndroid Build Coastguard Worker lws_http_compression_destroy(wsi);
2572*1c60b9acSAndroid Build Coastguard Worker #endif
2573*1c60b9acSAndroid Build Coastguard Worker lws_access_log(wsi);
2574*1c60b9acSAndroid Build Coastguard Worker
2575*1c60b9acSAndroid Build Coastguard Worker if (!wsi->hdr_parsing_completed
2576*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CGI)
2577*1c60b9acSAndroid Build Coastguard Worker && !wsi->http.cgi
2578*1c60b9acSAndroid Build Coastguard Worker #endif
2579*1c60b9acSAndroid Build Coastguard Worker ) {
2580*1c60b9acSAndroid Build Coastguard Worker char peer[64];
2581*1c60b9acSAndroid Build Coastguard Worker
2582*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_OPTEE)
2583*1c60b9acSAndroid Build Coastguard Worker lws_get_peer_simple(wsi, peer, sizeof(peer) - 1);
2584*1c60b9acSAndroid Build Coastguard Worker #else
2585*1c60b9acSAndroid Build Coastguard Worker peer[0] = '\0';
2586*1c60b9acSAndroid Build Coastguard Worker #endif
2587*1c60b9acSAndroid Build Coastguard Worker peer[sizeof(peer) - 1] = '\0';
2588*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: (from %s) ignoring, ah parsing incomplete\n",
2589*1c60b9acSAndroid Build Coastguard Worker __func__, peer);
2590*1c60b9acSAndroid Build Coastguard Worker return 0;
2591*1c60b9acSAndroid Build Coastguard Worker }
2592*1c60b9acSAndroid Build Coastguard Worker
2593*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CGI)
2594*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.cgi) {
2595*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: cleaning cgi\n", __func__);
2596*1c60b9acSAndroid Build Coastguard Worker wsi->http.cgi_transaction_complete = 1;
2597*1c60b9acSAndroid Build Coastguard Worker lws_cgi_remove_and_kill(wsi);
2598*1c60b9acSAndroid Build Coastguard Worker lws_spawn_piped_destroy(&wsi->http.cgi->lsp);
2599*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&wsi->http.cgi->sul_grace);
2600*1c60b9acSAndroid Build Coastguard Worker
2601*1c60b9acSAndroid Build Coastguard Worker lws_free_set_NULL(wsi->http.cgi);
2602*1c60b9acSAndroid Build Coastguard Worker wsi->http.cgi_transaction_complete = 0;
2603*1c60b9acSAndroid Build Coastguard Worker }
2604*1c60b9acSAndroid Build Coastguard Worker #endif
2605*1c60b9acSAndroid Build Coastguard Worker
2606*1c60b9acSAndroid Build Coastguard Worker /* if we can't go back to accept new headers, drop the connection */
2607*1c60b9acSAndroid Build Coastguard Worker if (wsi->mux_substream)
2608*1c60b9acSAndroid Build Coastguard Worker return 1;
2609*1c60b9acSAndroid Build Coastguard Worker
2610*1c60b9acSAndroid Build Coastguard Worker if (wsi->seen_zero_length_recv)
2611*1c60b9acSAndroid Build Coastguard Worker return 1;
2612*1c60b9acSAndroid Build Coastguard Worker
2613*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.conn_type != HTTP_CONNECTION_KEEP_ALIVE) {
2614*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: close connection\n", __func__, lws_wsi_tag(wsi));
2615*1c60b9acSAndroid Build Coastguard Worker return 1;
2616*1c60b9acSAndroid Build Coastguard Worker }
2617*1c60b9acSAndroid Build Coastguard Worker
2618*1c60b9acSAndroid Build Coastguard Worker if (lws_bind_protocol(wsi, &wsi->a.vhost->protocols[0], __func__))
2619*1c60b9acSAndroid Build Coastguard Worker return 1;
2620*1c60b9acSAndroid Build Coastguard Worker
2621*1c60b9acSAndroid Build Coastguard Worker /*
2622*1c60b9acSAndroid Build Coastguard Worker * otherwise set ourselves up ready to go again, but because we have no
2623*1c60b9acSAndroid Build Coastguard Worker * idea about the wsi writability, we make put it in a holding state
2624*1c60b9acSAndroid Build Coastguard Worker * until we can verify POLLOUT. The part of this that confirms POLLOUT
2625*1c60b9acSAndroid Build Coastguard Worker * with no partials is in lws_server_socket_service() below.
2626*1c60b9acSAndroid Build Coastguard Worker */
2627*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s: setting DEF_ACT from 0x%x: %p\n", __func__,
2628*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi), (int)wsi->wsistate, wsi->buflist);
2629*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_DEFERRING_ACTION);
2630*1c60b9acSAndroid Build Coastguard Worker wsi->http.tx_content_length = 0;
2631*1c60b9acSAndroid Build Coastguard Worker wsi->http.tx_content_remain = 0;
2632*1c60b9acSAndroid Build Coastguard Worker wsi->hdr_parsing_completed = 0;
2633*1c60b9acSAndroid Build Coastguard Worker wsi->sending_chunked = 0;
2634*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_ACCESS_LOG
2635*1c60b9acSAndroid Build Coastguard Worker wsi->http.access_log.sent = 0;
2636*1c60b9acSAndroid Build Coastguard Worker #endif
2637*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS) && (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
2638*1c60b9acSAndroid Build Coastguard Worker if (lwsi_role_http(wsi) && lwsi_role_server(wsi) &&
2639*1c60b9acSAndroid Build Coastguard Worker wsi->http.fop_fd != NULL)
2640*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&wsi->http.fop_fd);
2641*1c60b9acSAndroid Build Coastguard Worker #endif
2642*1c60b9acSAndroid Build Coastguard Worker
2643*1c60b9acSAndroid Build Coastguard Worker n = NO_PENDING_TIMEOUT;
2644*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->keepalive_timeout)
2645*1c60b9acSAndroid Build Coastguard Worker n = PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE;
2646*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, (enum pending_timeout)n, wsi->a.vhost->keepalive_timeout);
2647*1c60b9acSAndroid Build Coastguard Worker
2648*1c60b9acSAndroid Build Coastguard Worker /*
2649*1c60b9acSAndroid Build Coastguard Worker * We already know we are on http1.1 / keepalive and the next thing
2650*1c60b9acSAndroid Build Coastguard Worker * coming will be another header set.
2651*1c60b9acSAndroid Build Coastguard Worker *
2652*1c60b9acSAndroid Build Coastguard Worker * If there is no pending rx and we still have the ah, drop it and
2653*1c60b9acSAndroid Build Coastguard Worker * reacquire a new ah when the new headers start to arrive. (Otherwise
2654*1c60b9acSAndroid Build Coastguard Worker * we needlessly hog an ah indefinitely.)
2655*1c60b9acSAndroid Build Coastguard Worker *
2656*1c60b9acSAndroid Build Coastguard Worker * However if there is pending rx and we know from the keepalive state
2657*1c60b9acSAndroid Build Coastguard Worker * that is already at least the start of another header set, simply
2658*1c60b9acSAndroid Build Coastguard Worker * reset the existing header table and keep it.
2659*1c60b9acSAndroid Build Coastguard Worker */
2660*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.ah) {
2661*1c60b9acSAndroid Build Coastguard Worker // lws_buflist_describe(&wsi->buflist, wsi, __func__);
2662*1c60b9acSAndroid Build Coastguard Worker if (!lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
2663*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s: nothing in buflist, detaching ah\n",
2664*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(wsi));
2665*1c60b9acSAndroid Build Coastguard Worker lws_header_table_detach(wsi, 1);
2666*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_TLS
2667*1c60b9acSAndroid Build Coastguard Worker /*
2668*1c60b9acSAndroid Build Coastguard Worker * additionally... if we are hogging an SSL instance
2669*1c60b9acSAndroid Build Coastguard Worker * with no pending pipelined headers (or ah now), and
2670*1c60b9acSAndroid Build Coastguard Worker * SSL is scarce, drop this connection without waiting
2671*1c60b9acSAndroid Build Coastguard Worker */
2672*1c60b9acSAndroid Build Coastguard Worker
2673*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.vhost->tls.use_ssl &&
2674*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->simultaneous_ssl_restriction &&
2675*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->simultaneous_ssl ==
2676*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->simultaneous_ssl_restriction) {
2677*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: simultaneous_ssl_restriction\n",
2678*1c60b9acSAndroid Build Coastguard Worker __func__);
2679*1c60b9acSAndroid Build Coastguard Worker return 1;
2680*1c60b9acSAndroid Build Coastguard Worker }
2681*1c60b9acSAndroid Build Coastguard Worker #endif
2682*1c60b9acSAndroid Build Coastguard Worker } else {
2683*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: resetting/keeping ah as pipeline\n",
2684*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(wsi));
2685*1c60b9acSAndroid Build Coastguard Worker lws_header_table_reset(wsi, 0);
2686*1c60b9acSAndroid Build Coastguard Worker /*
2687*1c60b9acSAndroid Build Coastguard Worker * If we kept the ah, we should restrict the amount
2688*1c60b9acSAndroid Build Coastguard Worker * of time we are willing to keep it. Otherwise it
2689*1c60b9acSAndroid Build Coastguard Worker * will be bound the whole time the connection remains
2690*1c60b9acSAndroid Build Coastguard Worker * open.
2691*1c60b9acSAndroid Build Coastguard Worker */
2692*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, PENDING_TIMEOUT_HOLDING_AH,
2693*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->keepalive_timeout);
2694*1c60b9acSAndroid Build Coastguard Worker }
2695*1c60b9acSAndroid Build Coastguard Worker /* If we're (re)starting on headers, need other implied init */
2696*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.ah)
2697*1c60b9acSAndroid Build Coastguard Worker wsi->http.ah->ues = URIES_IDLE;
2698*1c60b9acSAndroid Build Coastguard Worker
2699*1c60b9acSAndroid Build Coastguard Worker //lwsi_set_state(wsi, LRS_ESTABLISHED); // !!!
2700*1c60b9acSAndroid Build Coastguard Worker } else
2701*1c60b9acSAndroid Build Coastguard Worker if (lws_buflist_next_segment_len(&wsi->buflist, NULL))
2702*1c60b9acSAndroid Build Coastguard Worker if (lws_header_table_attach(wsi, 0))
2703*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("acquired ah\n");
2704*1c60b9acSAndroid Build Coastguard Worker
2705*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s: keep-alive await new transaction (state 0x%x)\n",
2706*1c60b9acSAndroid Build Coastguard Worker __func__, lws_wsi_tag(wsi), (int)wsi->wsistate);
2707*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
2708*1c60b9acSAndroid Build Coastguard Worker
2709*1c60b9acSAndroid Build Coastguard Worker return 0;
2710*1c60b9acSAndroid Build Coastguard Worker }
2711*1c60b9acSAndroid Build Coastguard Worker
2712*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
2713*1c60b9acSAndroid Build Coastguard Worker int
lws_serve_http_file(struct lws * wsi,const char * file,const char * content_type,const char * other_headers,int other_headers_len)2714*1c60b9acSAndroid Build Coastguard Worker lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
2715*1c60b9acSAndroid Build Coastguard Worker const char *other_headers, int other_headers_len)
2716*1c60b9acSAndroid Build Coastguard Worker {
2717*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = lws_get_context(wsi);
2718*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
2719*1c60b9acSAndroid Build Coastguard Worker unsigned char *response = pt->serv_buf + LWS_PRE;
2720*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
2721*1c60b9acSAndroid Build Coastguard Worker struct lws_range_parsing *rp = &wsi->http.range;
2722*1c60b9acSAndroid Build Coastguard Worker #endif
2723*1c60b9acSAndroid Build Coastguard Worker int ret = 0, cclen = 8, n = HTTP_STATUS_OK;
2724*1c60b9acSAndroid Build Coastguard Worker char cache_control[50], *cc = "no-store";
2725*1c60b9acSAndroid Build Coastguard Worker lws_fop_flags_t fflags = LWS_O_RDONLY;
2726*1c60b9acSAndroid Build Coastguard Worker const struct lws_plat_file_ops *fops;
2727*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t total_content_length;
2728*1c60b9acSAndroid Build Coastguard Worker unsigned char *p = response;
2729*1c60b9acSAndroid Build Coastguard Worker unsigned char *end = p + context->pt_serv_buf_size - LWS_PRE;
2730*1c60b9acSAndroid Build Coastguard Worker const char *vpath;
2731*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
2732*1c60b9acSAndroid Build Coastguard Worker int ranges;
2733*1c60b9acSAndroid Build Coastguard Worker #endif
2734*1c60b9acSAndroid Build Coastguard Worker
2735*1c60b9acSAndroid Build Coastguard Worker if (wsi->handling_404)
2736*1c60b9acSAndroid Build Coastguard Worker n = HTTP_STATUS_NOT_FOUND;
2737*1c60b9acSAndroid Build Coastguard Worker
2738*1c60b9acSAndroid Build Coastguard Worker /*
2739*1c60b9acSAndroid Build Coastguard Worker * We either call the platform fops .open with first arg platform fops,
2740*1c60b9acSAndroid Build Coastguard Worker * or we call fops_zip .open with first arg platform fops, and fops_zip
2741*1c60b9acSAndroid Build Coastguard Worker * open will decide whether to switch to fops_zip or stay with fops_def.
2742*1c60b9acSAndroid Build Coastguard Worker *
2743*1c60b9acSAndroid Build Coastguard Worker * If wsi->http.fop_fd is already set, the caller already opened it
2744*1c60b9acSAndroid Build Coastguard Worker */
2745*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.fop_fd) {
2746*1c60b9acSAndroid Build Coastguard Worker fops = lws_vfs_select_fops(wsi->a.context->fops, file, &vpath);
2747*1c60b9acSAndroid Build Coastguard Worker fflags |= lws_vfs_prepare_flags(wsi);
2748*1c60b9acSAndroid Build Coastguard Worker wsi->http.fop_fd = fops->LWS_FOP_OPEN(wsi->a.context->fops,
2749*1c60b9acSAndroid Build Coastguard Worker file, vpath, &fflags);
2750*1c60b9acSAndroid Build Coastguard Worker if (!wsi->http.fop_fd) {
2751*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: Unable to open: '%s': errno %d\n",
2752*1c60b9acSAndroid Build Coastguard Worker __func__, file, errno);
2753*1c60b9acSAndroid Build Coastguard Worker if (lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND,
2754*1c60b9acSAndroid Build Coastguard Worker NULL))
2755*1c60b9acSAndroid Build Coastguard Worker return -1;
2756*1c60b9acSAndroid Build Coastguard Worker return !wsi->mux_substream;
2757*1c60b9acSAndroid Build Coastguard Worker }
2758*1c60b9acSAndroid Build Coastguard Worker }
2759*1c60b9acSAndroid Build Coastguard Worker
2760*1c60b9acSAndroid Build Coastguard Worker /*
2761*1c60b9acSAndroid Build Coastguard Worker * Caution... wsi->http.fop_fd is live from here
2762*1c60b9acSAndroid Build Coastguard Worker */
2763*1c60b9acSAndroid Build Coastguard Worker
2764*1c60b9acSAndroid Build Coastguard Worker wsi->http.filelen = lws_vfs_get_length(wsi->http.fop_fd);
2765*1c60b9acSAndroid Build Coastguard Worker total_content_length = wsi->http.filelen;
2766*1c60b9acSAndroid Build Coastguard Worker
2767*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
2768*1c60b9acSAndroid Build Coastguard Worker ranges = lws_ranges_init(wsi, rp, wsi->http.filelen);
2769*1c60b9acSAndroid Build Coastguard Worker
2770*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("Range count %d\n", ranges);
2771*1c60b9acSAndroid Build Coastguard Worker /*
2772*1c60b9acSAndroid Build Coastguard Worker * no ranges -> 200;
2773*1c60b9acSAndroid Build Coastguard Worker * 1 range -> 206 + Content-Type: normal; Content-Range;
2774*1c60b9acSAndroid Build Coastguard Worker * more -> 206 + Content-Type: multipart/byteranges
2775*1c60b9acSAndroid Build Coastguard Worker * Repeat the true Content-Type in each multipart header
2776*1c60b9acSAndroid Build Coastguard Worker * along with Content-Range
2777*1c60b9acSAndroid Build Coastguard Worker */
2778*1c60b9acSAndroid Build Coastguard Worker if (ranges < 0) {
2779*1c60b9acSAndroid Build Coastguard Worker /* it means he expressed a range in Range:, but it was illegal */
2780*1c60b9acSAndroid Build Coastguard Worker lws_return_http_status(wsi,
2781*1c60b9acSAndroid Build Coastguard Worker HTTP_STATUS_REQ_RANGE_NOT_SATISFIABLE, NULL);
2782*1c60b9acSAndroid Build Coastguard Worker if (lws_http_transaction_completed(wsi))
2783*1c60b9acSAndroid Build Coastguard Worker goto bail; /* <0 means just hang up */
2784*1c60b9acSAndroid Build Coastguard Worker
2785*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&wsi->http.fop_fd);
2786*1c60b9acSAndroid Build Coastguard Worker
2787*1c60b9acSAndroid Build Coastguard Worker return 0; /* == 0 means we did the transaction complete */
2788*1c60b9acSAndroid Build Coastguard Worker }
2789*1c60b9acSAndroid Build Coastguard Worker if (ranges)
2790*1c60b9acSAndroid Build Coastguard Worker n = HTTP_STATUS_PARTIAL_CONTENT;
2791*1c60b9acSAndroid Build Coastguard Worker #endif
2792*1c60b9acSAndroid Build Coastguard Worker
2793*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_status(wsi, (unsigned int)n, &p, end))
2794*1c60b9acSAndroid Build Coastguard Worker goto bail;
2795*1c60b9acSAndroid Build Coastguard Worker
2796*1c60b9acSAndroid Build Coastguard Worker if ((wsi->http.fop_fd->flags & (LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP |
2797*1c60b9acSAndroid Build Coastguard Worker LWS_FOP_FLAG_COMPR_IS_GZIP)) ==
2798*1c60b9acSAndroid Build Coastguard Worker (LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP | LWS_FOP_FLAG_COMPR_IS_GZIP)) {
2799*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
2800*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_ENCODING,
2801*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"gzip", 4, &p, end))
2802*1c60b9acSAndroid Build Coastguard Worker goto bail;
2803*1c60b9acSAndroid Build Coastguard Worker lwsl_info("file is being provided in gzip\n");
2804*1c60b9acSAndroid Build Coastguard Worker }
2805*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
2806*1c60b9acSAndroid Build Coastguard Worker else {
2807*1c60b9acSAndroid Build Coastguard Worker /*
2808*1c60b9acSAndroid Build Coastguard Worker * if we know its very compressible, and we can use
2809*1c60b9acSAndroid Build Coastguard Worker * compression, then use the most preferred compression
2810*1c60b9acSAndroid Build Coastguard Worker * method that the client said he will accept
2811*1c60b9acSAndroid Build Coastguard Worker */
2812*1c60b9acSAndroid Build Coastguard Worker
2813*1c60b9acSAndroid Build Coastguard Worker if (!wsi->interpreting && (
2814*1c60b9acSAndroid Build Coastguard Worker !strncmp(content_type, "text/", 5) ||
2815*1c60b9acSAndroid Build Coastguard Worker !strcmp(content_type, "application/javascript") ||
2816*1c60b9acSAndroid Build Coastguard Worker !strcmp(content_type, "image/svg+xml")))
2817*1c60b9acSAndroid Build Coastguard Worker lws_http_compression_apply(wsi, NULL, &p, end, 0);
2818*1c60b9acSAndroid Build Coastguard Worker }
2819*1c60b9acSAndroid Build Coastguard Worker #endif
2820*1c60b9acSAndroid Build Coastguard Worker
2821*1c60b9acSAndroid Build Coastguard Worker if (
2822*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
2823*1c60b9acSAndroid Build Coastguard Worker ranges < 2 &&
2824*1c60b9acSAndroid Build Coastguard Worker #endif
2825*1c60b9acSAndroid Build Coastguard Worker content_type && content_type[0])
2826*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
2827*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_TYPE,
2828*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)content_type,
2829*1c60b9acSAndroid Build Coastguard Worker (int)strlen(content_type),
2830*1c60b9acSAndroid Build Coastguard Worker &p, end))
2831*1c60b9acSAndroid Build Coastguard Worker goto bail;
2832*1c60b9acSAndroid Build Coastguard Worker
2833*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
2834*1c60b9acSAndroid Build Coastguard Worker if (ranges >= 2) { /* multipart byteranges */
2835*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(wsi->http.multipart_content_type, content_type,
2836*1c60b9acSAndroid Build Coastguard Worker sizeof(wsi->http.multipart_content_type));
2837*1c60b9acSAndroid Build Coastguard Worker
2838*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
2839*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_TYPE,
2840*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)
2841*1c60b9acSAndroid Build Coastguard Worker "multipart/byteranges; "
2842*1c60b9acSAndroid Build Coastguard Worker "boundary=_lws",
2843*1c60b9acSAndroid Build Coastguard Worker 20, &p, end))
2844*1c60b9acSAndroid Build Coastguard Worker goto bail;
2845*1c60b9acSAndroid Build Coastguard Worker
2846*1c60b9acSAndroid Build Coastguard Worker /*
2847*1c60b9acSAndroid Build Coastguard Worker * our overall content length has to include
2848*1c60b9acSAndroid Build Coastguard Worker *
2849*1c60b9acSAndroid Build Coastguard Worker * - (n + 1) x "_lws\r\n"
2850*1c60b9acSAndroid Build Coastguard Worker * - n x Content-Type: xxx/xxx\r\n
2851*1c60b9acSAndroid Build Coastguard Worker * - n x Content-Range: bytes xxx-yyy/zzz\r\n
2852*1c60b9acSAndroid Build Coastguard Worker * - n x /r/n
2853*1c60b9acSAndroid Build Coastguard Worker * - the actual payloads (aggregated in rp->agg)
2854*1c60b9acSAndroid Build Coastguard Worker *
2855*1c60b9acSAndroid Build Coastguard Worker * Precompute it for the main response header
2856*1c60b9acSAndroid Build Coastguard Worker */
2857*1c60b9acSAndroid Build Coastguard Worker
2858*1c60b9acSAndroid Build Coastguard Worker total_content_length = (lws_filepos_t)rp->agg +
2859*1c60b9acSAndroid Build Coastguard Worker 6 /* final _lws\r\n */;
2860*1c60b9acSAndroid Build Coastguard Worker
2861*1c60b9acSAndroid Build Coastguard Worker lws_ranges_reset(rp);
2862*1c60b9acSAndroid Build Coastguard Worker while (lws_ranges_next(rp)) {
2863*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf(cache_control, sizeof(cache_control),
2864*1c60b9acSAndroid Build Coastguard Worker "bytes %llu-%llu/%llu",
2865*1c60b9acSAndroid Build Coastguard Worker rp->start, rp->end, rp->extent);
2866*1c60b9acSAndroid Build Coastguard Worker
2867*1c60b9acSAndroid Build Coastguard Worker total_content_length = total_content_length +
2868*1c60b9acSAndroid Build Coastguard Worker (lws_filepos_t)(
2869*1c60b9acSAndroid Build Coastguard Worker 6 /* header _lws\r\n */ +
2870*1c60b9acSAndroid Build Coastguard Worker /* Content-Type: xxx/xxx\r\n */
2871*1c60b9acSAndroid Build Coastguard Worker 14 + (int)strlen(content_type) + 2 +
2872*1c60b9acSAndroid Build Coastguard Worker /* Content-Range: xxxx\r\n */
2873*1c60b9acSAndroid Build Coastguard Worker 15 + n + 2 +
2874*1c60b9acSAndroid Build Coastguard Worker 2); /* /r/n */
2875*1c60b9acSAndroid Build Coastguard Worker }
2876*1c60b9acSAndroid Build Coastguard Worker
2877*1c60b9acSAndroid Build Coastguard Worker lws_ranges_reset(rp);
2878*1c60b9acSAndroid Build Coastguard Worker lws_ranges_next(rp);
2879*1c60b9acSAndroid Build Coastguard Worker }
2880*1c60b9acSAndroid Build Coastguard Worker
2881*1c60b9acSAndroid Build Coastguard Worker if (ranges == 1) {
2882*1c60b9acSAndroid Build Coastguard Worker total_content_length = (lws_filepos_t)rp->agg;
2883*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf(cache_control, sizeof(cache_control),
2884*1c60b9acSAndroid Build Coastguard Worker "bytes %llu-%llu/%llu",
2885*1c60b9acSAndroid Build Coastguard Worker rp->start, rp->end, rp->extent);
2886*1c60b9acSAndroid Build Coastguard Worker
2887*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
2888*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CONTENT_RANGE,
2889*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)cache_control,
2890*1c60b9acSAndroid Build Coastguard Worker n, &p, end))
2891*1c60b9acSAndroid Build Coastguard Worker goto bail;
2892*1c60b9acSAndroid Build Coastguard Worker }
2893*1c60b9acSAndroid Build Coastguard Worker
2894*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.inside = 0;
2895*1c60b9acSAndroid Build Coastguard Worker
2896*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ACCEPT_RANGES,
2897*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"bytes", 5, &p, end))
2898*1c60b9acSAndroid Build Coastguard Worker goto bail;
2899*1c60b9acSAndroid Build Coastguard Worker #endif
2900*1c60b9acSAndroid Build Coastguard Worker
2901*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mux_substream) {
2902*1c60b9acSAndroid Build Coastguard Worker /* for http/1.1 ... */
2903*1c60b9acSAndroid Build Coastguard Worker if (!wsi->sending_chunked
2904*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
2905*1c60b9acSAndroid Build Coastguard Worker && !wsi->http.lcs
2906*1c60b9acSAndroid Build Coastguard Worker #endif
2907*1c60b9acSAndroid Build Coastguard Worker ) {
2908*1c60b9acSAndroid Build Coastguard Worker /* ... if not already using chunked and not using an
2909*1c60b9acSAndroid Build Coastguard Worker * http compression translation, then send the naive
2910*1c60b9acSAndroid Build Coastguard Worker * content length
2911*1c60b9acSAndroid Build Coastguard Worker */
2912*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_content_length(wsi,
2913*1c60b9acSAndroid Build Coastguard Worker total_content_length, &p, end))
2914*1c60b9acSAndroid Build Coastguard Worker goto bail;
2915*1c60b9acSAndroid Build Coastguard Worker } else {
2916*1c60b9acSAndroid Build Coastguard Worker
2917*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
2918*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.lcs) {
2919*1c60b9acSAndroid Build Coastguard Worker
2920*1c60b9acSAndroid Build Coastguard Worker /* ...otherwise, for http 1 it must go chunked.
2921*1c60b9acSAndroid Build Coastguard Worker * For the compression case, the reason is we
2922*1c60b9acSAndroid Build Coastguard Worker * compress on the fly and do not know the
2923*1c60b9acSAndroid Build Coastguard Worker * compressed content-length until it has all
2924*1c60b9acSAndroid Build Coastguard Worker * been sent. Http/1.1 pipelining must be able
2925*1c60b9acSAndroid Build Coastguard Worker * to know where the transaction boundaries are
2926*1c60b9acSAndroid Build Coastguard Worker * ... so chunking...
2927*1c60b9acSAndroid Build Coastguard Worker */
2928*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
2929*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_TRANSFER_ENCODING,
2930*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)"chunked", 7,
2931*1c60b9acSAndroid Build Coastguard Worker &p, end))
2932*1c60b9acSAndroid Build Coastguard Worker goto bail;
2933*1c60b9acSAndroid Build Coastguard Worker
2934*1c60b9acSAndroid Build Coastguard Worker /*
2935*1c60b9acSAndroid Build Coastguard Worker * ...this is fun, isn't it :-) For h1 that is
2936*1c60b9acSAndroid Build Coastguard Worker * using an http compression translation, the
2937*1c60b9acSAndroid Build Coastguard Worker * compressor must chunk its output privately.
2938*1c60b9acSAndroid Build Coastguard Worker *
2939*1c60b9acSAndroid Build Coastguard Worker * h2 doesn't need (or support) any of this
2940*1c60b9acSAndroid Build Coastguard Worker * crap.
2941*1c60b9acSAndroid Build Coastguard Worker */
2942*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("setting chunking\n");
2943*1c60b9acSAndroid Build Coastguard Worker wsi->http.comp_ctx.chunking = 1;
2944*1c60b9acSAndroid Build Coastguard Worker }
2945*1c60b9acSAndroid Build Coastguard Worker #endif
2946*1c60b9acSAndroid Build Coastguard Worker }
2947*1c60b9acSAndroid Build Coastguard Worker }
2948*1c60b9acSAndroid Build Coastguard Worker
2949*1c60b9acSAndroid Build Coastguard Worker if (wsi->cache_secs && wsi->cache_reuse) {
2950*1c60b9acSAndroid Build Coastguard Worker if (!wsi->cache_revalidate) {
2951*1c60b9acSAndroid Build Coastguard Worker cc = cache_control;
2952*1c60b9acSAndroid Build Coastguard Worker cclen = sprintf(cache_control, "%s, max-age=%u",
2953*1c60b9acSAndroid Build Coastguard Worker intermediates[wsi->cache_intermediaries],
2954*1c60b9acSAndroid Build Coastguard Worker wsi->cache_secs);
2955*1c60b9acSAndroid Build Coastguard Worker } else {
2956*1c60b9acSAndroid Build Coastguard Worker cc = cache_control;
2957*1c60b9acSAndroid Build Coastguard Worker cclen = sprintf(cache_control,
2958*1c60b9acSAndroid Build Coastguard Worker "must-revalidate, %s, max-age=%u",
2959*1c60b9acSAndroid Build Coastguard Worker intermediates[wsi->cache_intermediaries],
2960*1c60b9acSAndroid Build Coastguard Worker wsi->cache_secs);
2961*1c60b9acSAndroid Build Coastguard Worker
2962*1c60b9acSAndroid Build Coastguard Worker }
2963*1c60b9acSAndroid Build Coastguard Worker }
2964*1c60b9acSAndroid Build Coastguard Worker
2965*1c60b9acSAndroid Build Coastguard Worker /* Only add cache control if its not specified by any other_headers. */
2966*1c60b9acSAndroid Build Coastguard Worker if (!other_headers ||
2967*1c60b9acSAndroid Build Coastguard Worker (!strstr(other_headers, "cache-control") &&
2968*1c60b9acSAndroid Build Coastguard Worker !strstr(other_headers, "Cache-Control"))) {
2969*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi,
2970*1c60b9acSAndroid Build Coastguard Worker WSI_TOKEN_HTTP_CACHE_CONTROL,
2971*1c60b9acSAndroid Build Coastguard Worker (unsigned char *)cc, cclen, &p, end))
2972*1c60b9acSAndroid Build Coastguard Worker goto bail;
2973*1c60b9acSAndroid Build Coastguard Worker }
2974*1c60b9acSAndroid Build Coastguard Worker
2975*1c60b9acSAndroid Build Coastguard Worker if (other_headers) {
2976*1c60b9acSAndroid Build Coastguard Worker if ((end - p) < other_headers_len)
2977*1c60b9acSAndroid Build Coastguard Worker goto bail;
2978*1c60b9acSAndroid Build Coastguard Worker memcpy(p, other_headers, (unsigned int)other_headers_len);
2979*1c60b9acSAndroid Build Coastguard Worker p += other_headers_len;
2980*1c60b9acSAndroid Build Coastguard Worker }
2981*1c60b9acSAndroid Build Coastguard Worker
2982*1c60b9acSAndroid Build Coastguard Worker if (lws_finalize_http_header(wsi, &p, end))
2983*1c60b9acSAndroid Build Coastguard Worker goto bail;
2984*1c60b9acSAndroid Build Coastguard Worker
2985*1c60b9acSAndroid Build Coastguard Worker ret = lws_write(wsi, response, lws_ptr_diff_size_t(p, response), LWS_WRITE_HTTP_HEADERS);
2986*1c60b9acSAndroid Build Coastguard Worker if (ret != (p - response)) {
2987*1c60b9acSAndroid Build Coastguard Worker lwsl_err("_write returned %d from %ld\n", ret,
2988*1c60b9acSAndroid Build Coastguard Worker (long)(p - response));
2989*1c60b9acSAndroid Build Coastguard Worker goto bail;
2990*1c60b9acSAndroid Build Coastguard Worker }
2991*1c60b9acSAndroid Build Coastguard Worker
2992*1c60b9acSAndroid Build Coastguard Worker wsi->http.filepos = 0;
2993*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_ISSUING_FILE);
2994*1c60b9acSAndroid Build Coastguard Worker
2995*1c60b9acSAndroid Build Coastguard Worker if (lws_hdr_total_length(wsi, WSI_TOKEN_HEAD_URI)) {
2996*1c60b9acSAndroid Build Coastguard Worker /* we do not emit the body */
2997*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&wsi->http.fop_fd);
2998*1c60b9acSAndroid Build Coastguard Worker if (lws_http_transaction_completed(wsi))
2999*1c60b9acSAndroid Build Coastguard Worker goto bail;
3000*1c60b9acSAndroid Build Coastguard Worker
3001*1c60b9acSAndroid Build Coastguard Worker return 0;
3002*1c60b9acSAndroid Build Coastguard Worker }
3003*1c60b9acSAndroid Build Coastguard Worker
3004*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
3005*1c60b9acSAndroid Build Coastguard Worker
3006*1c60b9acSAndroid Build Coastguard Worker return 0;
3007*1c60b9acSAndroid Build Coastguard Worker
3008*1c60b9acSAndroid Build Coastguard Worker bail:
3009*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&wsi->http.fop_fd);
3010*1c60b9acSAndroid Build Coastguard Worker
3011*1c60b9acSAndroid Build Coastguard Worker return -1;
3012*1c60b9acSAndroid Build Coastguard Worker }
3013*1c60b9acSAndroid Build Coastguard Worker #endif
3014*1c60b9acSAndroid Build Coastguard Worker
3015*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
3016*1c60b9acSAndroid Build Coastguard Worker
lws_serve_http_file_fragment(struct lws * wsi)3017*1c60b9acSAndroid Build Coastguard Worker int lws_serve_http_file_fragment(struct lws *wsi)
3018*1c60b9acSAndroid Build Coastguard Worker {
3019*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = wsi->a.context;
3020*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
3021*1c60b9acSAndroid Build Coastguard Worker struct lws_process_html_args args;
3022*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t amount, poss;
3023*1c60b9acSAndroid Build Coastguard Worker unsigned char *p, *pstart;
3024*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
3025*1c60b9acSAndroid Build Coastguard Worker unsigned char finished = 0;
3026*1c60b9acSAndroid Build Coastguard Worker #endif
3027*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
3028*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi;
3029*1c60b9acSAndroid Build Coastguard Worker #endif
3030*1c60b9acSAndroid Build Coastguard Worker int n, m;
3031*1c60b9acSAndroid Build Coastguard Worker
3032*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("wsi->mux_substream %d\n", wsi->mux_substream);
3033*1c60b9acSAndroid Build Coastguard Worker
3034*1c60b9acSAndroid Build Coastguard Worker do {
3035*1c60b9acSAndroid Build Coastguard Worker
3036*1c60b9acSAndroid Build Coastguard Worker /* priority 1: buffered output */
3037*1c60b9acSAndroid Build Coastguard Worker
3038*1c60b9acSAndroid Build Coastguard Worker if (lws_has_buffered_out(wsi)) {
3039*1c60b9acSAndroid Build Coastguard Worker if (lws_issue_raw(wsi, NULL, 0) < 0) {
3040*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: closing\n", __func__);
3041*1c60b9acSAndroid Build Coastguard Worker goto file_had_it;
3042*1c60b9acSAndroid Build Coastguard Worker }
3043*1c60b9acSAndroid Build Coastguard Worker break;
3044*1c60b9acSAndroid Build Coastguard Worker }
3045*1c60b9acSAndroid Build Coastguard Worker
3046*1c60b9acSAndroid Build Coastguard Worker /* priority 2: buffered pre-compression-transform */
3047*1c60b9acSAndroid Build Coastguard Worker
3048*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
3049*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.comp_ctx.buflist_comp ||
3050*1c60b9acSAndroid Build Coastguard Worker wsi->http.comp_ctx.may_have_more) {
3051*1c60b9acSAndroid Build Coastguard Worker enum lws_write_protocol wp = LWS_WRITE_HTTP;
3052*1c60b9acSAndroid Build Coastguard Worker
3053*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: completing comp partial (buflist %p, may %d)\n",
3054*1c60b9acSAndroid Build Coastguard Worker __func__, wsi->http.comp_ctx.buflist_comp,
3055*1c60b9acSAndroid Build Coastguard Worker wsi->http.comp_ctx.may_have_more);
3056*1c60b9acSAndroid Build Coastguard Worker
3057*1c60b9acSAndroid Build Coastguard Worker if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol) &&
3058*1c60b9acSAndroid Build Coastguard Worker lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol).
3059*1c60b9acSAndroid Build Coastguard Worker write_role_protocol(wsi, NULL, 0, &wp) < 0) {
3060*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s signalling to close\n", __func__);
3061*1c60b9acSAndroid Build Coastguard Worker goto file_had_it;
3062*1c60b9acSAndroid Build Coastguard Worker }
3063*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
3064*1c60b9acSAndroid Build Coastguard Worker
3065*1c60b9acSAndroid Build Coastguard Worker break;
3066*1c60b9acSAndroid Build Coastguard Worker }
3067*1c60b9acSAndroid Build Coastguard Worker #endif
3068*1c60b9acSAndroid Build Coastguard Worker
3069*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.filepos == wsi->http.filelen)
3070*1c60b9acSAndroid Build Coastguard Worker goto all_sent;
3071*1c60b9acSAndroid Build Coastguard Worker
3072*1c60b9acSAndroid Build Coastguard Worker n = 0;
3073*1c60b9acSAndroid Build Coastguard Worker p = pstart = pt->serv_buf + LWS_H2_FRAME_HEADER_LENGTH;
3074*1c60b9acSAndroid Build Coastguard Worker
3075*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
3076*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.range.count_ranges && !wsi->http.range.inside) {
3077*1c60b9acSAndroid Build Coastguard Worker
3078*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: doing range start %llu\n", __func__,
3079*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.start);
3080*1c60b9acSAndroid Build Coastguard Worker
3081*1c60b9acSAndroid Build Coastguard Worker if ((long long)lws_vfs_file_seek_cur(wsi->http.fop_fd,
3082*1c60b9acSAndroid Build Coastguard Worker (lws_fileofs_t)wsi->http.range.start -
3083*1c60b9acSAndroid Build Coastguard Worker (lws_fileofs_t)wsi->http.filepos) < 0)
3084*1c60b9acSAndroid Build Coastguard Worker goto file_had_it;
3085*1c60b9acSAndroid Build Coastguard Worker
3086*1c60b9acSAndroid Build Coastguard Worker wsi->http.filepos = wsi->http.range.start;
3087*1c60b9acSAndroid Build Coastguard Worker
3088*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.range.count_ranges > 1) {
3089*1c60b9acSAndroid Build Coastguard Worker n = lws_snprintf((char *)p,
3090*1c60b9acSAndroid Build Coastguard Worker context->pt_serv_buf_size -
3091*1c60b9acSAndroid Build Coastguard Worker LWS_H2_FRAME_HEADER_LENGTH,
3092*1c60b9acSAndroid Build Coastguard Worker "_lws\x0d\x0a"
3093*1c60b9acSAndroid Build Coastguard Worker "Content-Type: %s\x0d\x0a"
3094*1c60b9acSAndroid Build Coastguard Worker "Content-Range: bytes "
3095*1c60b9acSAndroid Build Coastguard Worker "%llu-%llu/%llu\x0d\x0a"
3096*1c60b9acSAndroid Build Coastguard Worker "\x0d\x0a",
3097*1c60b9acSAndroid Build Coastguard Worker wsi->http.multipart_content_type,
3098*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.start,
3099*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.end,
3100*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.extent);
3101*1c60b9acSAndroid Build Coastguard Worker p += n;
3102*1c60b9acSAndroid Build Coastguard Worker }
3103*1c60b9acSAndroid Build Coastguard Worker
3104*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.budget = wsi->http.range.end -
3105*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.start + 1;
3106*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.inside = 1;
3107*1c60b9acSAndroid Build Coastguard Worker }
3108*1c60b9acSAndroid Build Coastguard Worker #endif
3109*1c60b9acSAndroid Build Coastguard Worker
3110*1c60b9acSAndroid Build Coastguard Worker poss = context->pt_serv_buf_size;
3111*1c60b9acSAndroid Build Coastguard Worker
3112*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
3113*1c60b9acSAndroid Build Coastguard Worker /*
3114*1c60b9acSAndroid Build Coastguard Worker * If it's h2, restrict any lump that we are sending to the
3115*1c60b9acSAndroid Build Coastguard Worker * max h2 frame size the peer indicated he could handle in
3116*1c60b9acSAndroid Build Coastguard Worker * his SETTINGS
3117*1c60b9acSAndroid Build Coastguard Worker */
3118*1c60b9acSAndroid Build Coastguard Worker nwsi = lws_get_network_wsi(wsi);
3119*1c60b9acSAndroid Build Coastguard Worker if (nwsi->h2.h2n &&
3120*1c60b9acSAndroid Build Coastguard Worker poss > (lws_filepos_t)nwsi->h2.h2n->peer_set.s[H2SET_MAX_FRAME_SIZE])
3121*1c60b9acSAndroid Build Coastguard Worker poss = (lws_filepos_t)nwsi->h2.h2n->peer_set.s[H2SET_MAX_FRAME_SIZE];
3122*1c60b9acSAndroid Build Coastguard Worker #endif
3123*1c60b9acSAndroid Build Coastguard Worker poss = poss - (lws_filepos_t)(n + LWS_H2_FRAME_HEADER_LENGTH);
3124*1c60b9acSAndroid Build Coastguard Worker
3125*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.tx_content_length)
3126*1c60b9acSAndroid Build Coastguard Worker if (poss > wsi->http.tx_content_remain)
3127*1c60b9acSAndroid Build Coastguard Worker poss = wsi->http.tx_content_remain;
3128*1c60b9acSAndroid Build Coastguard Worker
3129*1c60b9acSAndroid Build Coastguard Worker /*
3130*1c60b9acSAndroid Build Coastguard Worker * If there is a hint about how much we will do well to send at
3131*1c60b9acSAndroid Build Coastguard Worker * one time, restrict ourselves to only trying to send that.
3132*1c60b9acSAndroid Build Coastguard Worker */
3133*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.protocol->tx_packet_size &&
3134*1c60b9acSAndroid Build Coastguard Worker poss > wsi->a.protocol->tx_packet_size)
3135*1c60b9acSAndroid Build Coastguard Worker poss = wsi->a.protocol->tx_packet_size;
3136*1c60b9acSAndroid Build Coastguard Worker
3137*1c60b9acSAndroid Build Coastguard Worker if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_tx_credit)) {
3138*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t txc = (unsigned int)lws_rops_func_fidx(wsi->role_ops,
3139*1c60b9acSAndroid Build Coastguard Worker LWS_ROPS_tx_credit).
3140*1c60b9acSAndroid Build Coastguard Worker tx_credit(wsi, LWSTXCR_US_TO_PEER, 0);
3141*1c60b9acSAndroid Build Coastguard Worker
3142*1c60b9acSAndroid Build Coastguard Worker if (!txc) {
3143*1c60b9acSAndroid Build Coastguard Worker /*
3144*1c60b9acSAndroid Build Coastguard Worker * We shouldn't've been able to get the
3145*1c60b9acSAndroid Build Coastguard Worker * WRITEABLE if we are skint
3146*1c60b9acSAndroid Build Coastguard Worker */
3147*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: %s: no tx credit\n", __func__,
3148*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi));
3149*1c60b9acSAndroid Build Coastguard Worker
3150*1c60b9acSAndroid Build Coastguard Worker return 0;
3151*1c60b9acSAndroid Build Coastguard Worker }
3152*1c60b9acSAndroid Build Coastguard Worker if (txc < poss)
3153*1c60b9acSAndroid Build Coastguard Worker poss = txc;
3154*1c60b9acSAndroid Build Coastguard Worker
3155*1c60b9acSAndroid Build Coastguard Worker /*
3156*1c60b9acSAndroid Build Coastguard Worker * Tracking consumption of the actual payload amount
3157*1c60b9acSAndroid Build Coastguard Worker * will be handled when the role data frame is sent...
3158*1c60b9acSAndroid Build Coastguard Worker */
3159*1c60b9acSAndroid Build Coastguard Worker }
3160*1c60b9acSAndroid Build Coastguard Worker
3161*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
3162*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.range.count_ranges) {
3163*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.range.count_ranges > 1)
3164*1c60b9acSAndroid Build Coastguard Worker poss -= 7; /* allow for final boundary */
3165*1c60b9acSAndroid Build Coastguard Worker if (poss > wsi->http.range.budget)
3166*1c60b9acSAndroid Build Coastguard Worker poss = wsi->http.range.budget;
3167*1c60b9acSAndroid Build Coastguard Worker }
3168*1c60b9acSAndroid Build Coastguard Worker #endif
3169*1c60b9acSAndroid Build Coastguard Worker if (wsi->sending_chunked) {
3170*1c60b9acSAndroid Build Coastguard Worker /* we need to drop the chunk size in here */
3171*1c60b9acSAndroid Build Coastguard Worker p += 10;
3172*1c60b9acSAndroid Build Coastguard Worker /* allow for the chunk to grow by 128 in translation */
3173*1c60b9acSAndroid Build Coastguard Worker poss -= 10 + 128;
3174*1c60b9acSAndroid Build Coastguard Worker }
3175*1c60b9acSAndroid Build Coastguard Worker
3176*1c60b9acSAndroid Build Coastguard Worker amount = 0;
3177*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_read(wsi->http.fop_fd, &amount, p, poss) < 0)
3178*1c60b9acSAndroid Build Coastguard Worker goto file_had_it; /* caller will close */
3179*1c60b9acSAndroid Build Coastguard Worker
3180*1c60b9acSAndroid Build Coastguard Worker if (wsi->sending_chunked)
3181*1c60b9acSAndroid Build Coastguard Worker n = (int)amount;
3182*1c60b9acSAndroid Build Coastguard Worker else
3183*1c60b9acSAndroid Build Coastguard Worker n = lws_ptr_diff(p, pstart) + (int)amount;
3184*1c60b9acSAndroid Build Coastguard Worker
3185*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: sending %d\n", __func__, n);
3186*1c60b9acSAndroid Build Coastguard Worker
3187*1c60b9acSAndroid Build Coastguard Worker if (n) {
3188*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
3189*1c60b9acSAndroid Build Coastguard Worker (int)context->timeout_secs);
3190*1c60b9acSAndroid Build Coastguard Worker
3191*1c60b9acSAndroid Build Coastguard Worker if (wsi->interpreting) {
3192*1c60b9acSAndroid Build Coastguard Worker args.p = (char *)p;
3193*1c60b9acSAndroid Build Coastguard Worker args.len = n;
3194*1c60b9acSAndroid Build Coastguard Worker args.max_len = (int)(unsigned int)poss + 128;
3195*1c60b9acSAndroid Build Coastguard Worker args.final = wsi->http.filepos + (unsigned int)n ==
3196*1c60b9acSAndroid Build Coastguard Worker wsi->http.filelen;
3197*1c60b9acSAndroid Build Coastguard Worker args.chunked = wsi->sending_chunked;
3198*1c60b9acSAndroid Build Coastguard Worker if (user_callback_handle_rxflow(
3199*1c60b9acSAndroid Build Coastguard Worker wsi->a.vhost->protocols[
3200*1c60b9acSAndroid Build Coastguard Worker (int)wsi->protocol_interpret_idx].callback,
3201*1c60b9acSAndroid Build Coastguard Worker wsi, LWS_CALLBACK_PROCESS_HTML,
3202*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, &args, 0) < 0)
3203*1c60b9acSAndroid Build Coastguard Worker goto file_had_it;
3204*1c60b9acSAndroid Build Coastguard Worker n = args.len;
3205*1c60b9acSAndroid Build Coastguard Worker p = (unsigned char *)args.p;
3206*1c60b9acSAndroid Build Coastguard Worker } else
3207*1c60b9acSAndroid Build Coastguard Worker p = pstart;
3208*1c60b9acSAndroid Build Coastguard Worker
3209*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
3210*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.range.send_ctr + 1 ==
3211*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.count_ranges && // last range
3212*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.count_ranges > 1 && // was 2+ ranges (ie, multipart)
3213*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.budget - amount == 0) {// final part
3214*1c60b9acSAndroid Build Coastguard Worker n += lws_snprintf((char *)pstart + n, 6,
3215*1c60b9acSAndroid Build Coastguard Worker "_lws\x0d\x0a"); // append trailing boundary
3216*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("added trailing boundary\n");
3217*1c60b9acSAndroid Build Coastguard Worker }
3218*1c60b9acSAndroid Build Coastguard Worker #endif
3219*1c60b9acSAndroid Build Coastguard Worker m = lws_write(wsi, p, (unsigned int)n, wsi->http.filepos + amount ==
3220*1c60b9acSAndroid Build Coastguard Worker wsi->http.filelen ?
3221*1c60b9acSAndroid Build Coastguard Worker LWS_WRITE_HTTP_FINAL : LWS_WRITE_HTTP);
3222*1c60b9acSAndroid Build Coastguard Worker if (m < 0)
3223*1c60b9acSAndroid Build Coastguard Worker goto file_had_it;
3224*1c60b9acSAndroid Build Coastguard Worker
3225*1c60b9acSAndroid Build Coastguard Worker wsi->http.filepos += amount;
3226*1c60b9acSAndroid Build Coastguard Worker
3227*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
3228*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.range.count_ranges >= 1) {
3229*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.budget -= amount;
3230*1c60b9acSAndroid Build Coastguard Worker if (wsi->http.range.budget == 0) {
3231*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("range budget exhausted\n");
3232*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.inside = 0;
3233*1c60b9acSAndroid Build Coastguard Worker wsi->http.range.send_ctr++;
3234*1c60b9acSAndroid Build Coastguard Worker
3235*1c60b9acSAndroid Build Coastguard Worker if (lws_ranges_next(&wsi->http.range) < 1) {
3236*1c60b9acSAndroid Build Coastguard Worker finished = 1;
3237*1c60b9acSAndroid Build Coastguard Worker goto all_sent;
3238*1c60b9acSAndroid Build Coastguard Worker }
3239*1c60b9acSAndroid Build Coastguard Worker }
3240*1c60b9acSAndroid Build Coastguard Worker }
3241*1c60b9acSAndroid Build Coastguard Worker #endif
3242*1c60b9acSAndroid Build Coastguard Worker
3243*1c60b9acSAndroid Build Coastguard Worker if (m != n) {
3244*1c60b9acSAndroid Build Coastguard Worker /* adjust for what was not sent */
3245*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_seek_cur(wsi->http.fop_fd,
3246*1c60b9acSAndroid Build Coastguard Worker m - n) ==
3247*1c60b9acSAndroid Build Coastguard Worker (lws_fileofs_t)-1)
3248*1c60b9acSAndroid Build Coastguard Worker goto file_had_it;
3249*1c60b9acSAndroid Build Coastguard Worker }
3250*1c60b9acSAndroid Build Coastguard Worker }
3251*1c60b9acSAndroid Build Coastguard Worker
3252*1c60b9acSAndroid Build Coastguard Worker all_sent:
3253*1c60b9acSAndroid Build Coastguard Worker if ((!lws_has_buffered_out(wsi)
3254*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
3255*1c60b9acSAndroid Build Coastguard Worker && !wsi->http.comp_ctx.buflist_comp &&
3256*1c60b9acSAndroid Build Coastguard Worker !wsi->http.comp_ctx.may_have_more
3257*1c60b9acSAndroid Build Coastguard Worker #endif
3258*1c60b9acSAndroid Build Coastguard Worker ) && (wsi->http.filepos >= wsi->http.filelen
3259*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_RANGES)
3260*1c60b9acSAndroid Build Coastguard Worker || finished)
3261*1c60b9acSAndroid Build Coastguard Worker #else
3262*1c60b9acSAndroid Build Coastguard Worker )
3263*1c60b9acSAndroid Build Coastguard Worker #endif
3264*1c60b9acSAndroid Build Coastguard Worker ) {
3265*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_ESTABLISHED);
3266*1c60b9acSAndroid Build Coastguard Worker /* we might be in keepalive, so close it off here */
3267*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&wsi->http.fop_fd);
3268*1c60b9acSAndroid Build Coastguard Worker
3269*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("file completed\n");
3270*1c60b9acSAndroid Build Coastguard Worker
3271*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.protocol->callback &&
3272*1c60b9acSAndroid Build Coastguard Worker user_callback_handle_rxflow(wsi->a.protocol->callback,
3273*1c60b9acSAndroid Build Coastguard Worker wsi, LWS_CALLBACK_HTTP_FILE_COMPLETION,
3274*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, NULL, 0) < 0) {
3275*1c60b9acSAndroid Build Coastguard Worker /*
3276*1c60b9acSAndroid Build Coastguard Worker * For http/1.x, the choices from
3277*1c60b9acSAndroid Build Coastguard Worker * transaction_completed are either
3278*1c60b9acSAndroid Build Coastguard Worker * 0 to use the connection for pipelined
3279*1c60b9acSAndroid Build Coastguard Worker * or nonzero to hang it up.
3280*1c60b9acSAndroid Build Coastguard Worker *
3281*1c60b9acSAndroid Build Coastguard Worker * However for http/2. while we are
3282*1c60b9acSAndroid Build Coastguard Worker * still interested in hanging up the
3283*1c60b9acSAndroid Build Coastguard Worker * nwsi if there was a network-level
3284*1c60b9acSAndroid Build Coastguard Worker * fatal error, simply completing the
3285*1c60b9acSAndroid Build Coastguard Worker * transaction is a matter of the stream
3286*1c60b9acSAndroid Build Coastguard Worker * state, not the root connection at the
3287*1c60b9acSAndroid Build Coastguard Worker * network level
3288*1c60b9acSAndroid Build Coastguard Worker */
3289*1c60b9acSAndroid Build Coastguard Worker if (wsi->mux_substream)
3290*1c60b9acSAndroid Build Coastguard Worker return 1;
3291*1c60b9acSAndroid Build Coastguard Worker else
3292*1c60b9acSAndroid Build Coastguard Worker return -1;
3293*1c60b9acSAndroid Build Coastguard Worker }
3294*1c60b9acSAndroid Build Coastguard Worker
3295*1c60b9acSAndroid Build Coastguard Worker return 1; /* >0 indicates completed */
3296*1c60b9acSAndroid Build Coastguard Worker }
3297*1c60b9acSAndroid Build Coastguard Worker /*
3298*1c60b9acSAndroid Build Coastguard Worker * while(1) here causes us to spam the whole file contents into
3299*1c60b9acSAndroid Build Coastguard Worker * a hugely bloated output buffer if it ever can't send the
3300*1c60b9acSAndroid Build Coastguard Worker * whole chunk...
3301*1c60b9acSAndroid Build Coastguard Worker */
3302*1c60b9acSAndroid Build Coastguard Worker } while (!lws_send_pipe_choked(wsi));
3303*1c60b9acSAndroid Build Coastguard Worker
3304*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
3305*1c60b9acSAndroid Build Coastguard Worker
3306*1c60b9acSAndroid Build Coastguard Worker return 0; /* indicates further processing must be done */
3307*1c60b9acSAndroid Build Coastguard Worker
3308*1c60b9acSAndroid Build Coastguard Worker file_had_it:
3309*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&wsi->http.fop_fd);
3310*1c60b9acSAndroid Build Coastguard Worker
3311*1c60b9acSAndroid Build Coastguard Worker return -1;
3312*1c60b9acSAndroid Build Coastguard Worker }
3313*1c60b9acSAndroid Build Coastguard Worker
3314*1c60b9acSAndroid Build Coastguard Worker #endif
3315*1c60b9acSAndroid Build Coastguard Worker
3316*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
3317*1c60b9acSAndroid Build Coastguard Worker void
lws_server_get_canonical_hostname(struct lws_context * context,const struct lws_context_creation_info * info)3318*1c60b9acSAndroid Build Coastguard Worker lws_server_get_canonical_hostname(struct lws_context *context,
3319*1c60b9acSAndroid Build Coastguard Worker const struct lws_context_creation_info *info)
3320*1c60b9acSAndroid Build Coastguard Worker {
3321*1c60b9acSAndroid Build Coastguard Worker if (lws_check_opt(info->options,
3322*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME))
3323*1c60b9acSAndroid Build Coastguard Worker return;
3324*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_FREERTOS)
3325*1c60b9acSAndroid Build Coastguard Worker /* find canonical hostname */
3326*1c60b9acSAndroid Build Coastguard Worker if (gethostname((char *)context->canonical_hostname,
3327*1c60b9acSAndroid Build Coastguard Worker sizeof(context->canonical_hostname) - 1))
3328*1c60b9acSAndroid Build Coastguard Worker lws_strncpy((char *)context->canonical_hostname, "unknown",
3329*1c60b9acSAndroid Build Coastguard Worker sizeof(context->canonical_hostname));
3330*1c60b9acSAndroid Build Coastguard Worker
3331*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, " canonical_hostname = %s\n",
3332*1c60b9acSAndroid Build Coastguard Worker context->canonical_hostname);
3333*1c60b9acSAndroid Build Coastguard Worker #else
3334*1c60b9acSAndroid Build Coastguard Worker (void)context;
3335*1c60b9acSAndroid Build Coastguard Worker #endif
3336*1c60b9acSAndroid Build Coastguard Worker }
3337*1c60b9acSAndroid Build Coastguard Worker #endif
3338*1c60b9acSAndroid Build Coastguard Worker
3339*1c60b9acSAndroid Build Coastguard Worker int
lws_chunked_html_process(struct lws_process_html_args * args,struct lws_process_html_state * s)3340*1c60b9acSAndroid Build Coastguard Worker lws_chunked_html_process(struct lws_process_html_args *args,
3341*1c60b9acSAndroid Build Coastguard Worker struct lws_process_html_state *s)
3342*1c60b9acSAndroid Build Coastguard Worker {
3343*1c60b9acSAndroid Build Coastguard Worker char *sp, buffer[32];
3344*1c60b9acSAndroid Build Coastguard Worker const char *pc;
3345*1c60b9acSAndroid Build Coastguard Worker int old_len, n;
3346*1c60b9acSAndroid Build Coastguard Worker
3347*1c60b9acSAndroid Build Coastguard Worker /* do replacements */
3348*1c60b9acSAndroid Build Coastguard Worker sp = args->p;
3349*1c60b9acSAndroid Build Coastguard Worker old_len = args->len;
3350*1c60b9acSAndroid Build Coastguard Worker args->len = 0;
3351*1c60b9acSAndroid Build Coastguard Worker s->start = sp;
3352*1c60b9acSAndroid Build Coastguard Worker while (sp < args->p + old_len) {
3353*1c60b9acSAndroid Build Coastguard Worker
3354*1c60b9acSAndroid Build Coastguard Worker if (args->len + 7 >= args->max_len) {
3355*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Used up interpret padding\n");
3356*1c60b9acSAndroid Build Coastguard Worker return -1;
3357*1c60b9acSAndroid Build Coastguard Worker }
3358*1c60b9acSAndroid Build Coastguard Worker
3359*1c60b9acSAndroid Build Coastguard Worker if ((!s->pos && *sp == '$') || s->pos) {
3360*1c60b9acSAndroid Build Coastguard Worker int hits = 0, hit = 0;
3361*1c60b9acSAndroid Build Coastguard Worker
3362*1c60b9acSAndroid Build Coastguard Worker if (!s->pos)
3363*1c60b9acSAndroid Build Coastguard Worker s->start = sp;
3364*1c60b9acSAndroid Build Coastguard Worker s->swallow[s->pos++] = *sp;
3365*1c60b9acSAndroid Build Coastguard Worker if (s->pos == sizeof(s->swallow) - 1)
3366*1c60b9acSAndroid Build Coastguard Worker goto skip;
3367*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < s->count_vars; n++)
3368*1c60b9acSAndroid Build Coastguard Worker if (!strncmp(s->swallow, s->vars[n], (unsigned int)s->pos)) {
3369*1c60b9acSAndroid Build Coastguard Worker hits++;
3370*1c60b9acSAndroid Build Coastguard Worker hit = n;
3371*1c60b9acSAndroid Build Coastguard Worker }
3372*1c60b9acSAndroid Build Coastguard Worker if (!hits) {
3373*1c60b9acSAndroid Build Coastguard Worker skip:
3374*1c60b9acSAndroid Build Coastguard Worker s->swallow[s->pos] = '\0';
3375*1c60b9acSAndroid Build Coastguard Worker memcpy(s->start, s->swallow, (unsigned int)s->pos);
3376*1c60b9acSAndroid Build Coastguard Worker args->len++;
3377*1c60b9acSAndroid Build Coastguard Worker s->pos = 0;
3378*1c60b9acSAndroid Build Coastguard Worker sp = s->start + 1;
3379*1c60b9acSAndroid Build Coastguard Worker continue;
3380*1c60b9acSAndroid Build Coastguard Worker }
3381*1c60b9acSAndroid Build Coastguard Worker if (hits == 1 && s->pos == (int)strlen(s->vars[hit])) {
3382*1c60b9acSAndroid Build Coastguard Worker pc = s->replace(s->data, hit);
3383*1c60b9acSAndroid Build Coastguard Worker if (!pc)
3384*1c60b9acSAndroid Build Coastguard Worker pc = "NULL";
3385*1c60b9acSAndroid Build Coastguard Worker n = (int)strlen(pc);
3386*1c60b9acSAndroid Build Coastguard Worker s->swallow[s->pos] = '\0';
3387*1c60b9acSAndroid Build Coastguard Worker if (n != s->pos) {
3388*1c60b9acSAndroid Build Coastguard Worker memmove(s->start + n, s->start + s->pos,
3389*1c60b9acSAndroid Build Coastguard Worker (unsigned int)(old_len - (sp - args->p) - 1));
3390*1c60b9acSAndroid Build Coastguard Worker old_len += (n - s->pos) + 1;
3391*1c60b9acSAndroid Build Coastguard Worker }
3392*1c60b9acSAndroid Build Coastguard Worker memcpy(s->start, pc, (unsigned int)n);
3393*1c60b9acSAndroid Build Coastguard Worker args->len++;
3394*1c60b9acSAndroid Build Coastguard Worker sp = s->start + 1;
3395*1c60b9acSAndroid Build Coastguard Worker
3396*1c60b9acSAndroid Build Coastguard Worker s->pos = 0;
3397*1c60b9acSAndroid Build Coastguard Worker }
3398*1c60b9acSAndroid Build Coastguard Worker sp++;
3399*1c60b9acSAndroid Build Coastguard Worker continue;
3400*1c60b9acSAndroid Build Coastguard Worker }
3401*1c60b9acSAndroid Build Coastguard Worker
3402*1c60b9acSAndroid Build Coastguard Worker args->len++;
3403*1c60b9acSAndroid Build Coastguard Worker sp++;
3404*1c60b9acSAndroid Build Coastguard Worker }
3405*1c60b9acSAndroid Build Coastguard Worker
3406*1c60b9acSAndroid Build Coastguard Worker if (args->chunked) {
3407*1c60b9acSAndroid Build Coastguard Worker /* no space left for final chunk trailer */
3408*1c60b9acSAndroid Build Coastguard Worker if (args->final && args->len + 7 >= args->max_len)
3409*1c60b9acSAndroid Build Coastguard Worker return -1;
3410*1c60b9acSAndroid Build Coastguard Worker
3411*1c60b9acSAndroid Build Coastguard Worker n = sprintf(buffer, "%X\x0d\x0a", args->len);
3412*1c60b9acSAndroid Build Coastguard Worker
3413*1c60b9acSAndroid Build Coastguard Worker args->p -= n;
3414*1c60b9acSAndroid Build Coastguard Worker memcpy(args->p, buffer, (unsigned int)n);
3415*1c60b9acSAndroid Build Coastguard Worker args->len += n;
3416*1c60b9acSAndroid Build Coastguard Worker
3417*1c60b9acSAndroid Build Coastguard Worker if (args->final) {
3418*1c60b9acSAndroid Build Coastguard Worker sp = args->p + args->len;
3419*1c60b9acSAndroid Build Coastguard Worker *sp++ = '\x0d';
3420*1c60b9acSAndroid Build Coastguard Worker *sp++ = '\x0a';
3421*1c60b9acSAndroid Build Coastguard Worker *sp++ = '0';
3422*1c60b9acSAndroid Build Coastguard Worker *sp++ = '\x0d';
3423*1c60b9acSAndroid Build Coastguard Worker *sp++ = '\x0a';
3424*1c60b9acSAndroid Build Coastguard Worker *sp++ = '\x0d';
3425*1c60b9acSAndroid Build Coastguard Worker *sp++ = '\x0a';
3426*1c60b9acSAndroid Build Coastguard Worker args->len += 7;
3427*1c60b9acSAndroid Build Coastguard Worker } else {
3428*1c60b9acSAndroid Build Coastguard Worker sp = args->p + args->len;
3429*1c60b9acSAndroid Build Coastguard Worker *sp++ = '\x0d';
3430*1c60b9acSAndroid Build Coastguard Worker *sp++ = '\x0a';
3431*1c60b9acSAndroid Build Coastguard Worker args->len += 2;
3432*1c60b9acSAndroid Build Coastguard Worker }
3433*1c60b9acSAndroid Build Coastguard Worker }
3434*1c60b9acSAndroid Build Coastguard Worker
3435*1c60b9acSAndroid Build Coastguard Worker return 0;
3436*1c60b9acSAndroid Build Coastguard Worker }
3437