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#define MIN(a, b) ((a) < (b) ? (a) : (b)) 28 29size_t get_res_size(struct addrinfo *res) 30{ 31 size_t size = 0; 32 for (struct addrinfo *p = res; p; p = p->ai_next) { 33 if (p->ai_family != AF_INET && p->ai_family != AF_INET6) { 34 continue; 35 } 36 ++size; 37 } 38 return size; 39} 40 41struct addrinfo **get_dns_res(struct addrinfo *res, sa_family_t family, size_t totalLength, size_t *size) 42{ 43 struct addrinfo **temp = (struct addrinfo **)(malloc(sizeof(struct addrinfo *) * totalLength)); 44 if (!temp) { 45 return NULL; 46 } 47 size_t index = 0; 48 for (struct addrinfo *p = res; p; p = p->ai_next) { 49 if (p->ai_family == family) { 50 temp[index] = p; 51 ++index; 52 } 53 } 54 *size = index; 55 return temp; 56} 57 58sa_family_t change_family(sa_family_t nowFamily) 59{ 60 if (nowFamily == AF_INET6) { 61 return AF_INET; 62 } 63 return AF_INET6; 64} 65 66struct addrinfo *sort_dns(struct addrinfo *res) 67{ 68 size_t totalLength = get_res_size(res); 69 if (totalLength == 0) { 70 return NULL; 71 } 72 73 size_t ipv6Size = 0; 74 struct addrinfo **ipv6Dns = get_dns_res(res, AF_INET6, totalLength, &ipv6Size); 75 size_t ipv4Size = 0; 76 struct addrinfo **ipv4Dns = get_dns_res(res, AF_INET, totalLength, &ipv4Size); 77 if (ipv4Dns == NULL && ipv6Dns == NULL) { 78 return NULL; 79 } 80 81 for (size_t i = 0; i < ipv6Size; ++i) { 82 ipv6Dns[i]->ai_next = NULL; 83 } 84 for (size_t i = 0; i < ipv4Size; ++i) { 85 ipv4Dns[i]->ai_next = NULL; 86 } 87 88 size_t ipv6Index = 0; 89 size_t ipv4Index = 0; 90 sa_family_t now = AF_INET6; 91 92 struct addrinfo *head = (struct addrinfo *)malloc(sizeof(struct addrinfo)); 93 memset(head, 0, sizeof(struct addrinfo)); 94 struct addrinfo *next = head; 95 96 size_t minSize = MIN(ipv6Size, ipv4Size); 97 size_t index = 0; 98 while (index < 2 * minSize) { 99 if (now == AF_INET6) { 100 next->ai_next = ipv6Dns[ipv6Index++]; 101 } else { 102 next->ai_next = ipv4Dns[ipv4Index++]; 103 } 104 ++index; 105 now = change_family(now); 106 next = next->ai_next; 107 } 108 while (ipv6Index < ipv6Size) { 109 next->ai_next = ipv6Dns[ipv6Index++]; 110 ++index; 111 next = next->ai_next; 112 } 113 while (ipv4Index < ipv4Size) { 114 next->ai_next = ipv4Dns[ipv4Index++]; 115 ++index; 116 next = next->ai_next; 117 } 118 struct addrinfo *result = head->ai_next; 119 free(head); 120 if (ipv6Dns) { 121 free(ipv6Dns); 122 } 123 if (ipv4Dns) { 124 free(ipv4Dns); 125 } 126 return result; 127} 128 129void 130lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul) 131{ 132 struct lws *wsi = lws_container_of(sul, struct lws, 133 sul_connect_timeout); 134 135 /* 136 * This is used to constrain the time we're willing to wait for a 137 * connection before giving up on it and retrying. 138 */ 139 140 lwsl_wsi_info(wsi, "connect wait timeout has fired"); 141 lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL); 142} 143 144void 145lws_client_dns_retry_timeout(lws_sorted_usec_list_t *sul) 146{ 147 struct lws *wsi = lws_container_of(sul, struct lws, 148 sul_connect_timeout); 149 150 /* 151 * This limits the amount of dns lookups we will try before 152 * giving up and failing... it reuses sul_connect_timeout, which 153 * isn't officially used until we connected somewhere. 154 */ 155 156 lwsl_wsi_info(wsi, "dns retry"); 157 if (!lws_client_connect_2_dnsreq(wsi)) 158 lwsl_wsi_notice(wsi, "DNS lookup failed"); 159} 160 161/* 162 * Figure out if an ongoing connect() has arrived at a final disposition or not 163 * 164 * We can check using getsockopt if our connect actually completed. 165 * Posix connect() allows nonblocking to redo the connect to 166 * find out if it succeeded. 167 */ 168 169typedef enum { 170 LCCCR_CONNECTED = 1, 171 LCCCR_CONTINUE = 0, 172 LCCCR_FAILED = -1, 173} lcccr_t; 174 175static lcccr_t 176lws_client_connect_check(struct lws *wsi, int *real_errno) 177{ 178 int en = 0; 179#if !defined(WIN32) 180 int e; 181 socklen_t sl = sizeof(e); 182#endif 183 184 (void)en; 185 186 /* 187 * This resets SO_ERROR after reading it. If there's an error 188 * condition, the connect definitively failed. 189 */ 190 191#if !defined(WIN32) 192 if (!getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR, &e, &sl)) { 193 en = LWS_ERRNO; 194 if (!e) { 195 lwsl_wsi_debug(wsi, "getsockopt: conn OK errno %d", en); 196 197 return LCCCR_CONNECTED; 198 } 199 200 lwsl_wsi_notice(wsi, "getsockopt fd %d says e %d", 201 wsi->desc.sockfd, e); 202 203 *real_errno = e; 204 205 return LCCCR_FAILED; 206 } 207 208#else 209 210 if (!connect(wsi->desc.sockfd, (const struct sockaddr *)&wsi->sa46_peer.sa4, 211#if defined(WIN32) 212 sizeof(struct sockaddr))) 213#else 214 0)) 215#endif 216 217 return LCCCR_CONNECTED; 218 219 en = LWS_ERRNO; 220 221 if (en == WSAEISCONN) /* already connected */ 222 return LCCCR_CONNECTED; 223 224 if (en == WSAEALREADY) { 225 /* reset the POLLOUT wait */ 226 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) 227 lwsl_wsi_notice(wsi, "pollfd failed"); 228 } 229 230 if (!en || en == WSAEINVAL || 231 en == WSAEWOULDBLOCK || 232 en == WSAEALREADY) { 233 lwsl_wsi_debug(wsi, "errno %d", en); 234 return LCCCR_CONTINUE; 235 } 236#endif 237 238 lwsl_wsi_notice(wsi, "connect check FAILED: %d", 239 *real_errno || en); 240 241 return LCCCR_FAILED; 242} 243 244/* 245 * We come here to fire off a connect, and to check its disposition later. 246 * 247 * If it did not complete before the individual attempt timeout, we will try to 248 * connect again with the next dns result. 249 */ 250 251struct lws * 252lws_client_connect_3_connect(struct lws *wsi, const char *ads, 253 const struct addrinfo *result, int n, void *opaque) 254{ 255#if defined(LWS_WITH_UNIX_SOCK) 256 struct sockaddr_un sau; 257#endif 258 struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 259 const char *cce = "Unable to connect", *iface; 260 const struct sockaddr *psa = NULL; 261 uint16_t port = wsi->conn_port; 262 lws_dns_sort_t *curr; 263 ssize_t plen = 0; 264 lws_dll2_t *d; 265 char dcce[48]; 266#if defined(LWS_WITH_SYS_FAULT_INJECTION) 267 int cfail; 268#endif 269 int m, af = 0; 270 271 /* 272 * If we come here with result set, we need to convert getaddrinfo 273 * results to a lws_dns_sort_t list one time and free the results. 274 * 275 * We use this pattern because ASYNC_DNS will callback here with the 276 * results when it gets them (and may come here more than once, eg, for 277 * AAAA then A or vice-versa) 278 */ 279 280 if (result) { 281 lws_sul_cancel(&wsi->sul_connect_timeout); 282 283#if defined(LWS_WITH_CONMON) 284 /* append a copy from before the sorting */ 285 lws_conmon_append_copy_new_dns_results(wsi, result); 286#endif 287 288 result = sort_dns((struct addrinfo *)result); 289 lws_sort_dns(wsi, result); 290#if defined(LWS_WITH_SYS_ASYNC_DNS) 291 lws_async_dns_freeaddrinfo(&result); 292#else 293 freeaddrinfo((struct addrinfo *)result); 294#endif 295 result = NULL; 296 } 297 298#if defined(LWS_WITH_UNIX_SOCK) 299 memset(&sau, 0, sizeof(sau)); 300#endif 301 302 /* 303 * async dns calls back here for everybody who cares when it gets a 304 * result... but if we are piggybacking, we do not want to connect 305 * ourselves 306 */ 307 308 if (!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) 309 return wsi; 310 311 if (n && /* calling back with a problem */ 312 !wsi->dns_sorted_list.count && /* there's no results */ 313 !lws_socket_is_valid(wsi->desc.sockfd) && /* no attempt ongoing */ 314 !wsi->speculative_connect_owner.count /* no spec attempt */ ) { 315 lwsl_wsi_notice(wsi, "dns lookup failed %d", n); 316 317 /* 318 * DNS lookup itself failed... let's try again until we 319 * timeout 320 */ 321 322 lwsi_set_state(wsi, LRS_UNCONNECTED); 323 lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout, 324 lws_client_dns_retry_timeout, 325 LWS_USEC_PER_SEC); 326 return wsi; 327 328// cce = "dns lookup failed"; 329// goto oom4; 330 } 331 332 /* 333 * We come back here again when we think the connect() may have 334 * completed one way or the other, we can't proceed until we know we 335 * actually connected. 336 */ 337 338 if (lwsi_state(wsi) == LRS_WAITING_CONNECT && 339 lws_socket_is_valid(wsi->desc.sockfd)) { 340 341 if (!wsi->dns_sorted_list.count && 342 !wsi->sul_connect_timeout.list.owner) 343 /* no dns results and no ongoing timeout for one */ 344 goto connect_to; 345 346 /* 347 * If the connection failed, the OS-level errno may be 348 * something like EINPROGRESS rather than the actual problem 349 * that prevented a connection. This value will represent the 350 * "real" problem that we should report to the caller. 351 */ 352 int real_errno = 0; 353 354 switch (lws_client_connect_check(wsi, &real_errno)) { 355 case LCCCR_CONNECTED: 356 /* 357 * Oh, it has happened... 358 */ 359 goto conn_good; 360 case LCCCR_CONTINUE: 361 return NULL; 362 default: 363 if (!real_errno) 364 real_errno = LWS_ERRNO; 365 lws_snprintf(dcce, sizeof(dcce), "conn fail: %d", 366 real_errno); 367 368 cce = dcce; 369 lwsl_wsi_debug(wsi, "%s", dcce); 370 lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); 371 goto try_next_dns_result_fds; 372 } 373 } 374 375#if defined(LWS_WITH_UNIX_SOCK) 376 377 if (ads && *ads == '+') { 378 ads++; 379 memset(&wsi->sa46_peer, 0, sizeof(wsi->sa46_peer)); 380 af = sau.sun_family = AF_UNIX; 381 strncpy(sau.sun_path, ads, sizeof(sau.sun_path)); 382 sau.sun_path[sizeof(sau.sun_path) - 1] = '\0'; 383 384 lwsl_wsi_info(wsi, "Unix skt: %s", ads); 385 386 if (sau.sun_path[0] == '@') 387 sau.sun_path[0] = '\0'; 388 389 goto ads_known; 390 } 391#endif 392 393#if defined(LWS_WITH_SYS_ASYNC_DNS) 394 if (n == LADNS_RET_FAILED) { 395 lwsl_wsi_notice(wsi, "adns failed %s", ads); 396 /* 397 * Caller that is giving us LADNS_RET_FAILED will deal 398 * with cleanup 399 */ 400 return NULL; 401 } 402#endif 403 404 /* 405 * Let's try directly connecting to each of the results in turn until 406 * one works, or we run out of results... 407 * 408 * We have a sorted dll2 list with the head one most preferable 409 */ 410 411next_dns_result: 412 413 cce = "Unable to connect"; 414 415 if (!wsi->dns_sorted_list.count) 416 goto failed1; 417 418 /* 419 * Copy the wsi head sorted dns result into the wsi->sa46_peer, and 420 * remove and free the original from the sorted list 421 */ 422 423 d = lws_dll2_get_head(&wsi->dns_sorted_list); 424 curr = lws_container_of(d, lws_dns_sort_t, list); 425 426 lws_dll2_remove(&curr->list); 427 wsi->sa46_peer = curr->dest; 428#if defined(LWS_WITH_NETLINK) 429 wsi->peer_route_uidx = curr->uidx; 430 lwsl_wsi_info(wsi, "peer_route_uidx %d", wsi->peer_route_uidx); 431#endif 432 433 lws_free(curr); 434 435 sa46_sockport(&wsi->sa46_peer, htons(port)); 436 437 psa = sa46_sockaddr(&wsi->sa46_peer); 438 n = (int)sa46_socklen(&wsi->sa46_peer); 439 440#if defined(LWS_WITH_UNIX_SOCK) 441ads_known: 442#endif 443 444 /* 445 * Now we prepared psa, if not already connecting, create the related 446 * socket and add to the fds 447 */ 448 449 if (!lws_socket_is_valid(wsi->desc.sockfd)) { 450 451 if (wsi->a.context->event_loop_ops->check_client_connect_ok && 452 wsi->a.context->event_loop_ops->check_client_connect_ok(wsi) 453 ) { 454 cce = "waiting for event loop watcher to close"; 455 goto oom4; 456 } 457 458#if defined(LWS_WITH_UNIX_SOCK) 459 af = 0; 460 if (wsi->unix_skt) { 461 af = AF_UNIX; 462 wsi->desc.sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 463 } 464 else 465#endif 466 { 467 af = wsi->sa46_peer.sa4.sin_family; 468 wsi->desc.sockfd = socket(wsi->sa46_peer.sa4.sin_family, 469 SOCK_STREAM, 0); 470 } 471 472 if (!lws_socket_is_valid(wsi->desc.sockfd)) { 473 lws_snprintf(dcce, sizeof(dcce), 474 "conn fail: skt creation: errno %d", 475 LWS_ERRNO); 476 cce = dcce; 477 lwsl_wsi_warn(wsi, "%s", dcce); 478 goto try_next_dns_result; 479 } 480 481 if (lws_plat_set_socket_options(wsi->a.vhost, wsi->desc.sockfd, 482#if defined(LWS_WITH_UNIX_SOCK) 483 wsi->unix_skt)) { 484#else 485 0)) { 486#endif 487 lws_snprintf(dcce, sizeof(dcce), 488 "conn fail: skt options: errno %d", 489 LWS_ERRNO); 490 cce = dcce; 491 lwsl_wsi_warn(wsi, "%s", dcce); 492 goto try_next_dns_result_closesock; 493 } 494 495 /* apply requested socket options */ 496 if (lws_plat_set_socket_options_ip(wsi->desc.sockfd, 497 wsi->c_pri, wsi->flags)) 498 lwsl_wsi_warn(wsi, "unable to set ip options"); 499 500 lwsl_wsi_debug(wsi, "WAITING_CONNECT"); 501 lwsi_set_state(wsi, LRS_WAITING_CONNECT); 502 503 if (wsi->a.context->event_loop_ops->sock_accept) 504 if (wsi->a.context->event_loop_ops->sock_accept(wsi)) { 505 lws_snprintf(dcce, sizeof(dcce), 506 "conn fail: sock accept"); 507 cce = dcce; 508 lwsl_wsi_warn(wsi, "%s", dcce); 509 goto try_next_dns_result_closesock; 510 } 511 512 lws_pt_lock(pt, __func__); 513 if (__insert_wsi_socket_into_fds(wsi->a.context, wsi)) { 514 lws_snprintf(dcce, sizeof(dcce), 515 "conn fail: insert fd"); 516 cce = dcce; 517 lws_pt_unlock(pt); 518 goto try_next_dns_result_closesock; 519 } 520 lws_pt_unlock(pt); 521 522 /* 523 * The fd + wsi combination is entered into the wsi tables 524 * at this point, with a pollfd 525 * 526 * Past here, we can't simply free the structs as error 527 * handling as oom4 does. 528 * 529 * We can run the whole close flow, or unpick the fds inclusion 530 * and anything else we have done. 531 */ 532 533 if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { 534 lws_snprintf(dcce, sizeof(dcce), 535 "conn fail: change pollfd"); 536 cce = dcce; 537 goto try_next_dns_result_fds; 538 } 539 540 if (!wsi->a.protocol) 541 wsi->a.protocol = &wsi->a.vhost->protocols[0]; 542 543 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE, 544 wsi->a.vhost->connect_timeout_secs); 545 546 iface = lws_wsi_client_stash_item(wsi, CIS_IFACE, 547 _WSI_TOKEN_CLIENT_IFACE); 548 549 if (iface && *iface) { 550 m = lws_socket_bind(wsi->a.vhost, wsi, wsi->desc.sockfd, 551 0, iface, af); 552 if (m < 0) { 553 lws_snprintf(dcce, sizeof(dcce), 554 "conn fail: socket bind"); 555 cce = dcce; 556 goto try_next_dns_result_fds; 557 } 558 } 559 } 560 561#if defined(LWS_WITH_UNIX_SOCK) 562 if (wsi->unix_skt) { 563 psa = (const struct sockaddr *)&sau; 564 if (sau.sun_path[0]) 565 n = (int)(sizeof(uint16_t) + strlen(sau.sun_path)); 566 else 567 n = (int)(sizeof(uint16_t) + 568 strlen(&sau.sun_path[1]) + 1); 569 } else 570#endif 571 572 if (!psa) /* coverity */ 573 goto try_next_dns_result_fds; 574 575 /* 576 * The actual connection attempt 577 */ 578 579#if defined(LWS_ESP_PLATFORM) 580 errno = 0; 581#endif 582 583 /* grab a copy for peer tracking */ 584#if defined(LWS_WITH_UNIX_SOCK) 585 if (!wsi->unix_skt) 586#endif 587 memmove(&wsi->sa46_peer, psa, (unsigned int)n); 588 589 /* 590 * Finally, make the actual connection attempt 591 */ 592 593#if defined(LWS_WITH_SYS_METRICS) 594 if (wsi->cal_conn.mt) { 595 lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); 596 } 597 lws_metrics_caliper_bind(wsi->cal_conn, wsi->a.context->mt_conn_tcp); 598#endif 599 600 wsi->socket_is_permanently_unusable = 0; 601 602 if (lws_fi(&wsi->fic, "conn_cb_rej") || 603 user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, 604 LWS_CALLBACK_CONNECTING, wsi->user_space, 605 (void *)(intptr_t)wsi->desc.sockfd, 0)) { 606 lwsl_wsi_info(wsi, "CONNECTION CB closed"); 607 goto failed1; 608 } 609 610#if defined(LWS_WITH_SYS_FAULT_INJECTION) 611 cfail = lws_fi(&wsi->fic, "connfail"); 612 if (cfail) 613 m = -1; 614 else 615#endif 616 m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, 617 (socklen_t)n); 618 619#if defined(LWS_WITH_CONMON) 620 wsi->conmon_datum = lws_now_usecs(); 621 wsi->conmon.ciu_sockconn = 0; 622#endif 623 624 if (m == -1) { 625 /* 626 * Since we're nonblocking, connect not having completed is not 627 * necessarily indicating any problem... we have to look at 628 * either errno or the socket to understand if we actually 629 * failed already... 630 */ 631 632 int errno_copy = LWS_ERRNO; 633 634#if defined(LWS_WITH_SYS_FAULT_INJECTION) 635 if (cfail) 636 /* fake an abnormal, fatal situation */ 637 errno_copy = 999; 638#endif 639 640 lwsl_wsi_debug(wsi, "connect: fd %d errno: %d", 641 wsi->desc.sockfd, errno_copy); 642 643 if (errno_copy && 644 errno_copy != LWS_EALREADY && 645 errno_copy != LWS_EINPROGRESS && 646 errno_copy != LWS_EWOULDBLOCK 647#ifdef _WIN32 648 && errno_copy != WSAEINVAL 649 && errno_copy != WSAEISCONN 650#endif 651 ) { 652 /* 653 * The connect() failed immediately... 654 */ 655 656#if defined(LWS_WITH_CONMON) 657 wsi->conmon.ciu_sockconn = (lws_conmon_interval_us_t) 658 (lws_now_usecs() - wsi->conmon_datum); 659#endif 660 661 lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); 662 663#if defined(_DEBUG) 664#if defined(LWS_WITH_UNIX_SOCK) 665 if (!wsi->unix_skt) { 666#endif 667 668 char nads[48]; 669 670 lws_sa46_write_numeric_address(&wsi->sa46_peer, nads, 671 sizeof(nads)); 672 673 lws_snprintf(dcce, sizeof(dcce), 674 "conn fail: errno %d: %s:%d", 675 errno_copy, nads, port); 676 cce = dcce; 677 678 wsi->sa46_peer.sa4.sin_family = 0; 679 lwsl_wsi_info(wsi, "%s", cce); 680#if defined(LWS_WITH_UNIX_SOCK) 681 } else { 682 lws_snprintf(dcce, sizeof(dcce), 683 "conn fail: errno %d: UDS %s", 684 errno_copy, ads); 685 cce = dcce; 686 } 687#endif 688#endif 689 690 goto try_next_dns_result_fds; 691 } 692 693#if defined(WIN32) 694 if (lws_plat_check_connection_error(wsi)) 695 goto try_next_dns_result_fds; 696 697 if (errno_copy == WSAEISCONN) 698 goto conn_good; 699#endif 700 701 /* 702 * The connection attempt is ongoing asynchronously... let's set 703 * a specialized timeout for this connect attempt completion, it 704 * uses wsi->sul_connect_timeout just for this purpose 705 */ 706 707 lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout, 708 lws_client_conn_wait_timeout, 709 wsi->a.context->timeout_secs * 710 LWS_USEC_PER_SEC); 711 712 /* 713 * must do specifically a POLLOUT poll to hear 714 * about the connect completion 715 */ 716 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) 717 goto try_next_dns_result_fds; 718 719 return wsi; 720 } 721 722conn_good: 723 724 /* 725 * The connection has happened 726 */ 727 728#if defined(LWS_WITH_CONMON) 729 wsi->conmon.ciu_sockconn = (lws_conmon_interval_us_t) 730 (lws_now_usecs() - wsi->conmon_datum); 731#endif 732 733#if !defined(LWS_PLAT_OPTEE) 734 { 735 socklen_t salen = sizeof(wsi->sa46_local); 736#if defined(_DEBUG) 737 char buf[64]; 738#endif 739 if (getsockname((int)wsi->desc.sockfd, 740 (struct sockaddr *)&wsi->sa46_local, 741 &salen) == -1) 742 lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO)); 743#if defined(_DEBUG) 744#if defined(LWS_WITH_UNIX_SOCK) 745 if (wsi->unix_skt) 746 buf[0] = '\0'; 747 else 748#endif 749 lws_sa46_write_numeric_address(&wsi->sa46_local, buf, sizeof(buf)); 750 751 lwsl_wsi_info(wsi, "source ads %s", buf); 752#endif 753 } 754#endif 755 756 lws_sul_cancel(&wsi->sul_connect_timeout); 757 lws_metrics_caliper_report(wsi->cal_conn, METRES_GO); 758 759 lws_addrinfo_clean(wsi); 760 761 if (wsi->a.protocol) 762 wsi->a.protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE, 763 wsi->user_space, NULL, 0); 764 765 lwsl_wsi_debug(wsi, "going into connect_4"); 766 767 return lws_client_connect_4_established(wsi, NULL, plen); 768 769oom4: 770 /* 771 * We get here if we're trying to clean up a connection attempt that 772 * didn't make it as far as getting inserted into the wsi / fd tables 773 */ 774 775 if (lwsi_role_client(wsi) && wsi->a.protocol 776 /* && lwsi_state_est(wsi) */) 777 lws_inform_client_conn_fail(wsi,(void *)cce, strlen(cce)); 778 779 /* take care that we might be inserted in fds already */ 780 if (wsi->position_in_fds_table != LWS_NO_FDS_POS) 781 /* do the full wsi close flow */ 782 goto failed1; 783 784 lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); 785 786 /* 787 * We can't be an active client connection any more, if we thought 788 * that was what we were going to be doing. It should be if we are 789 * failing by oom4 path, we are still called by 790 * lws_client_connect_via_info() and will be returning NULL to that, 791 * so nobody else should have had a chance to queue on us. 792 */ 793 { 794 struct lws_vhost *vhost = wsi->a.vhost; 795 lws_sockfd_type sfd = wsi->desc.sockfd; 796 797 //lws_vhost_lock(vhost); 798 __lws_free_wsi(wsi); /* acquires vhost lock in wsi reset */ 799 //lws_vhost_unlock(vhost); 800 801 sanity_assert_no_wsi_traces(vhost->context, wsi); 802 sanity_assert_no_sockfd_traces(vhost->context, sfd); 803 } 804 805 return NULL; 806 807connect_to: 808 /* 809 * It looks like the sul_connect_timeout fired 810 */ 811 lwsl_wsi_info(wsi, "abandoning connect due to timeout"); 812 813try_next_dns_result_fds: 814 lws_pt_lock(pt, __func__); 815 __remove_wsi_socket_from_fds(wsi); 816 lws_pt_unlock(pt); 817 818try_next_dns_result_closesock: 819 /* 820 * We are killing the socket but leaving 821 */ 822 compatible_close(wsi->desc.sockfd); 823 wsi->desc.sockfd = LWS_SOCK_INVALID; 824 825try_next_dns_result: 826 lws_sul_cancel(&wsi->sul_connect_timeout); 827 if (lws_dll2_get_head(&wsi->dns_sorted_list)) 828 goto next_dns_result; 829 830 lws_addrinfo_clean(wsi); 831 lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); 832 833failed1: 834 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect3"); 835 836 return NULL; 837} 838