xref: /aosp_15_r20/external/libwebsockets/lib/roles/http/server/server.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
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