connect3.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
  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. #include "private-lib-core.h"
  25. void
  26. lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul)
  27. {
  28. struct lws *wsi = lws_container_of(sul, struct lws,
  29. sul_connect_timeout);
  30. /*
  31. * This is used to constrain the time we're willing to wait for a
  32. * connection before giving up on it and retrying.
  33. */
  34. lwsl_info("%s: connect wait timeout has fired\n", __func__);
  35. lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL);
  36. }
  37. struct lws *
  38. lws_client_connect_3_connect(struct lws *wsi, const char *ads,
  39. const struct addrinfo *result, int n, void *opaque)
  40. {
  41. #if defined(LWS_WITH_UNIX_SOCK)
  42. struct sockaddr_un sau;
  43. #endif
  44. #ifdef LWS_WITH_IPV6
  45. char ipv6only = lws_check_opt(wsi->a.vhost->options,
  46. LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY |
  47. LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE);
  48. #endif
  49. struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
  50. const struct sockaddr *psa = NULL;
  51. uint16_t port = wsi->c_port;
  52. const char *cce, *iface;
  53. lws_sockaddr46 sa46;
  54. ssize_t plen = 0;
  55. char ni[48];
  56. int m;
  57. if (n == LWS_CONNECT_COMPLETION_GOOD)
  58. goto conn_good;
  59. #if defined(LWS_WITH_IPV6) && defined(__ANDROID__)
  60. ipv6only = 0;
  61. #endif
  62. /*
  63. * async dns calls back here for everybody who cares when it gets a
  64. * result... but if we are piggybacking, we do not want to connect
  65. * ourselves
  66. */
  67. if (!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue))
  68. return wsi;
  69. /*
  70. * We can check using getsockopt if our connect actually completed.
  71. * Posix connect() allows nonblocking to redo the connect to
  72. * find out if it succeeded, for win32 we have to use this path
  73. * and take WSAEALREADY as a successful connect.
  74. */
  75. if (lwsi_state(wsi) == LRS_WAITING_CONNECT &&
  76. lws_socket_is_valid(wsi->desc.sockfd)) {
  77. #if !defined(WIN32)
  78. socklen_t sl = sizeof(int);
  79. int e = 0;
  80. #endif
  81. if (!result && /* no dns results... */
  82. /* no ongoing connect timeout */
  83. !wsi->sul_connect_timeout.list.owner)
  84. goto connect_to;
  85. #if defined(WIN32)
  86. if (!connect(wsi->desc.sockfd, NULL, 0)) {
  87. goto conn_good;
  88. } else {
  89. if (!LWS_ERRNO ||
  90. LWS_ERRNO == WSAEINVAL ||
  91. LWS_ERRNO == WSAEWOULDBLOCK ||
  92. LWS_ERRNO == WSAEALREADY) {
  93. lwsl_info("%s: errno %d\n", __func__, errno);
  94. return NULL;
  95. }
  96. lwsl_info("%s: connect check take as FAILED\n",
  97. __func__);
  98. }
  99. #else
  100. /*
  101. * this resets SO_ERROR after reading it. If there's an error
  102. * condition the connect definitively failed.
  103. */
  104. if (!getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR,
  105. &e, &sl)) {
  106. if (!e) {
  107. lwsl_debug("%s: getsockopt check: "
  108. "conn OK errno %d\n", __func__,
  109. errno);
  110. goto conn_good;
  111. }
  112. lwsl_debug("%s: getsockopt fd %d says err %d\n",
  113. __func__, wsi->desc.sockfd, e);
  114. }
  115. #endif
  116. lwsl_debug("%s: getsockopt check: conn fail: errno %d\n",
  117. __func__, LWS_ERRNO);
  118. goto try_next_result_fds;
  119. }
  120. #if defined(LWS_WITH_UNIX_SOCK)
  121. if (ads && *ads == '+') {
  122. ads++;
  123. memset(&sa46, 0, sizeof(sa46));
  124. memset(&sau, 0, sizeof(sau));
  125. sau.sun_family = AF_UNIX;
  126. strncpy(sau.sun_path, ads, sizeof(sau.sun_path));
  127. sau.sun_path[sizeof(sau.sun_path) - 1] = '\0';
  128. lwsl_info("%s: Unix skt: %s\n", __func__, ads);
  129. if (sau.sun_path[0] == '@')
  130. sau.sun_path[0] = '\0';
  131. goto ads_known;
  132. }
  133. #endif
  134. #if defined(LWS_WITH_SYS_ASYNC_DNS)
  135. if (n == LADNS_RET_FAILED) {
  136. lwsl_notice("%s: adns failed %s\n", __func__, ads);
  137. /*
  138. * Caller that is giving us LADNS_RET_FAILED will deal
  139. * with cleanup
  140. */
  141. return NULL;
  142. }
  143. #endif
  144. if (!wsi->dns_results) {
  145. wsi->dns_results_next = wsi->dns_results = result;
  146. if (result)
  147. lwsl_debug("%s: result %p result->ai_next %p\n",
  148. __func__, result, result->ai_next);
  149. }
  150. #if defined(LWS_WITH_DETAILED_LATENCY)
  151. if (lwsi_state(wsi) == LRS_WAITING_DNS &&
  152. wsi->a.context->detailed_latency_cb) {
  153. wsi->detlat.type = LDLT_NAME_RESOLUTION;
  154. wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
  155. lws_now_usecs() -
  156. wsi->detlat.earliest_write_req_pre_write;
  157. wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
  158. lws_det_lat_cb(wsi->a.context, &wsi->detlat);
  159. wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
  160. }
  161. #endif
  162. #if defined(LWS_CLIENT_HTTP_PROXYING) && \
  163. (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
  164. /* Decide what it is we need to connect to:
  165. *
  166. * Priority 1: connect to http proxy */
  167. if (wsi->a.vhost->http.http_proxy_port) {
  168. port = wsi->a.vhost->http.http_proxy_port;
  169. #else
  170. if (0) {
  171. #endif
  172. #if defined(LWS_WITH_SOCKS5)
  173. /* Priority 2: Connect to SOCK5 Proxy */
  174. } else if (wsi->a.vhost->socks_proxy_port) {
  175. if (lws_socks5c_generate_msg(wsi, SOCKS_MSG_GREETING, &plen)) {
  176. cce = "socks msg too large";
  177. goto oom4;
  178. }
  179. lwsl_client("Sending SOCKS Greeting\n");
  180. ads = wsi->a.vhost->socks_proxy_address;
  181. port = wsi->a.vhost->socks_proxy_port;
  182. #endif
  183. }
  184. memset(&sa46, 0, sizeof(sa46));
  185. if (n || !wsi->dns_results) {
  186. /* lws_getaddrinfo46 failed, there is no usable result */
  187. lwsl_notice("%s: lws_getaddrinfo46 failed %d\n",
  188. __func__, n);
  189. cce = "ipv6 lws_getaddrinfo46 failed";
  190. goto oom4;
  191. }
  192. /*
  193. * Let's try connecting to each of the results in turn until one works
  194. * or we run out of results
  195. */
  196. next_result:
  197. psa = (const struct sockaddr *)&sa46;
  198. n = sizeof(sa46);
  199. memset(&sa46, 0, sizeof(sa46));
  200. switch (wsi->dns_results_next->ai_family) {
  201. case AF_INET:
  202. #if defined(LWS_WITH_IPV6)
  203. if (ipv6only) {
  204. sa46.sa4.sin_family = AF_INET6;
  205. /* map IPv4 to IPv6 */
  206. memset((char *)&sa46.sa6.sin6_addr, 0,
  207. sizeof(sa46.sa6.sin6_addr));
  208. sa46.sa6.sin6_addr.s6_addr[10] = 0xff;
  209. sa46.sa6.sin6_addr.s6_addr[11] = 0xff;
  210. memcpy(&sa46.sa6.sin6_addr.s6_addr[12],
  211. &((struct sockaddr_in *)
  212. wsi->dns_results_next->ai_addr)->sin_addr,
  213. sizeof(struct in_addr));
  214. sa46.sa6.sin6_port = htons(port);
  215. ni[0] = '\0';
  216. lws_write_numeric_address(sa46.sa6.sin6_addr.s6_addr,
  217. 16, ni, sizeof(ni));
  218. lwsl_info("%s: %s ipv4->ipv6 %s\n", __func__,
  219. ads ? ads : "(null)", ni);
  220. break;
  221. }
  222. #endif
  223. sa46.sa4.sin_family = AF_INET;
  224. sa46.sa4.sin_addr.s_addr =
  225. ((struct sockaddr_in *)wsi->dns_results_next->ai_addr)->
  226. sin_addr.s_addr;
  227. memset(&sa46.sa4.sin_zero, 0, sizeof(sa46.sa4.sin_zero));
  228. sa46.sa4.sin_port = htons(port);
  229. n = sizeof(struct sockaddr_in);
  230. lws_write_numeric_address((uint8_t *)&sa46.sa4.sin_addr.s_addr,
  231. 4, ni, sizeof(ni));
  232. lwsl_info("%s: %s ipv4 %s\n", __func__,
  233. ads ? ads : "(null)", ni);
  234. break;
  235. case AF_INET6:
  236. #if defined(LWS_WITH_IPV6)
  237. if (!wsi->ipv6)
  238. goto try_next_result;
  239. sa46.sa4.sin_family = AF_INET6;
  240. memcpy(&sa46.sa6.sin6_addr,
  241. &((struct sockaddr_in6 *)
  242. wsi->dns_results_next->ai_addr)->
  243. sin6_addr, sizeof(struct in6_addr));
  244. sa46.sa6.sin6_scope_id = ((struct sockaddr_in6 *)
  245. wsi->dns_results_next->ai_addr)->sin6_scope_id;
  246. sa46.sa6.sin6_flowinfo = ((struct sockaddr_in6 *)
  247. wsi->dns_results_next->ai_addr)->sin6_flowinfo;
  248. sa46.sa6.sin6_port = htons(port);
  249. lws_write_numeric_address((uint8_t *)&sa46.sa6.sin6_addr,
  250. 16, ni, sizeof(ni));
  251. lwsl_info("%s: %s ipv6 %s\n", __func__,
  252. ads ? ads : "(null)", ni);
  253. #else
  254. goto try_next_result; /* ipv4 only can't use this */
  255. #endif
  256. break;
  257. }
  258. #if defined(LWS_WITH_UNIX_SOCK)
  259. ads_known:
  260. #endif
  261. /* now we decided on ipv4 or ipv6, set the port and create socket*/
  262. if (!lws_socket_is_valid(wsi->desc.sockfd)) {
  263. if (wsi->a.context->event_loop_ops->check_client_connect_ok &&
  264. wsi->a.context->event_loop_ops->check_client_connect_ok(wsi)
  265. ) {
  266. cce = "waiting for event loop watcher to close";
  267. goto oom4;
  268. }
  269. #if defined(LWS_WITH_UNIX_SOCK)
  270. if (wsi->unix_skt)
  271. wsi->desc.sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
  272. else
  273. #endif
  274. wsi->desc.sockfd = socket(sa46.sa4.sin_family,
  275. SOCK_STREAM, 0);
  276. if (!lws_socket_is_valid(wsi->desc.sockfd)) {
  277. lwsl_warn("Unable to open socket\n");
  278. goto try_next_result;
  279. }
  280. if (lws_plat_set_socket_options(wsi->a.vhost, wsi->desc.sockfd,
  281. #if defined(LWS_WITH_UNIX_SOCK)
  282. wsi->unix_skt)) {
  283. #else
  284. 0)) {
  285. #endif
  286. lwsl_err("Failed to set wsi socket options\n");
  287. goto try_next_result_closesock;
  288. }
  289. lwsl_debug("%s: %p: WAITING_CONNECT\n", __func__, wsi);
  290. lwsi_set_state(wsi, LRS_WAITING_CONNECT);
  291. if (wsi->a.context->event_loop_ops->sock_accept)
  292. if (wsi->a.context->event_loop_ops->sock_accept(wsi))
  293. goto try_next_result_closesock;
  294. lws_pt_lock(pt, __func__);
  295. if (__insert_wsi_socket_into_fds(wsi->a.context, wsi)) {
  296. lws_pt_unlock(pt);
  297. goto try_next_result_closesock;
  298. }
  299. lws_pt_unlock(pt);
  300. /*
  301. * The fd + wsi combination is entered into the wsi tables
  302. * at this point, with a pollfd
  303. *
  304. * Past here, we can't simply free the structs as error
  305. * handling as oom4 does.
  306. *
  307. * We can run the whole close flow, or unpick the fds inclusion
  308. * and anything else we have done.
  309. */
  310. if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
  311. goto try_next_result_fds;
  312. if (!wsi->a.protocol)
  313. wsi->a.protocol = &wsi->a.vhost->protocols[0];
  314. lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
  315. wsi->a.vhost->connect_timeout_secs);
  316. iface = lws_wsi_client_stash_item(wsi, CIS_IFACE,
  317. _WSI_TOKEN_CLIENT_IFACE);
  318. if (iface && *iface) {
  319. m = lws_socket_bind(wsi->a.vhost, wsi->desc.sockfd, 0,
  320. iface, wsi->ipv6);
  321. if (m < 0)
  322. goto try_next_result_fds;
  323. }
  324. }
  325. #if defined(LWS_WITH_UNIX_SOCK)
  326. if (wsi->unix_skt) {
  327. psa = (const struct sockaddr *)&sau;
  328. if (sau.sun_path[0])
  329. n = (int)(sizeof(uint16_t) + strlen(sau.sun_path));
  330. else
  331. n = (int)(sizeof(uint16_t) +
  332. strlen(&sau.sun_path[1]) + 1);
  333. } else
  334. #endif
  335. if (!psa) /* coverity */
  336. goto try_next_result_fds;
  337. /*
  338. * The actual connection attempt
  339. */
  340. #if defined(LWS_WITH_DETAILED_LATENCY)
  341. wsi->detlat.earliest_write_req =
  342. wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
  343. #endif
  344. #if defined(LWS_ESP_PLATFORM)
  345. errno = 0;
  346. #endif
  347. m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, n);
  348. if (m == -1) {
  349. int errno_copy = LWS_ERRNO;
  350. lwsl_debug("%s: connect says errno: %d\n", __func__,
  351. errno_copy);
  352. if (errno_copy && errno_copy != LWS_EALREADY &&
  353. errno_copy != LWS_EINPROGRESS &&
  354. errno_copy != LWS_EWOULDBLOCK
  355. #ifdef _WIN32
  356. && errno_copy != WSAEINVAL
  357. && errno_copy != WSAEISCONN
  358. #endif
  359. ) {
  360. #if defined(_DEBUG)
  361. char nads[48];
  362. lws_sa46_write_numeric_address(&sa46, nads,
  363. sizeof(nads));
  364. lwsl_info("%s: Connect failed: %s port %d\n",
  365. __func__, nads, port);
  366. #endif
  367. goto try_next_result_fds;
  368. }
  369. #if defined(WIN32)
  370. if (lws_plat_check_connection_error(wsi))
  371. goto try_next_result_fds;
  372. if (errno_copy == WSAEISCONN)
  373. goto conn_good;
  374. #endif
  375. /*
  376. * Let's set a specialized timeout for this connect attempt
  377. * completion, it uses wsi->sul_connect_timeout just for this
  378. * purpose
  379. */
  380. lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout,
  381. lws_client_conn_wait_timeout,
  382. wsi->a.context->timeout_secs *
  383. LWS_USEC_PER_SEC);
  384. /*
  385. * must do specifically a POLLOUT poll to hear
  386. * about the connect completion
  387. */
  388. #if !defined(WIN32)
  389. if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
  390. goto try_next_result_fds;
  391. #endif
  392. return wsi;
  393. }
  394. conn_good:
  395. lws_sul_cancel(&wsi->sul_connect_timeout);
  396. lwsl_info("%s: Connection started %p\n", __func__, wsi->dns_results);
  397. /* the tcp connection has happend */
  398. #if defined(LWS_WITH_DETAILED_LATENCY)
  399. if (wsi->a.context->detailed_latency_cb) {
  400. wsi->detlat.type = LDLT_CONNECTION;
  401. wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
  402. lws_now_usecs() -
  403. wsi->detlat.earliest_write_req_pre_write;
  404. wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
  405. lws_det_lat_cb(wsi->a.context, &wsi->detlat);
  406. wsi->detlat.earliest_write_req =
  407. wsi->detlat.earliest_write_req_pre_write =
  408. lws_now_usecs();
  409. }
  410. #endif
  411. lws_addrinfo_clean(wsi);
  412. if (wsi->a.protocol)
  413. wsi->a.protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE,
  414. wsi->user_space, NULL, 0);
  415. lwsl_debug("%s: going into connect_4\n", __func__);
  416. return lws_client_connect_4_established(wsi, NULL, plen);
  417. oom4:
  418. /*
  419. * We get here if we're trying to clean up a connection attempt that
  420. * didn't make it as far as getting inserted into the wsi / fd tables
  421. */
  422. if (lwsi_role_client(wsi) && wsi->a.protocol
  423. /* && lwsi_state_est(wsi) */)
  424. lws_inform_client_conn_fail(wsi,(void *)cce, strlen(cce));
  425. /* take care that we might be inserted in fds already */
  426. if (wsi->position_in_fds_table != LWS_NO_FDS_POS)
  427. /* do the full wsi close flow */
  428. goto failed1;
  429. /*
  430. * We can't be an active client connection any more, if we thought
  431. * that was what we were going to be doing. It should be if we are
  432. * failing by oom4 path, we are still called by
  433. * lws_client_connect_via_info() and will be returning NULL to that,
  434. * so nobody else should have had a chance to queue on us.
  435. */
  436. {
  437. struct lws_vhost *vhost = wsi->a.vhost;
  438. lws_sockfd_type sfd = wsi->desc.sockfd;
  439. lws_vhost_lock(vhost);
  440. __lws_free_wsi(wsi);
  441. lws_vhost_unlock(vhost);
  442. sanity_assert_no_wsi_traces(vhost->context, wsi);
  443. sanity_assert_no_sockfd_traces(vhost->context, sfd);
  444. }
  445. return NULL;
  446. connect_to:
  447. /*
  448. * It looks like the sul_connect_timeout fired
  449. */
  450. lwsl_info("%s: abandoning connect due to timeout\n", __func__);
  451. try_next_result_fds:
  452. __remove_wsi_socket_from_fds(wsi);
  453. try_next_result_closesock:
  454. /*
  455. * We are killing the socket but leaving
  456. */
  457. compatible_close(wsi->desc.sockfd);
  458. wsi->desc.sockfd = LWS_SOCK_INVALID;
  459. try_next_result:
  460. lws_sul_cancel(&wsi->sul_connect_timeout);
  461. if (wsi->dns_results_next) {
  462. wsi->dns_results_next = wsi->dns_results_next->ai_next;
  463. if (wsi->dns_results_next)
  464. goto next_result;
  465. }
  466. lws_addrinfo_clean(wsi);
  467. cce = "Unable to connect";
  468. //failed:
  469. lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
  470. failed1:
  471. lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
  472. return NULL;
  473. }