1 #include "private-libwebsockets.h"
4 lws_client_connect_2(struct lws *wsi)
7 struct sockaddr_in6 server_addr6;
8 struct sockaddr_in6 client_addr6;
9 struct addrinfo hints, *result;
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;
20 lwsl_client("%s\n", __func__);
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),
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);
36 plen += sprintf((char *)pt->serv_buf + plen, "\x0d\x0a");
37 ads = context->http_proxy_address;
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);
45 server_addr4.sin_port = htons(context->http_proxy_port);
48 ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
50 if (LWS_IPV6_ENABLED(context)) {
51 memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
52 server_addr6.sin6_port = htons(wsi->u.hdr.c_port);
55 server_addr4.sin_port = htons(wsi->u.hdr.c_port);
59 * prepare the actual connection (to the proxy, if any)
61 lwsl_client("%s: address %s\n", __func__, ads);
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;
70 n = getaddrinfo(ads, NULL, &hints, &result);
73 lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n));
75 lwsl_err("getaddrinfo: %s\n", gai_strerror(n));
80 server_addr6.sin6_family = AF_INET6;
81 switch (result->ai_family) {
82 #if defined(__ANDROID__)
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));
95 memcpy(&server_addr6.sin6_addr,
96 &((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
97 sizeof(struct in6_addr));
100 lwsl_err("Unknown address family\n");
101 freeaddrinfo(result);
105 freeaddrinfo(result);
109 struct addrinfo ai, *res, *result;
112 memset (&ai, 0, sizeof ai);
113 ai.ai_family = PF_UNSPEC;
114 ai.ai_socktype = SOCK_STREAM;
115 ai.ai_flags = AI_CANONNAME;
117 if (getaddrinfo(ads, NULL, &ai, &result))
122 switch (res->ai_family) {
124 p = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
132 freeaddrinfo(result);
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);
142 if (!lws_socket_is_valid(wsi->sock)) {
145 if (LWS_IPV6_ENABLED(context))
146 wsi->sock = socket(AF_INET6, SOCK_STREAM, 0);
149 wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
151 if (!lws_socket_is_valid(wsi->sock)) {
152 lwsl_warn("Unable to open socket\n");
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);
162 wsi->mode = LWSCM_WSCL_WAITING_CONNECT;
164 lws_libev_accept(wsi, wsi->sock);
165 if (insert_wsi_socket_into_fds(context, wsi)) {
166 compatible_close(wsi->sock);
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.
176 PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
179 if (LWS_IPV6_ENABLED(context)) {
180 v = (struct sockaddr *)&client_addr6;
181 n = sizeof(client_addr6);
183 client_addr6.sin6_family = AF_INET6;
187 v = (struct sockaddr *)&client_addr4;
188 n = sizeof(client_addr4);
190 client_addr4.sin_family = AF_INET;
193 if (context->iface) {
194 if (interface_to_sa(context, context->iface,
195 (struct sockaddr_in *)v, n) < 0) {
196 lwsl_err("Unable to find interface %s\n",
201 if (bind(wsi->sock, v, n) < 0) {
202 lwsl_err("Error binding to interface %s",
210 if (LWS_IPV6_ENABLED(context)) {
211 v = (struct sockaddr *)&server_addr6;
212 n = sizeof(struct sockaddr_in6);
216 v = (struct sockaddr *)&server_addr4;
217 n = sizeof(struct sockaddr);
220 if (connect(wsi->sock, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
221 if (LWS_ERRNO == LWS_EALREADY ||
222 LWS_ERRNO == LWS_EINPROGRESS ||
223 LWS_ERRNO == LWS_EWOULDBLOCK
225 || LWS_ERRNO == WSAEINVAL
228 lwsl_client("nonblocking connect retry\n");
231 * must do specifically a POLLOUT poll to hear
232 * about the connect completion
234 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
240 if (LWS_ERRNO != LWS_EISCONN) {
241 lwsl_debug("Connect failed errno=%d\n", LWS_ERRNO);
246 lwsl_client("connected\n");
248 /* we are connected to server, or proxy */
250 if (context->http_proxy_port) {
253 * OK from now on we talk via the proxy, so connect to that
255 * (will overwrite existing pointer,
256 * leaving old string/frag there but unreferenced)
258 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
259 context->http_proxy_address))
261 wsi->u.hdr.c_port = context->http_proxy_port;
263 n = send(wsi->sock, (char *)pt->serv_buf, plen,
266 lwsl_debug("ERROR writing to proxy socket\n");
270 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
273 wsi->mode = LWSCM_WSCL_WAITING_PROXY_REPLY;
279 * provoke service to issue the handshake directly
280 * we need to do it this way because in the proxy case, this is the
281 * next state and executed only if and when we get a good proxy
282 * response inside the state machine... but notice in SSL case this
283 * may not have sent anything yet with 0 return, and won't until some
284 * many retries from main loop. To stop that becoming endless,
285 * cover with a timeout.
288 lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
291 wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE;
293 pfd.revents = LWS_POLLIN;
295 n = lws_service_fd(context, &pfd);
298 if (n) /* returns 1 on failure after closing wsi */
304 /* we're closing, losing some rx is OK */
305 wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
306 lws_header_table_detach(wsi, 0);
312 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
318 * lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect)
319 * this only works if still in HTTP, ie, not upgraded yet
320 * wsi: connection to reset
321 * address: network address of the new server
322 * port: port to connect to
323 * path: uri path to connect to on the new server
324 * host: host header to send to the new server
326 LWS_VISIBLE struct lws *
327 lws_client_reset(struct lws *wsi, int ssl, const char *address, int port, const char *path, const char *host)
329 if (wsi->u.hdr.redirects == 3) {
330 lwsl_err("%s: Too many redirects\n", __func__);
333 wsi->u.hdr.redirects++;
335 #ifdef LWS_OPENSSL_SUPPORT
339 lwsl_err("%s: not configured for ssl\n", __func__);
344 lwsl_notice("redirect ads='%s', port=%d, path='%s'\n", address, port, path);
346 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
349 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
352 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
355 compatible_close(wsi->sock);
356 remove_wsi_socket_from_fds(wsi);
357 wsi->sock = LWS_SOCK_INVALID;
358 wsi->state = LWSS_CLIENT_UNCONNECTED;
359 wsi->protocol = NULL;
360 wsi->pending_timeout = NO_PENDING_TIMEOUT;
361 wsi->u.hdr.c_port = port;
363 return lws_client_connect_2(wsi);
367 * lws_client_connect_via_info() - Connect to another websocket server
368 * @i:pointer to lws_client_connect_info struct
370 * This function creates a connection to a remote server
374 LWS_VISIBLE struct lws *
375 lws_client_connect_via_info(struct lws_client_connect_info *i)
378 int v = SPEC_LATEST_SUPPORTED;
380 wsi = lws_zalloc(sizeof(struct lws));
384 wsi->context = i->context;
385 /* assert the mode and union status (hdr) clearly */
386 lws_union_transition(wsi, LWSCM_HTTP_CLIENT);
387 wsi->sock = LWS_SOCK_INVALID;
389 /* 1) fill up the wsi with stuff from the connect_info as far as it
390 * can go. It's because not only is our connection async, we might
391 * not even be able to get ahold of an ah at this point.
394 /* -1 means just use latest supported */
395 if (i->ietf_version_or_minus_one != -1 && i->ietf_version_or_minus_one)
396 v = i->ietf_version_or_minus_one;
398 wsi->ietf_spec_revision = v;
399 wsi->user_space = NULL;
400 wsi->state = LWSS_CLIENT_UNCONNECTED;
401 wsi->protocol = NULL;
402 wsi->pending_timeout = NO_PENDING_TIMEOUT;
403 wsi->position_in_fds_table = -1;
404 wsi->u.hdr.c_port = i->port;
406 wsi->protocol = &i->context->protocols[0];
407 if (wsi && !wsi->user_space && i->userdata) {
408 wsi->user_space_externally_allocated = 1;
409 wsi->user_space = i->userdata;
412 #ifdef LWS_OPENSSL_SUPPORT
413 wsi->use_ssl = i->ssl_connection;
415 if (i->ssl_connection) {
416 lwsl_err("libwebsockets not configured for ssl\n");
420 wsi->protocol = &i->context->protocols[0];
421 if (wsi && !wsi->user_space && i->userdata) {
422 wsi->user_space_externally_allocated = 1;
423 wsi->user_space = i->userdata;
426 /* 2) stash the things from connect_info that we can't process without
427 * an ah. Because if no ah, we will go on the ah waiting list and
428 * process those things later (after the connect_info and maybe the
429 * things pointed to have gone out of scope.
432 wsi->u.hdr.stash = lws_malloc(sizeof(*wsi->u.hdr.stash));
433 if (!wsi->u.hdr.stash) {
434 lwsl_err("%s: OOM\n", __func__);
438 wsi->u.hdr.stash->origin[0] = '\0';
439 wsi->u.hdr.stash->protocol[0] = '\0';
440 wsi->u.hdr.stash->method[0] = '\0';
442 strncpy(wsi->u.hdr.stash->address, i->address,
443 sizeof(wsi->u.hdr.stash->address) - 1);
444 strncpy(wsi->u.hdr.stash->path, i->path,
445 sizeof(wsi->u.hdr.stash->path) - 1);
446 strncpy(wsi->u.hdr.stash->host, i->host,
447 sizeof(wsi->u.hdr.stash->host) - 1);
449 strncpy(wsi->u.hdr.stash->origin, i->origin,
450 sizeof(wsi->u.hdr.stash->origin) - 1);
452 strncpy(wsi->u.hdr.stash->protocol, i->protocol,
453 sizeof(wsi->u.hdr.stash->protocol) - 1);
455 strncpy(wsi->u.hdr.stash->method, i->method,
456 sizeof(wsi->u.hdr.stash->method) - 1);
458 wsi->u.hdr.stash->address[sizeof(wsi->u.hdr.stash->address) - 1] = '\0';
459 wsi->u.hdr.stash->path[sizeof(wsi->u.hdr.stash->path) - 1] = '\0';
460 wsi->u.hdr.stash->host[sizeof(wsi->u.hdr.stash->host) - 1] = '\0';
461 wsi->u.hdr.stash->origin[sizeof(wsi->u.hdr.stash->origin) - 1] = '\0';
462 wsi->u.hdr.stash->protocol[sizeof(wsi->u.hdr.stash->protocol) - 1] = '\0';
463 wsi->u.hdr.stash->method[sizeof(wsi->u.hdr.stash->method) - 1] = '\0';
465 /* if we went on the waiting list, no probs just return the wsi
466 * when we get the ah, now or later, he will call
467 * lws_client_connect_via_info2() below
469 if (lws_header_table_attach(wsi, 0))
470 lwsl_debug("%s: went on ah wait list\n", __func__);
481 lws_client_connect_via_info2(struct lws *wsi)
483 struct client_info_stash *stash = wsi->u.hdr.stash;
489 * we're not necessarily in a position to action these right away,
490 * stash them... we only need during connect phase so u.hdr is fine
492 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
496 /* these only need u.hdr lifetime as well */
498 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, stash->path))
501 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, stash->host))
504 if (stash->origin[0])
505 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
509 * this is a list of protocols we tell the server we're okay with
510 * stash it for later when we compare server response with it
512 if (stash->protocol[0])
513 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
516 if (stash->method[0])
517 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
521 lws_free_set_NULL(wsi->u.hdr.stash);
524 * Check with each extension if it is able to route and proxy this
525 * connection for us. For example, an extension like x-google-mux
526 * can handle this and then we don't need an actual socket for this
530 if (lws_ext_cb_all_exts(wsi->context, wsi,
531 LWS_EXT_CB_CAN_PROXY_CLIENT_CONNECTION,
532 (void *)stash->address,
533 wsi->u.hdr.c_port) > 0) {
534 lwsl_client("lws_client_connect: ext handling conn\n");
537 PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
540 wsi->mode = LWSCM_WSCL_WAITING_EXTENSION_CONNECT;
543 lwsl_client("lws_client_connect: direct conn\n");
544 wsi->context->count_wsi_allocated++;
546 return lws_client_connect_2(wsi);
549 lws_free_set_NULL(wsi->u.hdr.stash);
556 * lws_client_connect_extended() - Connect to another websocket server
557 * DEPRECATED use lws_client_connect_via_info
558 * @context: Websocket context
559 * @address: Remote server address, eg, "myserver.com"
560 * @port: Port to connect to on the remote server, eg, 80
561 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
563 * @path: Websocket path on server
564 * @host: Hostname on server
565 * @origin: Socket origin name
566 * @protocol: Comma-separated list of protocols being asked for from
567 * the server, or just one. The server will pick the one it
569 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
570 * protocol supported, or the specific protocol ordinal
571 * @userdata: Pre-allocated user data
573 * This function creates a connection to a remote server
576 LWS_VISIBLE struct lws *
577 lws_client_connect_extended(struct lws_context *context, const char *address,
578 int port, int ssl_connection, const char *path,
579 const char *host, const char *origin,
580 const char *protocol, int ietf_version_or_minus_one,
583 struct lws_client_connect_info i;
585 memset(&i, 0, sizeof(i));
590 i.ssl_connection = ssl_connection;
594 i.protocol = protocol;
595 i.ietf_version_or_minus_one = ietf_version_or_minus_one;
596 i.userdata = userdata;
598 return lws_client_connect_via_info(&i);
601 * lws_client_connect_info() - Connect to another websocket server
602 * DEPRECATED use lws_client_connect_via_info
603 * @context: Websocket context
604 * @address: Remote server address, eg, "myserver.com"
605 * @port: Port to connect to on the remote server, eg, 80
606 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
608 * @path: Websocket path on server
609 * @host: Hostname on server
610 * @origin: Socket origin name
611 * @protocol: Comma-separated list of protocols being asked for from
612 * the server, or just one. The server will pick the one it
613 * likes best. If you don't want to specify a protocol, which is
614 * legal, use NULL here.
615 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
616 * protocol supported, or the specific protocol ordinal
618 * This function creates a connection to a remote server
622 LWS_VISIBLE struct lws *
623 lws_client_connect(struct lws_context *context, const char *address,
624 int port, int ssl_connection, const char *path,
625 const char *host, const char *origin,
626 const char *protocol, int ietf_version_or_minus_one)
628 struct lws_client_connect_info i;
630 memset(&i, 0, sizeof(i));
635 i.ssl_connection = ssl_connection;
639 i.protocol = protocol;
640 i.ietf_version_or_minus_one = ietf_version_or_minus_one;
643 return lws_client_connect_via_info(&i);