blob: 11dcc29da646290b7e2167cd07b6656b45ee0b5d [file] [log] [blame]
Andy Green4739e5c2011-01-22 12:51:57 +00001#include "private-libwebsockets.h"
Andy Green4739e5c2011-01-22 12:51:57 +00002
Andy Green4b85c1d2015-12-04 11:08:32 +08003struct lws *lws_client_connect_2(
4 struct lws_context *context,
5 struct lws *wsi
Andy Greena41314f2011-05-23 10:00:03 +01006) {
Andy Green4b85c1d2015-12-04 11:08:32 +08007 struct lws_pollfd pfd;
Andy Green055f2972014-03-24 16:09:25 +08008#ifdef LWS_USE_IPV6
James Devine3f13ea22014-03-24 16:09:25 +08009 struct sockaddr_in6 server_addr6;
10 struct sockaddr_in6 client_addr6;
11 struct addrinfo hints, *result;
12#endif
13 struct sockaddr_in server_addr4;
14 struct sockaddr_in client_addr4;
James Devine3f13ea22014-03-24 16:09:25 +080015
16 struct sockaddr *v;
Andy Greena41314f2011-05-23 10:00:03 +010017 int n;
18 int plen = 0;
Andy Greene77fb802013-02-11 13:04:45 +080019 const char *ads;
Andy Greena41314f2011-05-23 10:00:03 +010020
Andy Green62304762015-12-04 08:43:54 +080021 lwsl_client("lws_client_connect_2\n");
Andy Greena41314f2011-05-23 10:00:03 +010022
23 /*
24 * proxy?
25 */
26
27 if (context->http_proxy_port) {
Andy Greene48ba312013-02-10 15:34:59 +080028 plen = sprintf((char *)context->service_buffer,
Andy Greenf54a94b2013-02-10 15:19:39 +080029 "CONNECT %s:%u HTTP/1.0\x0d\x0a"
Andy Green6e405562015-11-08 10:15:01 +080030 "User-agent: libwebsockets\x0d\x0a",
Andy Greene77fb802013-02-11 13:04:45 +080031 lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
Andy Greena7521de2013-02-18 10:38:45 +080032 wsi->u.hdr.ah->c_port);
Andy Green6e405562015-11-08 10:15:01 +080033
Andy Greenf2280d62015-11-18 19:32:01 +080034 if (context->proxy_basic_auth_token[0])
Andy Green6e405562015-11-08 10:15:01 +080035 plen += sprintf((char *)context->service_buffer + plen,
36 "Proxy-authorization: basic %s\x0d\x0a",
37 context->proxy_basic_auth_token);
38
39 plen += sprintf((char *)context->service_buffer + plen,
40 "\x0d\x0a");
41
Andy Green36efd822013-10-25 22:07:57 +080042 ads = context->http_proxy_address;
James Devine3f13ea22014-03-24 16:09:25 +080043
Andy Green055f2972014-03-24 16:09:25 +080044#ifdef LWS_USE_IPV6
James Devine3f13ea22014-03-24 16:09:25 +080045 if (LWS_IPV6_ENABLED(context))
46 server_addr6.sin6_port = htons(context->http_proxy_port);
47 else
48#endif
49 server_addr4.sin_port = htons(context->http_proxy_port);
50
Andy Green36efd822013-10-25 22:07:57 +080051 } else {
52 ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
Andy Green7844d042014-03-25 14:08:21 +080053#ifdef LWS_USE_IPV6
James Devine3f13ea22014-03-24 16:09:25 +080054 if (LWS_IPV6_ENABLED(context))
55 server_addr6.sin6_port = htons(wsi->u.hdr.ah->c_port);
56 else
57#endif
58 server_addr4.sin_port = htons(wsi->u.hdr.ah->c_port);
Andy Greena41314f2011-05-23 10:00:03 +010059 }
60
61 /*
62 * prepare the actual connection (to the proxy, if any)
63 */
Andy Green6e405562015-11-08 10:15:01 +080064 lwsl_client("%s: address %s\n", __func__, ads);
Andy Greene77fb802013-02-11 13:04:45 +080065
Andy Green055f2972014-03-24 16:09:25 +080066#ifdef LWS_USE_IPV6
James Devine3f13ea22014-03-24 16:09:25 +080067 if (LWS_IPV6_ENABLED(context)) {
68 memset(&hints, 0, sizeof(struct addrinfo));
69 n = getaddrinfo(ads, NULL, &hints, &result);
70 if (n) {
Patrick Ganstererfb9dc572014-04-15 18:42:57 +020071#ifdef _WIN32
72 lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n));
73#else
James Devine3f13ea22014-03-24 16:09:25 +080074 lwsl_err("getaddrinfo: %s\n", gai_strerror(n));
Patrick Ganstererfb9dc572014-04-15 18:42:57 +020075#endif
James Devine3f13ea22014-03-24 16:09:25 +080076 goto oom4;
77 }
78
79 server_addr6.sin6_family = AF_INET6;
80 switch (result->ai_family) {
81 case AF_INET:
82 /* map IPv4 to IPv6 */
83 bzero((char *)&server_addr6.sin6_addr,
84 sizeof(struct in6_addr));
Patrick Gansterer04473292014-03-28 08:28:02 +010085 server_addr6.sin6_addr.s6_addr[10] = 0xff;
86 server_addr6.sin6_addr.s6_addr[11] = 0xff;
87 memcpy(&server_addr6.sin6_addr.s6_addr[12],
88 &((struct sockaddr_in *)result->ai_addr)->sin_addr,
James Devine3f13ea22014-03-24 16:09:25 +080089 sizeof(struct in_addr));
90 break;
91 case AF_INET6:
92 memcpy(&server_addr6.sin6_addr,
93 &((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
94 sizeof(struct in6_addr));
95 break;
96 default:
97 lwsl_err("Unknown address family\n");
98 freeaddrinfo(result);
99 goto oom4;
100 }
101
102 freeaddrinfo(result);
103 } else
104#endif
105 {
Danomi Czaski7fb366a2015-04-11 07:00:51 +0800106 struct addrinfo ai, *res, *result;
Andy Green7e37d102015-01-28 21:03:49 +0800107 void *p = NULL;
108
109 memset (&ai, 0, sizeof ai);
110 ai.ai_family = PF_UNSPEC;
111 ai.ai_socktype = SOCK_STREAM;
112 ai.ai_flags = AI_CANONNAME;
113
Danomi Czaski7fb366a2015-04-11 07:00:51 +0800114 if (getaddrinfo(ads, NULL, &ai, &result))
James Devine3f13ea22014-03-24 16:09:25 +0800115 goto oom4;
Andy Green7e37d102015-01-28 21:03:49 +0800116
Danomi Czaski7fb366a2015-04-11 07:00:51 +0800117 res = result;
Andy Green7e37d102015-01-28 21:03:49 +0800118 while (!p && res) {
119 switch (res->ai_family) {
120 case AF_INET:
121 p = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
122 break;
123 }
124
125 res = res->ai_next;
James Devine3f13ea22014-03-24 16:09:25 +0800126 }
Andy Green7e37d102015-01-28 21:03:49 +0800127
Danomi Czaski7fb366a2015-04-11 07:00:51 +0800128 if (!p) {
129 freeaddrinfo(result);
Andy Green7e37d102015-01-28 21:03:49 +0800130 goto oom4;
Danomi Czaski7fb366a2015-04-11 07:00:51 +0800131 }
James Devine3f13ea22014-03-24 16:09:25 +0800132
133 server_addr4.sin_family = AF_INET;
Andy Green7e37d102015-01-28 21:03:49 +0800134 server_addr4.sin_addr = *((struct in_addr *)p);
James Devine3f13ea22014-03-24 16:09:25 +0800135 bzero(&server_addr4.sin_zero, 8);
Danomi Czaski7fb366a2015-04-11 07:00:51 +0800136 freeaddrinfo(result);
Andy Greena41314f2011-05-23 10:00:03 +0100137 }
138
Andy Greenc53f7ca2015-11-14 07:35:27 +0800139 if (!lws_socket_is_valid(wsi->sock)) {
Andy Green5dc62ea2013-09-20 20:26:12 +0800140
Andy Green055f2972014-03-24 16:09:25 +0800141#ifdef LWS_USE_IPV6
James Devine3f13ea22014-03-24 16:09:25 +0800142 if (LWS_IPV6_ENABLED(context))
143 wsi->sock = socket(AF_INET6, SOCK_STREAM, 0);
144 else
145#endif
146 wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
Andy Green5dc62ea2013-09-20 20:26:12 +0800147
Andy Greenc53f7ca2015-11-14 07:35:27 +0800148 if (!lws_socket_is_valid(wsi->sock)) {
Andy Green5dc62ea2013-09-20 20:26:12 +0800149 lwsl_warn("Unable to open socket\n");
150 goto oom4;
151 }
152
Andy Green158e8042014-04-02 14:25:10 +0800153 if (lws_plat_set_socket_options(context, wsi->sock)) {
Andy Green5dc62ea2013-09-20 20:26:12 +0800154 lwsl_err("Failed to set wsi socket options\n");
155 compatible_close(wsi->sock);
156 goto oom4;
157 }
158
159 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT;
160
Pokrovskiy20636ec2015-04-21 00:53:59 -0700161 lws_libev_accept(context, wsi, wsi->sock);
Andy Greenfc772cc2015-11-14 13:48:58 +0800162 if (insert_wsi_socket_into_fds(context, wsi)) {
163 compatible_close(wsi->sock);
Andy Green1963c9a2015-10-15 07:39:33 +0800164 goto oom4;
Andy Greenfc772cc2015-11-14 13:48:58 +0800165 }
Andy Green5dc62ea2013-09-20 20:26:12 +0800166
Andy Greenb5cf69f2015-10-18 18:47:37 +0800167 /*
168 * past here, we can't simply free the structs as error
169 * handling as oom4 does. We have to run the whole close flow.
170 */
171
Andy Green62304762015-12-04 08:43:54 +0800172 lws_set_timeout(wsi,
Andy Green5dc62ea2013-09-20 20:26:12 +0800173 PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
174 AWAITING_TIMEOUT);
Andy Green055f2972014-03-24 16:09:25 +0800175#ifdef LWS_USE_IPV6
James Devine3f13ea22014-03-24 16:09:25 +0800176 if (LWS_IPV6_ENABLED(context)) {
177 v = (struct sockaddr *)&client_addr6;
178 n = sizeof(client_addr6);
179 bzero((char *)v, n);
180 client_addr6.sin6_family = AF_INET6;
181 } else
182#endif
183 {
184 v = (struct sockaddr *)&client_addr4;
185 n = sizeof(client_addr4);
186 bzero((char *)v, n);
187 client_addr4.sin_family = AF_INET;
188 }
Mattias Lundberg03bb8f92014-02-18 10:06:57 +0100189
James Devine3f13ea22014-03-24 16:09:25 +0800190 if (context->iface) {
191 if (interface_to_sa(context, context->iface,
192 (struct sockaddr_in *)v, n) < 0) {
193 lwsl_err("Unable to find interface %s\n",
194 context->iface);
Mattias Lundberg03bb8f92014-02-18 10:06:57 +0100195 goto failed;
196 }
197
James Devine3f13ea22014-03-24 16:09:25 +0800198 if (bind(wsi->sock, v, n) < 0) {
199 lwsl_err("Error binding to interface %s",
200 context->iface);
Mattias Lundberg03bb8f92014-02-18 10:06:57 +0100201 goto failed;
202 }
203 }
Andy Greena41314f2011-05-23 10:00:03 +0100204 }
205
Andy Green055f2972014-03-24 16:09:25 +0800206#ifdef LWS_USE_IPV6
James Devine3f13ea22014-03-24 16:09:25 +0800207 if (LWS_IPV6_ENABLED(context)) {
208 v = (struct sockaddr *)&server_addr6;
209 n = sizeof(struct sockaddr_in6);
210 } else
211#endif
212 {
213 v = (struct sockaddr *)&server_addr4;
214 n = sizeof(struct sockaddr);
215 }
Andy Green36efd822013-10-25 22:07:57 +0800216
James Devine3f13ea22014-03-24 16:09:25 +0800217 if (connect(wsi->sock, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
Andy Green5dc62ea2013-09-20 20:26:12 +0800218
Frugality92b69632015-08-26 11:31:28 -0700219 if (LWS_ERRNO == LWS_EALREADY
220 || LWS_ERRNO == LWS_EINPROGRESS
221 || LWS_ERRNO == LWS_EWOULDBLOCK
222#ifdef _WIN32
223 || LWS_ERRNO == WSAEINVAL
224#endif
225 )
226 {
Andy Green5dc62ea2013-09-20 20:26:12 +0800227 lwsl_client("nonblocking connect retry\n");
228
229 /*
230 * must do specifically a POLLOUT poll to hear
231 * about the connect completion
232 */
Andy Green158e8042014-04-02 14:25:10 +0800233 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
Andy Greenb5cf69f2015-10-18 18:47:37 +0800234 goto failed;
Pokrovskiy20636ec2015-04-21 00:53:59 -0700235 lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
Andy Green5dc62ea2013-09-20 20:26:12 +0800236
237 return wsi;
238 }
239
Patrick Gansterer2dbd8372014-02-28 12:37:52 +0100240 if (LWS_ERRNO != LWS_EISCONN) {
Patrick Gansterer2dbd8372014-02-28 12:37:52 +0100241 lwsl_debug("Connect failed errno=%d\n", LWS_ERRNO);
shys5efcb3f2013-10-25 15:49:11 +0200242 goto failed;
243 }
Andy Greena41314f2011-05-23 10:00:03 +0100244 }
245
Andy Green43db0452013-01-10 19:50:35 +0800246 lwsl_client("connected\n");
Andy Greena41314f2011-05-23 10:00:03 +0100247
Andy Greena41314f2011-05-23 10:00:03 +0100248 /* we are connected to server, or proxy */
249
250 if (context->http_proxy_port) {
251
Andy Green36efd822013-10-25 22:07:57 +0800252 /* OK from now on we talk via the proxy, so connect to that */
253
254 /*
255 * (will overwrite existing pointer,
256 * leaving old string/frag there but unreferenced)
257 */
258 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
259 context->http_proxy_address))
260 goto failed;
261 wsi->u.hdr.ah->c_port = context->http_proxy_port;
262
Stephan Eberleb820e2c2015-10-23 08:10:55 +0200263 n = send(wsi->sock, (char *)context->service_buffer, plen, MSG_NOSIGNAL);
Andy Greena41314f2011-05-23 10:00:03 +0100264 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800265 lwsl_debug("ERROR writing to proxy socket\n");
Andy Green5dc62ea2013-09-20 20:26:12 +0800266 goto failed;
Andy Greena41314f2011-05-23 10:00:03 +0100267 }
268
Andy Green62304762015-12-04 08:43:54 +0800269 lws_set_timeout(wsi,
Andy Greenb5b23192013-02-11 17:13:32 +0800270 PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
271 AWAITING_TIMEOUT);
Andy Greena41314f2011-05-23 10:00:03 +0100272
273 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY;
274
275 return wsi;
276 }
277
278 /*
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
Andy Green73abc252013-01-13 11:05:30 +0800282 * 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.
Andy Greena41314f2011-05-23 10:00:03 +0100286 */
287
Andy Green62304762015-12-04 08:43:54 +0800288 lws_set_timeout(wsi,
Andy Green73abc252013-01-13 11:05:30 +0800289 PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, AWAITING_TIMEOUT);
290
Andy Greena41314f2011-05-23 10:00:03 +0100291 wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE;
292 pfd.fd = wsi->sock;
Patrick Ganstererb47f87b2014-03-30 09:18:05 +0200293 pfd.revents = LWS_POLLIN;
David Galeano36750b82013-01-09 16:17:04 +0800294
Andy Green62304762015-12-04 08:43:54 +0800295 n = lws_service_fd(context, &pfd);
David Galeano36750b82013-01-09 16:17:04 +0800296
297 if (n < 0)
Andy Green5dc62ea2013-09-20 20:26:12 +0800298 goto failed;
Andy Greena41314f2011-05-23 10:00:03 +0100299
David Galeano36750b82013-01-09 16:17:04 +0800300 if (n) /* returns 1 on failure after closing wsi */
301 return NULL;
302
Andy Greena41314f2011-05-23 10:00:03 +0100303 return wsi;
304
305oom4:
Alejandro Mery6ff28242014-12-04 23:59:35 +0100306 lws_free(wsi->u.hdr.ah);
307 lws_free(wsi);
Andy Green5dc62ea2013-09-20 20:26:12 +0800308 return NULL;
Andy Greena41314f2011-05-23 10:00:03 +0100309
Andy Green5dc62ea2013-09-20 20:26:12 +0800310failed:
Andy Green3ef579b2015-12-04 09:23:56 +0800311 lws_close_and_free_session(context, wsi,
Andy Green5dc62ea2013-09-20 20:26:12 +0800312 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greena41314f2011-05-23 10:00:03 +0100313 return NULL;
314}
315
Andy Green90c7cbc2011-01-27 06:26:52 +0000316/**
Andy Green62304762015-12-04 08:43:54 +0800317 * lws_client_connect() - Connect to another websocket server
Peter Hinz56885f32011-03-02 22:03:47 +0000318 * @context: Websocket context
Andy Green90c7cbc2011-01-27 06:26:52 +0000319 * @address: Remote server address, eg, "myserver.com"
320 * @port: Port to connect to on the remote server, eg, 80
321 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
322 * signed certs
323 * @path: Websocket path on server
324 * @host: Hostname on server
325 * @origin: Socket origin name
326 * @protocol: Comma-separated list of protocols being asked for from
327 * the server, or just one. The server will pick the one it
Andy Greena40760a2014-08-07 16:52:15 +0800328 * likes best. If you don't want to specify a protocol, which is
329 * legal, use NULL here.
Andy Greenbfb051f2011-02-09 08:49:14 +0000330 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
Andy Green6ee372f2012-04-09 15:09:01 +0800331 * protocol supported, or the specific protocol ordinal
Andy Green90c7cbc2011-01-27 06:26:52 +0000332 *
333 * This function creates a connection to a remote server
334 */
335
Andy Green4b85c1d2015-12-04 11:08:32 +0800336LWS_VISIBLE struct lws *
337lws_client_connect(struct lws_context *context,
Andy Green4739e5c2011-01-22 12:51:57 +0000338 const char *address,
339 int port,
Andy Green90c7cbc2011-01-27 06:26:52 +0000340 int ssl_connection,
Andy Green4739e5c2011-01-22 12:51:57 +0000341 const char *path,
342 const char *host,
343 const char *origin,
Andy Greenbfb051f2011-02-09 08:49:14 +0000344 const char *protocol,
345 int ietf_version_or_minus_one)
Andy Green4739e5c2011-01-22 12:51:57 +0000346{
Andy Green4b85c1d2015-12-04 11:08:32 +0800347 struct lws *wsi;
Andy Green3182ece2013-01-20 17:08:31 +0800348
Andy Green4b85c1d2015-12-04 11:08:32 +0800349 wsi = lws_zalloc(sizeof(struct lws));
Andy Greenbe93fef2011-02-14 20:25:43 +0000350 if (wsi == NULL)
Andy Green224149a2013-02-11 21:43:41 +0800351 goto bail;
Andy Green4739e5c2011-01-22 12:51:57 +0000352
Andy Greenfc772cc2015-11-14 13:48:58 +0800353 wsi->sock = LWS_SOCK_INVALID;
Darin Willitsc19456f2011-02-14 17:52:39 +0000354
Andy Greenbfb051f2011-02-09 08:49:14 +0000355 /* -1 means just use latest supported */
356
357 if (ietf_version_or_minus_one == -1)
Andy Green193306c2011-02-26 11:08:46 +0000358 ietf_version_or_minus_one = SPEC_LATEST_SUPPORTED;
Andy Greenbfb051f2011-02-09 08:49:14 +0000359
360 wsi->ietf_spec_revision = ietf_version_or_minus_one;
Andy Green4739e5c2011-01-22 12:51:57 +0000361 wsi->user_space = NULL;
362 wsi->state = WSI_STATE_CLIENT_UNCONNECTED;
Andy Green927eb7b2011-02-01 08:52:55 +0000363 wsi->protocol = NULL;
Andy Greena71eafc2011-02-14 17:59:43 +0000364 wsi->pending_timeout = NO_PENDING_TIMEOUT;
Andy Green2c24ec02014-04-02 19:45:42 +0800365
Andy Greenbe93fef2011-02-14 20:25:43 +0000366#ifdef LWS_OPENSSL_SUPPORT
367 wsi->use_ssl = ssl_connection;
Andy Greenc57037a2014-04-03 10:17:00 +0800368#else
369 if (ssl_connection) {
370 lwsl_err("libwebsockets not configured for ssl\n");
371 goto bail;
372 }
Andy Greenbe93fef2011-02-14 20:25:43 +0000373#endif
374
Andy Green16ab3182013-02-10 18:02:31 +0800375 if (lws_allocate_header_table(wsi))
Andy Greene77fb802013-02-11 13:04:45 +0800376 goto bail;
377
378 /*
379 * we're not necessarily in a position to action these right away,
380 * stash them... we only need during connect phase so u.hdr is fine
381 */
Andy Greena7521de2013-02-18 10:38:45 +0800382 wsi->u.hdr.ah->c_port = port;
Andy Greene77fb802013-02-11 13:04:45 +0800383 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
384 goto bail1;
385
386 /* these only need u.hdr lifetime as well */
387
388 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
389 goto bail1;
390
391 if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
392 goto bail1;
393
394 if (origin)
Andy Greenb5b23192013-02-11 17:13:32 +0800395 if (lws_hdr_simple_create(wsi,
396 _WSI_TOKEN_CLIENT_ORIGIN, origin))
Andy Greene77fb802013-02-11 13:04:45 +0800397 goto bail1;
398 /*
399 * this is a list of protocols we tell the server we're okay with
400 * stash it for later when we compare server response with it
401 */
402 if (protocol)
Andy Greenb5b23192013-02-11 17:13:32 +0800403 if (lws_hdr_simple_create(wsi,
404 _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, protocol))
Andy Greene77fb802013-02-11 13:04:45 +0800405 goto bail1;
406
407 wsi->protocol = &context->protocols[0];
Andy Green4739e5c2011-01-22 12:51:57 +0000408
409 /*
Andy Greena41314f2011-05-23 10:00:03 +0100410 * Check with each extension if it is able to route and proxy this
411 * connection for us. For example, an extension like x-google-mux
412 * can handle this and then we don't need an actual socket for this
413 * connection.
Andy Green9659f372011-01-27 22:01:43 +0000414 */
Andy Green2c24ec02014-04-02 19:45:42 +0800415
416 if (lws_ext_callback_for_each_extension_type(context, wsi,
Andy Greena41314f2011-05-23 10:00:03 +0100417 LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
Andy Green2c24ec02014-04-02 19:45:42 +0800418 (void *)address, port) > 0) {
Andy Green62304762015-12-04 08:43:54 +0800419 lwsl_client("lws_client_connect: ext handling conn\n");
Andy Green5b9a4c02011-01-28 09:39:29 +0000420
Andy Green62304762015-12-04 08:43:54 +0800421 lws_set_timeout(wsi,
Andy Greenb5b23192013-02-11 17:13:32 +0800422 PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
423 AWAITING_TIMEOUT);
Andy Green5b9a4c02011-01-28 09:39:29 +0000424
Andy Greena41314f2011-05-23 10:00:03 +0100425 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT;
Andy Greenbe93fef2011-02-14 20:25:43 +0000426 return wsi;
Andy Green9659f372011-01-27 22:01:43 +0000427 }
Andy Green62304762015-12-04 08:43:54 +0800428 lwsl_client("lws_client_connect: direct conn\n");
Andy Green4739e5c2011-01-22 12:51:57 +0000429
Andy Green62304762015-12-04 08:43:54 +0800430 return lws_client_connect_2(context, wsi);
Andy Green4739e5c2011-01-22 12:51:57 +0000431
Andy Green4739e5c2011-01-22 12:51:57 +0000432bail1:
Alejandro Mery6ff28242014-12-04 23:59:35 +0100433 lws_free(wsi->u.hdr.ah);
Andy Greene77fb802013-02-11 13:04:45 +0800434bail:
Alejandro Mery6ff28242014-12-04 23:59:35 +0100435 lws_free(wsi);
Andy Green4739e5c2011-01-22 12:51:57 +0000436
437 return NULL;
438}
David Brooks2c60d952012-04-20 12:19:01 +0800439
440
441/**
Andy Green62304762015-12-04 08:43:54 +0800442 * lws_client_connect_extended() - Connect to another websocket server
David Brooks2c60d952012-04-20 12:19:01 +0800443 * @context: Websocket context
444 * @address: Remote server address, eg, "myserver.com"
445 * @port: Port to connect to on the remote server, eg, 80
446 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
447 * signed certs
448 * @path: Websocket path on server
449 * @host: Hostname on server
450 * @origin: Socket origin name
451 * @protocol: Comma-separated list of protocols being asked for from
452 * the server, or just one. The server will pick the one it
453 * likes best.
454 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
Andy Greenb5b23192013-02-11 17:13:32 +0800455 * protocol supported, or the specific protocol ordinal
David Brooks2c60d952012-04-20 12:19:01 +0800456 * @userdata: Pre-allocated user data
457 *
458 * This function creates a connection to a remote server
459 */
460
Andy Green4b85c1d2015-12-04 11:08:32 +0800461LWS_VISIBLE struct lws *
462lws_client_connect_extended(struct lws_context *context,
David Brooks2c60d952012-04-20 12:19:01 +0800463 const char *address,
464 int port,
465 int ssl_connection,
466 const char *path,
467 const char *host,
468 const char *origin,
469 const char *protocol,
470 int ietf_version_or_minus_one,
Andy Greenb5b23192013-02-11 17:13:32 +0800471 void *userdata)
David Brooks2c60d952012-04-20 12:19:01 +0800472{
Andy Green4b85c1d2015-12-04 11:08:32 +0800473 struct lws *ws =
Andy Green62304762015-12-04 08:43:54 +0800474 lws_client_connect(context, address, port,
Andy Greenb5b23192013-02-11 17:13:32 +0800475 ssl_connection, path, host, origin, protocol,
476 ietf_version_or_minus_one);
David Brooks2c60d952012-04-20 12:19:01 +0800477
Andy Green97850852014-07-05 10:31:12 +0800478 if (ws && !ws->user_space && userdata) {
479 ws->user_space_externally_allocated = 1;
David Brooks2c60d952012-04-20 12:19:01 +0800480 ws->user_space = userdata ;
Andy Green97850852014-07-05 10:31:12 +0800481 }
David Brooks2c60d952012-04-20 12:19:01 +0800482
483 return ws ;
Andy Greenb5b23192013-02-11 17:13:32 +0800484}