1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2020 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 #include "private-lib-core.h"
26
27 #ifndef LWS_BUILD_HASH
28 #define LWS_BUILD_HASH "unknown-build-hash"
29 #endif
30
31 static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
32
33 #if defined(LWS_WITH_NETWORK)
34 /* in ms */
35 static uint32_t default_backoff_table[] = { 1000, 3000, 9000, 17000 };
36 #endif
37
38 /**
39 * lws_get_library_version: get version and git hash library built from
40 *
41 * returns a const char * to a string like "1.1 178d78c"
42 * representing the library version followed by the git head hash it
43 * was built from
44 */
45 const char *
lws_get_library_version(void)46 lws_get_library_version(void)
47 {
48 return library_version;
49 }
50
51 #if defined(LWS_WITH_STATS)
52 static void
lws_sul_stats_cb(lws_sorted_usec_list_t * sul)53 lws_sul_stats_cb(lws_sorted_usec_list_t *sul)
54 {
55 struct lws_context_per_thread *pt = lws_container_of(sul,
56 struct lws_context_per_thread, sul_stats);
57
58 lws_stats_log_dump(pt->context);
59
60 __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_stats, 10 * LWS_US_PER_SEC);
61 }
62 #endif
63 #if defined(LWS_WITH_PEER_LIMITS)
64 static void
lws_sul_peer_limits_cb(lws_sorted_usec_list_t * sul)65 lws_sul_peer_limits_cb(lws_sorted_usec_list_t *sul)
66 {
67 struct lws_context_per_thread *pt = lws_container_of(sul,
68 struct lws_context_per_thread, sul_peer_limits);
69
70 lws_peer_cull_peer_wait_list(pt->context);
71
72 __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_peer_limits, 10 * LWS_US_PER_SEC);
73 }
74 #endif
75
76 #if defined(LWS_WITH_NETWORK)
77
78 #if defined(_DEBUG)
79 static const char * system_state_names[] = {
80 "undef",
81 "CONTEXT_CREATED",
82 "INITIALIZED",
83 "IFACE_COLDPLUG",
84 "DHCP",
85 "TIME_VALID",
86 "POLICY_VALID",
87 "REGISTERED",
88 "AUTH1",
89 "AUTH2",
90 "OPERATIONAL",
91 "POLICY_INVALID"
92 };
93 #endif
94
95 /*
96 * Handle provoking protocol init when we pass through the right system state
97 */
98
99 static int
lws_state_notify_protocol_init(struct lws_state_manager * mgr,struct lws_state_notify_link * link,int current,int target)100 lws_state_notify_protocol_init(struct lws_state_manager *mgr,
101 struct lws_state_notify_link *link, int current,
102 int target)
103 {
104 struct lws_context *context = lws_container_of(mgr, struct lws_context,
105 mgr_system);
106 int n;
107
108 /*
109 * Deal with any attachments that were waiting for the right state
110 * to come along
111 */
112
113 for (n = 0; n < context->count_threads; n++)
114 lws_system_do_attach(&context->pt[n]);
115
116 #if defined(LWS_WITH_SYS_DHCP_CLIENT)
117 if (target == LWS_SYSTATE_DHCP) {
118 /*
119 * Don't let it past here until at least one iface has been
120 * configured for operation with DHCP
121 */
122
123 if (!lws_dhcpc_status(context, NULL))
124 return 1;
125 }
126 #endif
127
128 #if defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM)
129 /*
130 * Skip this if we are running something without the policy for it
131 *
132 * If root token is empty, skip too.
133 */
134 if (target == LWS_SYSTATE_AUTH1 &&
135 context->pss_policies &&
136 !lws_system_blob_get_size(lws_system_get_blob(context,
137 LWS_SYSBLOB_TYPE_AUTH,
138 0)) &&
139 lws_system_blob_get_size(lws_system_get_blob(context,
140 LWS_SYSBLOB_TYPE_AUTH,
141 1))) {
142 lwsl_info("%s: AUTH1 state triggering api.amazon.com auth\n", __func__);
143 /*
144 * Start trying to acquire it if it's not already in progress
145 * returns nonzero if we determine it's not needed
146 */
147 if (!lws_ss_sys_auth_api_amazon_com(context))
148 return 1;
149 }
150 #endif
151
152 #if defined(LWS_WITH_SECURE_STREAMS)
153 /*
154 * Skip this if we are running something without the policy for it
155 */
156 if (target == LWS_SYSTATE_POLICY_VALID &&
157 context->pss_policies && !context->policy_updated) {
158 /*
159 * Start trying to acquire it if it's not already in progress
160 * returns nonzero if we determine it's not needed
161 */
162 if (!lws_ss_sys_fetch_policy(context))
163 return 1;
164 }
165 #endif
166
167 /* protocol part */
168
169 if (context->protocol_init_done)
170 return 0;
171
172 if (target != LWS_SYSTATE_POLICY_VALID)
173 return 0;
174
175 lwsl_info("%s: doing protocol init on POLICY_VALID\n", __func__);
176 lws_protocol_init(context);
177
178 return 0;
179 }
180
181 static void
lws_context_creation_completion_cb(lws_sorted_usec_list_t * sul)182 lws_context_creation_completion_cb(lws_sorted_usec_list_t *sul)
183 {
184 struct lws_context *context = lws_container_of(sul, struct lws_context,
185 sul_system_state);
186
187 /* if nothing is there to intercept anything, go all the way */
188 lws_state_transition_steps(&context->mgr_system,
189 LWS_SYSTATE_OPERATIONAL);
190 }
191 #endif
192
193 struct lws_context *
lws_create_context(const struct lws_context_creation_info * info)194 lws_create_context(const struct lws_context_creation_info *info)
195 {
196 struct lws_context *context = NULL;
197 #if defined(LWS_WITH_FILE_OPS)
198 struct lws_plat_file_ops *prev;
199 #endif
200 #ifndef LWS_NO_DAEMONIZE
201 pid_t pid_daemon = get_daemonize_pid();
202 #endif
203 #if defined(LWS_WITH_NETWORK)
204 int n, count_threads = 1;
205 uint8_t *u;
206 #endif
207 #if defined(__ANDROID__)
208 struct rlimit rt;
209 #endif
210 size_t s1 = 4096, size = sizeof(struct lws_context);
211 int lpf = info->fd_limit_per_thread;
212
213 if (lpf) {
214 lpf+= 2;
215 #if defined(LWS_WITH_SYS_ASYNC_DNS)
216 lpf++;
217 #endif
218 #if defined(LWS_WITH_SYS_NTPCLIENT)
219 lpf++;
220 #endif
221 #if defined(LWS_WITH_SYS_DHCP_CLIENT)
222 lpf++;
223 #endif
224 }
225
226 lwsl_info("Initial logging level %d\n", log_level);
227 lwsl_info("Libwebsockets version: %s\n", library_version);
228
229 #ifdef LWS_WITH_IPV6
230 if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_IPV6))
231 lwsl_info("IPV6 compiled in and enabled\n");
232 else
233 lwsl_info("IPV6 compiled in but disabled\n");
234 #else
235 lwsl_info("IPV6 not compiled in\n");
236 #endif
237
238 lwsl_info(" LWS_DEF_HEADER_LEN : %u\n", LWS_DEF_HEADER_LEN);
239 lwsl_info(" LWS_MAX_SMP : %u\n", LWS_MAX_SMP);
240 lwsl_info(" sizeof (*info) : %ld\n", (long)sizeof(*info));
241 #if defined(LWS_WITH_STATS)
242 lwsl_info(" LWS_WITH_STATS : on\n");
243 #endif
244 lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
245 #if defined(LWS_WITH_HTTP2)
246 lwsl_info(" HTTP2 support : available\n");
247 #else
248 lwsl_info(" HTTP2 support : not configured\n");
249 #endif
250 if (lws_plat_context_early_init())
251 return NULL;
252
253 #if defined(LWS_WITH_NETWORK)
254 if (info->count_threads)
255 count_threads = info->count_threads;
256
257 if (count_threads > LWS_MAX_SMP)
258 count_threads = LWS_MAX_SMP;
259
260 if (info->pt_serv_buf_size)
261 s1 = info->pt_serv_buf_size;
262
263 /* pt fakewsi and the pt serv buf allocations ride after the context */
264 size += count_threads * (s1 + sizeof(struct lws));
265 #endif
266
267 context = lws_zalloc(size, "context");
268 if (!context) {
269 lwsl_err("No memory for websocket context\n");
270 return NULL;
271 }
272
273 context->uid = info->uid;
274 context->gid = info->gid;
275 context->username = info->username;
276 context->groupname = info->groupname;
277 context->system_ops = info->system_ops;
278 context->pt_serv_buf_size = (unsigned int)s1;
279 context->udp_loss_sim_tx_pc = info->udp_loss_sim_tx_pc;
280 context->udp_loss_sim_rx_pc = info->udp_loss_sim_rx_pc;
281
282 if (context->udp_loss_sim_tx_pc || context->udp_loss_sim_rx_pc)
283 lwsl_warn("%s: simulating udp loss tx: %d%%, rx: %d%%\n",
284 __func__, context->udp_loss_sim_tx_pc,
285 context->udp_loss_sim_rx_pc);
286
287 #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
288 context->ss_proxy_bind = info->ss_proxy_bind;
289 context->ss_proxy_port = info->ss_proxy_port;
290 context->ss_proxy_address = info->ss_proxy_address;
291 lwsl_notice("%s: using ss proxy bind '%s', port %d, ads '%s'\n",
292 __func__, context->ss_proxy_bind, context->ss_proxy_port,
293 context->ss_proxy_address);
294 #endif
295
296 #if defined(LWS_WITH_NETWORK)
297 context->count_threads = count_threads;
298 #if defined(LWS_WITH_DETAILED_LATENCY)
299 context->detailed_latency_cb = info->detailed_latency_cb;
300 context->detailed_latency_filepath = info->detailed_latency_filepath;
301 context->latencies_fd = -1;
302 #endif
303 #if defined(LWS_WITHOUT_EXTENSIONS)
304 if (info->extensions)
305 lwsl_warn("%s: LWS_WITHOUT_EXTENSIONS but extensions ptr set\n", __func__);
306 #endif
307 #endif
308
309 #if defined(LWS_WITH_SECURE_STREAMS)
310 context->pss_policies_json = info->pss_policies_json;
311 context->pss_plugins = info->pss_plugins;
312 #endif
313
314 /* if he gave us names, set the uid / gid */
315 if (lws_plat_drop_app_privileges(context, 0))
316 goto bail;
317
318 lwsl_info("context created\n");
319 #if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK)
320 #if defined(LWS_WITH_MBEDTLS)
321 context->tls_ops = &tls_ops_mbedtls;
322 #else
323 context->tls_ops = &tls_ops_openssl;
324 #endif
325 #endif
326
327 #if LWS_MAX_SMP > 1
328 lws_mutex_refcount_init(&context->mr);
329 #endif
330
331 #if defined(LWS_PLAT_FREERTOS)
332 #if defined(LWS_AMAZON_RTOS)
333 context->last_free_heap = xPortGetFreeHeapSize();
334 #else
335 context->last_free_heap = esp_get_free_heap_size();
336 #endif
337 #endif
338
339 #if defined(LWS_WITH_FILE_OPS)
340 /* default to just the platform fops implementation */
341
342 context->fops_platform.LWS_FOP_OPEN = _lws_plat_file_open;
343 context->fops_platform.LWS_FOP_CLOSE = _lws_plat_file_close;
344 context->fops_platform.LWS_FOP_SEEK_CUR = _lws_plat_file_seek_cur;
345 context->fops_platform.LWS_FOP_READ = _lws_plat_file_read;
346 context->fops_platform.LWS_FOP_WRITE = _lws_plat_file_write;
347 context->fops_platform.fi[0].sig = NULL;
348
349 /*
350 * arrange a linear linked-list of fops starting from context->fops
351 *
352 * platform fops
353 * [ -> fops_zip (copied into context so .next settable) ]
354 * [ -> info->fops ]
355 */
356
357 context->fops = &context->fops_platform;
358 prev = (struct lws_plat_file_ops *)context->fops;
359
360 #if defined(LWS_WITH_ZIP_FOPS)
361 /* make a soft copy so we can set .next */
362 context->fops_zip = fops_zip;
363 prev->next = &context->fops_zip;
364 prev = (struct lws_plat_file_ops *)prev->next;
365 #endif
366
367 /* if user provided fops, tack them on the end of the list */
368 if (info->fops)
369 prev->next = info->fops;
370 #endif
371
372 #if defined(LWS_WITH_SERVER)
373 context->reject_service_keywords = info->reject_service_keywords;
374 #endif
375 if (info->external_baggage_free_on_destroy)
376 context->external_baggage_free_on_destroy =
377 info->external_baggage_free_on_destroy;
378 #if defined(LWS_WITH_NETWORK)
379 context->time_up = lws_now_usecs();
380 #endif
381 context->pcontext_finalize = info->pcontext;
382
383 context->simultaneous_ssl_restriction =
384 info->simultaneous_ssl_restriction;
385
386 context->options = info->options;
387
388 #ifndef LWS_NO_DAEMONIZE
389 if (pid_daemon) {
390 context->started_with_parent = pid_daemon;
391 lwsl_info(" Started with daemon pid %u\n", (unsigned int)pid_daemon);
392 }
393 #endif
394 #if defined(__ANDROID__)
395 n = getrlimit(RLIMIT_NOFILE, &rt);
396 if (n == -1) {
397 lwsl_err("Get RLIMIT_NOFILE failed!\n");
398
399 return NULL;
400 }
401 context->max_fds = rt.rlim_cur;
402 #else
403 #if defined(WIN32) || defined(_WIN32) || defined(LWS_AMAZON_RTOS)
404 context->max_fds = getdtablesize();
405 #else
406 context->max_fds = sysconf(_SC_OPEN_MAX);
407 #endif
408 if (context->max_fds < 0) {
409 lwsl_err("%s: problem getting process max files\n",
410 __func__);
411
412 return NULL;
413 }
414 #endif
415
416 /*
417 * deal with any max_fds override, if it's reducing (setting it to
418 * more than ulimit -n is meaningless). The platform init will
419 * figure out what if this is something it can deal with.
420 */
421 if (info->fd_limit_per_thread) {
422 int mf = lpf * context->count_threads;
423
424 if (mf < context->max_fds) {
425 context->max_fds_unrelated_to_ulimit = 1;
426 context->max_fds = mf;
427 }
428 }
429
430 context->token_limits = info->token_limits;
431
432 #if defined(LWS_WITH_NETWORK)
433
434 /*
435 * set the context event loops ops struct
436 *
437 * after this, all event_loop actions use the generic ops
438 */
439
440 #if defined(LWS_WITH_POLL)
441 context->event_loop_ops = &event_loop_ops_poll;
442 #endif
443
444 if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
445 #if defined(LWS_WITH_LIBUV)
446 context->event_loop_ops = &event_loop_ops_uv;
447 #else
448 goto fail_event_libs;
449 #endif
450
451 if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEV))
452 #if defined(LWS_WITH_LIBEV)
453 context->event_loop_ops = &event_loop_ops_ev;
454 #else
455 goto fail_event_libs;
456 #endif
457
458 if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEVENT))
459 #if defined(LWS_WITH_LIBEVENT)
460 context->event_loop_ops = &event_loop_ops_event;
461 #else
462 goto fail_event_libs;
463 #endif
464
465 if (lws_check_opt(context->options, LWS_SERVER_OPTION_GLIB))
466 #if defined(LWS_WITH_GLIB)
467 context->event_loop_ops = &event_loop_ops_glib;
468 #else
469 goto fail_event_libs;
470 #endif
471
472 if (!context->event_loop_ops)
473 goto fail_event_libs;
474
475 lwsl_info("Using event loop: %s\n", context->event_loop_ops->name);
476 #endif
477
478 #if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK)
479 time(&context->tls.last_cert_check_s);
480 if (info->alpn)
481 context->tls.alpn_default = info->alpn;
482 else {
483 char *p = context->tls.alpn_discovered, first = 1;
484
485 LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
486 if (ar->alpn) {
487 if (!first)
488 *p++ = ',';
489 p += lws_snprintf(p,
490 context->tls.alpn_discovered +
491 sizeof(context->tls.alpn_discovered) -
492 2 - p, "%s", ar->alpn);
493 first = 0;
494 }
495 } LWS_FOR_EVERY_AVAILABLE_ROLE_END;
496
497 context->tls.alpn_default = context->tls.alpn_discovered;
498 }
499
500 lwsl_info("Default ALPN advertisment: %s\n", context->tls.alpn_default);
501 #endif
502
503 if (info->timeout_secs)
504 context->timeout_secs = info->timeout_secs;
505 else
506 context->timeout_secs = AWAITING_TIMEOUT;
507
508 context->ws_ping_pong_interval = info->ws_ping_pong_interval;
509
510 lwsl_info(" default timeout (secs): %u\n", context->timeout_secs);
511
512 if (info->max_http_header_data)
513 context->max_http_header_data = info->max_http_header_data;
514 else
515 if (info->max_http_header_data2)
516 context->max_http_header_data =
517 info->max_http_header_data2;
518 else
519 context->max_http_header_data = LWS_DEF_HEADER_LEN;
520
521 if (info->max_http_header_pool)
522 context->max_http_header_pool = info->max_http_header_pool;
523 else
524 if (info->max_http_header_pool2)
525 context->max_http_header_pool =
526 info->max_http_header_pool2;
527 else
528 context->max_http_header_pool = context->max_fds;
529
530
531 if (info->fd_limit_per_thread)
532 context->fd_limit_per_thread = lpf;
533 else
534 if (context->count_threads)
535 context->fd_limit_per_thread = context->max_fds /
536 context->count_threads;
537
538 #if defined(LWS_WITH_NETWORK)
539
540 context->default_retry.retry_ms_table = default_backoff_table;
541 context->default_retry.conceal_count =
542 context->default_retry.retry_ms_table_count =
543 LWS_ARRAY_SIZE(default_backoff_table);
544 context->default_retry.jitter_percent = 20;
545 context->default_retry.secs_since_valid_ping = 300;
546 context->default_retry.secs_since_valid_hangup = 310;
547
548 if (info->retry_and_idle_policy &&
549 info->retry_and_idle_policy->secs_since_valid_ping) {
550 context->default_retry.secs_since_valid_ping =
551 info->retry_and_idle_policy->secs_since_valid_ping;
552 context->default_retry.secs_since_valid_hangup =
553 info->retry_and_idle_policy->secs_since_valid_hangup;
554 }
555
556 /*
557 * Allocate the per-thread storage for scratchpad buffers,
558 * and header data pool
559 */
560 u = (uint8_t *)&context[1];
561 for (n = 0; n < context->count_threads; n++) {
562 context->pt[n].serv_buf = u;
563 u += context->pt_serv_buf_size;
564
565 context->pt[n].context = context;
566 context->pt[n].tid = n;
567
568 /*
569 * We overallocated for a fakewsi (can't compose it in the
570 * pt because size isn't known at that time). point to it
571 * and zero it down. Fakewsis are needed to make callbacks work
572 * when the source of the callback is not actually from a wsi
573 * context.
574 */
575 context->pt[n].fake_wsi = (struct lws *)u;
576 u += sizeof(struct lws);
577
578 memset(context->pt[n].fake_wsi, 0, sizeof(struct lws));
579
580 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
581 context->pt[n].http.ah_list = NULL;
582 context->pt[n].http.ah_pool_length = 0;
583 #endif
584 lws_pt_mutex_init(&context->pt[n]);
585 #if defined(LWS_WITH_SEQUENCER)
586 lws_seq_pt_init(&context->pt[n]);
587 #endif
588
589 LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
590 if (ar->pt_init_destroy)
591 ar->pt_init_destroy(context, info,
592 &context->pt[n], 0);
593 } LWS_FOR_EVERY_AVAILABLE_ROLE_END;
594
595 #if defined(LWS_WITH_CGI)
596 role_ops_cgi.pt_init_destroy(context, info, &context->pt[n], 0);
597 #endif
598 }
599
600 lwsl_info(" Threads: %d each %d fds\n", context->count_threads,
601 context->fd_limit_per_thread);
602
603 if (!info->ka_interval && info->ka_time > 0) {
604 lwsl_err("info->ka_interval can't be 0 if ka_time used\n");
605 return NULL;
606 }
607
608 #if defined(LWS_WITH_PEER_LIMITS)
609 /* scale the peer hash table according to the max fds for the process,
610 * so that the max list depth averages 16. Eg, 1024 fd -> 64,
611 * 102400 fd -> 6400
612 */
613
614 context->pl_hash_elements =
615 (context->count_threads * context->fd_limit_per_thread) / 16;
616 context->pl_hash_table = lws_zalloc(sizeof(struct lws_peer *) *
617 context->pl_hash_elements, "peer limits hash table");
618
619 context->ip_limit_ah = info->ip_limit_ah;
620 context->ip_limit_wsi = info->ip_limit_wsi;
621 #endif
622
623 lwsl_info(" mem: context: %5lu B (%ld ctx + (%ld thr x %d))\n",
624 (long)sizeof(struct lws_context) +
625 (context->count_threads * context->pt_serv_buf_size),
626 (long)sizeof(struct lws_context),
627 (long)context->count_threads,
628 context->pt_serv_buf_size);
629 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
630 lwsl_info(" mem: http hdr size: (%u + %lu), max count %u\n",
631 context->max_http_header_data,
632 (long)sizeof(struct allocated_headers),
633 context->max_http_header_pool);
634 #endif
635
636 /*
637 * fds table contains pollfd structs for as many pollfds as we can
638 * handle... spread across as many service threads as we have going
639 */
640 n = sizeof(struct lws_pollfd) * context->count_threads *
641 context->fd_limit_per_thread;
642 context->pt[0].fds = lws_zalloc(n, "fds table");
643 if (context->pt[0].fds == NULL) {
644 lwsl_err("OOM allocating %d fds\n", context->max_fds);
645 goto bail;
646 }
647 lwsl_info(" mem: pollfd map: %5u B\n", n);
648 #endif
649 #if defined(LWS_WITH_SERVER)
650 if (info->server_string) {
651 context->server_string = info->server_string;
652 context->server_string_len = (short)
653 strlen(context->server_string);
654 }
655 #endif
656
657 #if LWS_MAX_SMP > 1
658 /* each thread serves his own chunk of fds */
659 for (n = 1; n < (int)context->count_threads; n++)
660 context->pt[n].fds = context->pt[n - 1].fds +
661 context->fd_limit_per_thread;
662 #endif
663
664 if (lws_plat_init(context, info))
665 goto bail;
666
667 #if defined(LWS_WITH_NETWORK)
668 if (context->event_loop_ops->init_context)
669 if (context->event_loop_ops->init_context(context, info))
670 goto bail;
671
672
673 if (context->event_loop_ops->init_pt)
674 for (n = 0; n < context->count_threads; n++) {
675 void *lp = NULL;
676
677 if (info->foreign_loops)
678 lp = info->foreign_loops[n];
679
680 if (context->event_loop_ops->init_pt(context, lp, n))
681 goto bail;
682 }
683
684 if (lws_create_event_pipes(context))
685 goto bail;
686 #endif
687
688 lws_context_init_ssl_library(info);
689
690 context->user_space = info->user;
691
692 #if defined(LWS_WITH_SERVER)
693 strcpy(context->canonical_hostname, "unknown");
694 #if defined(LWS_WITH_NETWORK)
695 lws_server_get_canonical_hostname(context, info);
696 #endif
697 #endif
698
699 #if defined(LWS_WITH_STATS)
700 context->pt[0].sul_stats.cb = lws_sul_stats_cb;
701 __lws_sul_insert(&context->pt[0].pt_sul_owner, &context->pt[0].sul_stats,
702 10 * LWS_US_PER_SEC);
703 #endif
704 #if defined(LWS_WITH_PEER_LIMITS)
705 context->pt[0].sul_peer_limits.cb = lws_sul_peer_limits_cb;
706 __lws_sul_insert(&context->pt[0].pt_sul_owner,
707 &context->pt[0].sul_peer_limits, 10 * LWS_US_PER_SEC);
708 #endif
709
710 #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
711 memcpy(context->caps, info->caps, sizeof(context->caps));
712 context->count_caps = info->count_caps;
713 #endif
714
715
716 #if defined(LWS_WITH_NETWORK)
717
718 #if defined(LWS_WITH_SYS_ASYNC_DNS) || defined(LWS_WITH_SYS_NTPCLIENT) || \
719 defined(LWS_WITH_SYS_DHCP_CLIENT)
720 {
721 /*
722 * system vhost
723 */
724
725 struct lws_context_creation_info ii;
726 const struct lws_protocols *pp[4];
727 struct lws_vhost *vh;
728 #if defined(LWS_WITH_SYS_ASYNC_DNS)
729 extern const struct lws_protocols lws_async_dns_protocol;
730 #endif
731 #if defined(LWS_WITH_SYS_NTPCLIENT)
732 extern const struct lws_protocols lws_system_protocol_ntpc;
733 #endif
734 #if defined(LWS_WITH_SYS_DHCP_CLIENT)
735 extern const struct lws_protocols lws_system_protocol_dhcpc;
736 #endif
737
738 n = 0;
739 #if defined(LWS_WITH_SYS_ASYNC_DNS)
740 pp[n++] = &lws_async_dns_protocol;
741 #endif
742 #if defined(LWS_WITH_SYS_NTPCLIENT)
743 pp[n++] = &lws_system_protocol_ntpc;
744 #endif
745 #if defined(LWS_WITH_SYS_DHCP_CLIENT)
746 pp[n++] = &lws_system_protocol_dhcpc;
747 #endif
748 pp[n] = NULL;
749
750 memset(&ii, 0, sizeof(ii));
751 ii.vhost_name = "system";
752 ii.pprotocols = pp;
753
754 vh = lws_create_vhost(context, &ii);
755 if (!vh) {
756 lwsl_err("%s: failed to create system vhost\n",
757 __func__);
758 goto bail;
759 }
760
761 context->vhost_system = vh;
762
763 if (lws_protocol_init_vhost(vh, NULL)) {
764 lwsl_err("%s: failed to init system vhost\n", __func__);
765 goto bail;
766 }
767 #if defined(LWS_WITH_SYS_ASYNC_DNS)
768 if (lws_async_dns_init(context))
769 goto bail;
770 #endif
771 }
772 #endif
773
774 /*
775 * init the lws_state mgr for the system state
776 */
777 #if defined(_DEBUG)
778 context->mgr_system.state_names = system_state_names;
779 #endif
780 context->mgr_system.name = "system";
781 context->mgr_system.state = LWS_SYSTATE_CONTEXT_CREATED;
782 context->mgr_system.parent = context;
783
784 context->protocols_notify.name = "prot_init";
785 context->protocols_notify.notify_cb = lws_state_notify_protocol_init;
786
787 lws_state_reg_notifier(&context->mgr_system, &context->protocols_notify);
788
789 /*
790 * insert user notifiers here so they can participate with vetoing us
791 * trying to jump straight to operational, or at least observe us
792 * reaching 'operational', before we returned from context creation.
793 */
794
795 lws_state_reg_notifier_list(&context->mgr_system,
796 info->register_notifier_list);
797
798 /*
799 * if he's not saying he'll make his own vhosts later then act
800 * compatibly and make a default vhost using the data in the info
801 */
802 if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
803 if (!lws_create_vhost(context, info)) {
804 lwsl_err("Failed to create default vhost\n");
805
806 #if defined(LWS_WITH_PEER_LIMITS)
807 lws_free_set_NULL(context->pl_hash_table);
808 #endif
809 goto fail_clean_pipes;
810 }
811
812 #if defined(LWS_WITH_SECURE_STREAMS)
813
814 if (context->pss_policies_json) {
815 /*
816 * You must create your context with the explicit vhosts flag
817 * in order to use secure streams
818 */
819 assert(lws_check_opt(info->options,
820 LWS_SERVER_OPTION_EXPLICIT_VHOSTS));
821
822 if (lws_ss_policy_parse_begin(context))
823 goto bail;
824
825 n = lws_ss_policy_parse(context,
826 (uint8_t *)context->pss_policies_json,
827 strlen(context->pss_policies_json));
828 if (n != LEJP_CONTINUE && n < 0)
829 goto bail;
830
831 if (lws_ss_policy_set(context, "hardcoded")) {
832 lwsl_err("%s: policy set failed\n", __func__);
833 goto bail;
834 }
835 } else
836 lws_create_vhost(context, info);
837 #endif
838
839 lws_context_init_extensions(info, context);
840
841 lwsl_info(" mem: per-conn: %5lu bytes + protocol rx buf\n",
842 (unsigned long)sizeof(struct lws));
843
844 /*
845 * drop any root privs for this process
846 * to listen on port < 1023 we would have needed root, but now we are
847 * listening, we don't want the power for anything else
848 */
849 if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
850 if (lws_plat_drop_app_privileges(context, 1))
851 goto bail;
852
853 /*
854 * We want to move on the syste, state as far as it can go towards
855 * OPERATIONAL now. But we have to return from here first so the user
856 * code that called us can set its copy of context, which it may be
857 * relying on to perform operations triggered by the state change.
858 *
859 * We set up a sul to come back immediately and do the state change.
860 */
861
862 lws_sul_schedule(context, 0, &context->sul_system_state,
863 lws_context_creation_completion_cb, 1);
864
865 /* expedite post-context init (eg, protocols) */
866 lws_cancel_service(context);
867 #endif
868
869 return context;
870
871 #if defined(LWS_WITH_NETWORK)
872 fail_clean_pipes:
873 for (n = 0; n < context->count_threads; n++)
874 lws_destroy_event_pipe(context->pt[n].pipe_wsi);
875
876 lws_free_set_NULL(context->pt[0].fds);
877 lws_plat_context_late_destroy(context);
878 lws_free_set_NULL(context);
879
880 return NULL;
881 #endif
882
883 bail:
884 lws_context_destroy(context);
885
886 return NULL;
887
888 #if defined(LWS_WITH_NETWORK)
889 fail_event_libs:
890 lwsl_err("Requested event library support not configured, available:\n");
891 {
892 extern const struct lws_event_loop_ops *available_event_libs[];
893 const struct lws_event_loop_ops **elops = available_event_libs;
894
895 while (*elops) {
896 lwsl_err(" - %s\n", (*elops)->name);
897 elops++;
898 }
899 }
900 #endif
901 lws_free(context);
902
903 return NULL;
904 }
905
906 int
lws_context_is_deprecated(struct lws_context * context)907 lws_context_is_deprecated(struct lws_context *context)
908 {
909 return context->deprecated;
910 }
911
912 /*
913 * When using an event loop, the context destruction is in three separate
914 * parts. This is to cover both internal and foreign event loops cleanly.
915 *
916 * - lws_context_destroy() simply starts a soft close of all wsi and
917 * related allocations. The event loop continues.
918 *
919 * As the closes complete in the event loop, reference counting is used
920 * to determine when everything is closed. It then calls
921 * lws_context_destroy2().
922 *
923 * - lws_context_destroy2() cleans up the rest of the higher-level logical
924 * lws pieces like vhosts. If the loop was foreign, it then proceeds to
925 * lws_context_destroy3(). If it the loop is internal, it stops the
926 * internal loops and waits for lws_context_destroy() to be called again
927 * outside the event loop (since we cannot destroy the loop from
928 * within the loop). That will cause lws_context_destroy3() to run
929 * directly.
930 *
931 * - lws_context_destroy3() destroys any internal event loops and then
932 * destroys the context itself, setting what was info.pcontext to NULL.
933 */
934
935 /*
936 * destroy the actual context itself
937 */
938
939 static void
lws_context_destroy3(struct lws_context * context)940 lws_context_destroy3(struct lws_context *context)
941 {
942 struct lws_context **pcontext_finalize = context->pcontext_finalize;
943 int n;
944
945 #if defined(LWS_WITH_NETWORK)
946
947 context->finalize_destroy_after_internal_loops_stopped = 1;
948 if (context->event_loop_ops->destroy_context2)
949 context->event_loop_ops->destroy_context2(context);
950
951 for (n = 0; n < context->count_threads; n++) {
952 struct lws_context_per_thread *pt = &context->pt[n];
953 (void)pt;
954 #if defined(LWS_WITH_SEQUENCER)
955 lws_seq_destroy_all_on_pt(pt);
956 #endif
957 LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
958 if (ar->pt_init_destroy)
959 ar->pt_init_destroy(context, NULL, pt, 1);
960 } LWS_FOR_EVERY_AVAILABLE_ROLE_END;
961
962 #if defined(LWS_WITH_CGI)
963 role_ops_cgi.pt_init_destroy(context, NULL, pt, 1);
964 #endif
965 #if 0
966 if (context->event_loop_ops->destroy_pt)
967 context->event_loop_ops->destroy_pt(context, n);
968 #endif
969
970 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
971 while (pt->http.ah_list)
972 _lws_destroy_ah(pt, pt->http.ah_list);
973 #endif
974 }
975
976 #if defined(LWS_WITH_SYS_ASYNC_DNS)
977 lws_async_dns_deinit(&context->async_dns);
978 #endif
979 #if defined(LWS_WITH_SYS_DHCP_CLIENT)
980 lws_dhcpc_remove(context, NULL);
981 #endif
982
983 if (context->pt[0].fds)
984 lws_free_set_NULL(context->pt[0].fds);
985 #endif
986 lws_context_deinit_ssl_library(context);
987
988 #if defined(LWS_WITH_DETAILED_LATENCIES)
989 if (context->latencies_fd != -1)
990 compatible_close(context->latencies_fd);
991 #endif
992
993 for (n = 0; n < LWS_SYSBLOB_TYPE_COUNT; n++)
994 lws_system_blob_destroy(
995 lws_system_get_blob(context, n, 0));
996
997 lws_free(context);
998 lwsl_info("%s: ctx %p freed\n", __func__, context);
999
1000 if (pcontext_finalize)
1001 *pcontext_finalize = NULL;
1002 }
1003
1004 /*
1005 * really start destroying things
1006 */
1007
1008 void
lws_context_destroy2(struct lws_context * context)1009 lws_context_destroy2(struct lws_context *context)
1010 {
1011 #if defined(LWS_WITH_NETWORK)
1012 struct lws_vhost *vh = NULL, *vh1;
1013 int n;
1014 #endif
1015 #if defined(LWS_WITH_PEER_LIMITS)
1016 uint32_t nu;
1017 #endif
1018
1019 lwsl_info("%s: ctx %p\n", __func__, context);
1020
1021 lws_context_lock(context, "context destroy 2"); /* ------ context { */
1022
1023 context->being_destroyed2 = 1;
1024 #if defined(LWS_WITH_NETWORK)
1025
1026 /*
1027 * We're going to trash things like vhost-protocols
1028 * So we need to finish dealing with wsi close that
1029 * might make callbacks first
1030 */
1031 for (n = 0; n < context->count_threads; n++) {
1032 struct lws_context_per_thread *pt = &context->pt[n];
1033
1034 (void)pt;
1035
1036 #if defined(LWS_WITH_SECURE_STREAMS)
1037 lws_dll2_foreach_safe(&pt->ss_owner, NULL, lws_ss_destroy_dll);
1038 if (context->ac_policy)
1039 lwsac_free(&context->ac_policy);
1040 #endif
1041
1042 #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
1043 lws_dll2_foreach_safe(&pt->ss_client_owner, NULL, lws_sspc_destroy_dll);
1044 #endif
1045
1046 #if defined(LWS_WITH_SEQUENCER)
1047 lws_seq_destroy_all_on_pt(pt);
1048 #endif
1049 LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
1050 if (ar->pt_init_destroy)
1051 ar->pt_init_destroy(context, NULL, pt, 1);
1052 } LWS_FOR_EVERY_AVAILABLE_ROLE_END;
1053
1054 #if defined(LWS_WITH_CGI)
1055 role_ops_cgi.pt_init_destroy(context, NULL, pt, 1);
1056 #endif
1057
1058 if (context->event_loop_ops->destroy_pt)
1059 context->event_loop_ops->destroy_pt(context, n);
1060
1061 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
1062 while (pt->http.ah_list)
1063 _lws_destroy_ah(pt, pt->http.ah_list);
1064 #endif
1065 }
1066
1067 /*
1068 * free all the per-vhost allocations
1069 */
1070
1071 vh = context->vhost_list;
1072 while (vh) {
1073 vh1 = vh->vhost_next;
1074 __lws_vhost_destroy2(vh);
1075 vh = vh1;
1076 }
1077
1078 lwsl_debug("%p: post vh listl\n", __func__);
1079
1080 /* remove ourselves from the pending destruction list */
1081
1082 while (context->vhost_pending_destruction_list)
1083 /* removes itself from list */
1084 __lws_vhost_destroy2(context->vhost_pending_destruction_list);
1085 #endif
1086
1087 lwsl_debug("%p: post pdl\n", __func__);
1088
1089 lws_stats_log_dump(context);
1090 #if defined(LWS_WITH_NETWORK)
1091 lws_ssl_context_destroy(context);
1092 #endif
1093 lws_plat_context_late_destroy(context);
1094
1095 #if defined(LWS_WITH_PEER_LIMITS)
1096 for (nu = 0; nu < context->pl_hash_elements; nu++) {
1097 lws_start_foreach_llp(struct lws_peer **, peer,
1098 context->pl_hash_table[nu]) {
1099 struct lws_peer *df = *peer;
1100 *peer = df->next;
1101 lws_free(df);
1102 continue;
1103 } lws_end_foreach_llp(peer, next);
1104 }
1105 lws_free(context->pl_hash_table);
1106 #endif
1107
1108 lwsl_debug("%p: baggage\n", __func__);
1109
1110 if (context->external_baggage_free_on_destroy)
1111 free(context->external_baggage_free_on_destroy);
1112
1113 #if defined(LWS_WITH_NETWORK)
1114 lws_check_deferred_free(context, 0, 1);
1115 #endif
1116
1117 lws_context_unlock(context); /* } context ------ */
1118
1119 #if defined(LWS_WITH_NETWORK)
1120 if (context->event_loop_ops->destroy_context2)
1121 if (context->event_loop_ops->destroy_context2(context)) {
1122 context->finalize_destroy_after_internal_loops_stopped = 1;
1123 return;
1124 }
1125
1126 lwsl_debug("%p: post dc2\n", __func__);
1127
1128 if (!context->pt[0].event_loop_foreign) {
1129 int n;
1130 for (n = 0; n < context->count_threads; n++)
1131 if (context->pt[n].inside_service) {
1132 lwsl_debug("%p: bailing as inside service\n", __func__);
1133 return;
1134 }
1135 }
1136 #endif
1137
1138 lws_context_destroy3(context);
1139 }
1140
1141 #if defined(LWS_WITH_NETWORK)
1142 static void
lws_pt_destroy(struct lws_context_per_thread * pt)1143 lws_pt_destroy(struct lws_context_per_thread *pt)
1144 {
1145 volatile struct lws_foreign_thread_pollfd *ftp, *next;
1146 volatile struct lws_context_per_thread *vpt;
1147
1148 assert(!pt->is_destroyed);
1149 pt->destroy_self = 0;
1150
1151 vpt = (volatile struct lws_context_per_thread *)pt;
1152 ftp = vpt->foreign_pfd_list;
1153 while (ftp) {
1154 next = ftp->next;
1155 lws_free((void *)ftp);
1156 ftp = next;
1157 }
1158 vpt->foreign_pfd_list = NULL;
1159
1160 if (pt->pipe_wsi)
1161 lws_destroy_event_pipe(pt->pipe_wsi);
1162 pt->pipe_wsi = NULL;
1163
1164 while (pt->fds_count) {
1165 struct lws *wsi = wsi_from_fd(pt->context, pt->fds[0].fd);
1166
1167 if (!wsi)
1168 break;
1169
1170 lws_close_free_wsi(wsi,
1171 LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY,
1172 "ctx destroy"
1173 /* no protocol close */);
1174 }
1175 lws_pt_mutex_destroy(pt);
1176
1177 pt->is_destroyed = 1;
1178
1179 lwsl_info("%s: pt destroyed\n", __func__);
1180 }
1181 #endif
1182
1183 /*
1184 * Begin the context takedown
1185 */
1186
1187 void
lws_context_destroy(struct lws_context * context)1188 lws_context_destroy(struct lws_context *context)
1189 {
1190 #if defined(LWS_WITH_NETWORK)
1191 struct lws_vhost *vh = NULL;
1192 int m, deferred_pt = 0;
1193 #endif
1194
1195 if (!context || context->inside_context_destroy)
1196 return;
1197
1198 context->inside_context_destroy = 1;
1199
1200 #if defined(LWS_WITH_NETWORK)
1201 if (context->finalize_destroy_after_internal_loops_stopped) {
1202 if (context->event_loop_ops->destroy_context2)
1203 context->event_loop_ops->destroy_context2(context);
1204 lws_context_destroy3(context);
1205 /* context is invalid, no need to reset inside flag */
1206 return;
1207 }
1208 #endif
1209 if (context->being_destroyed1) {
1210 if (!context->being_destroyed2) {
1211 lws_context_destroy2(context);
1212
1213 return;
1214 }
1215 lwsl_info("%s: ctx %p: already being destroyed\n",
1216 __func__, context);
1217
1218 lws_context_destroy3(context);
1219 /* context is invalid, no need to reset inside flag */
1220 return;
1221 }
1222
1223 lwsl_info("%s: ctx %p\n", __func__, context);
1224
1225 context->being_destroyed = 1;
1226
1227 #if defined(LWS_WITH_NETWORK)
1228 lws_state_transition(&context->mgr_system, LWS_SYSTATE_POLICY_INVALID);
1229 m = context->count_threads;
1230
1231 while (m--) {
1232 struct lws_context_per_thread *pt = &context->pt[m];
1233
1234 if (pt->is_destroyed)
1235 continue;
1236
1237 if (pt->inside_lws_service) {
1238 pt->destroy_self = 1;
1239 deferred_pt = 1;
1240 continue;
1241 }
1242
1243 lws_pt_destroy(pt);
1244 }
1245
1246 if (deferred_pt) {
1247 lwsl_info("%s: waiting for deferred pt close\n", __func__);
1248 lws_cancel_service(context);
1249 goto out;
1250 }
1251
1252 context->being_destroyed1 = 1;
1253 context->requested_kill = 1;
1254
1255 /*
1256 * inform all the protocols that they are done and will have no more
1257 * callbacks.
1258 *
1259 * We can't free things until after the event loop shuts down.
1260 */
1261 if (context->protocol_init_done)
1262 vh = context->vhost_list;
1263 while (vh) {
1264 struct lws_vhost *vhn = vh->vhost_next;
1265 lws_vhost_destroy1(vh);
1266 vh = vhn;
1267 }
1268 #endif
1269
1270 lws_plat_context_early_destroy(context);
1271
1272 #if defined(LWS_WITH_NETWORK)
1273
1274 /*
1275 * We face two different needs depending if foreign loop or not.
1276 *
1277 * 1) If foreign loop, we really want to advance the destroy_context()
1278 * past here, and block only for libuv-style async close completion.
1279 *
1280 * 2a) If poll, and we exited by ourselves and are calling a final
1281 * destroy_context() outside of any service already, we want to
1282 * advance all the way in one step.
1283 *
1284 * 2b) If poll, and we are reacting to a SIGINT, service thread(s) may
1285 * be in poll wait or servicing. We can't advance the
1286 * destroy_context() to the point it's freeing things; we have to
1287 * leave that for the final destroy_context() after the service
1288 * thread(s) are finished calling for service.
1289 */
1290
1291 if (context->event_loop_ops->destroy_context1) {
1292 context->event_loop_ops->destroy_context1(context);
1293
1294 goto out;
1295 }
1296 #endif
1297
1298 #if defined(LWS_PLAT_FREERTOS)
1299 #if defined(LWS_AMAZON_RTOS)
1300 context->last_free_heap = xPortGetFreeHeapSize();
1301 #else
1302 context->last_free_heap = esp_get_free_heap_size();
1303 #endif
1304 #endif
1305
1306 context->inside_context_destroy = 0;
1307 lws_context_destroy2(context);
1308
1309 return;
1310
1311 #if defined(LWS_WITH_NETWORK)
1312 out:
1313 context->inside_context_destroy = 0;
1314 #endif
1315 }
1316
1317 struct lws_context *
lws_system_context_from_system_mgr(lws_state_manager_t * mgr)1318 lws_system_context_from_system_mgr(lws_state_manager_t *mgr)
1319 {
1320 #if defined(LWS_WITH_NETWORK)
1321 return lws_container_of(mgr, struct lws_context, mgr_system);
1322 #else
1323 return NULL;
1324 #endif
1325 }
1326