blob: 01aae4d86658dd734f4215a37ab09c01ed30af66 [file] [log] [blame]
Andy Green4739e5c2011-01-22 12:51:57 +00001#include "private-libwebsockets.h"
Andy Green4739e5c2011-01-22 12:51:57 +00002
Andy Green6ee372f2012-04-09 15:09:01 +08003struct libwebsocket *__libwebsocket_client_connect_2(
Andy Greena41314f2011-05-23 10:00:03 +01004 struct libwebsocket_context *context,
5 struct libwebsocket *wsi
6) {
7 struct pollfd pfd;
Andy Greena41314f2011-05-23 10:00:03 +01008 struct hostent *server_hostent;
9 struct sockaddr_in server_addr;
10 int n;
11 int plen = 0;
Andy Greena41314f2011-05-23 10:00:03 +010012
Andy Green43db0452013-01-10 19:50:35 +080013 lwsl_client("__libwebsocket_client_connect_2\n");
Andy Greena41314f2011-05-23 10:00:03 +010014
15 /*
16 * proxy?
17 */
18
19 if (context->http_proxy_port) {
Andy Greene48ba312013-02-10 15:34:59 +080020 plen = sprintf((char *)context->service_buffer,
Andy Greenf54a94b2013-02-10 15:19:39 +080021 "CONNECT %s:%u HTTP/1.0\x0d\x0a"
Andy Greena41314f2011-05-23 10:00:03 +010022 "User-agent: libwebsockets\x0d\x0a"
23/*Proxy-authorization: basic aGVsbG86d29ybGQ= */
24 "\x0d\x0a", wsi->c_address, wsi->c_port);
25
26 /* OK from now on we talk via the proxy */
27
28 free(wsi->c_address);
29 wsi->c_address = strdup(context->http_proxy_address);
30 wsi->c_port = context->http_proxy_port;
31 }
32
33 /*
34 * prepare the actual connection (to the proxy, if any)
35 */
36
Andy Greena690cd02013-02-09 12:25:31 +080037 lwsl_client("__libwebsocket_client_connect_2: address %s\n",
38 wsi->c_address);
Andy Green66a16f32011-05-24 22:07:45 +010039
Andy Greena41314f2011-05-23 10:00:03 +010040 server_hostent = gethostbyname(wsi->c_address);
41 if (server_hostent == NULL) {
Andy Green43db0452013-01-10 19:50:35 +080042 lwsl_err("Unable to get host name from %s\n", wsi->c_address);
Andy Greena41314f2011-05-23 10:00:03 +010043 goto oom4;
44 }
45
46 wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
47
48 if (wsi->sock < 0) {
Andy Green43db0452013-01-10 19:50:35 +080049 lwsl_warn("Unable to open socket\n");
Andy Greena41314f2011-05-23 10:00:03 +010050 goto oom4;
51 }
52
53 server_addr.sin_family = AF_INET;
54 server_addr.sin_port = htons(wsi->c_port);
55 server_addr.sin_addr = *((struct in_addr *)server_hostent->h_addr);
56 bzero(&server_addr.sin_zero, 8);
57
Andy Greena41314f2011-05-23 10:00:03 +010058 if (connect(wsi->sock, (struct sockaddr *)&server_addr,
Andy Green6ee372f2012-04-09 15:09:01 +080059 sizeof(struct sockaddr)) == -1) {
Andy Green43db0452013-01-10 19:50:35 +080060 lwsl_debug("Connect failed\n");
Andy Green3fc2c652013-01-14 15:35:02 +080061 compatible_close(wsi->sock);
Andy Greena41314f2011-05-23 10:00:03 +010062 goto oom4;
63 }
64
Andy Green43db0452013-01-10 19:50:35 +080065 lwsl_client("connected\n");
Andy Greena41314f2011-05-23 10:00:03 +010066
Andy Greena690cd02013-02-09 12:25:31 +080067 if (lws_set_socket_options(context, wsi->sock)) {
68 lwsl_err("Failed to set wsi socket options\n");
69 close(wsi->sock);
70 goto oom4;
71 }
72
Andy Greendfb23042013-01-17 12:26:48 +080073 insert_wsi_socket_into_fds(context, wsi);
Andy Greena41314f2011-05-23 10:00:03 +010074
75 /* we are connected to server, or proxy */
76
77 if (context->http_proxy_port) {
78
Andy Greenf54a94b2013-02-10 15:19:39 +080079 n = send(wsi->sock, context->service_buffer, plen, 0);
Andy Greena41314f2011-05-23 10:00:03 +010080 if (n < 0) {
Andy Green3fc2c652013-01-14 15:35:02 +080081 compatible_close(wsi->sock);
Andy Green43db0452013-01-10 19:50:35 +080082 lwsl_debug("ERROR writing to proxy socket\n");
Andy Greena41314f2011-05-23 10:00:03 +010083 goto bail1;
84 }
85
86 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +080087 PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE, AWAITING_TIMEOUT);
Andy Greena41314f2011-05-23 10:00:03 +010088
89 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY;
90
91 return wsi;
92 }
93
94 /*
95 * provoke service to issue the handshake directly
96 * we need to do it this way because in the proxy case, this is the
97 * next state and executed only if and when we get a good proxy
Andy Green73abc252013-01-13 11:05:30 +080098 * response inside the state machine... but notice in SSL case this
99 * may not have sent anything yet with 0 return, and won't until some
100 * many retries from main loop. To stop that becoming endless,
101 * cover with a timeout.
Andy Greena41314f2011-05-23 10:00:03 +0100102 */
103
Andy Green73abc252013-01-13 11:05:30 +0800104 libwebsocket_set_timeout(wsi,
105 PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, AWAITING_TIMEOUT);
106
Andy Greena41314f2011-05-23 10:00:03 +0100107 wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE;
108 pfd.fd = wsi->sock;
109 pfd.revents = POLLIN;
David Galeano36750b82013-01-09 16:17:04 +0800110
111 n = libwebsocket_service_fd(context, &pfd);
112
113 if (n < 0)
Andy Green3928f612012-07-20 12:58:38 +0800114 goto oom4;
Andy Greena41314f2011-05-23 10:00:03 +0100115
David Galeano36750b82013-01-09 16:17:04 +0800116 if (n) /* returns 1 on failure after closing wsi */
117 return NULL;
118
Andy Greena41314f2011-05-23 10:00:03 +0100119 return wsi;
120
121oom4:
122 if (wsi->c_protocol)
123 free(wsi->c_protocol);
124
125 if (wsi->c_origin)
126 free(wsi->c_origin);
127
128 free(wsi->c_host);
129 free(wsi->c_path);
130
131bail1:
132 free(wsi);
133
134 return NULL;
135}
136
Andy Green90c7cbc2011-01-27 06:26:52 +0000137/**
138 * libwebsocket_client_connect() - Connect to another websocket server
Peter Hinz56885f32011-03-02 22:03:47 +0000139 * @context: Websocket context
Andy Green90c7cbc2011-01-27 06:26:52 +0000140 * @address: Remote server address, eg, "myserver.com"
141 * @port: Port to connect to on the remote server, eg, 80
142 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
143 * signed certs
144 * @path: Websocket path on server
145 * @host: Hostname on server
146 * @origin: Socket origin name
147 * @protocol: Comma-separated list of protocols being asked for from
148 * the server, or just one. The server will pick the one it
149 * likes best.
Andy Greenbfb051f2011-02-09 08:49:14 +0000150 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
Andy Green6ee372f2012-04-09 15:09:01 +0800151 * protocol supported, or the specific protocol ordinal
Andy Green90c7cbc2011-01-27 06:26:52 +0000152 *
153 * This function creates a connection to a remote server
154 */
155
Andy Green4739e5c2011-01-22 12:51:57 +0000156struct libwebsocket *
Peter Hinz56885f32011-03-02 22:03:47 +0000157libwebsocket_client_connect(struct libwebsocket_context *context,
Andy Green4739e5c2011-01-22 12:51:57 +0000158 const char *address,
159 int port,
Andy Green90c7cbc2011-01-27 06:26:52 +0000160 int ssl_connection,
Andy Green4739e5c2011-01-22 12:51:57 +0000161 const char *path,
162 const char *host,
163 const char *origin,
Andy Greenbfb051f2011-02-09 08:49:14 +0000164 const char *protocol,
165 int ietf_version_or_minus_one)
Andy Green4739e5c2011-01-22 12:51:57 +0000166{
Andy Green4739e5c2011-01-22 12:51:57 +0000167 struct libwebsocket *wsi;
168 int n;
Andy Green3182ece2013-01-20 17:08:31 +0800169#ifndef LWS_NO_EXTENSIONS
Andy Greena41314f2011-05-23 10:00:03 +0100170 int m;
171 struct libwebsocket_extension *ext;
172 int handled;
Andy Green3182ece2013-01-20 17:08:31 +0800173#endif
174
Andy Greenbe93fef2011-02-14 20:25:43 +0000175#ifndef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000176 if (ssl_connection) {
Andy Green43db0452013-01-10 19:50:35 +0800177 lwsl_err("libwebsockets not configured for ssl\n");
Andy Green90c7cbc2011-01-27 06:26:52 +0000178 return NULL;
179 }
180#endif
Andy Green4739e5c2011-01-22 12:51:57 +0000181
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800182 wsi = (struct libwebsocket *) malloc(sizeof(struct libwebsocket));
Andy Greenbe93fef2011-02-14 20:25:43 +0000183 if (wsi == NULL)
184 goto bail1;
Andy Green4739e5c2011-01-22 12:51:57 +0000185
Darin Willitsc19456f2011-02-14 17:52:39 +0000186 memset(wsi, 0, sizeof *wsi);
187
Andy Greenbfb051f2011-02-09 08:49:14 +0000188 /* -1 means just use latest supported */
189
190 if (ietf_version_or_minus_one == -1)
Andy Green193306c2011-02-26 11:08:46 +0000191 ietf_version_or_minus_one = SPEC_LATEST_SUPPORTED;
Andy Greenbfb051f2011-02-09 08:49:14 +0000192
193 wsi->ietf_spec_revision = ietf_version_or_minus_one;
Andy Green623a98d2013-01-21 11:04:23 +0800194 wsi->u.hdr.name_buffer_pos = 0;
Andy Green4739e5c2011-01-22 12:51:57 +0000195 wsi->user_space = NULL;
196 wsi->state = WSI_STATE_CLIENT_UNCONNECTED;
Andy Green927eb7b2011-02-01 08:52:55 +0000197 wsi->protocol = NULL;
Andy Greena71eafc2011-02-14 17:59:43 +0000198 wsi->pending_timeout = NO_PENDING_TIMEOUT;
Andy Green3182ece2013-01-20 17:08:31 +0800199#ifndef LWS_NO_EXTENSIONS
Andy Greend6e09112011-03-05 16:12:15 +0000200 wsi->count_active_extensions = 0;
Andy Green3182ece2013-01-20 17:08:31 +0800201#endif
Andy Greenbe93fef2011-02-14 20:25:43 +0000202#ifdef LWS_OPENSSL_SUPPORT
203 wsi->use_ssl = ssl_connection;
204#endif
205
Andy Greena41314f2011-05-23 10:00:03 +0100206 wsi->c_port = port;
207 wsi->c_address = strdup(address);
208
Andy Greenbe93fef2011-02-14 20:25:43 +0000209 /* copy parameters over so state machine has access */
210
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800211 wsi->c_path = (char *)malloc(strlen(path) + 1);
Andy Greenbe93fef2011-02-14 20:25:43 +0000212 if (wsi->c_path == NULL)
213 goto bail1;
214 strcpy(wsi->c_path, path);
Andy Green6ee372f2012-04-09 15:09:01 +0800215
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800216 wsi->c_host = (char *)malloc(strlen(host) + 1);
Andy Greenbe93fef2011-02-14 20:25:43 +0000217 if (wsi->c_host == NULL)
218 goto oom1;
219 strcpy(wsi->c_host, host);
Andy Green6ee372f2012-04-09 15:09:01 +0800220
Andy Green08d33922011-02-26 10:22:49 +0000221 if (origin) {
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800222 wsi->c_origin = (char *)malloc(strlen(origin) + 1);
Andy Green08d33922011-02-26 10:22:49 +0000223 if (wsi->c_origin == NULL)
224 goto oom2;
Andy Green41c58032013-01-12 13:21:08 +0800225 strcpy(wsi->c_origin, origin);
Andy Green08d33922011-02-26 10:22:49 +0000226 } else
227 wsi->c_origin = NULL;
Andy Green6ee372f2012-04-09 15:09:01 +0800228
David Brooks993343b2012-04-20 12:16:52 +0800229 wsi->c_callback = NULL;
Andy Greenbe93fef2011-02-14 20:25:43 +0000230 if (protocol) {
David Brooks993343b2012-04-20 12:16:52 +0800231 const char *pc;
232 struct libwebsocket_protocols *pp;
233
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800234 wsi->c_protocol = (char *)malloc(strlen(protocol) + 1);
Andy Greenbe93fef2011-02-14 20:25:43 +0000235 if (wsi->c_protocol == NULL)
236 goto oom3;
David Brooks993343b2012-04-20 12:16:52 +0800237
Andy Greenbe93fef2011-02-14 20:25:43 +0000238 strcpy(wsi->c_protocol, protocol);
David Brooks993343b2012-04-20 12:16:52 +0800239
240 pc = protocol;
241 while (*pc && *pc != ',')
242 pc++;
243 n = pc - protocol;
244 pp = context->protocols;
245 while (pp->name && !wsi->c_callback) {
246 if (!strncmp(protocol, pp->name, n))
247 wsi->c_callback = pp->callback;
248 pp++;
249 }
Andy Greenbe93fef2011-02-14 20:25:43 +0000250 } else
251 wsi->c_protocol = NULL;
252
David Brooks993343b2012-04-20 12:16:52 +0800253 if (!wsi->c_callback)
254 wsi->c_callback = context->protocols[0].callback;
255
Andy Green16ab3182013-02-10 18:02:31 +0800256 if (lws_allocate_header_table(wsi))
257 goto oom3;
Andy Green4739e5c2011-01-22 12:51:57 +0000258
Andy Green3182ece2013-01-20 17:08:31 +0800259#ifndef LWS_NO_EXTENSIONS
Andy Green4739e5c2011-01-22 12:51:57 +0000260 /*
Andy Greena41314f2011-05-23 10:00:03 +0100261 * Check with each extension if it is able to route and proxy this
262 * connection for us. For example, an extension like x-google-mux
263 * can handle this and then we don't need an actual socket for this
264 * connection.
Andy Green9659f372011-01-27 22:01:43 +0000265 */
266
Andy Greena41314f2011-05-23 10:00:03 +0100267 handled = 0;
268 ext = context->extensions;
269 n = 0;
Andy Green9659f372011-01-27 22:01:43 +0000270
Andy Greena41314f2011-05-23 10:00:03 +0100271 while (ext && ext->callback && !handled) {
272 m = ext->callback(context, ext, wsi,
273 LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
274 (void *)(long)n, (void *)address, port);
275 if (m)
276 handled = 1;
Andy Green9659f372011-01-27 22:01:43 +0000277
Andy Greena41314f2011-05-23 10:00:03 +0100278 ext++;
279 n++;
Andy Green9659f372011-01-27 22:01:43 +0000280 }
281
Andy Greena41314f2011-05-23 10:00:03 +0100282 if (handled) {
Andy Green43db0452013-01-10 19:50:35 +0800283 lwsl_client("libwebsocket_client_connect: ext handling conn\n");
Andy Green5b9a4c02011-01-28 09:39:29 +0000284
Andy Greenbe93fef2011-02-14 20:25:43 +0000285 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +0800286 PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE, AWAITING_TIMEOUT);
Andy Green5b9a4c02011-01-28 09:39:29 +0000287
Andy Greena41314f2011-05-23 10:00:03 +0100288 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT;
Andy Greenbe93fef2011-02-14 20:25:43 +0000289 return wsi;
Andy Green9659f372011-01-27 22:01:43 +0000290 }
Andy Green3182ece2013-01-20 17:08:31 +0800291#endif
Andy Green43db0452013-01-10 19:50:35 +0800292 lwsl_client("libwebsocket_client_connect: direct conn\n");
Andy Green4739e5c2011-01-22 12:51:57 +0000293
Andy Greena41314f2011-05-23 10:00:03 +0100294 return __libwebsocket_client_connect_2(context, wsi);
Andy Green4739e5c2011-01-22 12:51:57 +0000295
Andy Greenbe93fef2011-02-14 20:25:43 +0000296oom3:
Andy Green08d33922011-02-26 10:22:49 +0000297 if (wsi->c_origin)
298 free(wsi->c_origin);
Andy Greenbe93fef2011-02-14 20:25:43 +0000299
300oom2:
301 free(wsi->c_host);
302
303oom1:
304 free(wsi->c_path);
305
Andy Green4739e5c2011-01-22 12:51:57 +0000306bail1:
307 free(wsi);
308
309 return NULL;
310}
David Brooks2c60d952012-04-20 12:19:01 +0800311
312
313/**
314 * libwebsocket_client_connect_extended() - Connect to another websocket server
315 * @context: Websocket context
316 * @address: Remote server address, eg, "myserver.com"
317 * @port: Port to connect to on the remote server, eg, 80
318 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
319 * signed certs
320 * @path: Websocket path on server
321 * @host: Hostname on server
322 * @origin: Socket origin name
323 * @protocol: Comma-separated list of protocols being asked for from
324 * the server, or just one. The server will pick the one it
325 * likes best.
326 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
327 * protocol supported, or the specific protocol ordinal
328 * @userdata: Pre-allocated user data
329 *
330 * This function creates a connection to a remote server
331 */
332
333struct libwebsocket *
334libwebsocket_client_connect_extended(struct libwebsocket_context *context,
335 const char *address,
336 int port,
337 int ssl_connection,
338 const char *path,
339 const char *host,
340 const char *origin,
341 const char *protocol,
342 int ietf_version_or_minus_one,
343 void *userdata)
344{
345 struct libwebsocket *ws =
346 libwebsocket_client_connect(context, address, port, ssl_connection, path, host, origin, protocol, ietf_version_or_minus_one) ;
347
348 if (ws && !ws->user_space && userdata)
349 ws->user_space = userdata ;
350
351 return ws ;
352 }