1 #include "private-libwebsockets.h"
4 lws_client_connect_2(struct lws *wsi)
7 struct sockaddr_in6 server_addr6;
8 struct addrinfo hints, *result;
10 struct lws_context *context = wsi->context;
11 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
12 struct sockaddr_in server_addr4;
13 struct lws_pollfd pfd;
15 const char *cce = "", *iface;
19 lwsl_client("%s\n", __func__);
22 cce = "ah was NULL at cc2";
23 lwsl_err("%s\n", cce);
30 if (wsi->vhost->http_proxy_port) {
31 plen = sprintf((char *)pt->serv_buf,
32 "CONNECT %s:%u HTTP/1.0\x0d\x0a"
33 "User-agent: libwebsockets\x0d\x0a",
34 lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
37 if (wsi->vhost->proxy_basic_auth_token[0])
38 plen += sprintf((char *)pt->serv_buf + plen,
39 "Proxy-authorization: basic %s\x0d\x0a",
40 wsi->vhost->proxy_basic_auth_token);
42 plen += sprintf((char *)pt->serv_buf + plen, "\x0d\x0a");
43 ads = wsi->vhost->http_proxy_address;
46 if (LWS_IPV6_ENABLED(wsi->vhost)) {
47 memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
48 server_addr6.sin6_port = htons(wsi->vhost->http_proxy_port);
51 server_addr4.sin_port = htons(wsi->vhost->http_proxy_port);
54 #if defined(LWS_WITH_SOCKS5)
56 else if (wsi->vhost->socks_proxy_port) {
57 socks_generate_msg(wsi, SOCKS_MSG_GREETING, (size_t *)&plen);
58 lwsl_client("%s\n", "Sending SOCKS Greeting.");
60 ads = wsi->vhost->socks_proxy_address;
63 if (LWS_IPV6_ENABLED(wsi->vhost)) {
64 memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
65 server_addr6.sin6_port = htons(wsi->vhost->socks_proxy_port);
68 server_addr4.sin_port = htons(wsi->vhost->socks_proxy_port);
73 ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
75 if (LWS_IPV6_ENABLED(wsi->vhost)) {
76 memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
77 server_addr6.sin6_port = htons(wsi->c_port);
80 server_addr4.sin_port = htons(wsi->c_port);
84 * prepare the actual connection (to the proxy, if any)
86 lwsl_notice("%s: %p: address %s\n", __func__, wsi, ads);
89 if (LWS_IPV6_ENABLED(wsi->vhost)) {
90 memset(&hints, 0, sizeof(struct addrinfo));
91 #if !defined(__ANDROID__)
92 hints.ai_family = AF_INET6;
93 hints.ai_flags = AI_V4MAPPED;
95 n = getaddrinfo(ads, NULL, &hints, &result);
98 lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n));
100 lwsl_err("getaddrinfo: %s\n", gai_strerror(n));
102 cce = "getaddrinfo (ipv6) failed";
106 server_addr6.sin6_family = AF_INET6;
107 switch (result->ai_family) {
108 #if defined(__ANDROID__)
110 /* map IPv4 to IPv6 */
111 bzero((char *)&server_addr6.sin6_addr,
112 sizeof(struct in6_addr));
113 server_addr6.sin6_addr.s6_addr[10] = 0xff;
114 server_addr6.sin6_addr.s6_addr[11] = 0xff;
115 memcpy(&server_addr6.sin6_addr.s6_addr[12],
116 &((struct sockaddr_in *)result->ai_addr)->sin_addr,
117 sizeof(struct in_addr));
121 memcpy(&server_addr6.sin6_addr,
122 &((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
123 sizeof(struct in6_addr));
124 server_addr6.sin6_scope_id = ((struct sockaddr_in6 *)result->ai_addr)->sin6_scope_id;
125 server_addr6.sin6_flowinfo = ((struct sockaddr_in6 *)result->ai_addr)->sin6_flowinfo;
128 lwsl_err("Unknown address family\n");
129 freeaddrinfo(result);
130 cce = "unknown address family";
134 freeaddrinfo(result);
138 struct addrinfo ai, *res, *result = NULL;
142 memset (&ai, 0, sizeof ai);
143 ai.ai_family = PF_UNSPEC;
144 ai.ai_socktype = SOCK_STREAM;
145 ai.ai_flags = AI_CANONNAME;
147 addr_rv = getaddrinfo(ads, NULL, &ai, &result);
151 switch (res->ai_family) {
153 p = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
159 #if defined(LWS_FALLBACK_GETHOSTBYNAME)
160 } else if (addr_rv == EAI_SYSTEM) {
161 struct hostent *host;
163 lwsl_info("getaddrinfo (ipv4) failed, trying gethostbyname\n");
164 host = gethostbyname(ads);
168 lwsl_err("gethostbyname failed\n");
169 cce = "gethostbyname (ipv4) failed";
174 lwsl_err("getaddrinfo failed\n");
175 cce = "getaddrinfo (ipv4) failed";
181 freeaddrinfo(result);
182 lwsl_err("Couldn't identify address\n");
183 cce = "unable to lookup address";
187 server_addr4.sin_family = AF_INET;
188 server_addr4.sin_addr = *((struct in_addr *)p);
189 bzero(&server_addr4.sin_zero, 8);
191 freeaddrinfo(result);
194 if (!lws_socket_is_valid(wsi->desc.sockfd)) {
197 if (LWS_IPV6_ENABLED(wsi->vhost))
198 wsi->desc.sockfd = socket(AF_INET6, SOCK_STREAM, 0);
201 wsi->desc.sockfd = socket(AF_INET, SOCK_STREAM, 0);
203 if (!lws_socket_is_valid(wsi->desc.sockfd)) {
204 lwsl_warn("Unable to open socket\n");
205 cce = "unable to open socket";
209 if (lws_plat_set_socket_options(wsi->vhost, wsi->desc.sockfd)) {
210 lwsl_err("Failed to set wsi socket options\n");
211 compatible_close(wsi->desc.sockfd);
212 cce = "set socket opts failed";
216 wsi->mode = LWSCM_WSCL_WAITING_CONNECT;
218 lws_libev_accept(wsi, wsi->desc);
219 lws_libuv_accept(wsi, wsi->desc);
220 lws_libevent_accept(wsi, wsi->desc);
221 if (insert_wsi_socket_into_fds(context, wsi)) {
222 compatible_close(wsi->desc.sockfd);
223 cce = "insert wsi failed";
227 lws_change_pollfd(wsi, 0, LWS_POLLIN);
230 * past here, we can't simply free the structs as error
231 * handling as oom4 does. We have to run the whole close flow.
235 wsi->protocol = &wsi->vhost->protocols[0];
237 wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE,
238 wsi->user_space, NULL, 0);
240 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
243 iface = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
246 n = lws_socket_bind(wsi->vhost, wsi->desc.sockfd, 0, iface);
248 cce = "unable to bind socket";
255 if (LWS_IPV6_ENABLED(wsi->vhost)) {
256 v = (struct sockaddr *)&server_addr6;
257 n = sizeof(struct sockaddr_in6);
261 v = (struct sockaddr *)&server_addr4;
262 n = sizeof(struct sockaddr);
265 if (connect(wsi->desc.sockfd, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
266 if (LWS_ERRNO == LWS_EALREADY ||
267 LWS_ERRNO == LWS_EINPROGRESS ||
268 LWS_ERRNO == LWS_EWOULDBLOCK
270 || LWS_ERRNO == WSAEINVAL
273 lwsl_client("nonblocking connect retry (errno = %d)\n",
276 if (lws_plat_check_connection_error(wsi)) {
277 cce = "socket connect failed";
282 * must do specifically a POLLOUT poll to hear
283 * about the connect completion
285 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
286 cce = "POLLOUT set failed";
293 if (LWS_ERRNO != LWS_EISCONN) {
294 lwsl_notice("Connect failed errno=%d\n", LWS_ERRNO);
295 cce = "connect failed";
300 lwsl_client("connected\n");
302 /* we are connected to server, or proxy */
305 if (wsi->vhost->http_proxy_port) {
308 * OK from now on we talk via the proxy, so connect to that
310 * (will overwrite existing pointer,
311 * leaving old string/frag there but unreferenced)
313 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
314 wsi->vhost->http_proxy_address))
316 wsi->c_port = wsi->vhost->http_proxy_port;
318 n = send(wsi->desc.sockfd, (char *)pt->serv_buf, plen,
321 lwsl_debug("ERROR writing to proxy socket\n");
322 cce = "proxy write failed";
326 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
329 wsi->mode = LWSCM_WSCL_WAITING_PROXY_REPLY;
333 #if defined(LWS_WITH_SOCKS5)
335 else if (wsi->vhost->socks_proxy_port) {
336 n = send(wsi->desc.sockfd, (char *)pt->serv_buf, plen,
339 lwsl_debug("ERROR writing greeting to socks proxy"
341 cce = "socks write failed";
345 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY,
348 wsi->mode = LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY;
355 * provoke service to issue the handshake directly
356 * we need to do it this way because in the proxy case, this is the
357 * next state and executed only if and when we get a good proxy
358 * response inside the state machine... but notice in SSL case this
359 * may not have sent anything yet with 0 return, and won't until some
360 * many retries from main loop. To stop that becoming endless,
361 * cover with a timeout.
364 lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
367 wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE;
368 pfd.fd = wsi->desc.sockfd;
369 pfd.events = LWS_POLLIN;
370 pfd.revents = LWS_POLLIN;
372 n = lws_service_fd(context, &pfd);
374 cce = "first service failed";
377 if (n) /* returns 1 on failure after closing wsi */
383 /* we're closing, losing some rx is OK */
385 wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
386 if (wsi->mode == LWSCM_HTTP_CLIENT ||
387 wsi->mode == LWSCM_HTTP_CLIENT_ACCEPTED ||
388 wsi->mode == LWSCM_WSCL_WAITING_CONNECT) {
389 wsi->vhost->protocols[0].callback(wsi,
390 LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
391 wsi->user_space, (void *)cce, strlen(cce));
392 wsi->already_did_cce = 1;
394 /* take care that we might be inserted in fds already */
395 if (wsi->position_in_fds_table != -1)
397 lws_remove_from_timeout_list(wsi);
398 lws_header_table_detach(wsi, 0);
404 wsi->vhost->protocols[0].callback(wsi,
405 LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
406 wsi->user_space, (void *)cce, strlen(cce));
407 wsi->already_did_cce = 1;
409 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
415 * lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect)
416 * this only works if still in HTTP, ie, not upgraded yet
417 * wsi: connection to reset
418 * address: network address of the new server
419 * port: port to connect to
420 * path: uri path to connect to on the new server
421 * host: host header to send to the new server
423 LWS_VISIBLE struct lws *
424 lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
425 const char *path, const char *host)
427 char origin[300] = "", protocol[300] = "", method[32] = "", iface[16] = "", *p;
428 struct lws *wsi = *pwsi;
430 if (wsi->redirects == 3) {
431 lwsl_err("%s: Too many redirects\n", __func__);
436 #ifdef LWS_OPENSSL_SUPPORT
440 lwsl_err("%s: not configured for ssl\n", __func__);
445 p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN);
447 strncpy(origin, p, sizeof(origin) - 1);
449 p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
451 strncpy(protocol, p, sizeof(protocol) - 1);
453 p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
455 strncpy(method, p, sizeof(method) - 1);
457 p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
459 strncpy(method, p, sizeof(iface) - 1);
461 lwsl_debug("redirect ads='%s', port=%d, path='%s', ssl = %d\n",
462 address, port, path, ssl);
464 /* close the connection by hand */
466 compatible_close(wsi->desc.sockfd);
467 remove_wsi_socket_from_fds(wsi);
469 wsi->desc.sockfd = LWS_SOCK_INVALID;
470 wsi->state = LWSS_CLIENT_UNCONNECTED;
471 wsi->protocol = NULL;
472 wsi->pending_timeout = NO_PENDING_TIMEOUT;
474 wsi->hdr_parsing_completed = 0;
475 _lws_header_table_reset(wsi->u.hdr.ah);
477 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
480 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
484 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
488 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
492 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
497 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_IFACE,
502 strncpy(&origin[1], path, sizeof(origin) - 2);
503 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, origin))
506 *pwsi = lws_client_connect_2(wsi);
511 #ifdef LWS_WITH_HTTP_PROXY
513 html_parser_cb(const hubbub_token *token, void *pw)
515 struct lws_rewrite *r = (struct lws_rewrite *)pw;
516 char buf[1024], *start = buf + LWS_PRE, *p = start,
517 *end = &buf[sizeof(buf) - 1];
520 switch (token->type) {
521 case HUBBUB_TOKEN_DOCTYPE:
523 p += lws_snprintf(p, end - p, "<!DOCTYPE %.*s %s ",
524 (int) token->data.doctype.name.len,
525 token->data.doctype.name.ptr,
526 token->data.doctype.force_quirks ?
527 "(force-quirks) " : "");
529 if (token->data.doctype.public_missing)
530 printf("\tpublic: missing\n");
532 p += lws_snprintf(p, end - p, "PUBLIC \"%.*s\"\n",
533 (int) token->data.doctype.public_id.len,
534 token->data.doctype.public_id.ptr);
536 if (token->data.doctype.system_missing)
537 printf("\tsystem: missing\n");
539 p += lws_snprintf(p, end - p, " \"%.*s\">\n",
540 (int) token->data.doctype.system_id.len,
541 token->data.doctype.system_id.ptr);
544 case HUBBUB_TOKEN_START_TAG:
545 p += lws_snprintf(p, end - p, "<%.*s", (int)token->data.tag.name.len,
546 token->data.tag.name.ptr);
548 /* (token->data.tag.self_closing) ?
549 "(self-closing) " : "",
550 (token->data.tag.n_attributes > 0) ?
553 for (i = 0; i < token->data.tag.n_attributes; i++) {
554 if (!hstrcmp(&token->data.tag.attributes[i].name, "href", 4) ||
555 !hstrcmp(&token->data.tag.attributes[i].name, "action", 6) ||
556 !hstrcmp(&token->data.tag.attributes[i].name, "src", 3)) {
557 const char *pp = (const char *)token->data.tag.attributes[i].value.ptr;
558 int plen = (int) token->data.tag.attributes[i].value.len;
560 if (!hstrcmp(&token->data.tag.attributes[i].value,
561 r->from, r->from_len)) {
565 p += lws_snprintf(p, end - p, " %.*s=\"%s/%.*s\"",
566 (int) token->data.tag.attributes[i].name.len,
567 token->data.tag.attributes[i].name.ptr,
572 p += lws_snprintf(p, end - p, " %.*s=\"%.*s\"",
573 (int) token->data.tag.attributes[i].name.len,
574 token->data.tag.attributes[i].name.ptr,
575 (int) token->data.tag.attributes[i].value.len,
576 token->data.tag.attributes[i].value.ptr);
578 p += lws_snprintf(p, end - p, ">\n");
580 case HUBBUB_TOKEN_END_TAG:
581 p += lws_snprintf(p, end - p, "</%.*s", (int) token->data.tag.name.len,
582 token->data.tag.name.ptr);
584 (token->data.tag.self_closing) ?
585 "(self-closing) " : "",
586 (token->data.tag.n_attributes > 0) ?
589 for (i = 0; i < token->data.tag.n_attributes; i++) {
590 p += lws_snprintf(p, end - p, " %.*s='%.*s'\n",
591 (int) token->data.tag.attributes[i].name.len,
592 token->data.tag.attributes[i].name.ptr,
593 (int) token->data.tag.attributes[i].value.len,
594 token->data.tag.attributes[i].value.ptr);
596 p += lws_snprintf(p, end - p, ">\n");
598 case HUBBUB_TOKEN_COMMENT:
599 p += lws_snprintf(p, end - p, "<!-- %.*s -->\n",
600 (int) token->data.comment.len,
601 token->data.comment.ptr);
603 case HUBBUB_TOKEN_CHARACTER:
604 p += lws_snprintf(p, end - p, "%.*s", (int) token->data.character.len,
605 token->data.character.ptr);
607 case HUBBUB_TOKEN_EOF:
608 p += lws_snprintf(p, end - p, "\n");
612 if (user_callback_handle_rxflow(r->wsi->protocol->callback,
613 r->wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
614 r->wsi->user_space, start, p - start))
621 LWS_VISIBLE struct lws *
622 lws_client_connect_via_info(struct lws_client_connect_info *i)
625 int v = SPEC_LATEST_SUPPORTED;
626 const struct lws_protocols *p;
628 if (i->context->requested_kill)
631 if (!i->context->protocol_init_done)
632 lws_protocol_init(i->context);
634 wsi = lws_zalloc(sizeof(struct lws));
638 wsi->context = i->context;
639 /* assert the mode and union status (hdr) clearly */
640 lws_union_transition(wsi, LWSCM_HTTP_CLIENT);
641 wsi->desc.sockfd = LWS_SOCK_INVALID;
643 /* 1) fill up the wsi with stuff from the connect_info as far as it
644 * can go. It's because not only is our connection async, we might
645 * not even be able to get ahold of an ah at this point.
648 /* -1 means just use latest supported */
649 if (i->ietf_version_or_minus_one != -1 && i->ietf_version_or_minus_one)
650 v = i->ietf_version_or_minus_one;
652 wsi->ietf_spec_revision = v;
653 wsi->user_space = NULL;
654 wsi->state = LWSS_CLIENT_UNCONNECTED;
655 wsi->pending_timeout = NO_PENDING_TIMEOUT;
656 wsi->position_in_fds_table = -1;
657 wsi->c_port = i->port;
658 wsi->vhost = i->vhost;
660 wsi->vhost = i->context->vhost_list;
662 wsi->protocol = &wsi->vhost->protocols[0];
664 /* for http[s] connection, allow protocol selection by name */
666 if (i->method && i->vhost && i->protocol) {
667 p = lws_vhost_name_to_protocol(i->vhost, i->protocol);
672 if (wsi && !wsi->user_space && i->userdata) {
673 wsi->user_space_externally_allocated = 1;
674 wsi->user_space = i->userdata;
676 /* if we stay in http, we can assign the user space now,
677 * otherwise do it after the protocol negotiated
680 if (lws_ensure_user_space(wsi))
683 #ifdef LWS_OPENSSL_SUPPORT
684 wsi->use_ssl = i->ssl_connection;
686 if (i->ssl_connection) {
687 lwsl_err("libwebsockets not configured for ssl\n");
692 /* 2) stash the things from connect_info that we can't process without
693 * an ah. Because if no ah, we will go on the ah waiting list and
694 * process those things later (after the connect_info and maybe the
695 * things pointed to have gone out of scope.
698 wsi->u.hdr.stash = lws_malloc(sizeof(*wsi->u.hdr.stash));
699 if (!wsi->u.hdr.stash) {
700 lwsl_err("%s: OOM\n", __func__);
704 wsi->u.hdr.stash->origin[0] = '\0';
705 wsi->u.hdr.stash->protocol[0] = '\0';
706 wsi->u.hdr.stash->method[0] = '\0';
707 wsi->u.hdr.stash->iface[0] = '\0';
709 strncpy(wsi->u.hdr.stash->address, i->address,
710 sizeof(wsi->u.hdr.stash->address) - 1);
711 strncpy(wsi->u.hdr.stash->path, i->path,
712 sizeof(wsi->u.hdr.stash->path) - 1);
713 strncpy(wsi->u.hdr.stash->host, i->host,
714 sizeof(wsi->u.hdr.stash->host) - 1);
716 strncpy(wsi->u.hdr.stash->origin, i->origin,
717 sizeof(wsi->u.hdr.stash->origin) - 1);
719 strncpy(wsi->u.hdr.stash->protocol, i->protocol,
720 sizeof(wsi->u.hdr.stash->protocol) - 1);
722 strncpy(wsi->u.hdr.stash->method, i->method,
723 sizeof(wsi->u.hdr.stash->method) - 1);
725 strncpy(wsi->u.hdr.stash->iface, i->iface,
726 sizeof(wsi->u.hdr.stash->iface) - 1);
728 wsi->u.hdr.stash->address[sizeof(wsi->u.hdr.stash->address) - 1] = '\0';
729 wsi->u.hdr.stash->path[sizeof(wsi->u.hdr.stash->path) - 1] = '\0';
730 wsi->u.hdr.stash->host[sizeof(wsi->u.hdr.stash->host) - 1] = '\0';
731 wsi->u.hdr.stash->origin[sizeof(wsi->u.hdr.stash->origin) - 1] = '\0';
732 wsi->u.hdr.stash->protocol[sizeof(wsi->u.hdr.stash->protocol) - 1] = '\0';
733 wsi->u.hdr.stash->method[sizeof(wsi->u.hdr.stash->method) - 1] = '\0';
734 wsi->u.hdr.stash->iface[sizeof(wsi->u.hdr.stash->iface) - 1] = '\0';
739 /* if we went on the waiting list, no probs just return the wsi
740 * when we get the ah, now or later, he will call
741 * lws_client_connect_via_info2() below.
743 if (lws_header_table_attach(wsi, 0) < 0) {
745 * if we failed here, the connection is already closed
752 lwsl_info("%s: created child %p of parent %p\n", __func__,
754 wsi->parent = i->parent_wsi;
755 wsi->sibling_list = i->parent_wsi->child_list;
756 i->parent_wsi->child_list = wsi;
758 #ifdef LWS_WITH_HTTP_PROXY
759 if (i->uri_replace_to)
760 wsi->rw = lws_rewrite_create(wsi, html_parser_cb,
778 lws_client_connect_via_info2(struct lws *wsi)
780 struct client_info_stash *stash = wsi->u.hdr.stash;
786 * we're not necessarily in a position to action these right away,
787 * stash them... we only need during connect phase so u.hdr is fine
789 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
793 /* these only need u.hdr lifetime as well */
795 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, stash->path))
798 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, stash->host))
801 if (stash->origin[0])
802 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
806 * this is a list of protocols we tell the server we're okay with
807 * stash it for later when we compare server response with it
809 if (stash->protocol[0])
810 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
813 if (stash->method[0])
814 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
818 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_IFACE,
822 #if defined(LWS_WITH_SOCKS5)
823 if (!wsi->vhost->socks_proxy_port)
824 lws_free_set_NULL(wsi->u.hdr.stash);
828 * Check with each extension if it is able to route and proxy this
829 * connection for us. For example, an extension like x-google-mux
830 * can handle this and then we don't need an actual socket for this
834 if (lws_ext_cb_all_exts(wsi->context, wsi,
835 LWS_EXT_CB_CAN_PROXY_CLIENT_CONNECTION,
836 (void *)stash->address,
838 lwsl_client("lws_client_connect: ext handling conn\n");
841 PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
844 wsi->mode = LWSCM_WSCL_WAITING_EXTENSION_CONNECT;
847 lwsl_client("lws_client_connect: direct conn\n");
848 wsi->context->count_wsi_allocated++;
850 return lws_client_connect_2(wsi);
853 #if defined(LWS_WITH_SOCKS5)
854 if (!wsi->vhost->socks_proxy_port)
855 lws_free_set_NULL(wsi->u.hdr.stash);
861 LWS_VISIBLE struct lws *
862 lws_client_connect_extended(struct lws_context *context, const char *address,
863 int port, int ssl_connection, const char *path,
864 const char *host, const char *origin,
865 const char *protocol, int ietf_version_or_minus_one,
868 struct lws_client_connect_info i;
870 memset(&i, 0, sizeof(i));
875 i.ssl_connection = ssl_connection;
879 i.protocol = protocol;
880 i.ietf_version_or_minus_one = ietf_version_or_minus_one;
881 i.userdata = userdata;
883 return lws_client_connect_via_info(&i);
886 LWS_VISIBLE struct lws *
887 lws_client_connect(struct lws_context *context, const char *address,
888 int port, int ssl_connection, const char *path,
889 const char *host, const char *origin,
890 const char *protocol, int ietf_version_or_minus_one)
892 struct lws_client_connect_info i;
894 memset(&i, 0, sizeof(i));
899 i.ssl_connection = ssl_connection;
903 i.protocol = protocol;
904 i.ietf_version_or_minus_one = ietf_version_or_minus_one;
907 return lws_client_connect_via_info(&i);
910 #if defined(LWS_WITH_SOCKS5)
911 void socks_generate_msg(struct lws *wsi, enum socks_msg_type type,
914 struct lws_context *context = wsi->context;
915 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
918 if (type == SOCKS_MSG_GREETING) {
919 /* socks version, version 5 only */
920 pt->serv_buf[len++] = SOCKS_VERSION_5;
921 /* number of methods */
922 pt->serv_buf[len++] = 2;
923 /* username password method */
924 pt->serv_buf[len++] = SOCKS_AUTH_USERNAME_PASSWORD;
925 /* no authentication method */
926 pt->serv_buf[len++] = SOCKS_AUTH_NO_AUTH;
928 else if (type == SOCKS_MSG_USERNAME_PASSWORD) {
930 size_t passwd_len = 0;
932 user_len = strlen(wsi->vhost->socks_user);
933 passwd_len = strlen(wsi->vhost->socks_password);
935 /* the subnegotiation version */
936 pt->serv_buf[len++] = SOCKS_SUBNEGOTIATION_VERSION_1;
937 /* length of the user name */
938 pt->serv_buf[len++] = user_len;
940 strncpy((char *)&pt->serv_buf[len], wsi->vhost->socks_user,
941 context->pt_serv_buf_size - len);
943 /* length of the password */
944 pt->serv_buf[len++] = passwd_len;
946 strncpy((char *)&pt->serv_buf[len], wsi->vhost->socks_password,
947 context->pt_serv_buf_size - len);
950 else if (type == SOCKS_MSG_CONNECT) {
951 size_t len_index = 0;
953 char *net_buf = (char*)&net_num;
956 pt->serv_buf[len++] = SOCKS_VERSION_5;
958 pt->serv_buf[len++] = SOCKS_COMMAND_CONNECT;
960 pt->serv_buf[len++] = 0;
962 pt->serv_buf[len++] = SOCKS_ATYP_DOMAINNAME;
965 /* the address we tell SOCKS proxy to connect to */
966 strncpy((char *)&(pt->serv_buf[len]), wsi->u.hdr.stash->address,
967 context->pt_serv_buf_size - len);
968 len += strlen(wsi->u.hdr.stash->address);
969 net_num = htons((short)wsi->c_port);
970 /* the port we tell SOCKS proxy to connect to */
971 pt->serv_buf[len++] = net_buf[0];
972 pt->serv_buf[len++] = net_buf[1];
973 /* the length of the address, excluding port */
974 pt->serv_buf[len_index] = strlen(wsi->u.hdr.stash->address);