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