~roger.light/ubuntu/vivid/libwebsockets/fix-for-1422623

« back to all changes in this revision

Viewing changes to lib/client-handshake.c

  • Committer: Roger A. Light
  • Date: 2015-02-19 16:00:08 UTC
  • mfrom: (1.1.1)
  • Revision ID: roger@atchoo.org-20150219160008-162cd9naiu2yekny
New upstream release 1.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#include "private-libwebsockets.h"
2
2
 
3
 
struct libwebsocket *__libwebsocket_client_connect_2(
 
3
struct libwebsocket *libwebsocket_client_connect_2(
4
4
        struct libwebsocket_context *context,
5
5
        struct libwebsocket *wsi
6
6
) {
7
 
        struct pollfd pfd;
 
7
        struct libwebsocket_pollfd pfd;
 
8
#ifdef LWS_USE_IPV6
 
9
        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;
8
15
        struct hostent *server_hostent;
9
 
        struct sockaddr_in server_addr;
 
16
 
 
17
        struct sockaddr *v;
10
18
        int n;
11
19
        int plen = 0;
12
20
        const char *ads;
13
21
 
14
 
        lwsl_client("__libwebsocket_client_connect_2\n");
 
22
       lwsl_client("libwebsocket_client_connect_2\n");
15
23
 
16
24
        /*
17
25
         * proxy?
24
32
/*Proxy-authorization: basic aGVsbG86d29ybGQ= */
25
33
                        "\x0d\x0a",
26
34
                        lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
27
 
                        wsi->u.hdr.c_port);
 
35
                        wsi->u.hdr.ah->c_port);
 
36
                ads = context->http_proxy_address;
 
37
 
 
38
#ifdef LWS_USE_IPV6
 
39
                if (LWS_IPV6_ENABLED(context))
 
40
                        server_addr6.sin6_port = htons(context->http_proxy_port);
 
41
                else
 
42
#endif
 
43
                        server_addr4.sin_port = htons(context->http_proxy_port);
 
44
 
 
45
        } else {
 
46
                ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
 
47
#ifdef LWS_USE_IPV6
 
48
                if (LWS_IPV6_ENABLED(context))
 
49
                        server_addr6.sin6_port = htons(wsi->u.hdr.ah->c_port);
 
50
                else
 
51
#endif
 
52
                        server_addr4.sin_port = htons(wsi->u.hdr.ah->c_port);
 
53
        }
 
54
 
 
55
        /*
 
56
         * prepare the actual connection (to the proxy, if any)
 
57
         */
 
58
       lwsl_client("libwebsocket_client_connect_2: address %s\n", ads);
 
59
 
 
60
#ifdef LWS_USE_IPV6
 
61
        if (LWS_IPV6_ENABLED(context)) {
 
62
                memset(&hints, 0, sizeof(struct addrinfo));
 
63
                n = getaddrinfo(ads, NULL, &hints, &result);
 
64
                if (n) {
 
65
#ifdef _WIN32
 
66
                        lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n));
 
67
#else
 
68
                        lwsl_err("getaddrinfo: %s\n", gai_strerror(n));
 
69
#endif
 
70
                        goto oom4;
 
71
                }
 
72
 
 
73
                server_addr6.sin6_family = AF_INET6;
 
74
                switch (result->ai_family) {
 
75
                case AF_INET:
 
76
                        /* map IPv4 to IPv6 */
 
77
                        bzero((char *)&server_addr6.sin6_addr,
 
78
                                                sizeof(struct in6_addr));
 
79
                        server_addr6.sin6_addr.s6_addr[10] = 0xff;
 
80
                        server_addr6.sin6_addr.s6_addr[11] = 0xff;
 
81
                        memcpy(&server_addr6.sin6_addr.s6_addr[12],
 
82
                                &((struct sockaddr_in *)result->ai_addr)->sin_addr,
 
83
                                                        sizeof(struct in_addr));
 
84
                        break;
 
85
                case AF_INET6:
 
86
                        memcpy(&server_addr6.sin6_addr,
 
87
                          &((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
 
88
                                                sizeof(struct in6_addr));
 
89
                        break;
 
90
                default:
 
91
                        lwsl_err("Unknown address family\n");
 
92
                        freeaddrinfo(result);
 
93
                        goto oom4;
 
94
                }
 
95
 
 
96
                freeaddrinfo(result);
 
97
        } else
 
98
#endif
 
99
        {
 
100
                server_hostent = gethostbyname(ads);
 
101
                if (!server_hostent) {
 
102
                        lwsl_err("Unable to get host name from %s\n", ads);
 
103
                        goto oom4;
 
104
                }
 
105
 
 
106
                server_addr4.sin_family = AF_INET;
 
107
                server_addr4.sin_addr =
 
108
                                *((struct in_addr *)server_hostent->h_addr);
 
109
                bzero(&server_addr4.sin_zero, 8);
 
110
        }
 
111
 
 
112
        if (wsi->sock < 0) {
 
113
 
 
114
#ifdef LWS_USE_IPV6
 
115
                if (LWS_IPV6_ENABLED(context))
 
116
                        wsi->sock = socket(AF_INET6, SOCK_STREAM, 0);
 
117
                else
 
118
#endif
 
119
                        wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
 
120
 
 
121
                if (wsi->sock < 0) {
 
122
                        lwsl_warn("Unable to open socket\n");
 
123
                        goto oom4;
 
124
                }
 
125
 
 
126
                if (lws_plat_set_socket_options(context, wsi->sock)) {
 
127
                        lwsl_err("Failed to set wsi socket options\n");
 
128
                        compatible_close(wsi->sock);
 
129
                        goto oom4;
 
130
                }
 
131
 
 
132
                wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT;
 
133
 
 
134
                insert_wsi_socket_into_fds(context, wsi);
 
135
 
 
136
                libwebsocket_set_timeout(wsi,
 
137
                        PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
 
138
                                                              AWAITING_TIMEOUT);
 
139
#ifdef LWS_USE_IPV6
 
140
                if (LWS_IPV6_ENABLED(context)) {
 
141
                        v = (struct sockaddr *)&client_addr6;
 
142
                        n = sizeof(client_addr6);
 
143
                        bzero((char *)v, n);
 
144
                        client_addr6.sin6_family = AF_INET6;
 
145
                } else
 
146
#endif
 
147
                {
 
148
                        v = (struct sockaddr *)&client_addr4;
 
149
                        n = sizeof(client_addr4);
 
150
                        bzero((char *)v, n);
 
151
                        client_addr4.sin_family = AF_INET;
 
152
                }
 
153
 
 
154
                if (context->iface) {
 
155
                        if (interface_to_sa(context, context->iface,
 
156
                                        (struct sockaddr_in *)v, n) < 0) {
 
157
                                lwsl_err("Unable to find interface %s\n",
 
158
                                                                context->iface);
 
159
                                compatible_close(wsi->sock);
 
160
                                goto failed;
 
161
                        }
 
162
 
 
163
                        if (bind(wsi->sock, v, n) < 0) {
 
164
                                lwsl_err("Error binding to interface %s",
 
165
                                                                context->iface);
 
166
                                compatible_close(wsi->sock);
 
167
                                goto failed;
 
168
                        }
 
169
                }
 
170
        }
 
171
 
 
172
#ifdef LWS_USE_IPV6
 
173
        if (LWS_IPV6_ENABLED(context)) {
 
174
                v = (struct sockaddr *)&server_addr6;
 
175
                n = sizeof(struct sockaddr_in6);
 
176
        } else
 
177
#endif
 
178
        {
 
179
                v = (struct sockaddr *)&server_addr4;
 
180
                n = sizeof(struct sockaddr);
 
181
        }
 
182
 
 
183
        if (connect(wsi->sock, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
 
184
 
 
185
                if (LWS_ERRNO == LWS_EALREADY || LWS_ERRNO == LWS_EINPROGRESS
 
186
                                              || LWS_ERRNO == LWS_EWOULDBLOCK) {
 
187
                        lwsl_client("nonblocking connect retry\n");
 
188
 
 
189
                        /*
 
190
                         * must do specifically a POLLOUT poll to hear
 
191
                         * about the connect completion
 
192
                         */
 
193
                        if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
 
194
                                goto oom4;
 
195
 
 
196
                        return wsi;
 
197
                }
 
198
 
 
199
                if (LWS_ERRNO != LWS_EISCONN) {
 
200
                        lwsl_debug("Connect failed errno=%d\n", LWS_ERRNO);
 
201
                        goto failed;
 
202
                }
 
203
        }
 
204
 
 
205
        lwsl_client("connected\n");
 
206
 
 
207
        /* we are connected to server, or proxy */
 
208
 
 
209
        if (context->http_proxy_port) {
28
210
 
29
211
                /* OK from now on we talk via the proxy, so connect to that */
30
212
 
34
216
                 */
35
217
                if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
36
218
                                                   context->http_proxy_address))
37
 
                        goto oom4;
38
 
                wsi->u.hdr.c_port = context->http_proxy_port;
39
 
        }
40
 
 
41
 
        /*
42
 
         * prepare the actual connection (to the proxy, if any)
43
 
         */
44
 
 
45
 
        ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
46
 
 
47
 
        lwsl_client("__libwebsocket_client_connect_2: address %s\n", ads);
48
 
 
49
 
        server_hostent = gethostbyname(ads);
50
 
        if (server_hostent == NULL) {
51
 
                lwsl_err("Unable to get host name from %s\n", ads);
52
 
                goto oom4;
53
 
        }
54
 
 
55
 
        wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
56
 
 
57
 
        if (wsi->sock < 0) {
58
 
                lwsl_warn("Unable to open socket\n");
59
 
                goto oom4;
60
 
        }
61
 
 
62
 
        server_addr.sin_family = AF_INET;
63
 
        server_addr.sin_port = htons(wsi->u.hdr.c_port);
64
 
        server_addr.sin_addr = *((struct in_addr *)server_hostent->h_addr);
65
 
        bzero(&server_addr.sin_zero, 8);
66
 
 
67
 
        if (connect(wsi->sock, (struct sockaddr *)&server_addr,
68
 
                                             sizeof(struct sockaddr)) == -1)  {
69
 
                lwsl_debug("Connect failed\n");
70
 
                compatible_close(wsi->sock);
71
 
                goto oom4;
72
 
        }
73
 
 
74
 
        lwsl_client("connected\n");
75
 
 
76
 
        if (lws_set_socket_options(context, wsi->sock)) {
77
 
                lwsl_err("Failed to set wsi socket options\n");
78
 
                close(wsi->sock);
79
 
                goto oom4;
80
 
        }
81
 
 
82
 
        insert_wsi_socket_into_fds(context, wsi);
83
 
 
84
 
        /* we are connected to server, or proxy */
85
 
 
86
 
        if (context->http_proxy_port) {
87
 
 
88
 
                n = send(wsi->sock, context->service_buffer, plen, 0);
 
219
                        goto failed;
 
220
                wsi->u.hdr.ah->c_port = context->http_proxy_port;
 
221
 
 
222
                n = send(wsi->sock, context->service_buffer, plen, MSG_NOSIGNAL);
89
223
                if (n < 0) {
90
 
                        compatible_close(wsi->sock);
91
224
                        lwsl_debug("ERROR writing to proxy socket\n");
92
 
                        goto oom4;
 
225
                        goto failed;
93
226
                }
94
227
 
95
228
                libwebsocket_set_timeout(wsi,
116
249
 
117
250
        wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE;
118
251
        pfd.fd = wsi->sock;
119
 
        pfd.revents = POLLIN;
 
252
        pfd.revents = LWS_POLLIN;
120
253
 
121
254
        n = libwebsocket_service_fd(context, &pfd);
122
255
 
123
256
        if (n < 0)
124
 
                goto oom4;
 
257
                goto failed;
125
258
 
126
259
        if (n) /* returns 1 on failure after closing wsi */
127
260
                return NULL;
131
264
oom4:
132
265
        free(wsi->u.hdr.ah);
133
266
        free(wsi);
 
267
        return NULL;
134
268
 
 
269
failed:
 
270
        libwebsocket_close_and_free_session(context, wsi,
 
271
                                                     LWS_CLOSE_STATUS_NOSTATUS);
135
272
        return NULL;
136
273
}
137
274
 
166
303
                              int ietf_version_or_minus_one)
167
304
{
168
305
        struct libwebsocket *wsi;
169
 
        int n;
170
 
#ifndef LWS_NO_EXTENSIONS
171
 
        int m;
172
 
        struct libwebsocket_extension *ext;
173
 
        int handled;
174
 
#endif
175
 
 
176
 
#ifndef LWS_OPENSSL_SUPPORT
177
 
        if (ssl_connection) {
178
 
                lwsl_err("libwebsockets not configured for ssl\n");
179
 
                return NULL;
180
 
        }
181
 
#endif
182
306
 
183
307
        wsi = (struct libwebsocket *) malloc(sizeof(struct libwebsocket));
184
308
        if (wsi == NULL)
185
309
                goto bail;
186
310
 
187
311
        memset(wsi, 0, sizeof(*wsi));
 
312
        wsi->sock = -1;
188
313
 
189
314
        /* -1 means just use latest supported */
190
315
 
192
317
                ietf_version_or_minus_one = SPEC_LATEST_SUPPORTED;
193
318
 
194
319
        wsi->ietf_spec_revision = ietf_version_or_minus_one;
195
 
        wsi->u.hdr.name_buffer_pos = 0;
196
320
        wsi->user_space = NULL;
197
321
        wsi->state = WSI_STATE_CLIENT_UNCONNECTED;
198
322
        wsi->protocol = NULL;
199
323
        wsi->pending_timeout = NO_PENDING_TIMEOUT;
200
 
#ifndef LWS_NO_EXTENSIONS
201
 
        wsi->count_active_extensions = 0;
202
 
#endif
 
324
 
203
325
#ifdef LWS_OPENSSL_SUPPORT
204
326
        wsi->use_ssl = ssl_connection;
 
327
#else
 
328
        if (ssl_connection) {
 
329
                lwsl_err("libwebsockets not configured for ssl\n");
 
330
                goto bail;
 
331
        }
205
332
#endif
206
333
 
207
334
        if (lws_allocate_header_table(wsi))
211
338
         * we're not necessarily in a position to action these right away,
212
339
         * stash them... we only need during connect phase so u.hdr is fine
213
340
         */
214
 
        wsi->u.hdr.c_port = port;
 
341
        wsi->u.hdr.ah->c_port = port;
215
342
        if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
216
343
                goto bail1;
217
344
 
238
365
 
239
366
        wsi->protocol = &context->protocols[0];
240
367
 
241
 
#ifndef LWS_NO_EXTENSIONS
242
368
        /*
243
369
         * Check with each extension if it is able to route and proxy this
244
370
         * connection for us.  For example, an extension like x-google-mux
245
371
         * can handle this and then we don't need an actual socket for this
246
372
         * connection.
247
373
         */
248
 
 
249
 
        handled = 0;
250
 
        ext = context->extensions;
251
 
        n = 0;
252
 
 
253
 
        while (ext && ext->callback && !handled) {
254
 
                m = ext->callback(context, ext, wsi,
 
374
        
 
375
        if (lws_ext_callback_for_each_extension_type(context, wsi,
255
376
                        LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
256
 
                                 (void *)(long)n, (void *)address, port);
257
 
                if (m)
258
 
                        handled = 1;
259
 
 
260
 
                ext++;
261
 
                n++;
262
 
        }
263
 
 
264
 
        if (handled) {
 
377
                                                (void *)address, port) > 0) {
265
378
                lwsl_client("libwebsocket_client_connect: ext handling conn\n");
266
379
 
267
380
                libwebsocket_set_timeout(wsi,
271
384
                wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT;
272
385
                return wsi;
273
386
        }
274
 
#endif
275
387
        lwsl_client("libwebsocket_client_connect: direct conn\n");
276
388
 
277
 
        return __libwebsocket_client_connect_2(context, wsi);
 
389
       return libwebsocket_client_connect_2(context, wsi);
278
390
 
279
391
bail1:
280
392
        free(wsi->u.hdr.ah);
322
434
                        ssl_connection, path, host, origin, protocol,
323
435
                                                     ietf_version_or_minus_one);
324
436
 
325
 
        if (ws && !ws->user_space && userdata)
 
437
        if (ws && !ws->user_space && userdata) {
 
438
                ws->user_space_externally_allocated = 1;
326
439
                ws->user_space = userdata ;
 
440
        }
327
441
 
328
442
        return ws ;
329
443
}