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#include "private-lib-core.h"
26
27static int
28lws_get_idlest_tsi(struct lws_context *context)
29{
30	unsigned int lowest = ~0u;
31	int n = 0, hit = -1;
32
33	for (; n < context->count_threads; n++) {
34		lwsl_cx_debug(context, "%d %d\n", context->pt[n].fds_count,
35				context->fd_limit_per_thread - 1);
36		if ((unsigned int)context->pt[n].fds_count !=
37		    context->fd_limit_per_thread - 1 &&
38		    (unsigned int)context->pt[n].fds_count < lowest) {
39			lowest = context->pt[n].fds_count;
40			hit = n;
41		}
42	}
43
44	return hit;
45}
46
47struct lws *
48lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi, const char *desc)
49{
50	struct lws *new_wsi;
51	int n = fixed_tsi;
52
53	if (n < 0)
54		n = lws_get_idlest_tsi(vhost->context);
55
56	if (n < 0) {
57		lwsl_vhost_err(vhost, "no space for new conn");
58		return NULL;
59	}
60
61	lws_context_lock(vhost->context, __func__);
62	new_wsi = __lws_wsi_create_with_role(vhost->context, n, NULL,
63					     vhost->lc.log_cx);
64	lws_context_unlock(vhost->context);
65	if (new_wsi == NULL) {
66		lwsl_vhost_err(vhost, "OOM");
67		return NULL;
68	}
69
70	lws_wsi_fault_timedclose(new_wsi);
71
72	__lws_lc_tag(vhost->context, &vhost->context->lcg[
73#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT)
74	strcmp(desc, "adopted") ? LWSLCG_WSI_MUX :
75#endif
76	LWSLCG_WSI_SERVER], &new_wsi->lc, desc);
77
78	new_wsi->wsistate |= LWSIFR_SERVER;
79	new_wsi->tsi = (char)n;
80	lwsl_wsi_debug(new_wsi, "joining vh %s, tsi %d",
81			vhost->name, new_wsi->tsi);
82
83	lws_vhost_bind_wsi(vhost, new_wsi);
84	new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
85	new_wsi->retry_policy = vhost->retry_policy;
86
87	/* initialize the instance struct */
88
89	lwsi_set_state(new_wsi, LRS_UNCONNECTED);
90	new_wsi->hdr_parsing_completed = 0;
91
92#ifdef LWS_WITH_TLS
93	new_wsi->tls.use_ssl = LWS_SSL_ENABLED(vhost);
94#endif
95
96	/*
97	 * these can only be set once the protocol is known
98	 * we set an un-established connection's protocol pointer
99	 * to the start of the supported list, so it can look
100	 * for matching ones during the handshake
101	 */
102	new_wsi->a.protocol = vhost->protocols;
103	new_wsi->user_space = NULL;
104
105	/*
106	 * outermost create notification for wsi
107	 * no user_space because no protocol selection
108	 */
109	vhost->protocols[0].callback(new_wsi, LWS_CALLBACK_WSI_CREATE, NULL,
110				     NULL, 0);
111
112	return new_wsi;
113}
114
115
116/* if not a socket, it's a raw, non-ssl file descriptor
117 * req cx lock, acq pt lock, acq vh lock
118 */
119
120static struct lws *
121__lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type,
122			    const char *vh_prot_name, struct lws *parent,
123			    void *opaque, const char *fi_wsi_name)
124{
125	struct lws_context *context;
126	struct lws_context_per_thread *pt;
127	struct lws *new_wsi;
128	int n;
129
130	/*
131	 * Notice that in SMP case, the wsi may be being created on an
132	 * entirely different pt / tsi for load balancing.  In that case as
133	 * we initialize it, it may become "live" concurrently unexpectedly...
134	 */
135
136	if (!vh)
137		return NULL;
138
139	context = vh->context;
140
141	lws_context_assert_lock_held(vh->context);
142
143	n = -1;
144	if (parent)
145		n = parent->tsi;
146	new_wsi = lws_create_new_server_wsi(vh, n, "adopted");
147	if (!new_wsi)
148		return NULL;
149
150	/* bring in specific fault injection rules early */
151	lws_fi_inherit_copy(&new_wsi->fic, &context->fic, "wsi", fi_wsi_name);
152
153	if (lws_fi(&new_wsi->fic, "createfail")) {
154		lws_fi_destroy(&new_wsi->fic);
155
156		return NULL;
157	}
158
159	new_wsi->a.opaque_user_data = opaque;
160
161	pt = &context->pt[(int)new_wsi->tsi];
162	lws_pt_lock(pt, __func__);
163
164	if (parent) {
165		new_wsi->parent = parent;
166		new_wsi->sibling_list = parent->child_list;
167		parent->child_list = new_wsi;
168	}
169
170	if (vh_prot_name) {
171		new_wsi->a.protocol = lws_vhost_name_to_protocol(new_wsi->a.vhost,
172							       vh_prot_name);
173		if (!new_wsi->a.protocol) {
174			lwsl_vhost_err(new_wsi->a.vhost, "Protocol %s not enabled",
175						      vh_prot_name);
176			goto bail;
177		}
178		if (lws_ensure_user_space(new_wsi)) {
179			lwsl_wsi_notice(new_wsi, "OOM");
180			goto bail;
181		}
182	}
183
184	if (!LWS_SSL_ENABLED(new_wsi->a.vhost) ||
185	    !(type & LWS_ADOPT_SOCKET))
186		type &= (unsigned int)~LWS_ADOPT_ALLOW_SSL;
187
188	if (lws_role_call_adoption_bind(new_wsi, (int)type, vh_prot_name)) {
189		lwsl_wsi_err(new_wsi, "no role for desc type 0x%x", type);
190		goto bail;
191	}
192
193#if defined(LWS_WITH_SERVER)
194	if (new_wsi->role_ops) {
195		lws_metrics_tag_wsi_add(new_wsi, "role", new_wsi->role_ops->name);
196	}
197#endif
198
199	lws_pt_unlock(pt);
200
201	/*
202	 * he's an allocated wsi, but he's not on any fds list or child list,
203	 * join him to the vhost's list of these kinds of incomplete wsi until
204	 * he gets another identity (he may do async dns now...)
205	 */
206	lws_vhost_lock(new_wsi->a.vhost);
207	lws_dll2_add_head(&new_wsi->vh_awaiting_socket,
208			  &new_wsi->a.vhost->vh_awaiting_socket_owner);
209	lws_vhost_unlock(new_wsi->a.vhost);
210
211	return new_wsi;
212
213bail:
214	lwsl_wsi_notice(new_wsi, "exiting on bail");
215	if (parent)
216		parent->child_list = new_wsi->sibling_list;
217	if (new_wsi->user_space)
218		lws_free(new_wsi->user_space);
219
220	lws_fi_destroy(&new_wsi->fic);
221
222	lws_pt_unlock(pt);
223	__lws_vhost_unbind_wsi(new_wsi); /* req cx, acq vh lock */
224
225	lws_free(new_wsi);
226
227	return NULL;
228}
229
230#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS)
231
232/*
233 * If the incoming wsi is bound to a vhost that is a ss server, this creates
234 * an accepted ss bound to the wsi.
235 *
236 * For h1 or raw, we can do the binding here, but for muxed protocols like h2
237 * or mqtt we have to do it not on the nwsi but on the stream.  And for h2 we
238 * start off bound to h1 role, since we don't know if we will upgrade to h2
239 * until we meet the server.
240 *
241 * 1) No tls is assumed to mean no muxed protocol so can do it at adopt.
242 *
243 * 2) After alpn if not muxed we can do it.
244 *
245 * 3) For muxed, do it at the nwsi migration and on new stream
246 */
247
248int
249lws_adopt_ss_server_accept(struct lws *new_wsi)
250{
251	struct lws_context_per_thread *pt =
252			&new_wsi->a.context->pt[(int)new_wsi->tsi];
253	lws_ss_handle_t *h;
254	void *pv, **ppv;
255
256	if (!new_wsi->a.vhost->ss_handle)
257		return 0;
258
259	pv = (char *)&new_wsi->a.vhost->ss_handle[1];
260
261	/*
262	 * Yes... the vhost is pointing to its secure stream representing the
263	 * server... we want to create an accepted SS and bind it to new_wsi,
264	 * the info/ssi from the server SS (so the SS callbacks defined there),
265	 * the opaque_user_data of the server object and the policy of it.
266	 */
267
268	ppv = (void **)((char *)pv +
269	      new_wsi->a.vhost->ss_handle->info.opaque_user_data_offset);
270
271	/*
272	 * indicate we are an accepted connection referencing the
273	 * server object
274	 */
275
276	new_wsi->a.vhost->ss_handle->info.flags |= LWSSSINFLAGS_SERVER;
277
278	if (lws_ss_create(new_wsi->a.context, new_wsi->tsi,
279			  &new_wsi->a.vhost->ss_handle->info,
280			  *ppv, &h, NULL, NULL)) {
281		lwsl_wsi_err(new_wsi, "accept ss creation failed");
282		goto fail1;
283	}
284
285	/*
286	 * We made a fresh accepted SS conn from the server pieces,
287	 * now bind the wsi... the problem is, this is the nwsi if it's
288	 * h2.
289	 */
290
291	h->wsi = new_wsi;
292	new_wsi->a.opaque_user_data = h;
293	h->info.flags |= LWSSSINFLAGS_ACCEPTED;
294	/* indicate wsi should invalidate any ss link to it on close */
295	new_wsi->for_ss = 1;
296
297	// lwsl_wsi_notice(new_wsi, "%s: opaq %p, role %s",
298	//			     new_wsi->a.opaque_user_data,
299	//			     new_wsi->role_ops->name);
300
301	h->policy = new_wsi->a.vhost->ss_handle->policy;
302
303	/* apply requested socket options */
304	if (lws_plat_set_socket_options_ip(new_wsi->desc.sockfd,
305					   h->policy->priority,
306		      (LCCSCF_IP_LOW_LATENCY *
307		       !!(h->policy->flags & LWSSSPOLF_ATTR_LOW_LATENCY)) |
308		      (LCCSCF_IP_HIGH_THROUGHPUT *
309		       !!(h->policy->flags & LWSSSPOLF_ATTR_HIGH_THROUGHPUT)) |
310		      (LCCSCF_IP_HIGH_RELIABILITY *
311		       !!(h->policy->flags & LWSSSPOLF_ATTR_HIGH_RELIABILITY)) |
312		      (LCCSCF_IP_LOW_COST *
313		       !!(h->policy->flags & LWSSSPOLF_ATTR_LOW_COST))))
314		lwsl_wsi_warn(new_wsi, "unable to set ip options");
315
316	/*
317	 * add us to the list of clients that came in from the server
318	 */
319
320	lws_pt_lock(pt, __func__);
321	lws_dll2_add_tail(&h->cli_list, &new_wsi->a.vhost->ss_handle->src_list);
322	lws_pt_unlock(pt);
323
324	/*
325	 * Let's give it appropriate state notifications
326	 */
327
328	if (lws_ss_event_helper(h, LWSSSCS_CREATING))
329		goto fail;
330	if (lws_ss_event_helper(h, LWSSSCS_CONNECTING))
331		goto fail;
332
333	/* defer CONNECTED until we see if he is upgrading */
334
335//	if (lws_ss_event_helper(h, LWSSSCS_CONNECTED))
336//		goto fail;
337
338	// lwsl_notice("%s: accepted ss complete, pcol %s\n", __func__,
339	//		new_wsi->a.protocol->name);
340
341	return 0;
342
343fail:
344	lws_ss_destroy(&h);
345fail1:
346	return 1;
347}
348
349#endif
350
351
352static struct lws *
353lws_adopt_descriptor_vhost2(struct lws *new_wsi, lws_adoption_type type,
354			    lws_sock_file_fd_type fd)
355{
356	struct lws_context_per_thread *pt =
357			&new_wsi->a.context->pt[(int)new_wsi->tsi];
358	int n;
359
360	/* enforce that every fd is nonblocking */
361
362	if (type & LWS_ADOPT_SOCKET) {
363		if (lws_plat_set_nonblocking(fd.sockfd)) {
364			lwsl_wsi_err(new_wsi, "unable to set sockfd %d nonblocking",
365				     fd.sockfd);
366			goto fail;
367		}
368	}
369#if !defined(WIN32)
370	else
371		if (lws_plat_set_nonblocking(fd.filefd)) {
372			lwsl_wsi_err(new_wsi, "unable to set filefd nonblocking");
373			goto fail;
374		}
375#endif
376
377	new_wsi->desc = fd;
378
379	if (!LWS_SSL_ENABLED(new_wsi->a.vhost) ||
380	    !(type & LWS_ADOPT_SOCKET))
381		type &= (unsigned int)~LWS_ADOPT_ALLOW_SSL;
382
383	/*
384	 * A new connection was accepted. Give the user a chance to
385	 * set properties of the newly created wsi. There's no protocol
386	 * selected yet so we issue this to the vhosts's default protocol,
387	 * itself by default protocols[0]
388	 */
389	new_wsi->wsistate |= LWSIFR_SERVER;
390	n = LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED;
391	if (new_wsi->role_ops->adoption_cb[lwsi_role_server(new_wsi)])
392		n = new_wsi->role_ops->adoption_cb[lwsi_role_server(new_wsi)];
393
394	if (new_wsi->a.context->event_loop_ops->sock_accept)
395		if (new_wsi->a.context->event_loop_ops->sock_accept(new_wsi))
396			goto fail;
397
398#if LWS_MAX_SMP > 1
399	/*
400	 * Caution: after this point the wsi is live on its service thread
401	 * which may be concurrent to this.  We mark the wsi as still undergoing
402	 * init in another pt so the assigned pt leaves it alone.
403	 */
404	new_wsi->undergoing_init_from_other_pt = 1;
405#endif
406
407	if (!(type & LWS_ADOPT_ALLOW_SSL)) {
408		lws_pt_lock(pt, __func__);
409		if (__insert_wsi_socket_into_fds(new_wsi->a.context, new_wsi)) {
410			lws_pt_unlock(pt);
411			lwsl_wsi_err(new_wsi, "fail inserting socket");
412			goto fail;
413		}
414		lws_pt_unlock(pt);
415	}
416#if defined(LWS_WITH_SERVER)
417	 else
418		if (lws_server_socket_service_ssl(new_wsi, fd.sockfd, 0)) {
419			lwsl_wsi_info(new_wsi, "fail ssl negotiation");
420
421			goto fail;
422		}
423#endif
424
425	lws_vhost_lock(new_wsi->a.vhost);
426	/* he has fds visibility now, remove from vhost orphan list */
427	lws_dll2_remove(&new_wsi->vh_awaiting_socket);
428	lws_vhost_unlock(new_wsi->a.vhost);
429
430	/*
431	 *  by deferring callback to this point, after insertion to fds,
432	 * lws_callback_on_writable() can work from the callback
433	 */
434	if ((new_wsi->a.protocol->callback)(new_wsi, (enum lws_callback_reasons)n, new_wsi->user_space,
435					  NULL, 0))
436		goto fail;
437
438	/* role may need to do something after all adoption completed */
439
440	lws_role_call_adoption_bind(new_wsi, (int)type | _LWS_ADOPT_FINISH,
441				    new_wsi->a.protocol->name);
442
443#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS)
444	/*
445	 * Did we come from an accepted client connection to a ss server?
446	 *
447	 * !!! For mux protocols, this will cause an additional inactive ss
448	 * representing the nwsi.  Doing that allows us to support both h1
449	 * (here) and h2 (at __lws_wsi_server_new())
450	 */
451
452	lwsl_wsi_info(new_wsi, "vhost %s", new_wsi->a.vhost->lc.gutag);
453
454	if (lws_adopt_ss_server_accept(new_wsi))
455		goto fail;
456#endif
457
458#if LWS_MAX_SMP > 1
459	/* its actual pt can service it now */
460
461	new_wsi->undergoing_init_from_other_pt = 0;
462#endif
463
464	lws_cancel_service_pt(new_wsi);
465
466	return new_wsi;
467
468fail:
469	if (type & LWS_ADOPT_SOCKET)
470		lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS,
471				   "adopt skt fail");
472
473	return NULL;
474}
475
476
477/* if not a socket, it's a raw, non-ssl file descriptor */
478
479struct lws *
480lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
481			   lws_sock_file_fd_type fd, const char *vh_prot_name,
482			   struct lws *parent)
483{
484	lws_adopt_desc_t info;
485
486	memset(&info, 0, sizeof(info));
487
488	info.vh = vh;
489	info.type = type;
490	info.fd = fd;
491	info.vh_prot_name = vh_prot_name;
492	info.parent = parent;
493
494	return lws_adopt_descriptor_vhost_via_info(&info);
495}
496
497struct lws *
498lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info)
499{
500	socklen_t slen = sizeof(lws_sockaddr46);
501	struct lws *new_wsi;
502
503#if defined(LWS_WITH_PEER_LIMITS)
504	struct lws_peer *peer = NULL;
505
506	if (info->type & LWS_ADOPT_SOCKET) {
507		peer = lws_get_or_create_peer(info->vh, info->fd.sockfd);
508
509		if (peer && info->vh->context->ip_limit_wsi &&
510		    peer->count_wsi >= info->vh->context->ip_limit_wsi) {
511			lwsl_info("Peer reached wsi limit %d\n",
512					info->vh->context->ip_limit_wsi);
513			if (info->vh->context->pl_notify_cb)
514				info->vh->context->pl_notify_cb(
515							info->vh->context,
516							info->fd.sockfd,
517							&peer->sa46);
518			compatible_close(info->fd.sockfd);
519			return NULL;
520		}
521	}
522#endif
523
524	lws_context_lock(info->vh->context, __func__);
525
526	new_wsi = __lws_adopt_descriptor_vhost1(info->vh, info->type,
527					      info->vh_prot_name, info->parent,
528					      info->opaque, info->fi_wsi_name);
529	if (!new_wsi) {
530		if (info->type & LWS_ADOPT_SOCKET)
531			compatible_close(info->fd.sockfd);
532		goto bail;
533	}
534
535	if (info->type & LWS_ADOPT_SOCKET &&
536	    getpeername(info->fd.sockfd, (struct sockaddr *)&new_wsi->sa46_peer,
537								    &slen) < 0)
538		lwsl_info("%s: getpeername failed\n", __func__);
539
540#if defined(LWS_WITH_PEER_LIMITS)
541	if (peer)
542		lws_peer_add_wsi(info->vh->context, peer, new_wsi);
543#endif
544
545	new_wsi = lws_adopt_descriptor_vhost2(new_wsi, info->type, info->fd);
546
547bail:
548	lws_context_unlock(info->vh->context);
549
550	return new_wsi;
551}
552
553struct lws *
554lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
555{
556	lws_sock_file_fd_type fd;
557
558	fd.sockfd = accept_fd;
559	return lws_adopt_descriptor_vhost(vh, LWS_ADOPT_SOCKET |
560			LWS_ADOPT_HTTP | LWS_ADOPT_ALLOW_SSL, fd, NULL, NULL);
561}
562
563struct lws *
564lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
565{
566	return lws_adopt_socket_vhost(context->vhost_list, accept_fd);
567}
568
569/* Common read-buffer adoption for lws_adopt_*_readbuf */
570static struct lws*
571adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)
572{
573	struct lws_context_per_thread *pt;
574	struct lws_pollfd *pfd;
575	int n;
576
577	if (!wsi)
578		return NULL;
579
580	if (!readbuf || len == 0)
581		return wsi;
582
583	if (wsi->position_in_fds_table == LWS_NO_FDS_POS)
584		return wsi;
585
586	pt = &wsi->a.context->pt[(int)wsi->tsi];
587
588	n = lws_buflist_append_segment(&wsi->buflist, (const uint8_t *)readbuf,
589				       len);
590	if (n < 0)
591		goto bail;
592	if (n)
593		lws_dll2_add_head(&wsi->dll_buflist, &pt->dll_buflist_owner);
594
595	/*
596	 * we can't process the initial read data until we can attach an ah.
597	 *
598	 * if one is available, get it and place the data in his ah rxbuf...
599	 * wsi with ah that have pending rxbuf get auto-POLLIN service.
600	 *
601	 * no autoservice because we didn't get a chance to attach the
602	 * readbuf data to wsi or ah yet, and we will do it next if we get
603	 * the ah.
604	 */
605	if (wsi->http.ah || !lws_header_table_attach(wsi, 0)) {
606
607		lwsl_notice("%s: calling service on readbuf ah\n", __func__);
608
609		/*
610		 * unlike a normal connect, we have the headers already
611		 * (or the first part of them anyway).
612		 * libuv won't come back and service us without a network
613		 * event, so we need to do the header service right here.
614		 */
615		pfd = &pt->fds[wsi->position_in_fds_table];
616		pfd->revents |= LWS_POLLIN;
617		lwsl_err("%s: calling service\n", __func__);
618		if (lws_service_fd_tsi(wsi->a.context, pfd, wsi->tsi))
619			/* service closed us */
620			return NULL;
621
622		return wsi;
623	}
624	lwsl_err("%s: deferring handling ah\n", __func__);
625
626	return wsi;
627
628bail:
629	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
630			   "adopt skt readbuf fail");
631
632	return NULL;
633}
634
635#if defined(LWS_WITH_UDP)
636#if defined(LWS_WITH_CLIENT)
637
638/*
639 * This is the ASYNC_DNS callback target for udp client, it's analogous to
640 * connect3()
641 */
642
643static struct lws *
644lws_create_adopt_udp2(struct lws *wsi, const char *ads,
645		      const struct addrinfo *r, int n, void *opaque)
646{
647	lws_sock_file_fd_type sock;
648	int bc = 1, m;
649
650	assert(wsi);
651
652	if (ads && (n < 0 || !r)) {
653		/*
654		 * DNS lookup failed: there are no usable results.  Fail the
655		 * overall connection request.
656		 */
657		lwsl_notice("%s: bad: n %d, r %p\n", __func__, n, r);
658
659		goto bail;
660	}
661
662	m = lws_sort_dns(wsi, r);
663#if defined(LWS_WITH_SYS_ASYNC_DNS)
664	lws_async_dns_freeaddrinfo(&r);
665#else
666	freeaddrinfo((struct addrinfo *)r);
667#endif
668	if (m)
669		goto bail;
670
671	while (lws_dll2_get_head(&wsi->dns_sorted_list)) {
672		lws_dns_sort_t *s = lws_container_of(
673				lws_dll2_get_head(&wsi->dns_sorted_list),
674				lws_dns_sort_t, list);
675
676		/*
677		 * Remove it from the head, but don't free it yet... we are
678		 * taking responsibility to free it
679		 */
680		lws_dll2_remove(&s->list);
681
682		/*
683		 * We have done the dns lookup, identify the result we want
684		 * if any, and then complete the adoption by binding wsi to
685		 * socket opened on it.
686		 *
687		 * Ignore the weak assumptions about protocol driven by port
688		 * number and force to DGRAM / UDP since that's what this
689		 * function is for.
690		 */
691
692#if !defined(__linux__)
693		sock.sockfd = socket(s->dest.sa4.sin_family,
694				     SOCK_DGRAM, IPPROTO_UDP);
695#else
696		/* PF_PACKET is linux-only */
697		sock.sockfd = socket(wsi->pf_packet ? PF_PACKET :
698						s->dest.sa4.sin_family,
699				     SOCK_DGRAM, wsi->pf_packet ?
700					htons(0x800) : IPPROTO_UDP);
701#endif
702		if (sock.sockfd == LWS_SOCK_INVALID)
703			goto resume;
704
705		/* ipv6 udp!!! */
706
707		if (s->af == AF_INET)
708			s->dest.sa4.sin_port = htons(wsi->c_port);
709#if defined(LWS_WITH_IPV6)
710		else
711			s->dest.sa6.sin6_port = htons(wsi->c_port);
712#endif
713
714		if (setsockopt(sock.sockfd, SOL_SOCKET, SO_REUSEADDR,
715			       (const char *)&bc, sizeof(bc)) < 0)
716			lwsl_err("%s: failed to set reuse\n", __func__);
717
718		if (wsi->do_broadcast &&
719		    setsockopt(sock.sockfd, SOL_SOCKET, SO_BROADCAST,
720			       (const char *)&bc, sizeof(bc)) < 0)
721			lwsl_err("%s: failed to set broadcast\n", __func__);
722
723		/* Bind the udp socket to a particular network interface */
724
725		if (opaque &&
726		    lws_plat_BINDTODEVICE(sock.sockfd, (const char *)opaque))
727			goto resume;
728
729		if (wsi->do_bind &&
730		    bind(sock.sockfd, sa46_sockaddr(&s->dest),
731#if defined(_WIN32)
732			 (int)sa46_socklen(&s->dest)
733#else
734			 sizeof(struct sockaddr)
735#endif
736		) == -1) {
737			lwsl_err("%s: bind failed\n", __func__);
738			goto resume;
739		}
740
741		if (!wsi->do_bind && !wsi->pf_packet) {
742#if !defined(__APPLE__)
743			if (connect(sock.sockfd, sa46_sockaddr(&s->dest),
744				    sa46_socklen(&s->dest)) == -1 &&
745			    errno != EADDRNOTAVAIL /* openbsd */ ) {
746				lwsl_err("%s: conn fd %d fam %d %s:%u failed "
747					 "errno %d\n", __func__, sock.sockfd,
748					 s->dest.sa4.sin_family,
749					 ads ? ads : "null", wsi->c_port,
750					 LWS_ERRNO);
751				compatible_close(sock.sockfd);
752				goto resume;
753			}
754#endif
755		}
756
757		if (wsi->udp)
758			wsi->udp->sa46 = s->dest;
759		wsi->sa46_peer = s->dest;
760
761		/* we connected: complete the udp socket adoption flow */
762
763#if defined(LWS_WITH_SYS_ASYNC_DNS)
764	if (wsi->a.context->async_dns.wsi == wsi)
765		wsi->a.context->async_dns.dns_server_connected = 1;
766#endif
767
768		lws_free(s);
769		lws_addrinfo_clean(wsi);
770		return lws_adopt_descriptor_vhost2(wsi,
771						LWS_ADOPT_RAW_SOCKET_UDP, sock);
772
773resume:
774		lws_free(s);
775	}
776
777	lwsl_err("%s: unable to create INET socket %d\n", __func__, LWS_ERRNO);
778	lws_addrinfo_clean(wsi);
779
780#if defined(LWS_WITH_SYS_ASYNC_DNS)
781	if (wsi->a.context->async_dns.wsi == wsi)
782		lws_async_dns_drop_server(wsi->a.context);
783#endif
784
785bail:
786
787	/* caller must close */
788
789	return NULL;
790}
791
792struct lws *
793lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port,
794		     int flags, const char *protocol_name, const char *ifname,
795		     struct lws *parent_wsi, void *opaque,
796		     const lws_retry_bo_t *retry_policy, const char *fi_wsi_name)
797{
798#if !defined(LWS_PLAT_OPTEE)
799	struct lws *wsi;
800	int n;
801
802	lwsl_info("%s: %s:%u\n", __func__, ads ? ads : "null", port);
803
804	/* create the logical wsi without any valid fd */
805
806	lws_context_lock(vhost->context, __func__);
807
808	wsi = __lws_adopt_descriptor_vhost1(vhost, LWS_ADOPT_SOCKET |
809						 LWS_ADOPT_RAW_SOCKET_UDP,
810					  protocol_name, parent_wsi, opaque,
811					  fi_wsi_name);
812
813	lws_context_unlock(vhost->context);
814	if (!wsi) {
815		lwsl_err("%s: udp wsi creation failed\n", __func__);
816		goto bail;
817	}
818
819	// lwsl_notice("%s: role %s\n", __func__, wsi->role_ops->name);
820
821	wsi->do_bind = !!(flags & LWS_CAUDP_BIND);
822	wsi->do_broadcast = !!(flags & LWS_CAUDP_BROADCAST);
823	wsi->pf_packet = !!(flags & LWS_CAUDP_PF_PACKET);
824	wsi->c_port = (uint16_t)(unsigned int)port;
825	if (retry_policy)
826		wsi->retry_policy = retry_policy;
827	else
828		wsi->retry_policy = vhost->retry_policy;
829
830#if !defined(LWS_WITH_SYS_ASYNC_DNS)
831	{
832		struct addrinfo *r, h;
833		char buf[16];
834
835		memset(&h, 0, sizeof(h));
836		h.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
837		h.ai_socktype = SOCK_DGRAM;
838		h.ai_protocol = IPPROTO_UDP;
839#if defined(AI_PASSIVE)
840		h.ai_flags = AI_PASSIVE;
841#endif
842#ifdef AI_ADDRCONFIG
843		h.ai_flags |= AI_ADDRCONFIG;
844#endif
845
846		/* if the dns lookup is synchronous, do the whole thing now */
847		lws_snprintf(buf, sizeof(buf), "%u", port);
848		n = getaddrinfo(ads, buf, &h, &r);
849		if (n) {
850
851#if (_LWS_ENABLED_LOGS & LLL_INFO)
852#if !defined(LWS_PLAT_FREERTOS)
853			lwsl_info("%s: getaddrinfo error: %s\n", __func__,
854				  gai_strerror(n));
855#else
856
857			lwsl_info("%s: getaddrinfo error: %s\n", __func__,
858					strerror(n));
859#endif
860#endif
861			//freeaddrinfo(r);
862			goto bail1;
863		}
864		/*
865		 * With synchronous dns, complete it immediately after the
866		 * blocking dns lookup finished... free r when connect either
867		 * completed or failed
868		 */
869		wsi = lws_create_adopt_udp2(wsi, ads, r, 0, NULL);
870
871		return wsi;
872	}
873#else
874	if (ads) {
875		/*
876		 * with async dns, use the wsi as the point about which to do
877		 * the dns lookup and have it call the second part when it's
878		 * done.
879		 *
880		 * Keep a refcount on the results and free it when we connected
881		 * or definitively failed.
882		 *
883		 * Notice wsi has no socket at this point (we don't know what
884		 * kind to ask for until we get the dns back).  But it is bound
885		 * to a vhost and can be cleaned up from that at vhost destroy.
886		 */
887		n = lws_async_dns_query(vhost->context, 0, ads,
888					LWS_ADNS_RECORD_A,
889					lws_create_adopt_udp2, wsi,
890					(void *)ifname);
891		// lwsl_notice("%s: dns query returned %d\n", __func__, n);
892		if (n == LADNS_RET_FAILED) {
893			lwsl_err("%s: async dns failed\n", __func__);
894			wsi = NULL;
895			/*
896			 * It was already closed by calling callback with error
897			 * from lws_async_dns_query()
898			 */
899			goto bail;
900		}
901	} else {
902		lwsl_debug("%s: udp adopt has no ads\n", __func__);
903		wsi = lws_create_adopt_udp2(wsi, ads, NULL, 0, (void *)ifname);
904	}
905
906	/* dns lookup is happening asynchronously */
907
908	// lwsl_notice("%s: returning wsi %p\n", __func__, wsi);
909
910	return wsi;
911#endif
912#if !defined(LWS_WITH_SYS_ASYNC_DNS)
913bail1:
914	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "adopt udp2 fail");
915	wsi = NULL;
916#endif
917bail:
918	return wsi;
919#else
920	return NULL;
921#endif
922}
923#endif
924#endif
925
926struct lws *
927lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
928			 const char *readbuf, size_t len)
929{
930        return adopt_socket_readbuf(lws_adopt_socket(context, accept_fd),
931				    readbuf, len);
932}
933
934struct lws *
935lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost,
936			       lws_sockfd_type accept_fd,
937			       const char *readbuf, size_t len)
938{
939        return adopt_socket_readbuf(lws_adopt_socket_vhost(vhost, accept_fd),
940				    readbuf, len);
941}
942