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