connect2.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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. #if !defined(LWS_WITH_SYS_ASYNC_DNS)
  26. static int
  27. lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result)
  28. {
  29. struct addrinfo hints;
  30. int n;
  31. memset(&hints, 0, sizeof(hints));
  32. *result = NULL;
  33. hints.ai_socktype = SOCK_STREAM;
  34. #ifdef LWS_WITH_IPV6
  35. if (wsi->ipv6) {
  36. #if !defined(__ANDROID__)
  37. hints.ai_family = AF_UNSPEC;
  38. hints.ai_flags = AI_V4MAPPED;
  39. #endif
  40. } else
  41. #endif
  42. {
  43. hints.ai_family = PF_UNSPEC;
  44. }
  45. n = getaddrinfo(ads, NULL, &hints, result);
  46. lwsl_info("%s: getaddrinfo '%s' says %d\n", __func__, ads, n);
  47. return n;
  48. }
  49. #endif
  50. struct lws *
  51. lws_client_connect_2_dnsreq(struct lws *wsi)
  52. {
  53. struct addrinfo *result = NULL;
  54. const char *meth = NULL, *ads;
  55. #if defined(LWS_WITH_IPV6)
  56. struct sockaddr_in addr;
  57. const char *iface;
  58. #endif
  59. const char *adsin;
  60. int n, port = 0;
  61. struct lws *w;
  62. if (lwsi_state(wsi) == LRS_WAITING_DNS ||
  63. lwsi_state(wsi) == LRS_WAITING_CONNECT) {
  64. lwsl_info("%s: LRS_WAITING_DNS / CONNECT\n", __func__);
  65. return wsi;
  66. }
  67. /*
  68. * The first job is figure out if we want to pipeline on or just join
  69. * an existing "active connection" to the same place
  70. */
  71. meth = lws_wsi_client_stash_item(wsi, CIS_METHOD,
  72. _WSI_TOKEN_CLIENT_METHOD);
  73. /* we only pipeline connections that said it was okay */
  74. if (!wsi->client_pipeline) {
  75. lwsl_debug("%s: new conn on no pipeline flag\n", __func__);
  76. goto solo;
  77. }
  78. /* only pipeline things we associate with being a stream */
  79. if (meth && strcmp(meth, "RAW") && strcmp(meth, "GET") &&
  80. strcmp(meth, "POST") && strcmp(meth, "PUT") &&
  81. strcmp(meth, "UDP") && strcmp(meth, "MQTT"))
  82. goto solo;
  83. /* consult active connections to find out disposition */
  84. adsin = lws_wsi_client_stash_item(wsi, CIS_ADDRESS,
  85. _WSI_TOKEN_CLIENT_PEER_ADDRESS);
  86. if (!adsin)
  87. /*
  88. * This cannot happen since user code must provide the client
  89. * address to get this far, it's here to satisfy Coverity
  90. */
  91. return NULL;
  92. switch (lws_vhost_active_conns(wsi, &w, adsin)) {
  93. case ACTIVE_CONNS_SOLO:
  94. break;
  95. case ACTIVE_CONNS_MUXED:
  96. lwsl_notice("%s: ACTIVE_CONNS_MUXED\n", __func__);
  97. if (lwsi_role_h2(wsi)) {
  98. if (wsi->a.protocol->callback(wsi,
  99. LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
  100. wsi->user_space, NULL, 0))
  101. goto failed1;
  102. //lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
  103. //lwsi_set_state(w, LRS_ESTABLISHED);
  104. lws_callback_on_writable(wsi);
  105. }
  106. return wsi;
  107. case ACTIVE_CONNS_QUEUED:
  108. lwsl_debug("%s: ACTIVE_CONNS_QUEUED st 0x%x: \n", __func__,
  109. lwsi_state(wsi));
  110. if (lwsi_state(wsi) == LRS_UNCONNECTED) {
  111. if (lwsi_role_h2(w))
  112. lwsi_set_state(wsi,
  113. LRS_H2_WAITING_TO_SEND_HEADERS);
  114. else
  115. lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
  116. }
  117. return lws_client_connect_4_established(wsi, w, 0);
  118. }
  119. solo:
  120. wsi->addrinfo_idx = 0;
  121. /*
  122. * clients who will create their own fresh connection keep a copy of
  123. * the hostname they originally connected to, in case other connections
  124. * want to use it too
  125. */
  126. if (!wsi->cli_hostname_copy) {
  127. if (wsi->stash && wsi->stash->cis[CIS_HOST])
  128. wsi->cli_hostname_copy =
  129. lws_strdup(wsi->stash->cis[CIS_HOST]);
  130. #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
  131. else {
  132. char *pa = lws_hdr_simple_ptr(wsi,
  133. _WSI_TOKEN_CLIENT_PEER_ADDRESS);
  134. if (pa)
  135. wsi->cli_hostname_copy = lws_strdup(pa);
  136. }
  137. #endif
  138. }
  139. /*
  140. * If we made our own connection, and we're doing a method that can
  141. * take a pipeline, we are an "active client connection".
  142. *
  143. * Add ourselves to the vhost list of those so that others can
  144. * piggyback on our transaction queue
  145. */
  146. if (meth && (!strcmp(meth, "RAW") || !strcmp(meth, "GET") ||
  147. !strcmp(meth, "POST") || !strcmp(meth, "PUT") ||
  148. !strcmp(meth, "MQTT")) &&
  149. lws_dll2_is_detached(&wsi->dll2_cli_txn_queue) &&
  150. lws_dll2_is_detached(&wsi->dll_cli_active_conns)) {
  151. lws_vhost_lock(wsi->a.vhost);
  152. lwsl_info("%s: adding active conn %p\n", __func__, wsi);
  153. /* caution... we will have to unpick this on oom4 path */
  154. lws_dll2_add_head(&wsi->dll_cli_active_conns,
  155. &wsi->a.vhost->dll_cli_active_conns_owner);
  156. lws_vhost_unlock(wsi->a.vhost);
  157. }
  158. /*
  159. * unix socket destination?
  160. */
  161. if (wsi->stash)
  162. ads = wsi->stash->cis[CIS_ADDRESS];
  163. else
  164. ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
  165. /*
  166. * Since address must be given at client creation, should not be
  167. * possible, but necessary to satisfy coverity
  168. */
  169. if (!ads)
  170. return NULL;
  171. #if defined(LWS_WITH_UNIX_SOCK)
  172. if (*ads == '+') {
  173. wsi->unix_skt = 1;
  174. n = 0;
  175. goto next_step;
  176. }
  177. #endif
  178. /*
  179. * start off allowing ipv6 on connection if vhost allows it
  180. */
  181. wsi->ipv6 = LWS_IPV6_ENABLED(wsi->a.vhost);
  182. #ifdef LWS_WITH_IPV6
  183. if (wsi->stash)
  184. iface = wsi->stash->cis[CIS_IFACE];
  185. else
  186. iface = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
  187. if (wsi->ipv6 && iface &&
  188. inet_pton(AF_INET, iface, &addr.sin_addr) == 1) {
  189. lwsl_notice("%s: client connection forced to IPv4\n", __func__);
  190. wsi->ipv6 = 0;
  191. }
  192. #endif
  193. #if defined(LWS_WITH_DETAILED_LATENCY)
  194. if (lwsi_state(wsi) == LRS_WAITING_DNS &&
  195. wsi->a.context->detailed_latency_cb) {
  196. wsi->detlat.type = LDLT_NAME_RESOLUTION;
  197. wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
  198. lws_now_usecs() -
  199. wsi->detlat.earliest_write_req_pre_write;
  200. wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
  201. lws_det_lat_cb(wsi->a.context, &wsi->detlat);
  202. wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
  203. }
  204. #endif
  205. #if defined(LWS_CLIENT_HTTP_PROXYING) && \
  206. (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
  207. /* Decide what it is we need to connect to:
  208. *
  209. * Priority 1: connect to http proxy */
  210. if (wsi->a.vhost->http.http_proxy_port) {
  211. ads = wsi->a.vhost->http.http_proxy_address;
  212. port = wsi->a.vhost->http.http_proxy_port;
  213. #else
  214. if (0) {
  215. #endif
  216. #if defined(LWS_WITH_SOCKS5)
  217. /* Priority 2: Connect to SOCK5 Proxy */
  218. } else if (wsi->a.vhost->socks_proxy_port) {
  219. lwsl_client("Sending SOCKS Greeting\n");
  220. ads = wsi->a.vhost->socks_proxy_address;
  221. port = wsi->a.vhost->socks_proxy_port;
  222. #endif
  223. } else {
  224. /* Priority 3: Connect directly */
  225. /* ads already set */
  226. port = wsi->c_port;
  227. }
  228. /*
  229. * prepare the actual connection
  230. * to whatever we decided to connect to
  231. */
  232. lwsi_set_state(wsi, LRS_WAITING_DNS);
  233. lwsl_info("%s: %p: lookup %s:%u\n", __func__, wsi, ads, port);
  234. (void)port;
  235. #if defined(LWS_WITH_DETAILED_LATENCY)
  236. wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
  237. #endif
  238. #if !defined(LWS_WITH_SYS_ASYNC_DNS)
  239. if (wsi->dns_results)
  240. n = 0;
  241. else
  242. n = lws_getaddrinfo46(wsi, ads, &result);
  243. #else
  244. lwsi_set_state(wsi, LRS_WAITING_DNS);
  245. /* this is either FAILED, CONTINUING, or already called connect_4 */
  246. n = lws_async_dns_query(wsi->a.context, wsi->tsi, ads,
  247. LWS_ADNS_RECORD_A, lws_client_connect_3_connect,
  248. wsi, NULL);
  249. if (n == LADNS_RET_FAILED_WSI_CLOSED)
  250. return NULL;
  251. if (n == LADNS_RET_FAILED)
  252. goto failed1;
  253. return wsi;
  254. #endif
  255. #if defined(LWS_WITH_UNIX_SOCK)
  256. next_step:
  257. #endif
  258. return lws_client_connect_3_connect(wsi, ads, result, n, NULL);
  259. //#if defined(LWS_WITH_SYS_ASYNC_DNS)
  260. failed1:
  261. lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
  262. return NULL;
  263. //#endif
  264. }