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