/src/libwebsockets/lib/plat/unix/unix-init.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * libwebsockets - small server side websockets and web server implementation |
3 | | * |
4 | | * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | | * of this software and associated documentation files (the "Software"), to |
8 | | * deal in the Software without restriction, including without limitation the |
9 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
10 | | * sell copies of the Software, and to permit persons to whom the Software is |
11 | | * furnished to do so, subject to the following conditions: |
12 | | * |
13 | | * The above copyright notice and this permission notice shall be included in |
14 | | * all copies or substantial portions of the Software. |
15 | | * |
16 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
22 | | * IN THE SOFTWARE. |
23 | | */ |
24 | | |
25 | | #if !defined(_GNU_SOURCE) |
26 | | #define _GNU_SOURCE |
27 | | #endif |
28 | | #include "private-lib-core.h" |
29 | | |
30 | | #include <pwd.h> |
31 | | #include <grp.h> |
32 | | |
33 | | #ifdef LWS_WITH_PLUGINS |
34 | | #include <dlfcn.h> |
35 | | #endif |
36 | | #include <dirent.h> |
37 | | |
38 | | #if defined(LWS_WITH_NETWORK) |
39 | | static void |
40 | | lws_sul_plat_unix(lws_sorted_usec_list_t *sul) |
41 | 0 | { |
42 | 0 | struct lws_context_per_thread *pt = |
43 | 0 | lws_container_of(sul, struct lws_context_per_thread, sul_plat); |
44 | 0 | struct lws_context *context = pt->context; |
45 | 0 | int n = 0, m = 0; |
46 | |
|
47 | | #if !defined(LWS_NO_DAEMONIZE) |
48 | | /* if our parent went down, don't linger around */ |
49 | | if (pt->context->started_with_parent && |
50 | | kill(pt->context->started_with_parent, 0) < 0) |
51 | | kill(getpid(), SIGTERM); |
52 | | #endif |
53 | |
|
54 | 0 | for (n = 0; n < context->count_threads; n++) |
55 | 0 | m = m | (int)pt->fds_count; |
56 | |
|
57 | 0 | if (context->deprecated && !m) { |
58 | 0 | lwsl_notice("%s: ending deprecated context\n", __func__); |
59 | 0 | kill(getpid(), SIGINT); |
60 | 0 | return; |
61 | 0 | } |
62 | | |
63 | 0 | #if defined(LWS_WITH_SERVER) |
64 | 0 | lws_context_lock(context, "periodic checks"); |
65 | 0 | lws_start_foreach_llp(struct lws_vhost **, pv, |
66 | 0 | context->no_listener_vhost_list) { |
67 | 0 | struct lws_vhost *v = *pv; |
68 | 0 | lwsl_debug("deferred iface: checking if on vh %s\n", (*pv)->name); |
69 | 0 | if (_lws_vhost_init_server(NULL, *pv) == 0) { |
70 | | /* became happy */ |
71 | 0 | lwsl_notice("vh %s: became connected\n", v->name); |
72 | 0 | *pv = v->no_listener_vhost_list; |
73 | 0 | v->no_listener_vhost_list = NULL; |
74 | 0 | break; |
75 | 0 | } |
76 | 0 | } lws_end_foreach_llp(pv, no_listener_vhost_list); |
77 | 0 | lws_context_unlock(context); |
78 | 0 | #endif |
79 | |
|
80 | 0 | __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], |
81 | 0 | &pt->sul_plat, 30 * LWS_US_PER_SEC); |
82 | 0 | } |
83 | | #endif |
84 | | |
85 | | #if defined(LWS_WITH_PLUGINS) |
86 | | static int |
87 | | protocol_plugin_cb(struct lws_plugin *pin, void *each_user) |
88 | | { |
89 | | struct lws_context *context = (struct lws_context *)each_user; |
90 | | const lws_plugin_protocol_t *plpr = |
91 | | (const lws_plugin_protocol_t *)pin->hdr; |
92 | | |
93 | | context->plugin_protocol_count = (short)(context->plugin_protocol_count + |
94 | | plpr->count_protocols); |
95 | | context->plugin_extension_count = (short)(context->plugin_extension_count + |
96 | | plpr->count_extensions); |
97 | | |
98 | | return 0; |
99 | | } |
100 | | #endif |
101 | | |
102 | | int |
103 | | lws_plat_init(struct lws_context *context, |
104 | | const struct lws_context_creation_info *info) |
105 | 0 | { |
106 | 0 | int fd; |
107 | 0 | #if defined(LWS_WITH_NETWORK) |
108 | | /* |
109 | | * context has the process-global fd lookup array. This can be |
110 | | * done two different ways now; one or the other is done depending on if |
111 | | * info->fd_limit_per_thread was snonzero |
112 | | * |
113 | | * - default: allocate a worst-case lookup array sized for ulimit -n |
114 | | * and use the fd directly as an index into it |
115 | | * |
116 | | * - slow: allocate context->max_fds entries only (which can be |
117 | | * forced at context creation time to be |
118 | | * info->fd_limit_per_thread * the number of threads) |
119 | | * and search the array to lookup fds |
120 | | * |
121 | | * the default way is optimized for server, if you only use one or two |
122 | | * client wsi the slow way may save a lot of memory. |
123 | | * |
124 | | * Both ways allocate an array of struct lws *... one allocates it for |
125 | | * all possible fd indexes the process could produce and uses it as a |
126 | | * map, the other allocates for an amount of wsi the lws context is |
127 | | * expected to use and searches through it to manipulate it. |
128 | | */ |
129 | |
|
130 | 0 | context->lws_lookup = lws_zalloc(sizeof(struct lws *) * |
131 | 0 | context->max_fds, "lws_lookup"); |
132 | |
|
133 | 0 | if (!context->lws_lookup) { |
134 | 0 | lwsl_cx_err(context, "OOM on alloc lws_lookup array for %d conn", |
135 | 0 | context->max_fds); |
136 | 0 | return 1; |
137 | 0 | } |
138 | | |
139 | | #if defined(LWS_WITH_MBEDTLS) |
140 | | { |
141 | | int n; |
142 | | |
143 | | /* initialize platform random through mbedtls */ |
144 | | mbedtls_entropy_init(&context->mec); |
145 | | mbedtls_ctr_drbg_init(&context->mcdc); |
146 | | |
147 | | n = mbedtls_ctr_drbg_seed(&context->mcdc, mbedtls_entropy_func, |
148 | | &context->mec, NULL, 0); |
149 | | if (n) |
150 | | lwsl_err("%s: mbedtls_ctr_drbg_seed() returned 0x%x\n", |
151 | | __func__, n); |
152 | | #if 0 |
153 | | else { |
154 | | uint8_t rtest[16]; |
155 | | lwsl_notice("%s: started drbg\n", __func__); |
156 | | if (mbedtls_ctr_drbg_random(&context->mcdc, rtest, |
157 | | sizeof(rtest))) |
158 | | lwsl_err("%s: get random failed\n", __func__); |
159 | | else |
160 | | lwsl_hexdump_notice(rtest, sizeof(rtest)); |
161 | | } |
162 | | #endif |
163 | | } |
164 | | #endif |
165 | | |
166 | 0 | lwsl_cx_info(context, " mem: platform fd map: %5lu B", |
167 | 0 | (unsigned long)(sizeof(struct lws *) * context->max_fds)); |
168 | 0 | #endif |
169 | 0 | #if defined(LWS_WITH_FILE_OPS) |
170 | 0 | fd = lws_open(SYSTEM_RANDOM_FILEPATH, O_RDONLY); |
171 | | #else |
172 | | fd = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY); |
173 | | #endif |
174 | 0 | context->fd_random = fd; |
175 | 0 | if (context->fd_random < 0) { |
176 | 0 | lwsl_err("Unable to open random device %s %d, errno %d\n", |
177 | 0 | SYSTEM_RANDOM_FILEPATH, context->fd_random, errno); |
178 | 0 | return 1; |
179 | 0 | } |
180 | | |
181 | 0 | #if defined(LWS_HAVE_SSL_CTX_set_keylog_callback) && !defined(__COVERITY__) && \ |
182 | 0 | defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT) |
183 | 0 | { |
184 | 0 | char *klf_env = getenv("SSLKEYLOGFILE"); |
185 | 0 | size_t n = 0; |
186 | | |
187 | | /* ... coverity taint with lws_strncpy()... */ |
188 | |
|
189 | 0 | while (klf_env && n < sizeof(context->keylog_file) - 1 && |
190 | 0 | klf_env[n]) { |
191 | 0 | context->keylog_file[n] = klf_env[n]; |
192 | 0 | n++; |
193 | 0 | } |
194 | 0 | context->keylog_file[n] = '\0'; |
195 | 0 | } |
196 | 0 | #endif |
197 | |
|
198 | | #if defined(LWS_WITH_PLUGINS) && !defined(LWS_WITH_PLUGINS_BUILTIN) |
199 | | { |
200 | | const char *pp[8] = { }; |
201 | | int n = 0; |
202 | | |
203 | | if (info->plugin_dirs) { |
204 | | int m = 0; |
205 | | |
206 | | while (info->plugin_dirs[m] && n < (int)LWS_ARRAY_SIZE(pp) - 1) |
207 | | pp[n++] = info->plugin_dirs[m++]; |
208 | | } |
209 | | |
210 | | if (n < (int)LWS_ARRAY_SIZE(pp) - 1) |
211 | | pp[n++] = LWS_INSTALL_DATADIR"/libwebsockets-test-server/plugins"; |
212 | | |
213 | | pp[n] = NULL; |
214 | | |
215 | | /* We'll also look at LD_LIBRARY_PATH first in here */ |
216 | | |
217 | | lws_plugins_init(&context->plugin_list, pp, |
218 | | "lws_protocol_plugin", NULL, |
219 | | protocol_plugin_cb, context); |
220 | | } |
221 | | |
222 | | #endif |
223 | | #if defined(LWS_BUILTIN_PLUGIN_NAMES) && defined(LWS_WITH_PLUGINS) |
224 | | lws_plugins_handle_builtin(&context->plugin_list, |
225 | | protocol_plugin_cb, context); |
226 | | #endif |
227 | | |
228 | |
|
229 | 0 | #if defined(LWS_WITH_NETWORK) |
230 | | /* we only need to do this on pt[0] */ |
231 | |
|
232 | 0 | context->pt[0].sul_plat.cb = lws_sul_plat_unix; |
233 | 0 | __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], |
234 | 0 | &context->pt[0].sul_plat, 30 * LWS_US_PER_SEC); |
235 | 0 | #endif |
236 | |
|
237 | 0 | return 0; |
238 | 0 | } |
239 | | |
240 | | int |
241 | | lws_plat_context_early_init(void) |
242 | 0 | { |
243 | 0 | #if !defined(LWS_AVOID_SIGPIPE_IGN) |
244 | 0 | signal(SIGPIPE, SIG_IGN); |
245 | 0 | #endif |
246 | |
|
247 | 0 | return 0; |
248 | 0 | } |
249 | | |
250 | | void |
251 | | lws_plat_context_early_destroy(struct lws_context *context) |
252 | 0 | { |
253 | 0 | } |
254 | | |
255 | | void |
256 | | lws_plat_context_late_destroy(struct lws_context *context) |
257 | 0 | { |
258 | | #if defined(LWS_WITH_PLUGINS) |
259 | | if (context->plugin_list) |
260 | | lws_plugins_destroy(&context->plugin_list, NULL, NULL); |
261 | | #endif |
262 | 0 | #if defined(LWS_WITH_NETWORK) |
263 | 0 | if (context->lws_lookup) |
264 | 0 | lws_free_set_NULL(context->lws_lookup); |
265 | 0 | #endif |
266 | 0 | if (!context->fd_random) |
267 | 0 | lwsl_err("ZERO RANDOM FD\n"); |
268 | 0 | if (context->fd_random != LWS_INVALID_FILE) |
269 | 0 | close(context->fd_random); |
270 | |
|
271 | | #if defined(LWS_WITH_MBEDTLS) |
272 | | mbedtls_entropy_free(&context->mec); |
273 | | mbedtls_ctr_drbg_free(&context->mcdc); |
274 | | #endif |
275 | 0 | } |