add locking callback for fds
[platform/upstream/libwebsockets.git] / lib / server.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22
23 #include "private-libwebsockets.h"
24
25 #if defined(WIN32) || defined(_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)
43 {
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("*** %lu %s\n", err, buf);
50         }
51 }
52 #endif
53
54 int
55 interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen)
56 {
57         int rc = -1;
58 #if defined(WIN32) || defined(_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 && rc; ifc = ifc->ifa_next) {
67                 if (ifc->ifa_addr == NULL)
68                         continue;
69                 lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
70                 if (strcmp(ifc->ifa_name, ifname))
71                         continue;
72                 sin = (struct sockaddr_in *)ifc->ifa_addr;
73                 if (sin->sin_family != AF_INET)
74                         continue;
75                 memcpy(addr, sin, addrlen);
76                 rc = 0;
77         }
78
79         freeifaddrs(ifr);
80 #endif
81         return rc;
82 }
83
84 struct libwebsocket *
85 libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
86 {
87         struct libwebsocket *new_wsi;
88
89         new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
90         if (new_wsi == NULL) {
91                 lwsl_err("Out of memory for new connection\n");
92                 return NULL;
93         }
94
95         memset(new_wsi, 0, sizeof(struct libwebsocket));
96 #ifndef LWS_NO_EXTENSIONS
97         new_wsi->count_active_extensions = 0;
98 #endif
99         new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
100
101         /* intialize the instance struct */
102
103         new_wsi->state = WSI_STATE_HTTP;
104         new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
105         new_wsi->hdr_parsing_completed = 0;
106
107         if (lws_allocate_header_table(new_wsi)) {
108                 free(new_wsi);
109                 return NULL;
110         }
111
112         /*
113          * these can only be set once the protocol is known
114          * we set an unestablished connection's protocol pointer
115          * to the start of the supported list, so it can look
116          * for matching ones during the handshake
117          */
118         new_wsi->protocol = context->protocols;
119         new_wsi->user_space = NULL;
120         new_wsi->ietf_spec_revision = 0;
121
122         return new_wsi;
123 }
124
125 int lws_server_socket_service(struct libwebsocket_context *context,
126                         struct libwebsocket *wsi, struct pollfd *pollfd)
127 {
128         struct libwebsocket *new_wsi;
129         int accept_fd;
130         socklen_t clilen;
131         struct sockaddr_in cli_addr;
132         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
140
141         switch (wsi->mode) {
142
143         case LWS_CONNMODE_HTTP_SERVING:
144         case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
145
146                 /* handle http headers coming in */
147
148                 /* pending truncated sends have uber priority */
149
150                 if (wsi->truncated_send_malloc) {
151                         if (pollfd->revents & POLLOUT)
152                                 lws_issue_raw(wsi, wsi->truncated_send_malloc +
153                                         wsi->truncated_send_offset,
154                                                         wsi->truncated_send_len);
155                         /*
156                          * we can't afford to allow input processing send
157                          * something new, so spin around he event loop until
158                          * he doesn't have any partials
159                          */
160                         break;
161                 }
162
163                 /* any incoming data ready? */
164
165                 if (pollfd->revents & POLLIN) {
166
167         #ifdef LWS_OPENSSL_SUPPORT
168                         if (wsi->ssl)
169                                 len = SSL_read(wsi->ssl,
170                                         context->service_buffer,
171                                                sizeof(context->service_buffer));
172                         else
173         #endif
174                                 len = recv(pollfd->fd,
175                                         context->service_buffer,
176                                         sizeof(context->service_buffer), 0);
177
178                         if (len < 0) {
179                                 lwsl_debug("Socket read returned %d\n", len);
180                                 if (errno != EINTR && errno != EAGAIN)
181                                         libwebsocket_close_and_free_session(
182                                                 context, wsi,
183                                                 LWS_CLOSE_STATUS_NOSTATUS);
184                                 return 0;
185                         }
186                         if (!len) {
187                                 lwsl_info("lws_server_skt_srv: read 0 len\n");
188                                 /* lwsl_info("   state=%d\n", wsi->state); */
189                                 if (!wsi->hdr_parsing_completed)
190                                         free(wsi->u.hdr.ah);
191                                 libwebsocket_close_and_free_session(
192                                        context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
193                                 return 0;
194                         }
195
196                         /* hm this may want to send (via HTTP callback for example) */
197
198                         n = libwebsocket_read(context, wsi,
199                                                 context->service_buffer, len);
200                         if (n < 0)
201                                 /* we closed wsi */
202                                 return 0;
203
204                         /* hum he may have used up the writability above */
205
206                         break;
207                 }
208
209                 /* this handles POLLOUT for http serving fragments */
210
211                 if (!(pollfd->revents & POLLOUT))
212                         break;
213
214                 /* one shot */
215                 context->protocols[0].callback(context, wsi,
216                         LWS_CALLBACK_LOCK_POLL,
217                         wsi->user_space, (void *)(long)wsi->sock, 0);
218
219                 pollfd->events &= ~POLLOUT;
220
221                 /* external POLL support via protocol 0 */
222                 context->protocols[0].callback(context, wsi,
223                         LWS_CALLBACK_CLEAR_MODE_POLL_FD,
224                         wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
225
226                 context->protocols[0].callback(context, wsi,
227                         LWS_CALLBACK_UNLOCK_POLL,
228                         wsi->user_space, (void *)(long)wsi->sock, 0);
229
230
231                 if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
232                         n = user_callback_handle_rxflow(
233                                         wsi->protocol->callback,
234                                         wsi->protocol->owning_server,
235                                         wsi, LWS_CALLBACK_HTTP_WRITEABLE,
236                                         wsi->user_space,
237                                         NULL,
238                                         0);
239                         if (n < 0)
240                                 libwebsocket_close_and_free_session(
241                                        context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
242                         break;
243                 }
244
245                 /* nonzero for completion or error */
246                 if (libwebsockets_serve_http_file_fragment(context, wsi))
247                         libwebsocket_close_and_free_session(context, wsi,
248                                                LWS_CLOSE_STATUS_NOSTATUS);
249                 break;
250
251         case LWS_CONNMODE_SERVER_LISTENER:
252
253                 /* pollin means a client has connected to us then */
254
255                 if (!(pollfd->revents & POLLIN))
256                         break;
257
258                 /* listen socket got an unencrypted connection... */
259
260                 clilen = sizeof(cli_addr);
261                 lws_latency_pre(context, wsi);
262                 accept_fd  = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
263                                                                        &clilen);
264                 lws_latency(context, wsi,
265                         "unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
266                                                      accept_fd, accept_fd >= 0);
267                 if (accept_fd < 0) {
268                         if (errno == EAGAIN || errno == EWOULDBLOCK) {
269                                 lwsl_debug("accept asks to try again\n");
270                                 break;
271                         }
272                         lwsl_warn("ERROR on accept: %s\n", strerror(errno));
273                         break;
274                 }
275
276                 lws_set_socket_options(context, accept_fd);
277
278                 /*
279                  * look at who we connected to and give user code a chance
280                  * to reject based on client IP.  There's no protocol selected
281                  * yet so we issue this to protocols[0]
282                  */
283
284                 if ((context->protocols[0].callback)(context, wsi,
285                                 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
286                                            NULL, (void *)(long)accept_fd, 0)) {
287                         lwsl_debug("Callback denied network connection\n");
288                         compatible_close(accept_fd);
289                         break;
290                 }
291
292                 new_wsi = libwebsocket_create_new_server_wsi(context);
293                 if (new_wsi == NULL) {
294                         compatible_close(accept_fd);
295                         break;
296                 }
297
298                 new_wsi->sock = accept_fd;
299
300 #ifdef LWS_OPENSSL_SUPPORT
301                 new_wsi->ssl = NULL;
302                 if (!context->use_ssl) {
303 #endif
304
305                         lwsl_debug("accepted new conn  port %u on fd=%d\n",
306                                           ntohs(cli_addr.sin_port), accept_fd);
307
308                         insert_wsi_socket_into_fds(context, new_wsi);
309                         break;
310 #ifdef LWS_OPENSSL_SUPPORT
311                 }
312
313                 new_wsi->ssl = SSL_new(context->ssl_ctx);
314                 if (new_wsi->ssl == NULL) {
315                         lwsl_err("SSL_new failed: %s\n",
316                             ERR_error_string(SSL_get_error(
317                             new_wsi->ssl, 0), NULL));
318                             libwebsockets_decode_ssl_error();
319                         free(new_wsi);
320                         compatible_close(accept_fd);
321                         break;
322                 }
323
324                 SSL_set_ex_data(new_wsi->ssl,
325                         openssl_websocket_private_data_index, context);
326
327                 SSL_set_fd(new_wsi->ssl, accept_fd);
328
329                 #ifdef USE_CYASSL
330                 CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
331                 #else
332                 bio = SSL_get_rbio(new_wsi->ssl);
333                 if (bio)
334                         BIO_set_nbio(bio, 1); /* nonblocking */
335                 else
336                         lwsl_notice("NULL rbio\n");
337                 bio = SSL_get_wbio(new_wsi->ssl);
338                 if (bio)
339                         BIO_set_nbio(bio, 1); /* nonblocking */
340                 else
341                         lwsl_notice("NULL rbio\n");
342                 #endif
343
344                 /*
345                  * we are not accepted yet, but we need to enter ourselves
346                  * as a live connection.  That way we can retry when more
347                  * pieces come if we're not sorted yet
348                  */
349
350                 wsi = new_wsi;
351                 wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
352                 insert_wsi_socket_into_fds(context, wsi);
353
354                 libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
355                                                         AWAITING_TIMEOUT);
356
357                 lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
358
359                 /* fallthru */
360
361         case LWS_CONNMODE_SSL_ACK_PENDING:
362
363                 context->protocols[0].callback(context, wsi,
364                         LWS_CALLBACK_LOCK_POLL,
365                         wsi->user_space, (void *)(long)wsi->sock, 0);
366
367                 pollfd->events &= ~POLLOUT;
368
369                 /* external POLL support via protocol 0 */
370                 context->protocols[0].callback(context, wsi,
371                         LWS_CALLBACK_CLEAR_MODE_POLL_FD,
372                         wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
373
374                 context->protocols[0].callback(context, wsi,
375                         LWS_CALLBACK_UNLOCK_POLL,
376                         wsi->user_space, (void *)(long)wsi->sock, 0);
377
378                 lws_latency_pre(context, wsi);
379
380                 n = recv(wsi->sock, context->service_buffer,
381                         sizeof(context->service_buffer), MSG_PEEK);
382
383                 /*
384                  * optionally allow non-SSL connect on SSL listening socket
385                  * This is disabled by default, if enabled it goes around any
386                  * SSL-level access control (eg, client-side certs) so leave
387                  * it disabled unless you know it's not a problem for you
388                  */
389
390                 if (context->allow_non_ssl_on_ssl_port && n >= 1 &&
391                                         context->service_buffer[0] >= ' ') {
392                         /*
393                          * TLS content-type for Handshake is 0x16
394                          * TLS content-type for ChangeCipherSpec Record is 0x14
395                          *
396                          * A non-ssl session will start with the HTTP method in
397                          * ASCII.  If we see it's not a legit SSL handshake
398                          * kill the SSL for this connection and try to handle
399                          * as a HTTP connection upgrade directly.
400                          */
401                         wsi->use_ssl = 0;
402                         SSL_shutdown(wsi->ssl);
403                         SSL_free(wsi->ssl);
404                         wsi->ssl = NULL;
405                         goto accepted;
406                 }
407
408                 /* normal SSL connection processing path */
409
410                 n = SSL_accept(wsi->ssl);
411                 lws_latency(context, wsi,
412                         "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
413
414                 if (n != 1) {
415                         m = SSL_get_error(wsi->ssl, n);
416                         lwsl_debug("SSL_accept failed %d / %s\n",
417                                                   m, ERR_error_string(m, NULL));
418
419                         if (m == SSL_ERROR_WANT_READ) {
420                                 context->protocols[0].callback(context, wsi,
421                                         LWS_CALLBACK_LOCK_POLL,
422                                         wsi->user_space, (void *)(long)wsi->sock, 0);
423                                 context->fds[
424                                    wsi->position_in_fds_table].events |= POLLIN;
425
426                                 /* external POLL support via protocol 0 */
427                                 context->protocols[0].callback(context, wsi,
428                                         LWS_CALLBACK_SET_MODE_POLL_FD,
429                                         wsi->user_space,
430                                         (void *)(long)wsi->sock, POLLIN);
431                                 context->protocols[0].callback(context, wsi,
432                                         LWS_CALLBACK_UNLOCK_POLL,
433                                         wsi->user_space, (void *)(long)wsi->sock, 0);
434                                 lwsl_info("SSL_ERROR_WANT_READ\n");
435                                 break;
436                         }
437                         if (m == SSL_ERROR_WANT_WRITE) {
438                                 context->protocols[0].callback(context, wsi,
439                                         LWS_CALLBACK_LOCK_POLL,
440                                         wsi->user_space, (void *)(long)wsi->sock, 0);
441                                 context->fds[
442                                   wsi->position_in_fds_table].events |= POLLOUT;
443                                 /* external POLL support via protocol 0 */
444                                 context->protocols[0].callback(context, wsi,
445                                         LWS_CALLBACK_SET_MODE_POLL_FD,
446                                         wsi->user_space,
447                                         (void *)(long)wsi->sock, POLLOUT);
448                                 context->protocols[0].callback(context, wsi,
449                                         LWS_CALLBACK_UNLOCK_POLL,
450                                         wsi->user_space, (void *)(long)wsi->sock, 0);
451                                 break;
452                         }
453                         lwsl_debug("SSL_accept failed skt %u: %s\n",
454                                   pollfd->fd,
455                                   ERR_error_string(m, NULL));
456                         libwebsocket_close_and_free_session(context, wsi,
457                                                  LWS_CLOSE_STATUS_NOSTATUS);
458                         break;
459                 }
460
461 accepted:
462                 /* OK, we are accepted */
463
464                 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
465
466                 wsi->mode = LWS_CONNMODE_HTTP_SERVING;
467
468                 lwsl_debug("accepted new SSL conn\n");
469                 break;
470 #endif
471
472         default:
473                 break;
474         }
475         return 0;
476 }
477
478
479 static const char *err400[] = {
480         "Bad Request",
481         "Unauthorized",
482         "Payment Required",
483         "Forbidden",
484         "Not Found",
485         "Method Not Allowed",
486         "Not Acceptable",
487         "Proxy Auth Required",
488         "Request Timeout",
489         "Conflict",
490         "Gone",
491         "Length Required",
492         "Precondition Failed",
493         "Request Entity Too Large",
494         "Request URI too Long",
495         "Unsupported Media Type",
496         "Requested Range Not Satisfiable",
497         "Expectation Failed"
498 };
499
500 static const char *err500[] = {
501         "Internal Server Error",
502         "Not Implemented",
503         "Bad Gateway",
504         "Service Unavailable",
505         "Gateway Timeout",
506         "HTTP Version Not Supported"
507 };
508
509 /**
510  * libwebsockets_return_http_status() - Return simple http status
511  * @context:            libwebsockets context
512  * @wsi:                Websocket instance (available from user callback)
513  * @code:               Status index, eg, 404
514  * @html_body:          User-readable HTML description, or NULL
515  *
516  *      Helper to report HTTP errors back to the client cleanly and
517  *      consistently
518  */
519 LWS_VISIBLE int libwebsockets_return_http_status(
520                 struct libwebsocket_context *context, struct libwebsocket *wsi,
521                                        unsigned int code, const char *html_body)
522 {
523         int n, m;
524         const char *description = "";
525
526         if (!html_body)
527                 html_body = "";
528
529         if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
530                 description = err400[code - 400];
531         if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
532                 description = err500[code - 500];
533
534         n = sprintf((char *)context->service_buffer,
535                 "HTTP/1.0 %u %s\x0d\x0a"
536                 "Server: libwebsockets\x0d\x0a"
537                 "Mime-Type: text/html\x0d\x0a\x0d\x0a"
538                 "<h1>%u %s</h1>%s",
539                 code, description, code, description, html_body);
540
541         lwsl_info((const char *)context->service_buffer);
542
543         m = libwebsocket_write(wsi, context->service_buffer, n, LWS_WRITE_HTTP);
544
545         return m;
546 }
547
548 /**
549  * libwebsockets_serve_http_file() - Send a file back to the client using http
550  * @context:            libwebsockets context
551  * @wsi:                Websocket instance (available from user callback)
552  * @file:               The file to issue over http
553  * @content_type:       The http content type, eg, text/html
554  * @other_headers:      NULL or pointer to \0-terminated other header string
555  *
556  *      This function is intended to be called from the callback in response
557  *      to http requests from the client.  It allows the callback to issue
558  *      local files down the http link in a single step.
559  *
560  *      Returning <0 indicates error and the wsi should be closed.  Returning
561  *      >0 indicates the file was completely sent and the wsi should be closed.
562  *      ==0 indicates the file transfer is started and needs more service later,
563  *      the wsi should be left alone.
564  */
565
566 LWS_VISIBLE int libwebsockets_serve_http_file(
567                 struct libwebsocket_context *context,
568                         struct libwebsocket *wsi, const char *file,
569                            const char *content_type, const char *other_headers)
570 {
571         struct stat stat_buf;
572         unsigned char *p = context->service_buffer;
573         int ret = 0;
574         int n;
575
576         wsi->u.http.fd = open(file, O_RDONLY
577 #ifdef WIN32
578                          | _O_BINARY
579 #endif
580         );
581
582         if (wsi->u.http.fd < 1) {
583                 lwsl_err("Unable to open '%s'\n", file);
584                 libwebsockets_return_http_status(context, wsi,
585                                                 HTTP_STATUS_NOT_FOUND, NULL);
586                 wsi->u.http.fd = -1;
587                 return -1;
588         }
589
590         fstat(wsi->u.http.fd, &stat_buf);
591         wsi->u.http.filelen = stat_buf.st_size;
592         p += sprintf((char *)p,
593 "HTTP/1.0 200 OK\x0d\x0aServer: libwebsockets\x0d\x0a""Content-Type: %s\x0d\x0a",
594                                                                   content_type);
595         if (other_headers) {
596                 n = strlen(other_headers);
597                 memcpy(p, other_headers, n);
598                 p += n;
599         }
600         p += sprintf((char *)p,
601                 "Content-Length: %u\x0d\x0a\x0d\x0a",
602                                         (unsigned int)stat_buf.st_size);
603
604         ret = libwebsocket_write(wsi, context->service_buffer,
605                                    p - context->service_buffer, LWS_WRITE_HTTP);
606         if (ret != (p - context->service_buffer)) {
607                 lwsl_err("_write returned %d from %d\n", ret, (p - context->service_buffer));
608                 return -1;
609         }
610
611         wsi->u.http.filepos = 0;
612         wsi->state = WSI_STATE_HTTP_ISSUING_FILE;
613
614         return libwebsockets_serve_http_file_fragment(context, wsi);
615 }
616