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