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

« back to all changes in this revision

Viewing changes to lib/server.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:
22
22
 
23
23
#include "private-libwebsockets.h"
24
24
 
25
 
#ifdef WIN32
26
 
#include <tchar.h>
27
 
#include <io.h>
28
 
#else
29
 
#ifdef LWS_BUILTIN_GETIFADDRS
30
 
#include <getifaddrs.h>
31
 
#else
32
 
#include <ifaddrs.h>
33
 
#endif
34
 
#include <sys/un.h>
35
 
#include <sys/socket.h>
36
 
#include <netdb.h>
37
 
#endif
38
 
 
39
 
#ifdef LWS_OPENSSL_SUPPORT
40
 
 
41
 
static void
42
 
libwebsockets_decode_ssl_error(void)
 
25
int lws_context_init_server(struct lws_context_creation_info *info,
 
26
                            struct libwebsocket_context *context)
43
27
{
44
 
        char buf[256];
45
 
        u_long err;
46
 
 
47
 
        while ((err = ERR_get_error()) != 0) {
48
 
                ERR_error_string_n(err, buf, sizeof(buf));
49
 
                lwsl_err("*** %s\n", buf);
50
 
        }
 
28
        int n;
 
29
        int sockfd;
 
30
        struct sockaddr_in sin;
 
31
        socklen_t len = sizeof(sin);
 
32
        int opt = 1;
 
33
        struct libwebsocket *wsi;
 
34
#ifdef LWS_USE_IPV6
 
35
        struct sockaddr_in6 serv_addr6;
 
36
#endif
 
37
        struct sockaddr_in serv_addr4;
 
38
        struct sockaddr *v;
 
39
 
 
40
        /* set up our external listening socket we serve on */
 
41
 
 
42
        if (info->port == CONTEXT_PORT_NO_LISTEN)
 
43
                return 0;
 
44
 
 
45
#ifdef LWS_USE_IPV6
 
46
        if (LWS_IPV6_ENABLED(context))
 
47
                sockfd = socket(AF_INET6, SOCK_STREAM, 0);
 
48
        else
 
49
#endif
 
50
                sockfd = socket(AF_INET, SOCK_STREAM, 0);
 
51
 
 
52
        if (sockfd < 0) {
 
53
                lwsl_err("ERROR opening socket\n");
 
54
                return 1;
 
55
        }
 
56
 
 
57
        /*
 
58
         * allow us to restart even if old sockets in TIME_WAIT
 
59
         */
 
60
        setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
 
61
                                      (const void *)&opt, sizeof(opt));
 
62
 
 
63
        lws_plat_set_socket_options(context, sockfd);
 
64
 
 
65
#ifdef LWS_USE_IPV6
 
66
        if (LWS_IPV6_ENABLED(context)) {
 
67
                v = (struct sockaddr *)&serv_addr6;
 
68
                n = sizeof(struct sockaddr_in6);
 
69
                bzero((char *) &serv_addr6, sizeof(serv_addr6));
 
70
                serv_addr6.sin6_addr = in6addr_any;
 
71
                serv_addr6.sin6_family = AF_INET6;
 
72
                serv_addr6.sin6_port = htons(info->port);
 
73
        } else
 
74
#endif
 
75
        {
 
76
                v = (struct sockaddr *)&serv_addr4;
 
77
                n = sizeof(serv_addr4);
 
78
                bzero((char *) &serv_addr4, sizeof(serv_addr4));
 
79
                serv_addr4.sin_addr.s_addr = INADDR_ANY;
 
80
                serv_addr4.sin_family = AF_INET;
 
81
 
 
82
                if (info->iface) {
 
83
                        if (interface_to_sa(context, info->iface,
 
84
                                   (struct sockaddr_in *)v, n) < 0) {
 
85
                                lwsl_err("Unable to find interface %s\n",
 
86
                                                        info->iface);
 
87
                                compatible_close(sockfd);
 
88
                                return 1;
 
89
                        }
 
90
                }
 
91
 
 
92
                serv_addr4.sin_port = htons(info->port);
 
93
        } /* ipv4 */
 
94
 
 
95
        n = bind(sockfd, v, n);
 
96
        if (n < 0) {
 
97
                lwsl_err("ERROR on binding to port %d (%d %d)\n",
 
98
                                              info->port, n, LWS_ERRNO);
 
99
                compatible_close(sockfd);
 
100
                return 1;
 
101
        }
 
102
        
 
103
        if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1)
 
104
                lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
 
105
        else
 
106
                info->port = ntohs(sin.sin_port);
 
107
 
 
108
        context->listen_port = info->port;
 
109
 
 
110
        wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
 
111
        if (wsi == NULL) {
 
112
                lwsl_err("Out of mem\n");
 
113
                compatible_close(sockfd);
 
114
                return 1;
 
115
        }
 
116
        memset(wsi, 0, sizeof(struct libwebsocket));
 
117
        wsi->sock = sockfd;
 
118
        wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
 
119
 
 
120
        insert_wsi_socket_into_fds(context, wsi);
 
121
 
 
122
        context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
 
123
        context->listen_service_count = 0;
 
124
        context->listen_service_fd = sockfd;
 
125
 
 
126
        listen(sockfd, LWS_SOMAXCONN);
 
127
        lwsl_notice(" Listening on port %d\n", info->port);
 
128
        
 
129
        return 0;
51
130
}
52
 
#endif
53
131
 
54
132
int
55
 
interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen)
 
133
_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
56
134
{
57
 
        int rc = -1;
58
 
#ifdef WIN32
59
 
        /* TODO */
60
 
#else
61
 
        struct ifaddrs *ifr;
62
 
        struct ifaddrs *ifc;
63
 
        struct sockaddr_in *sin;
64
 
 
65
 
        getifaddrs(&ifr);
66
 
        for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) {
67
 
                if (strcmp(ifc->ifa_name, ifname))
68
 
                        continue;
69
 
                if (ifc->ifa_addr == NULL)
70
 
                        continue;
71
 
                sin = (struct sockaddr_in *)ifc->ifa_addr;
72
 
                if (sin->sin_family != AF_INET)
73
 
                        continue;
74
 
                memcpy(addr, sin, addrlen);
75
 
                rc = 0;
 
135
        struct libwebsocket_context *context = wsi->protocol->owning_server;
 
136
 
 
137
        /* there is no pending change */
 
138
        if (!(wsi->u.ws.rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
 
139
                return 0;
 
140
 
 
141
        /* stuff is still buffered, not ready to really accept new input */
 
142
        if (wsi->u.ws.rxflow_buffer) {
 
143
                /* get ourselves called back to deal with stashed buffer */
 
144
                libwebsocket_callback_on_writable(context, wsi);
 
145
                return 0;
76
146
        }
77
147
 
78
 
        freeifaddrs(ifr);
79
 
#endif
80
 
        return rc;
 
148
        /* pending is cleared, we can change rxflow state */
 
149
 
 
150
        wsi->u.ws.rxflow_change_to &= ~LWS_RXFLOW_PENDING_CHANGE;
 
151
 
 
152
        lwsl_info("rxflow: wsi %p change_to %d\n", wsi,
 
153
                              wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW);
 
154
 
 
155
        /* adjust the pollfd for this wsi */
 
156
 
 
157
        if (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW) {
 
158
                if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
 
159
                        lwsl_info("%s: fail\n", __func__);
 
160
                        return -1;
 
161
                }
 
162
        } else
 
163
                if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
 
164
                        return -1;
 
165
 
 
166
        return 0;
 
167
}
 
168
 
 
169
 
 
170
int lws_handshake_server(struct libwebsocket_context *context,
 
171
                struct libwebsocket *wsi, unsigned char **buf, size_t len)
 
172
{
 
173
        struct allocated_headers *ah;
 
174
        char *uri_ptr = NULL;
 
175
        int uri_len = 0;
 
176
        char content_length_str[32];
 
177
        int n;
 
178
 
 
179
        /* LWS_CONNMODE_WS_SERVING */
 
180
 
 
181
        while (len--) {
 
182
                if (libwebsocket_parse(context, wsi, *(*buf)++)) {
 
183
                        lwsl_info("libwebsocket_parse failed\n");
 
184
                        goto bail_nuke_ah;
 
185
                }
 
186
 
 
187
                if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
 
188
                        continue;
 
189
 
 
190
                lwsl_parser("libwebsocket_parse sees parsing complete\n");
 
191
 
 
192
                wsi->mode = LWS_CONNMODE_PRE_WS_SERVING_ACCEPT;
 
193
                libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
 
194
 
 
195
                /* is this websocket protocol or normal http 1.0? */
 
196
 
 
197
                if (!lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE) ||
 
198
                             !lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
 
199
 
 
200
                        /* it's not websocket.... shall we accept it as http? */
 
201
 
 
202
                        if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
 
203
                                !lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) &&
 
204
                                !lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
 
205
                                lwsl_warn("Missing URI in HTTP request\n");
 
206
                                goto bail_nuke_ah;
 
207
                        }
 
208
 
 
209
                        if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
 
210
                                lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
 
211
                                lwsl_warn("GET and POST methods?\n");
 
212
                                goto bail_nuke_ah;
 
213
                        }
 
214
 
 
215
                        if (libwebsocket_ensure_user_space(wsi))
 
216
                                goto bail_nuke_ah;
 
217
 
 
218
                        if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) {
 
219
                                uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
 
220
                                uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
 
221
                                lwsl_info("HTTP GET request for '%s'\n",
 
222
                                    lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI));
 
223
 
 
224
                        }
 
225
                        if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
 
226
                                lwsl_info("HTTP POST request for '%s'\n",
 
227
                                   lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI));
 
228
                                uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI);
 
229
                                uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI);
 
230
                        }
 
231
                        if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
 
232
                                lwsl_info("HTTP OPTIONS request for '%s'\n",
 
233
                                   lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI));
 
234
                                uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI);
 
235
                                uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI);
 
236
                        }
 
237
 
 
238
                        /*
 
239
                         * Hm we still need the headers so the
 
240
                         * callback can look at leaders like the URI, but we
 
241
                         * need to transition to http union state.... hold a
 
242
                         * copy of u.hdr.ah and deallocate afterwards
 
243
                         */
 
244
                        ah = wsi->u.hdr.ah;
 
245
 
 
246
                        /* union transition */
 
247
                        memset(&wsi->u, 0, sizeof(wsi->u));
 
248
                        wsi->mode = LWS_CONNMODE_HTTP_SERVING_ACCEPTED;
 
249
                        wsi->state = WSI_STATE_HTTP;
 
250
                        wsi->u.http.fd = LWS_INVALID_FILE;
 
251
 
 
252
                        /* expose it at the same offset as u.hdr */
 
253
                        wsi->u.http.ah = ah;
 
254
 
 
255
                        /* HTTP header had a content length? */
 
256
 
 
257
                        wsi->u.http.content_length = 0;
 
258
                        if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
 
259
                                wsi->u.http.content_length = 100 * 1024 * 1024;
 
260
 
 
261
                        if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
 
262
                                lws_hdr_copy(wsi, content_length_str,
 
263
                                                sizeof(content_length_str) - 1,
 
264
                                                                WSI_TOKEN_HTTP_CONTENT_LENGTH);
 
265
                                wsi->u.http.content_length = atoi(content_length_str);
 
266
                        }
 
267
 
 
268
                        if (wsi->u.http.content_length > 0) {
 
269
                                wsi->u.http.body_index = 0;
 
270
                                n = wsi->protocol->rx_buffer_size;
 
271
                                if (!n)
 
272
                                        n = LWS_MAX_SOCKET_IO_BUF;
 
273
                                wsi->u.http.post_buffer = malloc(n);
 
274
                                if (!wsi->u.http.post_buffer) {
 
275
                                        lwsl_err("Unable to allocate post buffer\n");
 
276
                                        n = -1;
 
277
                                        goto cleanup;
 
278
                                }
 
279
                        }
 
280
 
 
281
                        n = 0;
 
282
                        if (wsi->protocol->callback)
 
283
                                n = wsi->protocol->callback(context, wsi,
 
284
                                        LWS_CALLBACK_FILTER_HTTP_CONNECTION,
 
285
                                             wsi->user_space, uri_ptr, uri_len);
 
286
 
 
287
                        if (!n) {
 
288
                                /*
 
289
                                 * if there is content supposed to be coming,
 
290
                                 * put a timeout on it having arrived
 
291
                                 */
 
292
                                libwebsocket_set_timeout(wsi,
 
293
                                        PENDING_TIMEOUT_HTTP_CONTENT,
 
294
                                                              AWAITING_TIMEOUT);
 
295
 
 
296
                                if (wsi->protocol->callback)
 
297
                                        n = wsi->protocol->callback(context, wsi,
 
298
                                            LWS_CALLBACK_HTTP,
 
299
                                            wsi->user_space, uri_ptr, uri_len);
 
300
                        }
 
301
 
 
302
cleanup:
 
303
                        /* now drop the header info we kept a pointer to */
 
304
                        if (ah)
 
305
                                free(ah);
 
306
                        /* not possible to continue to use past here */
 
307
                        wsi->u.http.ah = NULL;
 
308
 
 
309
                        if (n) {
 
310
                                lwsl_info("LWS_CALLBACK_HTTP closing\n");
 
311
                                return 1; /* struct ah ptr already nuked */
 
312
                        }
 
313
 
 
314
                        /*
 
315
                         * (if callback didn't start sending a file)
 
316
                         * deal with anything else as body, whether
 
317
                         * there was a content-length or not
 
318
                         */
 
319
 
 
320
                        if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE)
 
321
                                wsi->state = WSI_STATE_HTTP_BODY;
 
322
                        return 2; /* goto http_postbody; */
 
323
                }
 
324
 
 
325
                if (!wsi->protocol)
 
326
                        lwsl_err("NULL protocol at libwebsocket_read\n");
 
327
 
 
328
                /*
 
329
                 * It's websocket
 
330
                 *
 
331
                 * Make sure user side is happy about protocol
 
332
                 */
 
333
 
 
334
                while (wsi->protocol->callback) {
 
335
 
 
336
                        if (!lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL)) {
 
337
                                if (wsi->protocol->name == NULL)
 
338
                                        break;
 
339
                        } else
 
340
                                if (wsi->protocol->name && strcmp(
 
341
                                        lws_hdr_simple_ptr(wsi,
 
342
                                                WSI_TOKEN_PROTOCOL),
 
343
                                                      wsi->protocol->name) == 0)
 
344
                                        break;
 
345
 
 
346
                        wsi->protocol++;
 
347
                }
 
348
 
 
349
                /* we didn't find a protocol he wanted? */
 
350
 
 
351
                if (wsi->protocol->callback == NULL) {
 
352
                        if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL) ==
 
353
                                                                         NULL) {
 
354
                                lwsl_info("no protocol -> prot 0 handler\n");
 
355
                                wsi->protocol = &context->protocols[0];
 
356
                        } else {
 
357
                                lwsl_err("Req protocol %s not supported\n",
 
358
                                   lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL));
 
359
                                goto bail_nuke_ah;
 
360
                        }
 
361
                }
 
362
 
 
363
                /* allocate wsi->user storage */
 
364
                if (libwebsocket_ensure_user_space(wsi))
 
365
                        goto bail_nuke_ah;
 
366
 
 
367
                /*
 
368
                 * Give the user code a chance to study the request and
 
369
                 * have the opportunity to deny it
 
370
                 */
 
371
 
 
372
                if ((wsi->protocol->callback)(wsi->protocol->owning_server, wsi,
 
373
                                LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
 
374
                                wsi->user_space,
 
375
                              lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
 
376
                        lwsl_warn("User code denied connection\n");
 
377
                        goto bail_nuke_ah;
 
378
                }
 
379
 
 
380
 
 
381
                /*
 
382
                 * Perform the handshake according to the protocol version the
 
383
                 * client announced
 
384
                 */
 
385
 
 
386
                switch (wsi->ietf_spec_revision) {
 
387
                case 13:
 
388
                        lwsl_parser("lws_parse calling handshake_04\n");
 
389
                        if (handshake_0405(context, wsi)) {
 
390
                                lwsl_info("hs0405 has failed the connection\n");
 
391
                                goto bail_nuke_ah;
 
392
                        }
 
393
                        break;
 
394
 
 
395
                default:
 
396
                        lwsl_warn("Unknown client spec version %d\n",
 
397
                                                       wsi->ietf_spec_revision);
 
398
                        goto bail_nuke_ah;
 
399
                }
 
400
 
 
401
                /* drop the header info -- no bail_nuke_ah after this */
 
402
 
 
403
                if (wsi->u.hdr.ah)
 
404
                        free(wsi->u.hdr.ah);
 
405
 
 
406
                wsi->mode = LWS_CONNMODE_WS_SERVING;
 
407
 
 
408
                /* union transition */
 
409
                memset(&wsi->u, 0, sizeof(wsi->u));
 
410
                wsi->u.ws.rxflow_change_to = LWS_RXFLOW_ALLOW;
 
411
 
 
412
                /*
 
413
                 * create the frame buffer for this connection according to the
 
414
                 * size mentioned in the protocol definition.  If 0 there, use
 
415
                 * a big default for compatibility
 
416
                 */
 
417
 
 
418
                n = wsi->protocol->rx_buffer_size;
 
419
                if (!n)
 
420
                        n = LWS_MAX_SOCKET_IO_BUF;
 
421
                n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
 
422
                wsi->u.ws.rx_user_buffer = malloc(n);
 
423
                if (!wsi->u.ws.rx_user_buffer) {
 
424
                        lwsl_err("Out of Mem allocating rx buffer %d\n", n);
 
425
                        return 1;
 
426
                }
 
427
                lwsl_info("Allocating RX buffer %d\n", n);
 
428
 
 
429
                if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
 
430
                        lwsl_warn("Failed to set SNDBUF to %d", n);
 
431
                        return 1;
 
432
                }
 
433
 
 
434
                lwsl_parser("accepted v%02d connection\n",
 
435
                                                       wsi->ietf_spec_revision);
 
436
        } /* while all chars are handled */
 
437
 
 
438
        return 0;
 
439
 
 
440
bail_nuke_ah:
 
441
        /* drop the header info */
 
442
        if (wsi->u.hdr.ah)
 
443
                free(wsi->u.hdr.ah);
 
444
        return 1;
81
445
}
82
446
 
83
447
struct libwebsocket *
92
456
        }
93
457
 
94
458
        memset(new_wsi, 0, sizeof(struct libwebsocket));
95
 
#ifndef LWS_NO_EXTENSIONS
96
 
        new_wsi->count_active_extensions = 0;
97
 
#endif
98
459
        new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
99
460
 
100
461
        /* intialize the instance struct */
101
462
 
102
463
        new_wsi->state = WSI_STATE_HTTP;
103
 
        new_wsi->u.hdr.name_buffer_pos = 0;
104
464
        new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
105
465
        new_wsi->hdr_parsing_completed = 0;
106
466
 
119
479
        new_wsi->user_space = NULL;
120
480
        new_wsi->ietf_spec_revision = 0;
121
481
 
 
482
        /*
 
483
         * outermost create notification for wsi
 
484
         * no user_space because no protocol selection
 
485
         */
 
486
        context->protocols[0].callback(context, new_wsi,
 
487
                        LWS_CALLBACK_WSI_CREATE, NULL, NULL, 0);
 
488
 
122
489
        return new_wsi;
123
490
}
124
491
 
125
492
int lws_server_socket_service(struct libwebsocket_context *context,
126
 
                        struct libwebsocket *wsi, struct pollfd *pollfd)
 
493
                        struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
127
494
{
128
 
        struct libwebsocket *new_wsi;
129
 
        int accept_fd;
130
 
        unsigned int clilen;
 
495
        struct libwebsocket *new_wsi = NULL;
 
496
        int accept_fd = 0;
 
497
        socklen_t clilen;
131
498
        struct sockaddr_in cli_addr;
132
499
        int n;
133
 
        ssize_t len;
134
 
#ifdef LWS_OPENSSL_SUPPORT
135
 
        int m;
136
 
#ifndef USE_CYASSL
137
 
        BIO *bio;
138
 
#endif
139
 
#endif
 
500
        int len;
140
501
 
141
502
        switch (wsi->mode) {
142
503
 
143
504
        case LWS_CONNMODE_HTTP_SERVING:
 
505
        case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
144
506
 
145
507
                /* handle http headers coming in */
146
508
 
 
509
                /* pending truncated sends have uber priority */
 
510
 
 
511
                if (wsi->truncated_send_malloc) {
 
512
                        if (pollfd->revents & LWS_POLLOUT)
 
513
                                if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
 
514
                                        wsi->truncated_send_offset,
 
515
                                                        wsi->truncated_send_len) < 0) {
 
516
                                        lwsl_info("closing from socket service\n");
 
517
                                        return -1;
 
518
                                }
 
519
                        /*
 
520
                         * we can't afford to allow input processing send
 
521
                         * something new, so spin around he event loop until
 
522
                         * he doesn't have any partials
 
523
                         */
 
524
                        break;
 
525
                }
 
526
 
147
527
                /* any incoming data ready? */
148
528
 
149
 
                if (pollfd->revents & POLLIN) {
150
 
 
151
 
        #ifdef LWS_OPENSSL_SUPPORT
152
 
                        if (wsi->ssl)
153
 
                                len = SSL_read(wsi->ssl,
154
 
                                        context->service_buffer,
155
 
                                               sizeof(context->service_buffer));
156
 
                        else
157
 
        #endif
158
 
                                len = recv(pollfd->fd,
159
 
                                        context->service_buffer,
160
 
                                        sizeof(context->service_buffer), 0);
161
 
 
162
 
                        if (len < 0) {
163
 
                                lwsl_debug("Socket read returned %d\n", len);
164
 
                                if (errno != EINTR && errno != EAGAIN)
165
 
                                        libwebsocket_close_and_free_session(
166
 
                                                context, wsi,
167
 
                                                LWS_CLOSE_STATUS_NOSTATUS);
168
 
                                return 0;
169
 
                        }
170
 
                        if (!len) {
 
529
                if (pollfd->revents & LWS_POLLIN) {
 
530
                        len = lws_ssl_capable_read(wsi,
 
531
                                        context->service_buffer,
 
532
                                                       sizeof(context->service_buffer));
 
533
                        switch (len) {
 
534
                        case 0:
171
535
                                lwsl_info("lws_server_skt_srv: read 0 len\n");
172
536
                                /* lwsl_info("   state=%d\n", wsi->state); */
173
537
                                if (!wsi->hdr_parsing_completed)
174
538
                                        free(wsi->u.hdr.ah);
 
539
                                /* fallthru */
 
540
                        case LWS_SSL_CAPABLE_ERROR:
175
541
                                libwebsocket_close_and_free_session(
176
 
                                       context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
177
 
                                return 0;
178
 
                        }
179
 
 
180
 
                        n = libwebsocket_read(context, wsi,
181
 
                                                context->service_buffer, len);
182
 
                        if (n < 0)
183
 
                                /* we closed wsi */
184
 
                                return 0;
 
542
                                                context, wsi,
 
543
                                                LWS_CLOSE_STATUS_NOSTATUS);
 
544
                                return 0;
 
545
                        case LWS_SSL_CAPABLE_MORE_SERVICE:
 
546
                                break;
 
547
                        }
 
548
 
 
549
                        /* just ignore incoming if waiting for close */
 
550
                        if (wsi->state != WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
 
551
                        
 
552
                                /* hm this may want to send (via HTTP callback for example) */
 
553
 
 
554
                                n = libwebsocket_read(context, wsi,
 
555
                                                        context->service_buffer, len);
 
556
                                if (n < 0)
 
557
                                        /* we closed wsi */
 
558
                                        return 0;
 
559
 
 
560
                                /* hum he may have used up the writability above */
 
561
                                break;
 
562
                        }
185
563
                }
186
564
 
187
565
                /* this handles POLLOUT for http serving fragments */
188
566
 
189
 
                if (!(pollfd->revents & POLLOUT))
 
567
                if (!(pollfd->revents & LWS_POLLOUT))
190
568
                        break;
191
569
 
192
570
                /* one shot */
193
 
                pollfd->events &= ~POLLOUT;
 
571
                if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
 
572
                        goto fail;
 
573
                
 
574
                lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
194
575
 
195
 
                if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE)
 
576
                if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
 
577
                        n = user_callback_handle_rxflow(
 
578
                                        wsi->protocol->callback,
 
579
                                        wsi->protocol->owning_server,
 
580
                                        wsi, LWS_CALLBACK_HTTP_WRITEABLE,
 
581
                                        wsi->user_space,
 
582
                                        NULL,
 
583
                                        0);
 
584
                        if (n < 0)
 
585
                                libwebsocket_close_and_free_session(
 
586
                                       context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
196
587
                        break;
 
588
                }
197
589
 
198
590
                /* nonzero for completion or error */
199
591
                if (libwebsockets_serve_http_file_fragment(context, wsi))
205
597
 
206
598
                /* pollin means a client has connected to us then */
207
599
 
208
 
                if (!(pollfd->revents & POLLIN))
 
600
                if (!(pollfd->revents & LWS_POLLIN))
209
601
                        break;
210
602
 
211
603
                /* listen socket got an unencrypted connection... */
218
610
                        "unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
219
611
                                                     accept_fd, accept_fd >= 0);
220
612
                if (accept_fd < 0) {
221
 
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
 
613
                        if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK) {
222
614
                                lwsl_debug("accept asks to try again\n");
223
615
                                break;
224
616
                        }
225
 
                        lwsl_warn("ERROR on accept: %s\n", strerror(errno));
 
617
                        lwsl_warn("ERROR on accept: %s\n", strerror(LWS_ERRNO));
226
618
                        break;
227
619
                }
228
620
 
229
 
                lws_set_socket_options(context, accept_fd);
 
621
                lws_plat_set_socket_options(context, accept_fd);
230
622
 
231
623
                /*
232
624
                 * look at who we connected to and give user code a chance
236
628
 
237
629
                if ((context->protocols[0].callback)(context, wsi,
238
630
                                LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
239
 
                                           (void *)(long)accept_fd, NULL, 0)) {
 
631
                                           NULL, (void *)(long)accept_fd, 0)) {
240
632
                        lwsl_debug("Callback denied network connection\n");
241
633
                        compatible_close(accept_fd);
242
634
                        break;
250
642
 
251
643
                new_wsi->sock = accept_fd;
252
644
 
253
 
#ifdef LWS_OPENSSL_SUPPORT
254
 
                new_wsi->ssl = NULL;
255
 
                if (!context->use_ssl) {
256
 
#endif
257
 
 
 
645
                /* the transport is accepted... give him time to negotiate */
 
646
                libwebsocket_set_timeout(new_wsi,
 
647
                        PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
 
648
                                                        AWAITING_TIMEOUT);
 
649
 
 
650
                /*
 
651
                 * A new connection was accepted. Give the user a chance to
 
652
                 * set properties of the newly created wsi. There's no protocol
 
653
                 * selected yet so we issue this to protocols[0]
 
654
                 */
 
655
 
 
656
                (context->protocols[0].callback)(context, new_wsi,
 
657
                        LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0);
 
658
 
 
659
                lws_libev_accept(context, new_wsi, accept_fd);
 
660
 
 
661
                if (!LWS_SSL_ENABLED(context)) {
258
662
                        lwsl_debug("accepted new conn  port %u on fd=%d\n",
259
663
                                          ntohs(cli_addr.sin_port), accept_fd);
260
664
 
261
665
                        insert_wsi_socket_into_fds(context, new_wsi);
262
 
                        break;
263
 
#ifdef LWS_OPENSSL_SUPPORT
264
 
                }
265
 
 
266
 
                new_wsi->ssl = SSL_new(context->ssl_ctx);
267
 
                if (new_wsi->ssl == NULL) {
268
 
                        lwsl_err("SSL_new failed: %s\n",
269
 
                            ERR_error_string(SSL_get_error(
270
 
                            new_wsi->ssl, 0), NULL));
271
 
                            libwebsockets_decode_ssl_error();
272
 
                        free(new_wsi);
273
 
                        compatible_close(accept_fd);
274
 
                        break;
275
 
                }
276
 
 
277
 
                SSL_set_ex_data(new_wsi->ssl,
278
 
                        openssl_websocket_private_data_index, context);
279
 
 
280
 
                SSL_set_fd(new_wsi->ssl, accept_fd);
281
 
 
282
 
                #ifdef USE_CYASSL
283
 
                CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
284
 
                #else
285
 
                bio = SSL_get_rbio(new_wsi->ssl);
286
 
                if (bio)
287
 
                        BIO_set_nbio(bio, 1); /* nonblocking */
288
 
                else
289
 
                        lwsl_notice("NULL rbio\n");
290
 
                bio = SSL_get_wbio(new_wsi->ssl);
291
 
                if (bio)
292
 
                        BIO_set_nbio(bio, 1); /* nonblocking */
293
 
                else
294
 
                        lwsl_notice("NULL rbio\n");
295
 
                #endif
296
 
 
297
 
                /*
298
 
                 * we are not accepted yet, but we need to enter ourselves
299
 
                 * as a live connection.  That way we can retry when more
300
 
                 * pieces come if we're not sorted yet
301
 
                 */
302
 
 
303
 
                wsi = new_wsi;
304
 
                wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
305
 
                insert_wsi_socket_into_fds(context, wsi);
306
 
 
307
 
                libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
308
 
                                                        AWAITING_TIMEOUT);
309
 
 
310
 
                lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
311
 
 
312
 
                /* fallthru */
313
 
 
314
 
        case LWS_CONNMODE_SSL_ACK_PENDING:
315
 
 
316
 
                pollfd->events &= ~POLLOUT;
317
 
 
318
 
                /* external POLL support via protocol 0 */
319
 
                context->protocols[0].callback(context, wsi,
320
 
                        LWS_CALLBACK_CLEAR_MODE_POLL_FD,
321
 
                        (void *)(long)wsi->sock, NULL, POLLOUT);
322
 
 
323
 
                lws_latency_pre(context, wsi);
324
 
                n = SSL_accept(wsi->ssl);
325
 
                lws_latency(context, wsi,
326
 
                        "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
327
 
 
328
 
                if (n != 1) {
329
 
                        m = SSL_get_error(wsi->ssl, n);
330
 
                        lwsl_debug("SSL_accept failed %d / %s\n",
331
 
                                                  m, ERR_error_string(m, NULL));
332
 
 
333
 
                        if (m == SSL_ERROR_WANT_READ) {
334
 
                                context->fds[
335
 
                                   wsi->position_in_fds_table].events |= POLLIN;
336
 
 
337
 
                                /* external POLL support via protocol 0 */
338
 
                                context->protocols[0].callback(context, wsi,
339
 
                                        LWS_CALLBACK_SET_MODE_POLL_FD,
340
 
                                        (void *)(long)wsi->sock, NULL, POLLIN);
341
 
                                lwsl_info("SSL_ERROR_WANT_READ\n");
342
 
                                break;
343
 
                        }
344
 
                        if (m == SSL_ERROR_WANT_WRITE) {
345
 
                                context->fds[
346
 
                                  wsi->position_in_fds_table].events |= POLLOUT;
347
 
 
348
 
                                /* external POLL support via protocol 0 */
349
 
                                context->protocols[0].callback(context, wsi,
350
 
                                        LWS_CALLBACK_SET_MODE_POLL_FD,
351
 
                                        (void *)(long)wsi->sock, NULL, POLLOUT);
352
 
                                break;
353
 
                        }
354
 
                        lwsl_debug("SSL_accept failed skt %u: %s\n",
355
 
                              pollfd->fd,
356
 
                              ERR_error_string(m, NULL));
357
 
                        libwebsocket_close_and_free_session(context, wsi,
358
 
                                                     LWS_CLOSE_STATUS_NOSTATUS);
359
 
                        break;
360
 
                }
361
 
 
362
 
                /* OK, we are accepted */
363
 
 
364
 
                libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
365
 
 
366
 
                wsi->mode = LWS_CONNMODE_HTTP_SERVING;
367
 
 
368
 
                lwsl_debug("accepted new SSL conn\n");
 
666
                }
369
667
                break;
370
 
#endif
371
668
 
372
669
        default:
373
670
                break;
374
671
        }
375
 
        return 0;
376
 
}
377
 
 
 
672
 
 
673
        if (lws_server_socket_service_ssl(context, &wsi, new_wsi, accept_fd, pollfd))
 
674
                goto fail;
 
675
 
 
676
        return 0;
 
677
        
 
678
fail:
 
679
        libwebsocket_close_and_free_session(context, wsi,
 
680
                                                 LWS_CLOSE_STATUS_NOSTATUS);
 
681
        return 1;
 
682
}
 
683
 
 
684
 
 
685
static const char *err400[] = {
 
686
        "Bad Request",
 
687
        "Unauthorized",
 
688
        "Payment Required",
 
689
        "Forbidden",
 
690
        "Not Found",
 
691
        "Method Not Allowed",
 
692
        "Not Acceptable",
 
693
        "Proxy Auth Required",
 
694
        "Request Timeout",
 
695
        "Conflict",
 
696
        "Gone",
 
697
        "Length Required",
 
698
        "Precondition Failed",
 
699
        "Request Entity Too Large",
 
700
        "Request URI too Long",
 
701
        "Unsupported Media Type",
 
702
        "Requested Range Not Satisfiable",
 
703
        "Expectation Failed"
 
704
};
 
705
 
 
706
static const char *err500[] = {
 
707
        "Internal Server Error",
 
708
        "Not Implemented",
 
709
        "Bad Gateway",
 
710
        "Service Unavailable",
 
711
        "Gateway Timeout",
 
712
        "HTTP Version Not Supported"
 
713
};
 
714
 
 
715
/**
 
716
 * libwebsockets_return_http_status() - Return simple http status
 
717
 * @context:            libwebsockets context
 
718
 * @wsi:                Websocket instance (available from user callback)
 
719
 * @code:               Status index, eg, 404
 
720
 * @html_body:          User-readable HTML description, or NULL
 
721
 *
 
722
 *      Helper to report HTTP errors back to the client cleanly and
 
723
 *      consistently
 
724
 */
 
725
LWS_VISIBLE int libwebsockets_return_http_status(
 
726
                struct libwebsocket_context *context, struct libwebsocket *wsi,
 
727
                                       unsigned int code, const char *html_body)
 
728
{
 
729
        int n, m;
 
730
        const char *description = "";
 
731
 
 
732
        if (!html_body)
 
733
                html_body = "";
 
734
 
 
735
        if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
 
736
                description = err400[code - 400];
 
737
        if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
 
738
                description = err500[code - 500];
 
739
 
 
740
        n = sprintf((char *)context->service_buffer,
 
741
                "HTTP/1.0 %u %s\x0d\x0a"
 
742
                "Server: libwebsockets\x0d\x0a"
 
743
                "Content-Type: text/html\x0d\x0a\x0d\x0a"
 
744
                "<h1>%u %s</h1>%s",
 
745
                code, description, code, description, html_body);
 
746
 
 
747
        lwsl_info((const char *)context->service_buffer);
 
748
 
 
749
        m = libwebsocket_write(wsi, context->service_buffer, n, LWS_WRITE_HTTP);
 
750
 
 
751
        return m;
 
752
}
 
753
 
 
754
/**
 
755
 * libwebsockets_serve_http_file() - Send a file back to the client using http
 
756
 * @context:            libwebsockets context
 
757
 * @wsi:                Websocket instance (available from user callback)
 
758
 * @file:               The file to issue over http
 
759
 * @content_type:       The http content type, eg, text/html
 
760
 * @other_headers:      NULL or pointer to \0-terminated other header string
 
761
 *
 
762
 *      This function is intended to be called from the callback in response
 
763
 *      to http requests from the client.  It allows the callback to issue
 
764
 *      local files down the http link in a single step.
 
765
 *
 
766
 *      Returning <0 indicates error and the wsi should be closed.  Returning
 
767
 *      >0 indicates the file was completely sent and the wsi should be closed.
 
768
 *      ==0 indicates the file transfer is started and needs more service later,
 
769
 *      the wsi should be left alone.
 
770
 */
 
771
 
 
772
LWS_VISIBLE int libwebsockets_serve_http_file(
 
773
                struct libwebsocket_context *context,
 
774
                        struct libwebsocket *wsi, const char *file,
 
775
                           const char *content_type, const char *other_headers)
 
776
{
 
777
        unsigned char *p = context->service_buffer;
 
778
        int ret = 0;
 
779
        int n;
 
780
 
 
781
        wsi->u.http.fd = lws_plat_open_file(file, &wsi->u.http.filelen);
 
782
 
 
783
        if (wsi->u.http.fd == LWS_INVALID_FILE) {
 
784
                lwsl_err("Unable to open '%s'\n", file);
 
785
                libwebsockets_return_http_status(context, wsi,
 
786
                                                HTTP_STATUS_NOT_FOUND, NULL);
 
787
                return -1;
 
788
        }
 
789
 
 
790
        p += sprintf((char *)p,
 
791
"HTTP/1.0 200 OK\x0d\x0aServer: libwebsockets\x0d\x0a""Content-Type: %s\x0d\x0a",
 
792
                                                                  content_type);
 
793
        if (other_headers) {
 
794
                n = strlen(other_headers);
 
795
                memcpy(p, other_headers, n);
 
796
                p += n;
 
797
        }
 
798
        p += sprintf((char *)p,
 
799
                "Content-Length: %lu\x0d\x0a\x0d\x0a", wsi->u.http.filelen);
 
800
 
 
801
        ret = libwebsocket_write(wsi, context->service_buffer,
 
802
                                   p - context->service_buffer, LWS_WRITE_HTTP);
 
803
        if (ret != (p - context->service_buffer)) {
 
804
                lwsl_err("_write returned %d from %d\n", ret, (p - context->service_buffer));
 
805
                return -1;
 
806
        }
 
807
 
 
808
        wsi->u.http.filepos = 0;
 
809
        wsi->state = WSI_STATE_HTTP_ISSUING_FILE;
 
810
 
 
811
        return libwebsockets_serve_http_file_fragment(context, wsi);
 
812
}
 
813
 
 
814
 
 
815
int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
 
816
                                                 unsigned char *buf, size_t len)
 
817
{
 
818
        size_t n = 0;
 
819
        int m;
 
820
 
 
821
#if 0
 
822
        lwsl_parser("received %d byte packet\n", (int)len);
 
823
        lwsl_hexdump(buf, len);
 
824
#endif
 
825
 
 
826
        /* let the rx protocol state machine have as much as it needs */
 
827
 
 
828
        while (n < len) {
 
829
                /*
 
830
                 * we were accepting input but now we stopped doing so
 
831
                 */
 
832
                if (!(wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW)) {
 
833
                        /* his RX is flowcontrolled, don't send remaining now */
 
834
                        if (!wsi->u.ws.rxflow_buffer) {
 
835
                                /* a new rxflow, buffer it and warn caller */
 
836
                                lwsl_info("new rxflow input buffer len %d\n",
 
837
                                                                       len - n);
 
838
                                wsi->u.ws.rxflow_buffer =
 
839
                                               (unsigned char *)malloc(len - n);
 
840
                                wsi->u.ws.rxflow_len = len - n;
 
841
                                wsi->u.ws.rxflow_pos = 0;
 
842
                                memcpy(wsi->u.ws.rxflow_buffer,
 
843
                                                        buf + n, len - n);
 
844
                        } else
 
845
                                /* rxflow while we were spilling prev rxflow */
 
846
                                lwsl_info("stalling in existing rxflow buf\n");
 
847
 
 
848
                        return 1;
 
849
                }
 
850
 
 
851
                /* account for what we're using in rxflow buffer */
 
852
                if (wsi->u.ws.rxflow_buffer)
 
853
                        wsi->u.ws.rxflow_pos++;
 
854
 
 
855
                /* process the byte */
 
856
                m = libwebsocket_rx_sm(wsi, buf[n++]);
 
857
                if (m < 0)
 
858
                        return -1;
 
859
        }
 
860
 
 
861
        return 0;
 
862
}
 
863
 
 
864
LWS_VISIBLE void
 
865
lws_server_get_canonical_hostname(struct libwebsocket_context *context,
 
866
                                struct lws_context_creation_info *info)
 
867
{
 
868
        if (info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)
 
869
                return;
 
870
 
 
871
        /* find canonical hostname */
 
872
        gethostname((char *)context->canonical_hostname,
 
873
                                       sizeof(context->canonical_hostname) - 1);
 
874
 
 
875
        lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);
 
876
}