1 #include "private-libwebsockets.h"
3 struct libwebsocket *__libwebsocket_client_connect_2(
4 struct libwebsocket_context *context,
5 struct libwebsocket *wsi
8 struct hostent *server_hostent;
9 struct sockaddr_in server_addr;
13 lwsl_client("__libwebsocket_client_connect_2\n");
14 #ifndef LWS_NO_EXTENSIONS
15 wsi->candidate_children_list = NULL;
22 if (context->http_proxy_port) {
23 plen = sprintf((char *)context->service_buffer,
24 "CONNECT %s:%u HTTP/1.0\x0d\x0a"
25 "User-agent: libwebsockets\x0d\x0a"
26 /*Proxy-authorization: basic aGVsbG86d29ybGQ= */
27 "\x0d\x0a", wsi->c_address, wsi->c_port);
29 /* OK from now on we talk via the proxy */
32 wsi->c_address = strdup(context->http_proxy_address);
33 wsi->c_port = context->http_proxy_port;
37 * prepare the actual connection (to the proxy, if any)
40 lwsl_client("__libwebsocket_client_connect_2: address %s\n",
43 server_hostent = gethostbyname(wsi->c_address);
44 if (server_hostent == NULL) {
45 lwsl_err("Unable to get host name from %s\n", wsi->c_address);
49 wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
52 lwsl_warn("Unable to open socket\n");
56 server_addr.sin_family = AF_INET;
57 server_addr.sin_port = htons(wsi->c_port);
58 server_addr.sin_addr = *((struct in_addr *)server_hostent->h_addr);
59 bzero(&server_addr.sin_zero, 8);
61 if (connect(wsi->sock, (struct sockaddr *)&server_addr,
62 sizeof(struct sockaddr)) == -1) {
63 lwsl_debug("Connect failed\n");
64 compatible_close(wsi->sock);
68 lwsl_client("connected\n");
70 if (lws_set_socket_options(context, wsi->sock)) {
71 lwsl_err("Failed to set wsi socket options\n");
76 insert_wsi_socket_into_fds(context, wsi);
78 /* we are connected to server, or proxy */
80 if (context->http_proxy_port) {
82 n = send(wsi->sock, context->service_buffer, plen, 0);
84 compatible_close(wsi->sock);
85 lwsl_debug("ERROR writing to proxy socket\n");
89 libwebsocket_set_timeout(wsi,
90 PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE, AWAITING_TIMEOUT);
92 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY;
98 * provoke service to issue the handshake directly
99 * we need to do it this way because in the proxy case, this is the
100 * next state and executed only if and when we get a good proxy
101 * response inside the state machine... but notice in SSL case this
102 * may not have sent anything yet with 0 return, and won't until some
103 * many retries from main loop. To stop that becoming endless,
104 * cover with a timeout.
107 libwebsocket_set_timeout(wsi,
108 PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, AWAITING_TIMEOUT);
110 wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE;
112 pfd.revents = POLLIN;
114 n = libwebsocket_service_fd(context, &pfd);
119 if (n) /* returns 1 on failure after closing wsi */
126 free(wsi->c_protocol);
141 * libwebsocket_client_connect() - Connect to another websocket server
142 * @context: Websocket context
143 * @address: Remote server address, eg, "myserver.com"
144 * @port: Port to connect to on the remote server, eg, 80
145 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
147 * @path: Websocket path on server
148 * @host: Hostname on server
149 * @origin: Socket origin name
150 * @protocol: Comma-separated list of protocols being asked for from
151 * the server, or just one. The server will pick the one it
153 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
154 * protocol supported, or the specific protocol ordinal
156 * This function creates a connection to a remote server
159 struct libwebsocket *
160 libwebsocket_client_connect(struct libwebsocket_context *context,
167 const char *protocol,
168 int ietf_version_or_minus_one)
170 struct libwebsocket *wsi;
172 #ifndef LWS_NO_EXTENSIONS
174 struct libwebsocket_extension *ext;
178 #ifndef LWS_OPENSSL_SUPPORT
179 if (ssl_connection) {
180 lwsl_err("libwebsockets not configured for ssl\n");
185 wsi = (struct libwebsocket *) malloc(sizeof(struct libwebsocket));
189 memset(wsi, 0, sizeof *wsi);
191 /* -1 means just use latest supported */
193 if (ietf_version_or_minus_one == -1)
194 ietf_version_or_minus_one = SPEC_LATEST_SUPPORTED;
196 wsi->ietf_spec_revision = ietf_version_or_minus_one;
197 wsi->u.hdr.name_buffer_pos = 0;
198 wsi->user_space = NULL;
199 wsi->state = WSI_STATE_CLIENT_UNCONNECTED;
200 wsi->u.ws.pings_vs_pongs = 0;
201 wsi->protocol = NULL;
202 wsi->pending_timeout = NO_PENDING_TIMEOUT;
203 #ifndef LWS_NO_EXTENSIONS
204 wsi->count_active_extensions = 0;
206 #ifdef LWS_OPENSSL_SUPPORT
207 wsi->use_ssl = ssl_connection;
211 wsi->c_address = strdup(address);
213 /* copy parameters over so state machine has access */
215 wsi->c_path = (char *)malloc(strlen(path) + 1);
216 if (wsi->c_path == NULL)
218 strcpy(wsi->c_path, path);
220 wsi->c_host = (char *)malloc(strlen(host) + 1);
221 if (wsi->c_host == NULL)
223 strcpy(wsi->c_host, host);
226 wsi->c_origin = (char *)malloc(strlen(origin) + 1);
227 if (wsi->c_origin == NULL)
229 strcpy(wsi->c_origin, origin);
231 wsi->c_origin = NULL;
233 wsi->c_callback = NULL;
236 struct libwebsocket_protocols *pp;
238 wsi->c_protocol = (char *)malloc(strlen(protocol) + 1);
239 if (wsi->c_protocol == NULL)
242 strcpy(wsi->c_protocol, protocol);
245 while (*pc && *pc != ',')
248 pp = context->protocols;
249 while (pp->name && !wsi->c_callback) {
250 if (!strncmp(protocol, pp->name, n))
251 wsi->c_callback = pp->callback;
255 wsi->c_protocol = NULL;
257 if (!wsi->c_callback)
258 wsi->c_callback = context->protocols[0].callback;
260 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
261 wsi->u.hdr.hdrs[n].token = NULL;
262 wsi->u.hdr.hdrs[n].token_len = 0;
265 #ifndef LWS_NO_EXTENSIONS
267 * Check with each extension if it is able to route and proxy this
268 * connection for us. For example, an extension like x-google-mux
269 * can handle this and then we don't need an actual socket for this
274 ext = context->extensions;
277 while (ext && ext->callback && !handled) {
278 m = ext->callback(context, ext, wsi,
279 LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
280 (void *)(long)n, (void *)address, port);
289 lwsl_client("libwebsocket_client_connect: ext handling conn\n");
291 libwebsocket_set_timeout(wsi,
292 PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE, AWAITING_TIMEOUT);
294 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT;
298 lwsl_client("libwebsocket_client_connect: direct conn\n");
300 return __libwebsocket_client_connect_2(context, wsi);
320 * libwebsocket_client_connect_extended() - Connect to another websocket server
321 * @context: Websocket context
322 * @address: Remote server address, eg, "myserver.com"
323 * @port: Port to connect to on the remote server, eg, 80
324 * @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
326 * @path: Websocket path on server
327 * @host: Hostname on server
328 * @origin: Socket origin name
329 * @protocol: Comma-separated list of protocols being asked for from
330 * the server, or just one. The server will pick the one it
332 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
333 * protocol supported, or the specific protocol ordinal
334 * @userdata: Pre-allocated user data
336 * This function creates a connection to a remote server
339 struct libwebsocket *
340 libwebsocket_client_connect_extended(struct libwebsocket_context *context,
347 const char *protocol,
348 int ietf_version_or_minus_one,
351 struct libwebsocket *ws =
352 libwebsocket_client_connect(context, address, port, ssl_connection, path, host, origin, protocol, ietf_version_or_minus_one) ;
354 if (ws && !ws->user_space && userdata)
355 ws->user_space = userdata ;