xref: /aosp_15_r20/external/libwebsockets/lib/plat/unix/unix-init.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 #if !defined(_GNU_SOURCE)
26*1c60b9acSAndroid Build Coastguard Worker #define _GNU_SOURCE
27*1c60b9acSAndroid Build Coastguard Worker #endif
28*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
29*1c60b9acSAndroid Build Coastguard Worker 
30*1c60b9acSAndroid Build Coastguard Worker #include <pwd.h>
31*1c60b9acSAndroid Build Coastguard Worker #include <grp.h>
32*1c60b9acSAndroid Build Coastguard Worker 
33*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_PLUGINS
34*1c60b9acSAndroid Build Coastguard Worker #include <dlfcn.h>
35*1c60b9acSAndroid Build Coastguard Worker #endif
36*1c60b9acSAndroid Build Coastguard Worker #include <dirent.h>
37*1c60b9acSAndroid Build Coastguard Worker 
38*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
39*1c60b9acSAndroid Build Coastguard Worker static void
lws_sul_plat_unix(lws_sorted_usec_list_t * sul)40*1c60b9acSAndroid Build Coastguard Worker lws_sul_plat_unix(lws_sorted_usec_list_t *sul)
41*1c60b9acSAndroid Build Coastguard Worker {
42*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt =
43*1c60b9acSAndroid Build Coastguard Worker 		lws_container_of(sul, struct lws_context_per_thread, sul_plat);
44*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context = pt->context;
45*1c60b9acSAndroid Build Coastguard Worker 	int n = 0, m = 0;
46*1c60b9acSAndroid Build Coastguard Worker 
47*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_NO_DAEMONIZE)
48*1c60b9acSAndroid Build Coastguard Worker 	/* if our parent went down, don't linger around */
49*1c60b9acSAndroid Build Coastguard Worker 	if (pt->context->started_with_parent &&
50*1c60b9acSAndroid Build Coastguard Worker 	    kill(pt->context->started_with_parent, 0) < 0)
51*1c60b9acSAndroid Build Coastguard Worker 		kill(getpid(), SIGTERM);
52*1c60b9acSAndroid Build Coastguard Worker #endif
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < context->count_threads; n++)
55*1c60b9acSAndroid Build Coastguard Worker 		m = m | (int)pt->fds_count;
56*1c60b9acSAndroid Build Coastguard Worker 
57*1c60b9acSAndroid Build Coastguard Worker 	if (context->deprecated && !m) {
58*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: ending deprecated context\n", __func__);
59*1c60b9acSAndroid Build Coastguard Worker 		kill(getpid(), SIGINT);
60*1c60b9acSAndroid Build Coastguard Worker 		return;
61*1c60b9acSAndroid Build Coastguard Worker 	}
62*1c60b9acSAndroid Build Coastguard Worker 
63*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
64*1c60b9acSAndroid Build Coastguard Worker 	lws_context_lock(context, "periodic checks");
65*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_llp(struct lws_vhost **, pv,
66*1c60b9acSAndroid Build Coastguard Worker 			      context->no_listener_vhost_list) {
67*1c60b9acSAndroid Build Coastguard Worker 		struct lws_vhost *v = *pv;
68*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("deferred iface: checking if on vh %s\n", (*pv)->name);
69*1c60b9acSAndroid Build Coastguard Worker 		if (_lws_vhost_init_server(NULL, *pv) == 0) {
70*1c60b9acSAndroid Build Coastguard Worker 			/* became happy */
71*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("vh %s: became connected\n", v->name);
72*1c60b9acSAndroid Build Coastguard Worker 			*pv = v->no_listener_vhost_list;
73*1c60b9acSAndroid Build Coastguard Worker 			v->no_listener_vhost_list = NULL;
74*1c60b9acSAndroid Build Coastguard Worker 			break;
75*1c60b9acSAndroid Build Coastguard Worker 		}
76*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_llp(pv, no_listener_vhost_list);
77*1c60b9acSAndroid Build Coastguard Worker 	lws_context_unlock(context);
78*1c60b9acSAndroid Build Coastguard Worker #endif
79*1c60b9acSAndroid Build Coastguard Worker 
80*1c60b9acSAndroid Build Coastguard Worker 	__lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED],
81*1c60b9acSAndroid Build Coastguard Worker 			    &pt->sul_plat, 30 * LWS_US_PER_SEC);
82*1c60b9acSAndroid Build Coastguard Worker }
83*1c60b9acSAndroid Build Coastguard Worker #endif
84*1c60b9acSAndroid Build Coastguard Worker 
85*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_PLUGINS)
86*1c60b9acSAndroid Build Coastguard Worker static int
protocol_plugin_cb(struct lws_plugin * pin,void * each_user)87*1c60b9acSAndroid Build Coastguard Worker protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
88*1c60b9acSAndroid Build Coastguard Worker {
89*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context = (struct lws_context *)each_user;
90*1c60b9acSAndroid Build Coastguard Worker 	const lws_plugin_protocol_t *plpr =
91*1c60b9acSAndroid Build Coastguard Worker 			(const lws_plugin_protocol_t *)pin->hdr;
92*1c60b9acSAndroid Build Coastguard Worker 
93*1c60b9acSAndroid Build Coastguard Worker 	context->plugin_protocol_count = (short)(context->plugin_protocol_count +
94*1c60b9acSAndroid Build Coastguard Worker 						 plpr->count_protocols);
95*1c60b9acSAndroid Build Coastguard Worker 	context->plugin_extension_count = (short)(context->plugin_extension_count +
96*1c60b9acSAndroid Build Coastguard Worker 						  plpr->count_extensions);
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker 	return 0;
99*1c60b9acSAndroid Build Coastguard Worker }
100*1c60b9acSAndroid Build Coastguard Worker #endif
101*1c60b9acSAndroid Build Coastguard Worker 
102*1c60b9acSAndroid Build Coastguard Worker int
lws_plat_init(struct lws_context * context,const struct lws_context_creation_info * info)103*1c60b9acSAndroid Build Coastguard Worker lws_plat_init(struct lws_context *context,
104*1c60b9acSAndroid Build Coastguard Worker 	      const struct lws_context_creation_info *info)
105*1c60b9acSAndroid Build Coastguard Worker {
106*1c60b9acSAndroid Build Coastguard Worker 	int fd;
107*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
108*1c60b9acSAndroid Build Coastguard Worker 	/*
109*1c60b9acSAndroid Build Coastguard Worker 	 * context has the process-global fd lookup array.  This can be
110*1c60b9acSAndroid Build Coastguard Worker 	 * done two different ways now; one or the other is done depending on if
111*1c60b9acSAndroid Build Coastguard Worker 	 * info->fd_limit_per_thread was snonzero
112*1c60b9acSAndroid Build Coastguard Worker 	 *
113*1c60b9acSAndroid Build Coastguard Worker 	 *  - default: allocate a worst-case lookup array sized for ulimit -n
114*1c60b9acSAndroid Build Coastguard Worker 	 *             and use the fd directly as an index into it
115*1c60b9acSAndroid Build Coastguard Worker 	 *
116*1c60b9acSAndroid Build Coastguard Worker 	 *  - slow:    allocate context->max_fds entries only (which can be
117*1c60b9acSAndroid Build Coastguard Worker 	 *             forced at context creation time to be
118*1c60b9acSAndroid Build Coastguard Worker 	 *             info->fd_limit_per_thread * the number of threads)
119*1c60b9acSAndroid Build Coastguard Worker 	 *             and search the array to lookup fds
120*1c60b9acSAndroid Build Coastguard Worker 	 *
121*1c60b9acSAndroid Build Coastguard Worker 	 * the default way is optimized for server, if you only use one or two
122*1c60b9acSAndroid Build Coastguard Worker 	 * client wsi the slow way may save a lot of memory.
123*1c60b9acSAndroid Build Coastguard Worker 	 *
124*1c60b9acSAndroid Build Coastguard Worker 	 * Both ways allocate an array of struct lws *... one allocates it for
125*1c60b9acSAndroid Build Coastguard Worker 	 * all possible fd indexes the process could produce and uses it as a
126*1c60b9acSAndroid Build Coastguard Worker 	 * map, the other allocates for an amount of wsi the lws context is
127*1c60b9acSAndroid Build Coastguard Worker 	 * expected to use and searches through it to manipulate it.
128*1c60b9acSAndroid Build Coastguard Worker 	 */
129*1c60b9acSAndroid Build Coastguard Worker 
130*1c60b9acSAndroid Build Coastguard Worker 	context->lws_lookup = lws_zalloc(sizeof(struct lws *) *
131*1c60b9acSAndroid Build Coastguard Worker 					 context->max_fds, "lws_lookup");
132*1c60b9acSAndroid Build Coastguard Worker 
133*1c60b9acSAndroid Build Coastguard Worker 	if (!context->lws_lookup) {
134*1c60b9acSAndroid Build Coastguard Worker 		lwsl_cx_err(context, "OOM on alloc lws_lookup array for %d conn",
135*1c60b9acSAndroid Build Coastguard Worker 			 context->max_fds);
136*1c60b9acSAndroid Build Coastguard Worker 		return 1;
137*1c60b9acSAndroid Build Coastguard Worker 	}
138*1c60b9acSAndroid Build Coastguard Worker 
139*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_MBEDTLS)
140*1c60b9acSAndroid Build Coastguard Worker 	{
141*1c60b9acSAndroid Build Coastguard Worker 		int n;
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker 		/* initialize platform random through mbedtls */
144*1c60b9acSAndroid Build Coastguard Worker 		mbedtls_entropy_init(&context->mec);
145*1c60b9acSAndroid Build Coastguard Worker 		mbedtls_ctr_drbg_init(&context->mcdc);
146*1c60b9acSAndroid Build Coastguard Worker 
147*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_ctr_drbg_seed(&context->mcdc, mbedtls_entropy_func,
148*1c60b9acSAndroid Build Coastguard Worker 					  &context->mec, NULL, 0);
149*1c60b9acSAndroid Build Coastguard Worker 		if (n)
150*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: mbedtls_ctr_drbg_seed() returned 0x%x\n",
151*1c60b9acSAndroid Build Coastguard Worker 				 __func__, n);
152*1c60b9acSAndroid Build Coastguard Worker #if 0
153*1c60b9acSAndroid Build Coastguard Worker 		else {
154*1c60b9acSAndroid Build Coastguard Worker 			uint8_t rtest[16];
155*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: started drbg\n", __func__);
156*1c60b9acSAndroid Build Coastguard Worker 			if (mbedtls_ctr_drbg_random(&context->mcdc, rtest,
157*1c60b9acSAndroid Build Coastguard Worker 							sizeof(rtest)))
158*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: get random failed\n", __func__);
159*1c60b9acSAndroid Build Coastguard Worker 			else
160*1c60b9acSAndroid Build Coastguard Worker 				lwsl_hexdump_notice(rtest, sizeof(rtest));
161*1c60b9acSAndroid Build Coastguard Worker 		}
162*1c60b9acSAndroid Build Coastguard Worker #endif
163*1c60b9acSAndroid Build Coastguard Worker 	}
164*1c60b9acSAndroid Build Coastguard Worker #endif
165*1c60b9acSAndroid Build Coastguard Worker 
166*1c60b9acSAndroid Build Coastguard Worker 	lwsl_cx_info(context, " mem: platform fd map: %5lu B",
167*1c60b9acSAndroid Build Coastguard Worker 		    (unsigned long)(sizeof(struct lws *) * context->max_fds));
168*1c60b9acSAndroid Build Coastguard Worker #endif
169*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_FILE_OPS)
170*1c60b9acSAndroid Build Coastguard Worker 	fd = lws_open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
171*1c60b9acSAndroid Build Coastguard Worker #else
172*1c60b9acSAndroid Build Coastguard Worker 	fd = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
173*1c60b9acSAndroid Build Coastguard Worker #endif
174*1c60b9acSAndroid Build Coastguard Worker 	context->fd_random = fd;
175*1c60b9acSAndroid Build Coastguard Worker 	if (context->fd_random < 0) {
176*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("Unable to open random device %s %d, errno %d\n",
177*1c60b9acSAndroid Build Coastguard Worker 			 SYSTEM_RANDOM_FILEPATH, context->fd_random, errno);
178*1c60b9acSAndroid Build Coastguard Worker 		return 1;
179*1c60b9acSAndroid Build Coastguard Worker 	}
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_PLUGINS)
182*1c60b9acSAndroid Build Coastguard Worker 	{
183*1c60b9acSAndroid Build Coastguard Worker 		char *ld_env = getenv("LD_LIBRARY_PATH");
184*1c60b9acSAndroid Build Coastguard Worker 
185*1c60b9acSAndroid Build Coastguard Worker 		if (ld_env) {
186*1c60b9acSAndroid Build Coastguard Worker 			const char *pp[2] = { ld_env, NULL };
187*1c60b9acSAndroid Build Coastguard Worker 
188*1c60b9acSAndroid Build Coastguard Worker 			lws_plugins_init(&context->plugin_list, pp,
189*1c60b9acSAndroid Build Coastguard Worker 					 "lws_protocol_plugin", NULL,
190*1c60b9acSAndroid Build Coastguard Worker 					 protocol_plugin_cb, context);
191*1c60b9acSAndroid Build Coastguard Worker 		}
192*1c60b9acSAndroid Build Coastguard Worker 
193*1c60b9acSAndroid Build Coastguard Worker 		if (info->plugin_dirs)
194*1c60b9acSAndroid Build Coastguard Worker 			lws_plugins_init(&context->plugin_list,
195*1c60b9acSAndroid Build Coastguard Worker 					 info->plugin_dirs,
196*1c60b9acSAndroid Build Coastguard Worker 					 "lws_protocol_plugin", NULL,
197*1c60b9acSAndroid Build Coastguard Worker 					 protocol_plugin_cb, context);
198*1c60b9acSAndroid Build Coastguard Worker 	}
199*1c60b9acSAndroid Build Coastguard Worker #endif
200*1c60b9acSAndroid Build Coastguard Worker 
201*1c60b9acSAndroid Build Coastguard Worker 
202*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
203*1c60b9acSAndroid Build Coastguard Worker 	/* we only need to do this on pt[0] */
204*1c60b9acSAndroid Build Coastguard Worker 
205*1c60b9acSAndroid Build Coastguard Worker 	context->pt[0].sul_plat.cb = lws_sul_plat_unix;
206*1c60b9acSAndroid Build Coastguard Worker 	__lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED],
207*1c60b9acSAndroid Build Coastguard Worker 			    &context->pt[0].sul_plat, 30 * LWS_US_PER_SEC);
208*1c60b9acSAndroid Build Coastguard Worker #endif
209*1c60b9acSAndroid Build Coastguard Worker 
210*1c60b9acSAndroid Build Coastguard Worker 	return 0;
211*1c60b9acSAndroid Build Coastguard Worker }
212*1c60b9acSAndroid Build Coastguard Worker 
213*1c60b9acSAndroid Build Coastguard Worker int
lws_plat_context_early_init(void)214*1c60b9acSAndroid Build Coastguard Worker lws_plat_context_early_init(void)
215*1c60b9acSAndroid Build Coastguard Worker {
216*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_AVOID_SIGPIPE_IGN)
217*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGPIPE, SIG_IGN);
218*1c60b9acSAndroid Build Coastguard Worker #endif
219*1c60b9acSAndroid Build Coastguard Worker 
220*1c60b9acSAndroid Build Coastguard Worker 	return 0;
221*1c60b9acSAndroid Build Coastguard Worker }
222*1c60b9acSAndroid Build Coastguard Worker 
223*1c60b9acSAndroid Build Coastguard Worker void
lws_plat_context_early_destroy(struct lws_context * context)224*1c60b9acSAndroid Build Coastguard Worker lws_plat_context_early_destroy(struct lws_context *context)
225*1c60b9acSAndroid Build Coastguard Worker {
226*1c60b9acSAndroid Build Coastguard Worker }
227*1c60b9acSAndroid Build Coastguard Worker 
228*1c60b9acSAndroid Build Coastguard Worker void
lws_plat_context_late_destroy(struct lws_context * context)229*1c60b9acSAndroid Build Coastguard Worker lws_plat_context_late_destroy(struct lws_context *context)
230*1c60b9acSAndroid Build Coastguard Worker {
231*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_PLUGINS)
232*1c60b9acSAndroid Build Coastguard Worker 	if (context->plugin_list)
233*1c60b9acSAndroid Build Coastguard Worker 		lws_plugins_destroy(&context->plugin_list, NULL, NULL);
234*1c60b9acSAndroid Build Coastguard Worker #endif
235*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
236*1c60b9acSAndroid Build Coastguard Worker 	if (context->lws_lookup)
237*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(context->lws_lookup);
238*1c60b9acSAndroid Build Coastguard Worker #endif
239*1c60b9acSAndroid Build Coastguard Worker 	if (!context->fd_random)
240*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("ZERO RANDOM FD\n");
241*1c60b9acSAndroid Build Coastguard Worker 	if (context->fd_random != LWS_INVALID_FILE)
242*1c60b9acSAndroid Build Coastguard Worker 		close(context->fd_random);
243*1c60b9acSAndroid Build Coastguard Worker }
244