client-handshake.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. #include "private-libwebsockets.h"
  2. struct lws *
  3. lws_client_connect_2(struct lws *wsi)
  4. {
  5. #ifdef LWS_USE_IPV6
  6. struct sockaddr_in6 server_addr6;
  7. struct addrinfo hints, *result;
  8. #endif
  9. struct lws_context *context = wsi->context;
  10. struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
  11. struct sockaddr_in server_addr4;
  12. struct lws_pollfd pfd;
  13. struct sockaddr *v;
  14. const char *cce = "";
  15. int n, plen = 0;
  16. const char *ads;
  17. lwsl_client("%s\n", __func__);
  18. if (!wsi->u.hdr.ah) {
  19. cce = "ah was NULL at cc2";
  20. lwsl_err("%s\n", cce);
  21. goto oom4;
  22. }
  23. /* proxy? */
  24. if (wsi->vhost->http_proxy_port) {
  25. plen = sprintf((char *)pt->serv_buf,
  26. "CONNECT %s:%u HTTP/1.0\x0d\x0a"
  27. "User-agent: libwebsockets\x0d\x0a",
  28. lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
  29. wsi->c_port);
  30. if (wsi->vhost->proxy_basic_auth_token[0])
  31. plen += sprintf((char *)pt->serv_buf + plen,
  32. "Proxy-authorization: basic %s\x0d\x0a",
  33. wsi->vhost->proxy_basic_auth_token);
  34. plen += sprintf((char *)pt->serv_buf + plen, "\x0d\x0a");
  35. ads = wsi->vhost->http_proxy_address;
  36. #ifdef LWS_USE_IPV6
  37. if (LWS_IPV6_ENABLED(wsi->vhost)) {
  38. memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
  39. server_addr6.sin6_port = htons(wsi->vhost->http_proxy_port);
  40. } else
  41. #endif
  42. server_addr4.sin_port = htons(wsi->vhost->http_proxy_port);
  43. } else {
  44. ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
  45. #ifdef LWS_USE_IPV6
  46. if (LWS_IPV6_ENABLED(wsi->vhost)) {
  47. memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
  48. server_addr6.sin6_port = htons(wsi->c_port);
  49. } else
  50. #endif
  51. server_addr4.sin_port = htons(wsi->c_port);
  52. }
  53. /*
  54. * prepare the actual connection (to the proxy, if any)
  55. */
  56. lwsl_notice("%s: address %s\n", __func__, ads);
  57. #ifdef LWS_USE_IPV6
  58. if (LWS_IPV6_ENABLED(wsi->vhost)) {
  59. memset(&hints, 0, sizeof(struct addrinfo));
  60. #if !defined(__ANDROID__)
  61. hints.ai_family = AF_INET6;
  62. hints.ai_flags = AI_V4MAPPED;
  63. #endif
  64. n = getaddrinfo(ads, NULL, &hints, &result);
  65. if (n) {
  66. #ifdef _WIN32
  67. lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n));
  68. #else
  69. lwsl_err("getaddrinfo: %s\n", gai_strerror(n));
  70. #endif
  71. cce = "getaddrinfo (ipv6) failed";
  72. goto oom4;
  73. }
  74. server_addr6.sin6_family = AF_INET6;
  75. switch (result->ai_family) {
  76. #if defined(__ANDROID__)
  77. case AF_INET:
  78. /* map IPv4 to IPv6 */
  79. bzero((char *)&server_addr6.sin6_addr,
  80. sizeof(struct in6_addr));
  81. server_addr6.sin6_addr.s6_addr[10] = 0xff;
  82. server_addr6.sin6_addr.s6_addr[11] = 0xff;
  83. memcpy(&server_addr6.sin6_addr.s6_addr[12],
  84. &((struct sockaddr_in *)result->ai_addr)->sin_addr,
  85. sizeof(struct in_addr));
  86. break;
  87. #endif
  88. case AF_INET6:
  89. memcpy(&server_addr6.sin6_addr,
  90. &((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
  91. sizeof(struct in6_addr));
  92. server_addr6.sin6_scope_id = ((struct sockaddr_in6 *)result->ai_addr)->sin6_scope_id;
  93. server_addr6.sin6_flowinfo = ((struct sockaddr_in6 *)result->ai_addr)->sin6_flowinfo;
  94. break;
  95. default:
  96. lwsl_err("Unknown address family\n");
  97. freeaddrinfo(result);
  98. cce = "unknown address family";
  99. goto oom4;
  100. }
  101. freeaddrinfo(result);
  102. } else
  103. #endif
  104. {
  105. struct addrinfo ai, *res, *result = NULL;
  106. void *p = NULL;
  107. int addr_rv;
  108. memset (&ai, 0, sizeof ai);
  109. ai.ai_family = PF_UNSPEC;
  110. ai.ai_socktype = SOCK_STREAM;
  111. ai.ai_flags = AI_CANONNAME;
  112. addr_rv = getaddrinfo(ads, NULL, &ai, &result);
  113. if (!addr_rv) {
  114. res = result;
  115. while (!p && res) {
  116. switch (res->ai_family) {
  117. case AF_INET:
  118. p = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
  119. break;
  120. }
  121. res = res->ai_next;
  122. }
  123. #if defined(LWS_FALLBACK_GETHOSTBYNAME)
  124. } else if (addr_rv == EAI_SYSTEM) {
  125. struct hostent *host;
  126. lwsl_info("getaddrinfo (ipv4) failed, trying gethostbyname\n");
  127. host = gethostbyname(ads);
  128. if (host) {
  129. p = host->h_addr;
  130. } else {
  131. lwsl_err("gethostbyname failed\n");
  132. cce = "gethostbyname (ipv4) failed";
  133. goto oom4;
  134. }
  135. #endif
  136. } else {
  137. lwsl_err("getaddrinfo failed\n");
  138. cce = "getaddrinfo (ipv4) failed";
  139. goto oom4;
  140. }
  141. if (!p) {
  142. if (result)
  143. freeaddrinfo(result);
  144. lwsl_err("Couldn't identify address\n");
  145. cce = "unable to lookup address";
  146. goto oom4;
  147. }
  148. server_addr4.sin_family = AF_INET;
  149. server_addr4.sin_addr = *((struct in_addr *)p);
  150. bzero(&server_addr4.sin_zero, 8);
  151. if (result)
  152. freeaddrinfo(result);
  153. }
  154. if (!lws_socket_is_valid(wsi->desc.sockfd)) {
  155. #ifdef LWS_USE_IPV6
  156. if (LWS_IPV6_ENABLED(wsi->vhost))
  157. wsi->desc.sockfd = socket(AF_INET6, SOCK_STREAM, 0);
  158. else
  159. #endif
  160. wsi->desc.sockfd = socket(AF_INET, SOCK_STREAM, 0);
  161. if (!lws_socket_is_valid(wsi->desc.sockfd)) {
  162. lwsl_warn("Unable to open socket\n");
  163. cce = "unable to open socket";
  164. goto oom4;
  165. }
  166. if (lws_plat_set_socket_options(wsi->vhost, wsi->desc.sockfd)) {
  167. lwsl_err("Failed to set wsi socket options\n");
  168. compatible_close(wsi->desc.sockfd);
  169. cce = "set socket opts failed";
  170. goto oom4;
  171. }
  172. wsi->mode = LWSCM_WSCL_WAITING_CONNECT;
  173. lws_libev_accept(wsi, wsi->desc);
  174. lws_libuv_accept(wsi, wsi->desc);
  175. if (insert_wsi_socket_into_fds(context, wsi)) {
  176. compatible_close(wsi->desc.sockfd);
  177. cce = "insert wsi failed";
  178. goto oom4;
  179. }
  180. lws_change_pollfd(wsi, 0, LWS_POLLIN);
  181. /*
  182. * past here, we can't simply free the structs as error
  183. * handling as oom4 does. We have to run the whole close flow.
  184. */
  185. if (!wsi->protocol)
  186. wsi->protocol = &wsi->vhost->protocols[0];
  187. wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE,
  188. wsi->user_space, NULL, 0);
  189. lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
  190. AWAITING_TIMEOUT);
  191. n = lws_socket_bind(wsi->vhost, wsi->desc.sockfd, 0, wsi->vhost->iface);
  192. if (n < 0) {
  193. cce = "unable to bind socket";
  194. goto failed;
  195. }
  196. }
  197. #ifdef LWS_USE_IPV6
  198. if (LWS_IPV6_ENABLED(wsi->vhost)) {
  199. v = (struct sockaddr *)&server_addr6;
  200. n = sizeof(struct sockaddr_in6);
  201. } else
  202. #endif
  203. {
  204. v = (struct sockaddr *)&server_addr4;
  205. n = sizeof(struct sockaddr);
  206. }
  207. if (connect(wsi->desc.sockfd, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
  208. if (LWS_ERRNO == LWS_EALREADY ||
  209. LWS_ERRNO == LWS_EINPROGRESS ||
  210. LWS_ERRNO == LWS_EWOULDBLOCK
  211. #ifdef _WIN32
  212. || LWS_ERRNO == WSAEINVAL
  213. #endif
  214. ) {
  215. lwsl_client("nonblocking connect retry (errno = %d)\n",
  216. LWS_ERRNO);
  217. if (lws_plat_check_connection_error(wsi)) {
  218. cce = "socket connect failed";
  219. goto failed;
  220. }
  221. /*
  222. * must do specifically a POLLOUT poll to hear
  223. * about the connect completion
  224. */
  225. if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
  226. cce = "POLLOUT set failed";
  227. goto failed;
  228. }
  229. return wsi;
  230. }
  231. if (LWS_ERRNO != LWS_EISCONN) {
  232. lwsl_notice("Connect failed errno=%d\n", LWS_ERRNO);
  233. cce = "connect failed";
  234. goto failed;
  235. }
  236. }
  237. lwsl_client("connected\n");
  238. /* we are connected to server, or proxy */
  239. if (wsi->vhost->http_proxy_port) {
  240. /*
  241. * OK from now on we talk via the proxy, so connect to that
  242. *
  243. * (will overwrite existing pointer,
  244. * leaving old string/frag there but unreferenced)
  245. */
  246. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
  247. wsi->vhost->http_proxy_address))
  248. goto failed;
  249. wsi->c_port = wsi->vhost->http_proxy_port;
  250. n = send(wsi->desc.sockfd, (char *)pt->serv_buf, plen,
  251. MSG_NOSIGNAL);
  252. if (n < 0) {
  253. lwsl_debug("ERROR writing to proxy socket\n");
  254. cce = "proxy write failed";
  255. goto failed;
  256. }
  257. lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
  258. AWAITING_TIMEOUT);
  259. wsi->mode = LWSCM_WSCL_WAITING_PROXY_REPLY;
  260. return wsi;
  261. }
  262. /*
  263. * provoke service to issue the handshake directly
  264. * we need to do it this way because in the proxy case, this is the
  265. * next state and executed only if and when we get a good proxy
  266. * response inside the state machine... but notice in SSL case this
  267. * may not have sent anything yet with 0 return, and won't until some
  268. * many retries from main loop. To stop that becoming endless,
  269. * cover with a timeout.
  270. */
  271. lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
  272. AWAITING_TIMEOUT);
  273. wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE;
  274. pfd.fd = wsi->desc.sockfd;
  275. pfd.events = LWS_POLLIN;
  276. pfd.revents = LWS_POLLIN;
  277. n = lws_service_fd(context, &pfd);
  278. if (n < 0) {
  279. cce = "first service failed";
  280. goto failed;
  281. }
  282. if (n) /* returns 1 on failure after closing wsi */
  283. return NULL;
  284. return wsi;
  285. oom4:
  286. /* we're closing, losing some rx is OK */
  287. if (wsi->u.hdr.ah)
  288. wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
  289. if (wsi->mode == LWSCM_HTTP_CLIENT ||
  290. wsi->mode == LWSCM_HTTP_CLIENT_ACCEPTED ||
  291. wsi->mode == LWSCM_WSCL_WAITING_CONNECT) {
  292. wsi->vhost->protocols[0].callback(wsi,
  293. LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
  294. wsi->user_space, (void *)cce, strlen(cce));
  295. wsi->already_did_cce = 1;
  296. }
  297. /* take care that we might be inserted in fds already */
  298. if (wsi->position_in_fds_table != -1)
  299. goto failed1;
  300. lws_remove_from_timeout_list(wsi);
  301. lws_header_table_detach(wsi, 0);
  302. lws_free(wsi);
  303. return NULL;
  304. failed:
  305. wsi->vhost->protocols[0].callback(wsi,
  306. LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
  307. wsi->user_space, (void *)cce, strlen(cce));
  308. wsi->already_did_cce = 1;
  309. failed1:
  310. lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
  311. return NULL;
  312. }
  313. /**
  314. * lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect)
  315. * this only works if still in HTTP, ie, not upgraded yet
  316. * wsi: connection to reset
  317. * address: network address of the new server
  318. * port: port to connect to
  319. * path: uri path to connect to on the new server
  320. * host: host header to send to the new server
  321. */
  322. LWS_VISIBLE struct lws *
  323. lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
  324. const char *path, const char *host)
  325. {
  326. char origin[300] = "", protocol[300] = "", method[32] = "", *p;
  327. struct lws *wsi = *pwsi;
  328. if (wsi->redirects == 3) {
  329. lwsl_err("%s: Too many redirects\n", __func__);
  330. return NULL;
  331. }
  332. wsi->redirects++;
  333. #ifdef LWS_OPENSSL_SUPPORT
  334. wsi->use_ssl = ssl;
  335. #else
  336. if (ssl) {
  337. lwsl_err("%s: not configured for ssl\n", __func__);
  338. return NULL;
  339. }
  340. #endif
  341. p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN);
  342. if (p)
  343. strncpy(origin, p, sizeof(origin) - 1);
  344. p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
  345. if (p)
  346. strncpy(protocol, p, sizeof(protocol) - 1);
  347. p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
  348. if (p)
  349. strncpy(method, p, sizeof(method) - 1);
  350. lwsl_debug("redirect ads='%s', port=%d, path='%s', ssl = %d\n",
  351. address, port, path, ssl);
  352. /* close the connection by hand */
  353. compatible_close(wsi->desc.sockfd);
  354. remove_wsi_socket_from_fds(wsi);
  355. wsi->desc.sockfd = LWS_SOCK_INVALID;
  356. wsi->state = LWSS_CLIENT_UNCONNECTED;
  357. wsi->protocol = NULL;
  358. wsi->pending_timeout = NO_PENDING_TIMEOUT;
  359. wsi->c_port = port;
  360. wsi->hdr_parsing_completed = 0;
  361. _lws_header_table_reset(wsi->u.hdr.ah);
  362. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
  363. return NULL;
  364. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
  365. return NULL;
  366. if (origin[0])
  367. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
  368. origin))
  369. return NULL;
  370. if (protocol[0])
  371. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
  372. protocol))
  373. return NULL;
  374. if (method[0])
  375. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
  376. method))
  377. return NULL;
  378. origin[0] = '/';
  379. strncpy(&origin[1], path, sizeof(origin) - 2);
  380. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, origin))
  381. return NULL;
  382. *pwsi = lws_client_connect_2(wsi);
  383. return *pwsi;
  384. }
  385. #ifdef LWS_WITH_HTTP_PROXY
  386. static hubbub_error
  387. html_parser_cb(const hubbub_token *token, void *pw)
  388. {
  389. struct lws_rewrite *r = (struct lws_rewrite *)pw;
  390. char buf[1024], *start = buf + LWS_PRE, *p = start,
  391. *end = &buf[sizeof(buf) - 1];
  392. size_t i;
  393. switch (token->type) {
  394. case HUBBUB_TOKEN_DOCTYPE:
  395. p += lws_snprintf(p, end - p, "<!DOCTYPE %.*s %s ",
  396. (int) token->data.doctype.name.len,
  397. token->data.doctype.name.ptr,
  398. token->data.doctype.force_quirks ?
  399. "(force-quirks) " : "");
  400. if (token->data.doctype.public_missing)
  401. printf("\tpublic: missing\n");
  402. else
  403. p += lws_snprintf(p, end - p, "PUBLIC \"%.*s\"\n",
  404. (int) token->data.doctype.public_id.len,
  405. token->data.doctype.public_id.ptr);
  406. if (token->data.doctype.system_missing)
  407. printf("\tsystem: missing\n");
  408. else
  409. p += lws_snprintf(p, end - p, " \"%.*s\">\n",
  410. (int) token->data.doctype.system_id.len,
  411. token->data.doctype.system_id.ptr);
  412. break;
  413. case HUBBUB_TOKEN_START_TAG:
  414. p += lws_snprintf(p, end - p, "<%.*s", (int)token->data.tag.name.len,
  415. token->data.tag.name.ptr);
  416. /* (token->data.tag.self_closing) ?
  417. "(self-closing) " : "",
  418. (token->data.tag.n_attributes > 0) ?
  419. "attributes:" : "");
  420. */
  421. for (i = 0; i < token->data.tag.n_attributes; i++) {
  422. if (!hstrcmp(&token->data.tag.attributes[i].name, "href", 4) ||
  423. !hstrcmp(&token->data.tag.attributes[i].name, "action", 6) ||
  424. !hstrcmp(&token->data.tag.attributes[i].name, "src", 3)) {
  425. const char *pp = (const char *)token->data.tag.attributes[i].value.ptr;
  426. int plen = (int) token->data.tag.attributes[i].value.len;
  427. if (!hstrcmp(&token->data.tag.attributes[i].value,
  428. r->from, r->from_len)) {
  429. pp += r->from_len;
  430. plen -= r->from_len;
  431. }
  432. p += lws_snprintf(p, end - p, " %.*s=\"%s/%.*s\"",
  433. (int) token->data.tag.attributes[i].name.len,
  434. token->data.tag.attributes[i].name.ptr,
  435. r->to, plen, pp);
  436. } else
  437. p += lws_snprintf(p, end - p, " %.*s=\"%.*s\"",
  438. (int) token->data.tag.attributes[i].name.len,
  439. token->data.tag.attributes[i].name.ptr,
  440. (int) token->data.tag.attributes[i].value.len,
  441. token->data.tag.attributes[i].value.ptr);
  442. }
  443. p += lws_snprintf(p, end - p, ">\n");
  444. break;
  445. case HUBBUB_TOKEN_END_TAG:
  446. p += lws_snprintf(p, end - p, "</%.*s", (int) token->data.tag.name.len,
  447. token->data.tag.name.ptr);
  448. /*
  449. (token->data.tag.self_closing) ?
  450. "(self-closing) " : "",
  451. (token->data.tag.n_attributes > 0) ?
  452. "attributes:" : "");
  453. */
  454. for (i = 0; i < token->data.tag.n_attributes; i++) {
  455. p += lws_snprintf(p, end - p, " %.*s='%.*s'\n",
  456. (int) token->data.tag.attributes[i].name.len,
  457. token->data.tag.attributes[i].name.ptr,
  458. (int) token->data.tag.attributes[i].value.len,
  459. token->data.tag.attributes[i].value.ptr);
  460. }
  461. p += lws_snprintf(p, end - p, ">\n");
  462. break;
  463. case HUBBUB_TOKEN_COMMENT:
  464. p += lws_snprintf(p, end - p, "<!-- %.*s -->\n",
  465. (int) token->data.comment.len,
  466. token->data.comment.ptr);
  467. break;
  468. case HUBBUB_TOKEN_CHARACTER:
  469. p += lws_snprintf(p, end - p, "%.*s", (int) token->data.character.len,
  470. token->data.character.ptr);
  471. break;
  472. case HUBBUB_TOKEN_EOF:
  473. p += lws_snprintf(p, end - p, "\n");
  474. break;
  475. }
  476. if (user_callback_handle_rxflow(r->wsi->protocol->callback,
  477. r->wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
  478. r->wsi->user_space, start, p - start))
  479. return -1;
  480. return HUBBUB_OK;
  481. }
  482. #endif
  483. LWS_VISIBLE struct lws *
  484. lws_client_connect_via_info(struct lws_client_connect_info *i)
  485. {
  486. struct lws *wsi;
  487. int v = SPEC_LATEST_SUPPORTED;
  488. const struct lws_protocols *p;
  489. if (i->context->requested_kill)
  490. return NULL;
  491. if (!i->context->protocol_init_done)
  492. lws_protocol_init(i->context);
  493. wsi = lws_zalloc(sizeof(struct lws));
  494. if (wsi == NULL)
  495. goto bail;
  496. wsi->context = i->context;
  497. /* assert the mode and union status (hdr) clearly */
  498. lws_union_transition(wsi, LWSCM_HTTP_CLIENT);
  499. wsi->desc.sockfd = LWS_SOCK_INVALID;
  500. /* 1) fill up the wsi with stuff from the connect_info as far as it
  501. * can go. It's because not only is our connection async, we might
  502. * not even be able to get ahold of an ah at this point.
  503. */
  504. /* -1 means just use latest supported */
  505. if (i->ietf_version_or_minus_one != -1 && i->ietf_version_or_minus_one)
  506. v = i->ietf_version_or_minus_one;
  507. wsi->ietf_spec_revision = v;
  508. wsi->user_space = NULL;
  509. wsi->state = LWSS_CLIENT_UNCONNECTED;
  510. wsi->pending_timeout = NO_PENDING_TIMEOUT;
  511. wsi->position_in_fds_table = -1;
  512. wsi->c_port = i->port;
  513. wsi->vhost = i->vhost;
  514. if (!wsi->vhost)
  515. wsi->vhost = i->context->vhost_list;
  516. wsi->protocol = &wsi->vhost->protocols[0];
  517. /* for http[s] connection, allow protocol selection by name */
  518. if (i->method && i->vhost && i->protocol) {
  519. p = lws_vhost_name_to_protocol(i->vhost, i->protocol);
  520. if (p)
  521. wsi->protocol = p;
  522. }
  523. if (wsi && !wsi->user_space && i->userdata) {
  524. wsi->user_space_externally_allocated = 1;
  525. wsi->user_space = i->userdata;
  526. } else
  527. /* if we stay in http, we can assign the user space now,
  528. * otherwise do it after the protocol negotiated
  529. */
  530. if (i->method)
  531. if (lws_ensure_user_space(wsi))
  532. goto bail;
  533. #ifdef LWS_OPENSSL_SUPPORT
  534. wsi->use_ssl = i->ssl_connection;
  535. #else
  536. if (i->ssl_connection) {
  537. lwsl_err("libwebsockets not configured for ssl\n");
  538. goto bail;
  539. }
  540. #endif
  541. /* 2) stash the things from connect_info that we can't process without
  542. * an ah. Because if no ah, we will go on the ah waiting list and
  543. * process those things later (after the connect_info and maybe the
  544. * things pointed to have gone out of scope.
  545. */
  546. wsi->u.hdr.stash = lws_malloc(sizeof(*wsi->u.hdr.stash));
  547. if (!wsi->u.hdr.stash) {
  548. lwsl_err("%s: OOM\n", __func__);
  549. goto bail;
  550. }
  551. wsi->u.hdr.stash->origin[0] = '\0';
  552. wsi->u.hdr.stash->protocol[0] = '\0';
  553. wsi->u.hdr.stash->method[0] = '\0';
  554. strncpy(wsi->u.hdr.stash->address, i->address,
  555. sizeof(wsi->u.hdr.stash->address) - 1);
  556. strncpy(wsi->u.hdr.stash->path, i->path,
  557. sizeof(wsi->u.hdr.stash->path) - 1);
  558. strncpy(wsi->u.hdr.stash->host, i->host,
  559. sizeof(wsi->u.hdr.stash->host) - 1);
  560. if (i->origin)
  561. strncpy(wsi->u.hdr.stash->origin, i->origin,
  562. sizeof(wsi->u.hdr.stash->origin) - 1);
  563. if (i->protocol)
  564. strncpy(wsi->u.hdr.stash->protocol, i->protocol,
  565. sizeof(wsi->u.hdr.stash->protocol) - 1);
  566. if (i->method)
  567. strncpy(wsi->u.hdr.stash->method, i->method,
  568. sizeof(wsi->u.hdr.stash->method) - 1);
  569. wsi->u.hdr.stash->address[sizeof(wsi->u.hdr.stash->address) - 1] = '\0';
  570. wsi->u.hdr.stash->path[sizeof(wsi->u.hdr.stash->path) - 1] = '\0';
  571. wsi->u.hdr.stash->host[sizeof(wsi->u.hdr.stash->host) - 1] = '\0';
  572. wsi->u.hdr.stash->origin[sizeof(wsi->u.hdr.stash->origin) - 1] = '\0';
  573. wsi->u.hdr.stash->protocol[sizeof(wsi->u.hdr.stash->protocol) - 1] = '\0';
  574. wsi->u.hdr.stash->method[sizeof(wsi->u.hdr.stash->method) - 1] = '\0';
  575. if (i->pwsi)
  576. *i->pwsi = wsi;
  577. /* if we went on the waiting list, no probs just return the wsi
  578. * when we get the ah, now or later, he will call
  579. * lws_client_connect_via_info2() below.
  580. */
  581. if (lws_header_table_attach(wsi, 0) < 0) {
  582. /*
  583. * if we failed here, the connection is already closed
  584. * and freed.
  585. */
  586. goto bail1;
  587. }
  588. if (i->parent_wsi) {
  589. lwsl_info("%s: created child %p of parent %p\n", __func__,
  590. wsi, i->parent_wsi);
  591. wsi->parent = i->parent_wsi;
  592. wsi->sibling_list = i->parent_wsi->child_list;
  593. i->parent_wsi->child_list = wsi;
  594. }
  595. #ifdef LWS_WITH_HTTP_PROXY
  596. if (i->uri_replace_to)
  597. wsi->rw = lws_rewrite_create(wsi, html_parser_cb,
  598. i->uri_replace_from,
  599. i->uri_replace_to);
  600. #endif
  601. return wsi;
  602. bail:
  603. lws_free(wsi);
  604. bail1:
  605. if (i->pwsi)
  606. *i->pwsi = NULL;
  607. return NULL;
  608. }
  609. struct lws *
  610. lws_client_connect_via_info2(struct lws *wsi)
  611. {
  612. struct client_info_stash *stash = wsi->u.hdr.stash;
  613. if (!stash)
  614. return wsi;
  615. /*
  616. * we're not necessarily in a position to action these right away,
  617. * stash them... we only need during connect phase so u.hdr is fine
  618. */
  619. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
  620. stash->address))
  621. goto bail1;
  622. /* these only need u.hdr lifetime as well */
  623. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, stash->path))
  624. goto bail1;
  625. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, stash->host))
  626. goto bail1;
  627. if (stash->origin[0])
  628. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
  629. stash->origin))
  630. goto bail1;
  631. /*
  632. * this is a list of protocols we tell the server we're okay with
  633. * stash it for later when we compare server response with it
  634. */
  635. if (stash->protocol[0])
  636. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
  637. stash->protocol))
  638. goto bail1;
  639. if (stash->method[0])
  640. if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
  641. stash->method))
  642. goto bail1;
  643. lws_free_set_NULL(wsi->u.hdr.stash);
  644. /*
  645. * Check with each extension if it is able to route and proxy this
  646. * connection for us. For example, an extension like x-google-mux
  647. * can handle this and then we don't need an actual socket for this
  648. * connection.
  649. */
  650. if (lws_ext_cb_all_exts(wsi->context, wsi,
  651. LWS_EXT_CB_CAN_PROXY_CLIENT_CONNECTION,
  652. (void *)stash->address,
  653. wsi->c_port) > 0) {
  654. lwsl_client("lws_client_connect: ext handling conn\n");
  655. lws_set_timeout(wsi,
  656. PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
  657. AWAITING_TIMEOUT);
  658. wsi->mode = LWSCM_WSCL_WAITING_EXTENSION_CONNECT;
  659. return wsi;
  660. }
  661. lwsl_client("lws_client_connect: direct conn\n");
  662. wsi->context->count_wsi_allocated++;
  663. return lws_client_connect_2(wsi);
  664. bail1:
  665. lws_free_set_NULL(wsi->u.hdr.stash);
  666. return NULL;
  667. }
  668. LWS_VISIBLE struct lws *
  669. lws_client_connect_extended(struct lws_context *context, const char *address,
  670. int port, int ssl_connection, const char *path,
  671. const char *host, const char *origin,
  672. const char *protocol, int ietf_version_or_minus_one,
  673. void *userdata)
  674. {
  675. struct lws_client_connect_info i;
  676. memset(&i, 0, sizeof(i));
  677. i.context = context;
  678. i.address = address;
  679. i.port = port;
  680. i.ssl_connection = ssl_connection;
  681. i.path = path;
  682. i.host = host;
  683. i.origin = origin;
  684. i.protocol = protocol;
  685. i.ietf_version_or_minus_one = ietf_version_or_minus_one;
  686. i.userdata = userdata;
  687. return lws_client_connect_via_info(&i);
  688. }
  689. LWS_VISIBLE struct lws *
  690. lws_client_connect(struct lws_context *context, const char *address,
  691. int port, int ssl_connection, const char *path,
  692. const char *host, const char *origin,
  693. const char *protocol, int ietf_version_or_minus_one)
  694. {
  695. struct lws_client_connect_info i;
  696. memset(&i, 0, sizeof(i));
  697. i.context = context;
  698. i.address = address;
  699. i.port = port;
  700. i.ssl_connection = ssl_connection;
  701. i.path = path;
  702. i.host = host;
  703. i.origin = origin;
  704. i.protocol = protocol;
  705. i.ietf_version_or_minus_one = ietf_version_or_minus_one;
  706. i.userdata = NULL;
  707. return lws_client_connect_via_info(&i);
  708. }