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