• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 static int
lws_get_idlest_tsi(struct lws_context * context)28 lws_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 
47 struct lws *
lws_create_new_server_wsi(struct lws_vhost * vhost,int fixed_tsi,const char * desc)48 lws_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 
120 static struct lws *
__lws_adopt_descriptor_vhost1(struct lws_vhost * vh,lws_adoption_type type,const char * vh_prot_name,struct lws * parent,void * opaque,const char * fi_wsi_name)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 
213 bail:
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 
248 int
lws_adopt_ss_server_accept(struct lws * new_wsi)249 lws_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 
343 fail:
344 	lws_ss_destroy(&h);
345 fail1:
346 	return 1;
347 }
348 
349 #endif
350 
351 
352 static struct lws *
lws_adopt_descriptor_vhost2(struct lws * new_wsi,lws_adoption_type type,lws_sock_file_fd_type fd)353 lws_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 
468 fail:
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 
479 struct lws *
lws_adopt_descriptor_vhost(struct lws_vhost * vh,lws_adoption_type type,lws_sock_file_fd_type fd,const char * vh_prot_name,struct lws * parent)480 lws_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 
497 struct lws *
lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t * info)498 lws_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 
547 bail:
548 	lws_context_unlock(info->vh->context);
549 
550 	return new_wsi;
551 }
552 
553 struct lws *
lws_adopt_socket_vhost(struct lws_vhost * vh,lws_sockfd_type accept_fd)554 lws_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 
563 struct lws *
lws_adopt_socket(struct lws_context * context,lws_sockfd_type accept_fd)564 lws_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 */
570 static struct lws*
adopt_socket_readbuf(struct lws * wsi,const char * readbuf,size_t len)571 adopt_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 
628 bail:
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 
643 static struct lws *
lws_create_adopt_udp2(struct lws * wsi,const char * ads,const struct addrinfo * r,int n,void * opaque)644 lws_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 
773 resume:
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 
785 bail:
786 
787 	/* caller must close */
788 
789 	return NULL;
790 }
791 
792 struct lws *
lws_create_adopt_udp(struct lws_vhost * vhost,const char * ads,int port,int flags,const char * protocol_name,const char * ifname,struct lws * parent_wsi,void * opaque,const lws_retry_bo_t * retry_policy,const char * fi_wsi_name)793 lws_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 #if !defined(LWS_PLAT_FREERTOS)
851 			lwsl_info("%s: getaddrinfo error: %s\n", __func__,
852 				  gai_strerror(n));
853 #else
854 			lwsl_info("%s: getaddrinfo error: %s\n", __func__,
855 					strerror(n));
856 #endif
857 			//freeaddrinfo(r);
858 			goto bail1;
859 		}
860 		/*
861 		 * With synchronous dns, complete it immediately after the
862 		 * blocking dns lookup finished... free r when connect either
863 		 * completed or failed
864 		 */
865 		wsi = lws_create_adopt_udp2(wsi, ads, r, 0, NULL);
866 
867 		return wsi;
868 	}
869 #else
870 	if (ads) {
871 		/*
872 		 * with async dns, use the wsi as the point about which to do
873 		 * the dns lookup and have it call the second part when it's
874 		 * done.
875 		 *
876 		 * Keep a refcount on the results and free it when we connected
877 		 * or definitively failed.
878 		 *
879 		 * Notice wsi has no socket at this point (we don't know what
880 		 * kind to ask for until we get the dns back).  But it is bound
881 		 * to a vhost and can be cleaned up from that at vhost destroy.
882 		 */
883 		n = lws_async_dns_query(vhost->context, 0, ads,
884 					LWS_ADNS_RECORD_A,
885 					lws_create_adopt_udp2, wsi,
886 					(void *)ifname);
887 		// lwsl_notice("%s: dns query returned %d\n", __func__, n);
888 		if (n == LADNS_RET_FAILED) {
889 			lwsl_err("%s: async dns failed\n", __func__);
890 			wsi = NULL;
891 			/*
892 			 * It was already closed by calling callback with error
893 			 * from lws_async_dns_query()
894 			 */
895 			goto bail;
896 		}
897 	} else {
898 		lwsl_debug("%s: udp adopt has no ads\n", __func__);
899 		wsi = lws_create_adopt_udp2(wsi, ads, NULL, 0, (void *)ifname);
900 	}
901 
902 	/* dns lookup is happening asynchronously */
903 
904 	// lwsl_notice("%s: returning wsi %p\n", __func__, wsi);
905 
906 	return wsi;
907 #endif
908 #if !defined(LWS_WITH_SYS_ASYNC_DNS)
909 bail1:
910 	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "adopt udp2 fail");
911 	wsi = NULL;
912 #endif
913 bail:
914 	return wsi;
915 #else
916 	return NULL;
917 #endif
918 }
919 #endif
920 #endif
921 
922 struct lws *
lws_adopt_socket_readbuf(struct lws_context * context,lws_sockfd_type accept_fd,const char * readbuf,size_t len)923 lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
924 			 const char *readbuf, size_t len)
925 {
926         return adopt_socket_readbuf(lws_adopt_socket(context, accept_fd),
927 				    readbuf, len);
928 }
929 
930 struct lws *
lws_adopt_socket_vhost_readbuf(struct lws_vhost * vhost,lws_sockfd_type accept_fd,const char * readbuf,size_t len)931 lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost,
932 			       lws_sockfd_type accept_fd,
933 			       const char *readbuf, size_t len)
934 {
935         return adopt_socket_readbuf(lws_adopt_socket_vhost(vhost, accept_fd),
936 				    readbuf, len);
937 }
938