2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
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.
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.
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,
23 #include "private-libwebsockets.h"
25 int lws_context_init_server(struct lws_context_creation_info *info,
26 struct lws_context *context)
29 struct sockaddr_in6 serv_addr6;
32 struct sockaddr_in serv_addr4;
33 socklen_t len = sizeof(struct sockaddr);
34 struct sockaddr_in sin;
36 int n, opt = 1, limit = 1;
39 lws_sockfd_type sockfd;
42 /* set up our external listening socket we serve on */
44 if (info->port == CONTEXT_PORT_NO_LISTEN)
48 #if defined(__linux__)
49 limit = context->count_threads;
52 for (m = 0; m < limit; m++) {
54 if (LWS_IPV6_ENABLED(context))
55 sockfd = socket(AF_INET6, SOCK_STREAM, 0);
58 sockfd = socket(AF_INET, SOCK_STREAM, 0);
62 sockfd = mbed3_create_tcp_stream_socket();
63 if (!lws_sockfd_valid(sockfd)) {
65 lwsl_err("ERROR opening socket\n");
71 * allow us to restart even if old sockets in TIME_WAIT
73 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
74 (const void *)&opt, sizeof(opt)) < 0) {
75 compatible_close(sockfd);
78 #if defined(__linux__) && defined(SO_REUSEPORT) && LWS_MAX_SMP > 1
79 if (context->count_threads > 1)
80 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
81 (const void *)&opt, sizeof(opt)) < 0) {
82 compatible_close(sockfd);
87 lws_plat_set_socket_options(context, sockfd);
91 if (LWS_IPV6_ENABLED(context)) {
92 v = (struct sockaddr *)&serv_addr6;
93 n = sizeof(struct sockaddr_in6);
94 bzero((char *) &serv_addr6, sizeof(serv_addr6));
95 serv_addr6.sin6_addr = in6addr_any;
96 serv_addr6.sin6_family = AF_INET6;
97 serv_addr6.sin6_port = htons(info->port);
101 v = (struct sockaddr *)&serv_addr4;
102 n = sizeof(serv_addr4);
103 bzero((char *) &serv_addr4, sizeof(serv_addr4));
104 serv_addr4.sin_addr.s_addr = INADDR_ANY;
105 serv_addr4.sin_family = AF_INET;
107 if (info->iface && interface_to_sa(context, info->iface,
108 (struct sockaddr_in *)v, n) < 0) {
109 lwsl_err("Unable to find interface %s\n", info->iface);
113 serv_addr4.sin_port = htons(info->port);
116 n = bind(sockfd, v, n);
118 lwsl_err("ERROR on binding to port %d (%d %d)\n",
119 info->port, n, LWS_ERRNO);
123 if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1)
124 lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
126 info->port = ntohs(sin.sin_port);
128 context->listen_port = info->port;
130 wsi = lws_zalloc(sizeof(struct lws));
132 lwsl_err("Out of mem\n");
135 wsi->context = context;
137 wsi->mode = LWSCM_SERVER_LISTENER;
138 wsi->protocol = context->protocols;
141 context->pt[m].wsi_listening = wsi;
142 if (insert_wsi_socket_into_fds(context, wsi))
145 context->pt[m].lserv_fd = sockfd;
148 listen(wsi->sock, LWS_SOMAXCONN);
149 } /* for each thread able to independently lister */
151 mbed3_tcp_stream_bind(wsi->sock, info->port, wsi);
153 lwsl_notice(" Listening on port %d\n", info->port);
158 compatible_close(sockfd);
164 _lws_server_listen_accept_flow_control(struct lws *twsi, int on)
166 struct lws_context_per_thread *pt = &twsi->context->pt[(int)twsi->tsi];
167 struct lws *wsi = pt->wsi_listening;
170 if (!wsi || twsi->context->being_destroyed)
173 lwsl_debug("%s: Thr %d: LISTEN wsi %p: state %d\n",
174 __func__, twsi->tsi, (void *)wsi, on);
177 n = lws_change_pollfd(wsi, 0, LWS_POLLIN);
179 n = lws_change_pollfd(wsi, LWS_POLLIN, 0);
184 int lws_http_action(struct lws *wsi)
186 enum http_connection_type connection_type;
187 enum http_version request_version;
188 char content_length_str[32];
189 unsigned int n, count = 0;
190 char http_version_str[10];
191 char http_conn_str[20];
192 int http_version_len;
193 char *uri_ptr = NULL;
196 static const unsigned char methods[] = {
199 WSI_TOKEN_OPTIONS_URI,
202 WSI_TOKEN_DELETE_URI,
204 WSI_TOKEN_HTTP_COLON_PATH,
208 static const char * const method_names[] = {
209 "GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE",
216 /* it's not websocket.... shall we accept it as http? */
218 for (n = 0; n < ARRAY_SIZE(methods); n++)
219 if (lws_hdr_total_length(wsi, methods[n]))
222 lwsl_warn("Missing URI in HTTP request\n");
227 lwsl_warn("multiple methods?\n");
231 if (lws_ensure_user_space(wsi))
234 for (n = 0; n < ARRAY_SIZE(methods); n++)
235 if (lws_hdr_total_length(wsi, methods[n])) {
236 uri_ptr = lws_hdr_simple_ptr(wsi, methods[n]);
237 uri_len = lws_hdr_total_length(wsi, methods[n]);
238 lwsl_info("Method: %s request for '%s'\n",
239 method_names[n], uri_ptr);
243 /* HTTP header had a content length? */
245 wsi->u.http.content_length = 0;
246 if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) ||
247 lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI) ||
248 lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI))
249 wsi->u.http.content_length = 100 * 1024 * 1024;
251 if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
252 lws_hdr_copy(wsi, content_length_str,
253 sizeof(content_length_str) - 1,
254 WSI_TOKEN_HTTP_CONTENT_LENGTH);
255 wsi->u.http.content_length = atoi(content_length_str);
258 /* http_version? Default to 1.0, override with token: */
259 request_version = HTTP_VERSION_1_0;
261 /* Works for single digit HTTP versions. : */
262 http_version_len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP);
263 if (http_version_len > 7) {
264 lws_hdr_copy(wsi, http_version_str,
265 sizeof(http_version_str) - 1, WSI_TOKEN_HTTP);
266 if (http_version_str[5] == '1' && http_version_str[7] == '1')
267 request_version = HTTP_VERSION_1_1;
269 wsi->u.http.request_version = request_version;
271 /* HTTP/1.1 defaults to "keep-alive", 1.0 to "close" */
272 if (request_version == HTTP_VERSION_1_1)
273 connection_type = HTTP_CONNECTION_KEEP_ALIVE;
275 connection_type = HTTP_CONNECTION_CLOSE;
277 /* Override default if http "Connection:" header: */
278 if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
279 lws_hdr_copy(wsi, http_conn_str, sizeof(http_conn_str) - 1,
280 WSI_TOKEN_CONNECTION);
281 http_conn_str[sizeof(http_conn_str) - 1] = '\0';
282 if (!strcasecmp(http_conn_str, "keep-alive"))
283 connection_type = HTTP_CONNECTION_KEEP_ALIVE;
285 if (!strcasecmp(http_conn_str, "close"))
286 connection_type = HTTP_CONNECTION_CLOSE;
288 wsi->u.http.connection_type = connection_type;
290 n = wsi->protocol->callback(wsi, LWS_CALLBACK_FILTER_HTTP_CONNECTION,
291 wsi->user_space, uri_ptr, uri_len);
295 * if there is content supposed to be coming,
296 * put a timeout on it having arrived
298 lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
301 n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
302 wsi->user_space, uri_ptr, uri_len);
305 /* now drop the header info we kept a pointer to */
306 lws_free_header_table(wsi);
309 lwsl_info("LWS_CALLBACK_HTTP closing\n");
310 return 1; /* struct ah ptr already nuked */ }
313 * If we're not issuing a file, check for content_length or
314 * HTTP keep-alive. No keep-alive header allocation for
315 * ISSUING_FILE, as this uses HTTP/1.0.
317 * In any case, return 0 and let lws_read decide how to
318 * proceed based on state
320 if (wsi->state != LWSS_HTTP_ISSUING_FILE)
321 /* Prepare to read body if we have a content length: */
322 if (wsi->u.http.content_length > 0)
323 wsi->state = LWSS_HTTP_BODY;
328 lws_free_header_table(wsi);
334 int lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
336 struct lws_context *context = lws_get_context(wsi);
337 struct allocated_headers *ah;
338 int protocol_len, n, hit;
339 char protocol_list[128];
340 char protocol_name[32];
343 assert(wsi->u.hdr.ah);
347 assert(wsi->mode == LWSCM_HTTP_SERVING);
349 if (lws_parse(wsi, *(*buf)++)) {
350 lwsl_info("lws_parse failed\n");
354 if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
357 lwsl_parser("lws_parse sees parsing complete\n");
359 wsi->mode = LWSCM_PRE_WS_SERVING_ACCEPT;
360 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
362 /* is this websocket protocol or normal http 1.0? */
364 if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
365 if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
367 lwsl_info("Upgrade to ws\n");
371 if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
373 lwsl_info("Upgrade to h2c-14\n");
377 lwsl_err("Unknown upgrade\n");
378 /* dunno what he wanted to upgrade to */
382 /* no upgrade ack... he remained as HTTP */
384 lwsl_info("No upgrade\n");
387 lws_union_transition(wsi, LWSCM_HTTP_SERVING_ACCEPTED);
388 wsi->state = LWSS_HTTP;
389 wsi->u.http.fd = LWS_INVALID_FILE;
391 /* expose it at the same offset as u.hdr */
393 lwsl_debug("%s: wsi %p: ah %p\n", __func__, (void *)wsi, (void *)wsi->u.hdr.ah);
395 n = lws_http_action(wsi);
401 if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP2_SETTINGS)) {
402 lwsl_err("missing http2_settings\n");
406 lwsl_err("h2c upgrade...\n");
408 p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP2_SETTINGS);
409 /* convert the peer's HTTP-Settings */
410 n = lws_b64_decode_string(p, protocol_list,
411 sizeof(protocol_list));
413 lwsl_parser("HTTP2_SETTINGS too long\n");
417 /* adopt the header info */
421 lws_union_transition(wsi, LWSCM_HTTP2_SERVING);
423 /* http2 union member has http union struct at start */
426 lws_http2_init(&wsi->u.http2.peer_settings);
427 lws_http2_init(&wsi->u.http2.my_settings);
431 lws_http2_interpret_settings_payload(&wsi->u.http2.peer_settings,
432 (unsigned char *)protocol_list, n);
434 strcpy(protocol_list,
435 "HTTP/1.1 101 Switching Protocols\x0d\x0a"
436 "Connection: Upgrade\x0d\x0a"
437 "Upgrade: h2c\x0d\x0a\x0d\x0a");
438 n = lws_issue_raw(wsi, (unsigned char *)protocol_list,
439 strlen(protocol_list));
440 if (n != strlen(protocol_list)) {
441 lwsl_debug("http2 switch: ERROR writing to socket\n");
445 wsi->state = LWSS_HTTP2_AWAIT_CLIENT_PREFACE;
452 lwsl_err("NULL protocol at lws_read\n");
457 * Select the first protocol we support from the list
458 * the client sent us.
460 * Copy it to remove header fragmentation
463 if (lws_hdr_copy(wsi, protocol_list, sizeof(protocol_list) - 1,
464 WSI_TOKEN_PROTOCOL) < 0) {
465 lwsl_err("protocol list too long");
469 protocol_len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
470 protocol_list[protocol_len] = '\0';
476 while (n < sizeof(protocol_name) - 1 && *p && *p !=',')
477 protocol_name[n++] = *p++;
478 protocol_name[n] = '\0';
482 lwsl_info("checking %s\n", protocol_name);
485 while (context->protocols[n].callback) {
486 if (context->protocols[n].name &&
487 !strcmp(context->protocols[n].name,
489 lwsl_info("prot match %d\n", n);
490 wsi->protocol = &context->protocols[n];
499 /* we didn't find a protocol he wanted? */
502 if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL)) {
503 lwsl_err("No protocol from \"%s\" supported\n",
508 * some clients only have one protocol and
509 * do not sent the protocol list header...
510 * allow it and match to protocol 0
512 lwsl_info("defaulting to prot 0 handler\n");
513 wsi->protocol = &context->protocols[0];
516 /* allocate wsi->user storage */
517 if (lws_ensure_user_space(wsi))
521 * Give the user code a chance to study the request and
522 * have the opportunity to deny it
525 if ((wsi->protocol->callback)(wsi,
526 LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
528 lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
529 lwsl_warn("User code denied connection\n");
534 * Perform the handshake according to the protocol version the
538 switch (wsi->ietf_spec_revision) {
540 lwsl_parser("lws_parse calling handshake_04\n");
541 if (handshake_0405(context, wsi)) {
542 lwsl_info("hs0405 has failed the connection\n");
548 lwsl_warn("Unknown client spec version %d\n",
549 wsi->ietf_spec_revision);
553 /* drop the header info -- no bail_nuke_ah after this */
554 lws_free_header_table(wsi);
556 lws_union_transition(wsi, LWSCM_WS_SERVING);
559 * create the frame buffer for this connection according to the
560 * size mentioned in the protocol definition. If 0 there, use
561 * a big default for compatibility
564 n = wsi->protocol->rx_buffer_size;
566 n = LWS_MAX_SOCKET_IO_BUF;
568 wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */);
569 if (!wsi->u.ws.rx_ubuf) {
570 lwsl_err("Out of Mem allocating rx buffer %d\n", n);
573 wsi->u.ws.rx_ubuf_alloc = n;
574 lwsl_info("Allocating RX buffer %d\n", n);
576 if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF,
577 (const char *)&n, sizeof n)) {
578 lwsl_warn("Failed to set SNDBUF to %d", n);
582 lwsl_parser("accepted v%02d connection\n", wsi->ietf_spec_revision);
585 } /* while all chars are handled */
590 /* drop the header info */
591 lws_free_header_table(wsi);
596 lws_get_idlest_tsi(struct lws_context *context)
598 unsigned int lowest = ~0;
601 for (; n < context->count_threads; n++) {
602 if ((unsigned int)context->pt[n].fds_count != context->fd_limit_per_thread - 1 &&
603 (unsigned int)context->pt[n].fds_count < lowest) {
604 lowest = context->pt[n].fds_count;
613 lws_create_new_server_wsi(struct lws_context *context)
616 int n = lws_get_idlest_tsi(context);
619 lwsl_err("no space for new conn\n");
623 new_wsi = lws_zalloc(sizeof(struct lws));
624 if (new_wsi == NULL) {
625 lwsl_err("Out of memory for new connection\n");
630 lwsl_info("Accepted %p to tsi %d\n", new_wsi, new_wsi->tsi);
632 new_wsi->context = context;
633 new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
634 new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
636 /* intialize the instance struct */
638 new_wsi->state = LWSS_HTTP;
639 new_wsi->mode = LWSCM_HTTP_SERVING;
640 new_wsi->hdr_parsing_completed = 0;
642 #ifdef LWS_OPENSSL_SUPPORT
643 new_wsi->use_ssl = LWS_SSL_ENABLED(context);
647 * these can only be set once the protocol is known
648 * we set an unestablished connection's protocol pointer
649 * to the start of the supported list, so it can look
650 * for matching ones during the handshake
652 new_wsi->protocol = context->protocols;
653 new_wsi->user_space = NULL;
654 new_wsi->ietf_spec_revision = 0;
655 new_wsi->sock = LWS_SOCK_INVALID;
659 * outermost create notification for wsi
660 * no user_space because no protocol selection
662 context->protocols[0].callback(new_wsi, LWS_CALLBACK_WSI_CREATE,
669 * lws_http_transaction_completed() - wait for new http transaction or close
670 * @wsi: websocket connection
672 * Returns 1 if the HTTP connection must close now
673 * Returns 0 and resets connection to wait for new HTTP header /
674 * transaction if possible
677 LWS_VISIBLE int LWS_WARN_UNUSED_RESULT
678 lws_http_transaction_completed(struct lws *wsi)
680 lwsl_debug("%s: wsi %p\n", __func__, wsi);
681 /* if we can't go back to accept new headers, drop the connection */
682 if (wsi->u.http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
683 lwsl_info("%s: %p: close connection\n", __func__, wsi);
687 /* otherwise set ourselves up ready to go again */
688 wsi->state = LWSS_HTTP;
689 wsi->mode = LWSCM_HTTP_SERVING;
690 wsi->u.http.content_length = 0;
692 /* He asked for it to stay alive indefinitely */
693 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
695 /* if we still have the headers, drop them and reacquire a new ah when
696 * the new headers arrive. Otherwise we hog an ah indefinitely,
699 lws_free_header_table(wsi);
701 /* If we're (re)starting on headers, need other implied init */
702 wsi->u.hdr.ues = URIES_IDLE;
704 lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi);
710 * lws_adopt_socket() - adopt foreign socket as if listen socket accepted it
711 * @context: lws context
712 * @accept_fd: fd of already-accepted socket to adopt
714 * Either returns new wsi bound to accept_fd, or closes accept_fd and
715 * returns NULL, having cleaned up any new wsi pieces.
717 * LWS adopts the socket in http serving mode, it's ready to accept an upgrade
718 * to ws or just serve http.
721 LWS_VISIBLE struct lws *
722 lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
724 struct lws *new_wsi = lws_create_new_server_wsi(context);
726 compatible_close(accept_fd);
730 new_wsi->sock = accept_fd;
732 /* the transport is accepted... give him time to negotiate */
733 lws_set_timeout(new_wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
737 mbed3_tcp_stream_accept(accept_fd, new_wsi);
741 * A new connection was accepted. Give the user a chance to
742 * set properties of the newly created wsi. There's no protocol
743 * selected yet so we issue this to protocols[0]
745 if ((context->protocols[0].callback)(new_wsi,
746 LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0)) {
747 compatible_close(new_wsi->sock);
752 lws_libev_accept(new_wsi, new_wsi->sock);
754 if (!LWS_SSL_ENABLED(context)) {
755 if (insert_wsi_socket_into_fds(context, new_wsi))
758 new_wsi->mode = LWSCM_SSL_INIT;
759 if (lws_server_socket_service_ssl(new_wsi, accept_fd))
766 lwsl_err("%s: fail\n", __func__);
767 lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS);
773 lws_server_socket_service(struct lws_context *context, struct lws *wsi,
774 struct lws_pollfd *pollfd)
776 lws_sockfd_type accept_fd = LWS_SOCK_INVALID;
777 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
779 struct sockaddr_in cli_addr;
787 case LWSCM_HTTP_SERVING:
788 case LWSCM_HTTP_SERVING_ACCEPTED:
789 case LWSCM_HTTP2_SERVING:
791 /* handle http headers coming in */
793 /* pending truncated sends have uber priority */
795 if (wsi->trunc_len) {
796 if (!(pollfd->revents & LWS_POLLOUT))
799 if (lws_issue_raw(wsi, wsi->trunc_alloc + wsi->trunc_offset,
803 * we can't afford to allow input processing send
804 * something new, so spin around he event loop until
805 * he doesn't have any partials
810 /* any incoming data ready? */
812 if (!(pollfd->revents & pollfd->events & LWS_POLLIN))
815 if (wsi->state == LWSS_HTTP && !wsi->u.hdr.ah)
816 if (lws_allocate_header_table(wsi))
819 len = lws_ssl_capable_read(wsi, pt->serv_buf,
820 LWS_MAX_SOCKET_IO_BUF);
821 lwsl_debug("%s: wsi %p read %d\r\n", __func__, wsi, len);
824 lwsl_info("%s: read 0 len\n", __func__);
825 /* lwsl_info(" state=%d\n", wsi->state); */
826 if (!wsi->hdr_parsing_completed)
827 lws_free_header_table(wsi);
829 case LWS_SSL_CAPABLE_ERROR:
831 case LWS_SSL_CAPABLE_MORE_SERVICE:
835 /* just ignore incoming if waiting for close */
836 if (wsi->state != LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
838 * hm this may want to send
839 * (via HTTP callback for example)
841 n = lws_read(wsi, pt->serv_buf, len);
842 if (n < 0) /* we closed wsi */
844 /* hum he may have used up the
845 * writability above */
850 /* this handles POLLOUT for http serving fragments */
852 if (!(pollfd->revents & LWS_POLLOUT))
856 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
857 lwsl_notice("%s a\n", __func__);
861 lws_libev_io(wsi, LWS_EV_STOP | LWS_EV_WRITE);
863 if (wsi->state != LWSS_HTTP_ISSUING_FILE) {
864 n = user_callback_handle_rxflow(
865 wsi->protocol->callback,
866 wsi, LWS_CALLBACK_HTTP_WRITEABLE,
867 wsi->user_space, NULL, 0);
869 lwsl_info("writeable_fail\n");
875 /* >0 == completion, <0 == error */
876 n = lws_serve_http_file_fragment(wsi);
877 if (n < 0 || (n > 0 && lws_http_transaction_completed(wsi))) {
878 lwsl_info("completed\n");
883 case LWSCM_SERVER_LISTENER:
886 /* pollin means a client has connected to us then */
889 if (!(pollfd->revents & LWS_POLLIN) || !(pollfd->events & LWS_POLLIN))
892 /* listen socket got an unencrypted connection... */
894 clilen = sizeof(cli_addr);
895 lws_latency_pre(context, wsi);
896 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
898 lws_latency(context, wsi, "listener accept", accept_fd,
901 if (LWS_ERRNO == LWS_EAGAIN ||
902 LWS_ERRNO == LWS_EWOULDBLOCK) {
903 lwsl_err("accept asks to try again\n");
906 lwsl_err("ERROR on accept: %s\n", strerror(LWS_ERRNO));
910 lws_plat_set_socket_options(context, accept_fd);
912 lwsl_debug("accepted new conn port %u on fd=%d\n",
913 ntohs(cli_addr.sin_port), accept_fd);
916 /* not very beautiful... */
917 accept_fd = (lws_sockfd_type)pollfd;
920 * look at who we connected to and give user code a chance
921 * to reject based on client IP. There's no protocol selected
922 * yet so we issue this to protocols[0]
924 if ((context->protocols[0].callback)(wsi,
925 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
926 NULL, (void *)(long)accept_fd, 0)) {
927 lwsl_debug("Callback denied network connection\n");
928 compatible_close(accept_fd);
932 if (!lws_adopt_socket(context, accept_fd))
933 /* already closed cleanly as necessary */
937 } while (pt->fds_count < context->fd_limit_per_thread - 1 &&
938 lws_poll_listen_fd(&pt->fds[wsi->position_in_fds_table]) > 0);
946 if (!lws_server_socket_service_ssl(wsi, accept_fd))
950 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
956 * lws_serve_http_file() - Send a file back to the client using http
957 * @wsi: Websocket instance (available from user callback)
958 * @file: The file to issue over http
959 * @content_type: The http content type, eg, text/html
960 * @other_headers: NULL or pointer to header string
961 * @other_headers_len: length of the other headers if non-NULL
963 * This function is intended to be called from the callback in response
964 * to http requests from the client. It allows the callback to issue
965 * local files down the http link in a single step.
967 * Returning <0 indicates error and the wsi should be closed. Returning
968 * >0 indicates the file was completely sent and
969 * lws_http_transaction_completed() called on the wsi (and close if != 0)
970 * ==0 indicates the file transfer is started and needs more service later,
971 * the wsi should be left alone.
974 LWS_VISIBLE int lws_serve_http_file(struct lws *wsi, const char *file,
975 const char *content_type,
976 const char *other_headers,
977 int other_headers_len)
979 struct lws_context *context = lws_get_context(wsi);
980 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
981 unsigned char *response = pt->serv_buf + LWS_PRE;
982 unsigned char *p = response;
983 unsigned char *end = p + LWS_MAX_SOCKET_IO_BUF - LWS_PRE;
986 wsi->u.http.fd = lws_plat_file_open(wsi, file, &wsi->u.http.filelen,
989 if (wsi->u.http.fd == LWS_INVALID_FILE) {
990 lwsl_err("Unable to open '%s'\n", file);
991 lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
996 if (lws_add_http_header_status(wsi, 200, &p, end))
998 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,
999 (unsigned char *)"libwebsockets", 13,
1002 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
1003 (unsigned char *)content_type,
1004 strlen(content_type), &p, end))
1006 if (lws_add_http_header_content_length(wsi, wsi->u.http.filelen, &p, end))
1009 if (other_headers) {
1010 if ((end - p) < other_headers_len)
1012 memcpy(p, other_headers, other_headers_len);
1013 p += other_headers_len;
1016 if (lws_finalize_http_header(wsi, &p, end))
1019 ret = lws_write(wsi, response, p - response, LWS_WRITE_HTTP_HEADERS);
1020 if (ret != (p - response)) {
1021 lwsl_err("_write returned %d from %d\n", ret, (p - response));
1025 wsi->u.http.filepos = 0;
1026 wsi->state = LWSS_HTTP_ISSUING_FILE;
1028 return lws_serve_http_file_fragment(wsi);
1032 lws_interpret_incoming_packet(struct lws *wsi, unsigned char **buf, size_t len)
1036 lwsl_parser("%s: received %d byte packet\n", __func__, (int)len);
1038 lwsl_hexdump(*buf, len);
1041 /* let the rx protocol state machine have as much as it needs */
1045 * we were accepting input but now we stopped doing so
1047 if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
1048 lws_rxflow_cache(wsi, *buf, 0, len);
1049 lwsl_parser("%s: cached %d\n", __func__, len);
1053 if (wsi->u.ws.rx_draining_ext) {
1054 m = lws_rx_sm(wsi, 0);
1060 /* account for what we're using in rxflow buffer */
1061 if (wsi->rxflow_buffer)
1064 /* process the byte */
1065 m = lws_rx_sm(wsi, *(*buf)++);
1071 lwsl_parser("%s: exit with %d unused\n", __func__, (int)len);
1077 lws_server_get_canonical_hostname(struct lws_context *context,
1078 struct lws_context_creation_info *info)
1080 if (info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)
1083 /* find canonical hostname */
1084 gethostname((char *)context->canonical_hostname,
1085 sizeof(context->canonical_hostname) - 1);
1087 lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);