client account for retries
[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 sockaddr_in6 client_addr6;
9         struct addrinfo hints, *result;
10 #endif
11         struct lws_context *context = wsi->context;
12         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
13         struct sockaddr_in server_addr4;
14         struct sockaddr_in client_addr4;
15         struct lws_pollfd pfd;
16         struct sockaddr *v;
17         int n, plen = 0;
18         const char *ads;
19
20         lwsl_client("%s\n", __func__);
21
22         /* proxy? */
23
24         if (context->http_proxy_port) {
25                 plen = sprintf((char *)pt->serv_buf,
26                         "CONNECT %s:%u HTTP/1.0\x0d\x0a"
27                         "User-agent: libwebsockets\x0d\x0a",
28                         lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
29                         wsi->u.hdr.ah->c_port);
30
31                 if (context->proxy_basic_auth_token[0])
32                         plen += sprintf((char *)pt->serv_buf + plen,
33                                         "Proxy-authorization: basic %s\x0d\x0a",
34                                         context->proxy_basic_auth_token);
35
36                 plen += sprintf((char *)pt->serv_buf + plen, "\x0d\x0a");
37                 ads = context->http_proxy_address;
38
39 #ifdef LWS_USE_IPV6
40                 if (LWS_IPV6_ENABLED(context)) {
41                         memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
42                         server_addr6.sin6_port = htons(context->http_proxy_port);
43                 } else
44 #endif
45                         server_addr4.sin_port = htons(context->http_proxy_port);
46
47         } else {
48                 ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
49 #ifdef LWS_USE_IPV6
50                 if (LWS_IPV6_ENABLED(context)) {
51                         memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
52                         server_addr6.sin6_port = htons(wsi->u.hdr.ah->c_port);
53                 } else
54 #endif
55                         server_addr4.sin_port = htons(wsi->u.hdr.ah->c_port);
56         }
57
58         /*
59          * prepare the actual connection (to the proxy, if any)
60          */
61        lwsl_client("%s: address %s\n", __func__, ads);
62
63 #ifdef LWS_USE_IPV6
64         if (LWS_IPV6_ENABLED(context)) {
65                 memset(&hints, 0, sizeof(struct addrinfo));
66 #if !defined(__ANDROID__)
67                 hints.ai_family = AF_INET6;
68                 hints.ai_flags = AI_V4MAPPED;
69 #endif
70                 n = getaddrinfo(ads, NULL, &hints, &result);
71                 if (n) {
72 #ifdef _WIN32
73                         lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n));
74 #else
75                         lwsl_err("getaddrinfo: %s\n", gai_strerror(n));
76 #endif
77                         goto oom4;
78                 }
79
80                 server_addr6.sin6_family = AF_INET6;
81                 switch (result->ai_family) {
82 #if defined(__ANDROID__)
83                 case AF_INET:
84                         /* map IPv4 to IPv6 */
85                         bzero((char *)&server_addr6.sin6_addr,
86                                                 sizeof(struct in6_addr));
87                         server_addr6.sin6_addr.s6_addr[10] = 0xff;
88                         server_addr6.sin6_addr.s6_addr[11] = 0xff;
89                         memcpy(&server_addr6.sin6_addr.s6_addr[12],
90                                 &((struct sockaddr_in *)result->ai_addr)->sin_addr,
91                                                         sizeof(struct in_addr));
92                         break;
93 #endif
94                 case AF_INET6:
95                         memcpy(&server_addr6.sin6_addr,
96                           &((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
97                                                 sizeof(struct in6_addr));
98                         break;
99                 default:
100                         lwsl_err("Unknown address family\n");
101                         freeaddrinfo(result);
102                         goto oom4;
103                 }
104
105                 freeaddrinfo(result);
106         } else
107 #endif
108         {
109                 struct addrinfo ai, *res, *result;
110                 void *p = NULL;
111
112                 memset (&ai, 0, sizeof ai);
113                 ai.ai_family = PF_UNSPEC;
114                 ai.ai_socktype = SOCK_STREAM;
115                 ai.ai_flags = AI_CANONNAME;
116
117                 if (getaddrinfo(ads, NULL, &ai, &result))
118                         goto oom4;
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                         freeaddrinfo(result);
133                         goto oom4;
134                 }
135
136                 server_addr4.sin_family = AF_INET;
137                 server_addr4.sin_addr = *((struct in_addr *)p);
138                 bzero(&server_addr4.sin_zero, 8);
139                 freeaddrinfo(result);
140         }
141
142         if (!lws_socket_is_valid(wsi->sock)) {
143
144 #ifdef LWS_USE_IPV6
145                 if (LWS_IPV6_ENABLED(context))
146                         wsi->sock = socket(AF_INET6, SOCK_STREAM, 0);
147                 else
148 #endif
149                         wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
150
151                 if (!lws_socket_is_valid(wsi->sock)) {
152                         lwsl_warn("Unable to open socket\n");
153                         goto oom4;
154                 }
155
156                 if (lws_plat_set_socket_options(context, wsi->sock)) {
157                         lwsl_err("Failed to set wsi socket options\n");
158                         compatible_close(wsi->sock);
159                         goto oom4;
160                 }
161
162                 wsi->mode = LWSCM_WSCL_WAITING_CONNECT;
163
164                 lws_libev_accept(wsi, wsi->sock);
165                 if (insert_wsi_socket_into_fds(context, wsi)) {
166                         compatible_close(wsi->sock);
167                         goto oom4;
168                 }
169
170                 /*
171                  * past here, we can't simply free the structs as error
172                  * handling as oom4 does.  We have to run the whole close flow.
173                  */
174                 wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE,
175                                         wsi->user_space, NULL, 0);
176                 lws_set_timeout(wsi,
177                         PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
178                                                               AWAITING_TIMEOUT);
179 #ifdef LWS_USE_IPV6
180                 if (LWS_IPV6_ENABLED(context)) {
181                         v = (struct sockaddr *)&client_addr6;
182                         n = sizeof(client_addr6);
183                         bzero((char *)v, n);
184                         client_addr6.sin6_family = AF_INET6;
185                 } else
186 #endif
187                 {
188                         v = (struct sockaddr *)&client_addr4;
189                         n = sizeof(client_addr4);
190                         bzero((char *)v, n);
191                         client_addr4.sin_family = AF_INET;
192                 }
193
194                 if (context->iface) {
195                         if (interface_to_sa(context, context->iface,
196                                         (struct sockaddr_in *)v, n) < 0) {
197                                 lwsl_err("Unable to find interface %s\n",
198                                                                 context->iface);
199                                 goto failed;
200                         }
201
202                         if (bind(wsi->sock, v, n) < 0) {
203                                 lwsl_err("Error binding to interface %s",
204                                                                 context->iface);
205                                 goto failed;
206                         }
207                 }
208         }
209
210 #ifdef LWS_USE_IPV6
211         if (LWS_IPV6_ENABLED(context)) {
212                 v = (struct sockaddr *)&server_addr6;
213                 n = sizeof(struct sockaddr_in6);
214         } else
215 #endif
216         {
217                 v = (struct sockaddr *)&server_addr4;
218                 n = sizeof(struct sockaddr);
219         }
220
221         if (connect(wsi->sock, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
222                 if (LWS_ERRNO == LWS_EALREADY ||
223                     LWS_ERRNO == LWS_EINPROGRESS ||
224                     LWS_ERRNO == LWS_EWOULDBLOCK
225 #ifdef _WIN32
226                         || LWS_ERRNO == WSAEINVAL
227 #endif
228                 ) {
229                         lwsl_client("nonblocking connect retry\n");
230
231                         /*
232                          * must do specifically a POLLOUT poll to hear
233                          * about the connect completion
234                          */
235                         if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
236                                 goto failed;
237
238                         return wsi;
239                 }
240
241                 if (LWS_ERRNO != LWS_EISCONN) {
242                         lwsl_debug("Connect failed errno=%d\n", LWS_ERRNO);
243                         goto failed;
244                 }
245         }
246
247         lwsl_client("connected\n");
248
249         /* we are connected to server, or proxy */
250
251         if (context->http_proxy_port) {
252
253                 /*
254                  * OK from now on we talk via the proxy, so connect to that
255                  *
256                  * (will overwrite existing pointer,
257                  * leaving old string/frag there but unreferenced)
258                  */
259                 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
260                                           context->http_proxy_address))
261                         goto failed;
262                 wsi->u.hdr.ah->c_port = context->http_proxy_port;
263
264                 n = send(wsi->sock, (char *)pt->serv_buf, plen,
265                          MSG_NOSIGNAL);
266                 if (n < 0) {
267                         lwsl_debug("ERROR writing to proxy socket\n");
268                         goto failed;
269                 }
270
271                 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
272                                 AWAITING_TIMEOUT);
273
274                 wsi->mode = LWSCM_WSCL_WAITING_PROXY_REPLY;
275
276                 return wsi;
277         }
278
279         /*
280          * provoke service to issue the handshake directly
281          * we need to do it this way because in the proxy case, this is the
282          * next state and executed only if and when we get a good proxy
283          * response inside the state machine... but notice in SSL case this
284          * may not have sent anything yet with 0 return, and won't until some
285          * many retries from main loop.  To stop that becoming endless,
286          * cover with a timeout.
287          */
288
289         lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
290                         AWAITING_TIMEOUT);
291
292         wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE;
293         pfd.fd = wsi->sock;
294         pfd.revents = LWS_POLLIN;
295
296         n = lws_service_fd(context, &pfd);
297         if (n < 0)
298                 goto failed;
299         if (n) /* returns 1 on failure after closing wsi */
300                 return NULL;
301
302         return wsi;
303
304 oom4:
305         /* we're closing, losing some rx is OK */
306         wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
307         lws_header_table_detach(wsi);
308         /* take care that we might be inserted in fds already */
309         if (wsi->position_in_fds_table != -1)
310                 goto failed;
311         lws_free(wsi);
312
313         return NULL;
314
315 failed:
316         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
317
318         return NULL;
319 }
320
321 /**
322  * lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect)
323  *                      this only works if still in HTTP, ie, not upgraded yet
324  * wsi:         connection to reset
325  * address:     network address of the new server
326  * port:        port to connect to
327  * path:        uri path to connect to on the new server
328  * host:        host header to send to the new server
329  */
330 LWS_VISIBLE struct lws *
331 lws_client_reset(struct lws *wsi, int ssl, const char *address, int port, const char *path, const char *host)
332 {
333         if (wsi->u.hdr.redirects == 3) {
334                 lwsl_err("%s: Too many redirects\n", __func__);
335                 return NULL;
336         }
337         wsi->u.hdr.redirects++;
338
339 #ifdef LWS_OPENSSL_SUPPORT
340         wsi->use_ssl = ssl;
341 #else
342         if (ssl) {
343                 lwsl_err("%s: not configured for ssl\n", __func__);
344                 return NULL;
345         }
346 #endif
347
348         lwsl_notice("redirect ads='%s', port=%d, path='%s'\n", address, port, path);
349
350         if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
351                 return NULL;
352
353         if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
354                 return NULL;
355
356         if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
357                 return NULL;
358
359         compatible_close(wsi->sock);
360         remove_wsi_socket_from_fds(wsi);
361         wsi->sock = LWS_SOCK_INVALID;
362         wsi->state = LWSS_CLIENT_UNCONNECTED;
363         wsi->protocol = NULL;
364         wsi->pending_timeout = NO_PENDING_TIMEOUT;
365         wsi->u.hdr.ah->c_port = port;
366
367         return lws_client_connect_2(wsi);
368 }
369
370 /**
371  * lws_client_connect_via_info() - Connect to another websocket server
372  * @i:pointer to lws_client_connect_info struct
373  *
374  *      This function creates a connection to a remote server
375  */
376
377
378 LWS_VISIBLE struct lws *
379 lws_client_connect_via_info(struct lws_client_connect_info *i)
380 {
381         struct lws *wsi;
382         int v = SPEC_LATEST_SUPPORTED;
383
384         wsi = lws_zalloc(sizeof(struct lws));
385         if (wsi == NULL)
386                 goto bail;
387
388         wsi->context = i->context;
389         wsi->sock = LWS_SOCK_INVALID;
390
391         /* -1 means just use latest supported */
392
393         if (i->ietf_version_or_minus_one != -1 && i->ietf_version_or_minus_one)
394                 v = i->ietf_version_or_minus_one;
395
396         wsi->ietf_spec_revision = v;
397         wsi->user_space = NULL;
398         wsi->state = LWSS_CLIENT_UNCONNECTED;
399         wsi->protocol = NULL;
400         wsi->pending_timeout = NO_PENDING_TIMEOUT;
401         wsi->position_in_fds_table = -1;
402
403 #ifdef LWS_OPENSSL_SUPPORT
404         wsi->use_ssl = i->ssl_connection;
405 #else
406         if (i->ssl_connection) {
407                 lwsl_err("libwebsockets not configured for ssl\n");
408                 goto bail;
409         }
410 #endif
411
412         if (lws_header_table_attach(wsi))
413                 goto bail;
414
415         /*
416          * we're not necessarily in a position to action these right away,
417          * stash them... we only need during connect phase so u.hdr is fine
418          */
419         wsi->u.hdr.ah->c_port = i->port;
420         if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, i->address))
421                 goto bail1;
422
423         /* these only need u.hdr lifetime as well */
424
425         if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, i->path))
426                 goto bail1;
427
428         if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, i->host))
429                 goto bail1;
430
431         if (i->origin)
432                 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN, i->origin))
433                         goto bail1;
434         /*
435          * this is a list of protocols we tell the server we're okay with
436          * stash it for later when we compare server response with it
437          */
438         if (i->protocol)
439                 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
440                                           i->protocol))
441                         goto bail1;
442
443         wsi->protocol = &i->context->protocols[0];
444         if (wsi && !wsi->user_space && i->userdata) {
445                 wsi->user_space_externally_allocated = 1;
446                 wsi->user_space = i->userdata;
447         }
448
449         /*
450          * Check with each extension if it is able to route and proxy this
451          * connection for us.  For example, an extension like x-google-mux
452          * can handle this and then we don't need an actual socket for this
453          * connection.
454          */
455
456         if (lws_ext_cb_all_exts(i->context, wsi,
457                         LWS_EXT_CB_CAN_PROXY_CLIENT_CONNECTION,
458                                                      (void *)i->address, i->port) > 0) {
459                 lwsl_client("lws_client_connect: ext handling conn\n");
460
461                 lws_set_timeout(wsi,
462                         PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
463                                 AWAITING_TIMEOUT);
464
465                 wsi->mode = LWSCM_WSCL_WAITING_EXTENSION_CONNECT;
466                 return wsi;
467         }
468         lwsl_client("lws_client_connect: direct conn\n");
469
470         wsi->context->count_wsi_allocated++;
471
472         return lws_client_connect_2(wsi);
473
474 bail1:
475         /* we're closing, losing some rx is OK */
476         wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
477         lws_header_table_detach(wsi);
478 bail:
479         lws_free(wsi);
480
481         return NULL;
482 }
483
484
485 /**
486  * lws_client_connect_extended() - Connect to another websocket server
487  *                              DEPRECATED use lws_client_connect_via_info
488  * @context:    Websocket context
489  * @address:    Remote server address, eg, "myserver.com"
490  * @port:       Port to connect to on the remote server, eg, 80
491  * @ssl_connection:     0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
492  *                      signed certs
493  * @path:       Websocket path on server
494  * @host:       Hostname on server
495  * @origin:     Socket origin name
496  * @protocol:   Comma-separated list of protocols being asked for from
497  *              the server, or just one.  The server will pick the one it
498  *              likes best.
499  * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
500  *              protocol supported, or the specific protocol ordinal
501  * @userdata: Pre-allocated user data
502  *
503  *      This function creates a connection to a remote server
504  */
505
506 LWS_VISIBLE struct lws *
507 lws_client_connect_extended(struct lws_context *context, const char *address,
508                             int port, int ssl_connection, const char *path,
509                             const char *host, const char *origin,
510                             const char *protocol, int ietf_version_or_minus_one,
511                             void *userdata)
512 {
513         struct lws_client_connect_info i;
514
515         memset(&i, 0, sizeof(i));
516
517         i.context = context;
518         i.address = address;
519         i.port = port;
520         i.ssl_connection = ssl_connection;
521         i.path = path;
522         i.host = host;
523         i.origin = origin;
524         i.protocol = protocol;
525         i.ietf_version_or_minus_one = ietf_version_or_minus_one;
526         i.userdata = userdata;
527
528         return lws_client_connect_via_info(&i);
529 }
530 /**
531  * lws_client_connect_info() - Connect to another websocket server
532  *                              DEPRECATED use lws_client_connect_via_info
533  * @context:    Websocket context
534  * @address:    Remote server address, eg, "myserver.com"
535  * @port:       Port to connect to on the remote server, eg, 80
536  * @ssl_connection:     0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
537  *                      signed certs
538  * @path:       Websocket path on server
539  * @host:       Hostname on server
540  * @origin:     Socket origin name
541  * @protocol:   Comma-separated list of protocols being asked for from
542  *              the server, or just one.  The server will pick the one it
543  *              likes best.  If you don't want to specify a protocol, which is
544  *              legal, use NULL here.
545  * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
546  *              protocol supported, or the specific protocol ordinal
547  *
548  *      This function creates a connection to a remote server
549  */
550
551
552 LWS_VISIBLE struct lws *
553 lws_client_connect(struct lws_context *context, const char *address,
554                             int port, int ssl_connection, const char *path,
555                             const char *host, const char *origin,
556                             const char *protocol, int ietf_version_or_minus_one)
557 {
558         struct lws_client_connect_info i;
559
560         memset(&i, 0, sizeof(i));
561
562         i.context = context;
563         i.address = address;
564         i.port = port;
565         i.ssl_connection = ssl_connection;
566         i.path = path;
567         i.host = host;
568         i.origin = origin;
569         i.protocol = protocol;
570         i.ietf_version_or_minus_one = ietf_version_or_minus_one;
571         i.userdata = NULL;
572
573         return lws_client_connect_via_info(&i);
574 }
575