1 /*
2 * Copyright (c) 2023, Emna Rekik
3 * Copyright (c) 2024 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <errno.h>
9 #include <stdbool.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <strings.h>
14
15 #include <zephyr/fs/fs.h>
16 #include <zephyr/fs/fs_interface.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/logging/log.h>
19 #include <zephyr/net/http/service.h>
20 #include <zephyr/net/net_ip.h>
21 #include <zephyr/net/socket.h>
22 #include <zephyr/net/tls_credentials.h>
23 #include <zephyr/posix/sys/eventfd.h>
24 #include <zephyr/posix/fnmatch.h>
25 #include <zephyr/sys/util_macro.h>
26
27 LOG_MODULE_REGISTER(net_http_server, CONFIG_NET_HTTP_SERVER_LOG_LEVEL);
28
29 #include "../../ip/net_private.h"
30 #include "headers/server_internal.h"
31
32 #if defined(CONFIG_NET_TC_THREAD_COOPERATIVE)
33 /* Lowest priority cooperative thread */
34 #define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)
35 #else
36 #define THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1)
37 #endif
38
39 #define INVALID_SOCK -1
40 #define INACTIVITY_TIMEOUT K_SECONDS(CONFIG_HTTP_SERVER_CLIENT_INACTIVITY_TIMEOUT)
41
42 #define HTTP_SERVER_MAX_SERVICES CONFIG_HTTP_SERVER_NUM_SERVICES
43 #define HTTP_SERVER_MAX_CLIENTS CONFIG_HTTP_SERVER_MAX_CLIENTS
44 #define HTTP_SERVER_SOCK_COUNT (1 + HTTP_SERVER_MAX_SERVICES + HTTP_SERVER_MAX_CLIENTS)
45
46 struct http_server_ctx {
47 int listen_fds; /* max value of 1 + MAX_SERVICES */
48
49 /* First pollfd is eventfd that can be used to stop the server,
50 * then we have the server listen sockets,
51 * and then the accepted sockets.
52 */
53 struct zsock_pollfd fds[HTTP_SERVER_SOCK_COUNT];
54 struct http_client_ctx clients[HTTP_SERVER_MAX_CLIENTS];
55 };
56
57 static struct http_server_ctx server_ctx;
58 static K_SEM_DEFINE(server_start, 0, 1);
59 static bool server_running;
60
61 #if defined(CONFIG_HTTP_SERVER_TLS_USE_ALPN)
62 static const char *const alpn_list[] = {"h2", "http/1.1"};
63 #endif
64
65 static void close_client_connection(struct http_client_ctx *client);
66
67 HTTP_SERVER_CONTENT_TYPE(html, "text/html")
68 HTTP_SERVER_CONTENT_TYPE(css, "text/css")
69 HTTP_SERVER_CONTENT_TYPE(js, "text/javascript")
70 HTTP_SERVER_CONTENT_TYPE(jpg, "image/jpeg")
71 HTTP_SERVER_CONTENT_TYPE(png, "image/png")
72 HTTP_SERVER_CONTENT_TYPE(svg, "image/svg+xml")
73
http_server_init(struct http_server_ctx * ctx)74 int http_server_init(struct http_server_ctx *ctx)
75 {
76 int proto;
77 int failed = 0, count = 0;
78 int svc_count;
79 socklen_t len;
80 int fd, af, i;
81 struct sockaddr_storage addr_storage;
82 const union {
83 struct sockaddr *addr;
84 struct sockaddr_in *addr4;
85 struct sockaddr_in6 *addr6;
86 } addr = {
87 .addr = (struct sockaddr *)&addr_storage
88 };
89
90 HTTP_SERVICE_COUNT(&svc_count);
91
92 /* Initialize fds */
93 memset(ctx->fds, 0, sizeof(ctx->fds));
94 memset(ctx->clients, 0, sizeof(ctx->clients));
95
96 for (i = 0; i < ARRAY_SIZE(ctx->fds); i++) {
97 ctx->fds[i].fd = INVALID_SOCK;
98 }
99
100 /* Create an eventfd that can be used to trigger events during polling */
101 fd = eventfd(0, 0);
102 if (fd < 0) {
103 fd = -errno;
104 LOG_ERR("eventfd failed (%d)", fd);
105 return fd;
106 }
107
108 ctx->fds[count].fd = fd;
109 ctx->fds[count].events = ZSOCK_POLLIN;
110 count++;
111
112 HTTP_SERVICE_FOREACH(svc) {
113 /* set the default address (in6addr_any / INADDR_ANY are all 0) */
114 memset(&addr_storage, 0, sizeof(struct sockaddr_storage));
115
116 /* Set up the server address struct according to address family */
117 if (IS_ENABLED(CONFIG_NET_IPV6) && svc->host != NULL &&
118 zsock_inet_pton(AF_INET6, svc->host, &addr.addr6->sin6_addr) == 1) {
119 af = AF_INET6;
120 len = sizeof(*addr.addr6);
121
122 addr.addr6->sin6_family = AF_INET6;
123 addr.addr6->sin6_port = htons(*svc->port);
124 } else if (IS_ENABLED(CONFIG_NET_IPV4) && svc->host != NULL &&
125 zsock_inet_pton(AF_INET, svc->host, &addr.addr4->sin_addr) == 1) {
126 af = AF_INET;
127 len = sizeof(*addr.addr4);
128
129 addr.addr4->sin_family = AF_INET;
130 addr.addr4->sin_port = htons(*svc->port);
131 } else if (IS_ENABLED(CONFIG_NET_IPV6)) {
132 /* prefer IPv6 if both IPv6 and IPv4 are supported */
133 af = AF_INET6;
134 len = sizeof(*addr.addr6);
135
136 addr.addr6->sin6_family = AF_INET6;
137 addr.addr6->sin6_port = htons(*svc->port);
138 } else if (IS_ENABLED(CONFIG_NET_IPV4)) {
139 af = AF_INET;
140 len = sizeof(*addr.addr4);
141
142 addr.addr4->sin_family = AF_INET;
143 addr.addr4->sin_port = htons(*svc->port);
144 } else {
145 LOG_ERR("Neither IPv4 nor IPv6 is enabled");
146 failed++;
147 break;
148 }
149
150 /* Create a socket */
151 if (COND_CODE_1(CONFIG_NET_SOCKETS_SOCKOPT_TLS,
152 (svc->sec_tag_list != NULL),
153 (0))) {
154 proto = IPPROTO_TLS_1_2;
155 } else {
156 proto = IPPROTO_TCP;
157 }
158
159 if (svc->config != NULL && svc->config->socket_create != NULL) {
160 fd = svc->config->socket_create(svc, af, proto);
161 } else {
162 fd = zsock_socket(af, SOCK_STREAM, proto);
163 }
164 if (fd < 0) {
165 LOG_ERR("socket: %d", errno);
166 failed++;
167 continue;
168 }
169
170 /* If IPv4-to-IPv6 mapping is enabled, then turn off V6ONLY option
171 * so that IPv6 socket can serve IPv4 connections.
172 */
173 if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) {
174 int optval = 0;
175
176 (void)zsock_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval,
177 sizeof(optval));
178 }
179
180 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
181 if (svc->sec_tag_list != NULL) {
182 if (zsock_setsockopt(fd, SOL_TLS, TLS_SEC_TAG_LIST,
183 svc->sec_tag_list,
184 svc->sec_tag_list_size) < 0) {
185 LOG_ERR("setsockopt: %d", errno);
186 zsock_close(fd);
187 continue;
188 }
189
190 if (zsock_setsockopt(fd, SOL_TLS, TLS_HOSTNAME, "localhost",
191 sizeof("localhost")) < 0) {
192 LOG_ERR("setsockopt: %d", errno);
193 zsock_close(fd);
194 continue;
195 }
196
197 #if defined(CONFIG_HTTP_SERVER_TLS_USE_ALPN)
198 if (zsock_setsockopt(fd, SOL_TLS, TLS_ALPN_LIST, alpn_list,
199 sizeof(alpn_list)) < 0) {
200 LOG_ERR("setsockopt: %d", errno);
201 zsock_close(fd);
202 continue;
203 }
204 #endif /* defined(CONFIG_HTTP_SERVER_TLS_USE_ALPN) */
205 }
206 #endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */
207
208 if (zsock_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1},
209 sizeof(int)) < 0) {
210 LOG_ERR("setsockopt: %d", errno);
211 zsock_close(fd);
212 continue;
213 }
214
215 if (zsock_bind(fd, addr.addr, len) < 0) {
216 LOG_ERR("bind: %d", errno);
217 failed++;
218 zsock_close(fd);
219 continue;
220 }
221
222 if (*svc->port == 0) {
223 /* ephemeral port - read back the port number */
224 len = sizeof(addr_storage);
225 if (zsock_getsockname(fd, addr.addr, &len) < 0) {
226 LOG_ERR("getsockname: %d", errno);
227 zsock_close(fd);
228 continue;
229 }
230
231 *svc->port = ntohs(addr.addr4->sin_port);
232 }
233
234 svc->data->num_clients = 0;
235 if (zsock_listen(fd, svc->backlog) < 0) {
236 LOG_ERR("listen: %d", errno);
237 failed++;
238 zsock_close(fd);
239 continue;
240 }
241
242 LOG_DBG("Initialized HTTP Service %s:%u",
243 svc->host ? svc->host : "<any>", *svc->port);
244
245 *svc->fd = fd;
246 ctx->fds[count].fd = fd;
247 ctx->fds[count].events = ZSOCK_POLLIN;
248 count++;
249 }
250
251 if (failed >= svc_count) {
252 LOG_ERR("All services failed (%d)", failed);
253 /* Close eventfd socket */
254 zsock_close(ctx->fds[0].fd);
255 return -ESRCH;
256 }
257
258 ctx->listen_fds = count;
259
260 return 0;
261 }
262
accept_new_client(int server_fd)263 static int accept_new_client(int server_fd)
264 {
265 int new_socket;
266 socklen_t addrlen;
267 struct sockaddr_storage sa;
268
269 memset(&sa, 0, sizeof(sa));
270 addrlen = sizeof(sa);
271
272 new_socket = zsock_accept(server_fd, (struct sockaddr *)&sa, &addrlen);
273 if (new_socket < 0) {
274 new_socket = -errno;
275 LOG_DBG("[%d] accept failed (%d)", server_fd, new_socket);
276 return new_socket;
277 }
278
279 const char * const addrstr =
280 net_sprint_addr(sa.ss_family, &net_sin((struct sockaddr *)&sa)->sin_addr);
281 LOG_DBG("New client from %s:%d", addrstr != NULL ? addrstr : "<unknown>",
282 ntohs(net_sin((struct sockaddr *)&sa)->sin_port));
283
284 return new_socket;
285 }
286
close_all_sockets(struct http_server_ctx * ctx)287 static void close_all_sockets(struct http_server_ctx *ctx)
288 {
289 zsock_close(ctx->fds[0].fd); /* close eventfd */
290 ctx->fds[0].fd = -1;
291
292 for (int i = 1; i < ARRAY_SIZE(ctx->fds); i++) {
293 if (ctx->fds[i].fd < 0) {
294 continue;
295 }
296
297 if (i < ctx->listen_fds) {
298 zsock_close(ctx->fds[i].fd);
299 } else {
300 struct http_client_ctx *client =
301 &server_ctx.clients[i - ctx->listen_fds];
302
303 close_client_connection(client);
304 }
305
306 ctx->fds[i].fd = -1;
307 }
308
309 HTTP_SERVICE_FOREACH(svc) {
310 *svc->fd = -1;
311 }
312 }
313
client_release_resources(struct http_client_ctx * client)314 static void client_release_resources(struct http_client_ctx *client)
315 {
316 struct http_resource_detail *detail;
317 struct http_resource_detail_dynamic *dynamic_detail;
318 struct http_request_ctx request_ctx;
319 struct http_response_ctx response_ctx;
320
321 HTTP_SERVICE_FOREACH(service) {
322 HTTP_SERVICE_FOREACH_RESOURCE(service, resource) {
323 detail = resource->detail;
324
325 if (detail->type != HTTP_RESOURCE_TYPE_DYNAMIC) {
326 continue;
327 }
328
329 dynamic_detail = (struct http_resource_detail_dynamic *)detail;
330
331 if (dynamic_detail->holder != client) {
332 continue;
333 }
334
335 /* If the client still holds the resource at this point,
336 * it means the transaction was not complete. Release
337 * the resource and notify application.
338 */
339 dynamic_detail->holder = NULL;
340
341 if (dynamic_detail->cb == NULL) {
342 continue;
343 }
344
345 populate_request_ctx(&request_ctx, NULL, 0, NULL);
346
347 dynamic_detail->cb(client, HTTP_SERVER_DATA_ABORTED, &request_ctx,
348 &response_ctx, dynamic_detail->user_data);
349 }
350 }
351 }
352
http_server_release_client(struct http_client_ctx * client)353 void http_server_release_client(struct http_client_ctx *client)
354 {
355 int i;
356 struct k_work_sync sync;
357
358 __ASSERT_NO_MSG(IS_ARRAY_ELEMENT(server_ctx.clients, client));
359
360 k_work_cancel_delayable_sync(&client->inactivity_timer, &sync);
361 client_release_resources(client);
362
363 client->service->data->num_clients--;
364
365 for (i = 0; i < server_ctx.listen_fds; i++) {
366 if (server_ctx.fds[i].fd == *client->service->fd) {
367 server_ctx.fds[i].events = ZSOCK_POLLIN;
368 break;
369 }
370 }
371 for (i = server_ctx.listen_fds; i < ARRAY_SIZE(server_ctx.fds); i++) {
372 if (server_ctx.fds[i].fd == client->fd) {
373 server_ctx.fds[i].fd = INVALID_SOCK;
374 break;
375 }
376 }
377
378 memset(client, 0, sizeof(struct http_client_ctx));
379 client->fd = INVALID_SOCK;
380 }
381
close_client_connection(struct http_client_ctx * client)382 static void close_client_connection(struct http_client_ctx *client)
383 {
384 int fd = client->fd;
385
386 http_server_release_client(client);
387
388 (void)zsock_close(fd);
389 }
390
client_timeout(struct k_work * work)391 static void client_timeout(struct k_work *work)
392 {
393 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
394 struct http_client_ctx *client =
395 CONTAINER_OF(dwork, struct http_client_ctx, inactivity_timer);
396
397 LOG_DBG("Client %p timeout", client);
398
399 /* Shutdown the socket. This will be detected by poll() and a proper
400 * cleanup will proceed.
401 */
402 (void)zsock_shutdown(client->fd, ZSOCK_SHUT_RD);
403 }
404
http_client_timer_restart(struct http_client_ctx * client)405 void http_client_timer_restart(struct http_client_ctx *client)
406 {
407 __ASSERT_NO_MSG(IS_ARRAY_ELEMENT(server_ctx.clients, client));
408
409 k_work_reschedule(&client->inactivity_timer, INACTIVITY_TIMEOUT);
410 }
411
lookup_service(int server_fd)412 static const struct http_service_desc *lookup_service(int server_fd)
413 {
414 HTTP_SERVICE_FOREACH(svc) {
415 if (*svc->fd == server_fd) {
416 return svc;
417 }
418 }
419
420 return NULL;
421 }
422
init_client_ctx(struct http_client_ctx * client,const struct http_service_desc * svc,int new_socket)423 static void init_client_ctx(struct http_client_ctx *client, const struct http_service_desc *svc,
424 int new_socket)
425 {
426 client->fd = new_socket;
427 client->service = svc;
428 client->data_len = 0;
429 client->server_state = HTTP_SERVER_PREFACE_STATE;
430 client->has_upgrade_header = false;
431 client->preface_sent = false;
432 client->window_size = HTTP_SERVER_INITIAL_WINDOW_SIZE;
433
434 memset(client->buffer, 0, sizeof(client->buffer));
435 memset(client->url_buffer, 0, sizeof(client->url_buffer));
436 k_work_init_delayable(&client->inactivity_timer, client_timeout);
437 http_client_timer_restart(client);
438
439 ARRAY_FOR_EACH(client->streams, i) {
440 client->streams[i].stream_state = HTTP2_STREAM_IDLE;
441 client->streams[i].stream_id = 0;
442 }
443
444 client->current_stream = NULL;
445 }
446
handle_http_preface(struct http_client_ctx * client)447 static int handle_http_preface(struct http_client_ctx *client)
448 {
449 LOG_DBG("HTTP_SERVER_PREFACE_STATE.");
450
451 if (client->data_len < sizeof(HTTP2_PREFACE) - 1) {
452 /* We don't have full preface yet, get more data. */
453 return -EAGAIN;
454 }
455
456 if (IS_ENABLED(CONFIG_HTTP_SERVER_CAPTURE_HEADERS)) {
457 client->header_capture_ctx.count = 0;
458 client->header_capture_ctx.cursor = 0;
459 client->header_capture_ctx.status = HTTP_HEADER_STATUS_OK;
460 }
461
462 if (strncmp(client->cursor, HTTP2_PREFACE, sizeof(HTTP2_PREFACE) - 1) != 0) {
463 return enter_http1_request(client);
464 }
465
466 return enter_http2_request(client);
467 }
468
handle_http_done(struct http_client_ctx * client)469 static int handle_http_done(struct http_client_ctx *client)
470 {
471 LOG_DBG("HTTP_SERVER_DONE_STATE");
472
473 close_client_connection(client);
474
475 return -EAGAIN;
476 }
477
enter_http_done_state(struct http_client_ctx * client)478 int enter_http_done_state(struct http_client_ctx *client)
479 {
480 close_client_connection(client);
481
482 client->server_state = HTTP_SERVER_DONE_STATE;
483
484 return -EAGAIN;
485 }
486
handle_http_request(struct http_client_ctx * client)487 static int handle_http_request(struct http_client_ctx *client)
488 {
489 int ret = -EINVAL;
490
491 client->cursor = client->buffer;
492
493 do {
494 switch (client->server_state) {
495 case HTTP_SERVER_FRAME_DATA_STATE:
496 ret = handle_http_frame_data(client);
497 break;
498 case HTTP_SERVER_PREFACE_STATE:
499 ret = handle_http_preface(client);
500 break;
501 case HTTP_SERVER_REQUEST_STATE:
502 ret = handle_http1_request(client);
503 break;
504 case HTTP_SERVER_FRAME_HEADER_STATE:
505 ret = handle_http_frame_header(client);
506 break;
507 case HTTP_SERVER_FRAME_HEADERS_STATE:
508 ret = handle_http_frame_headers(client);
509 break;
510 case HTTP_SERVER_FRAME_CONTINUATION_STATE:
511 ret = handle_http_frame_continuation(client);
512 break;
513 case HTTP_SERVER_FRAME_SETTINGS_STATE:
514 ret = handle_http_frame_settings(client);
515 break;
516 case HTTP_SERVER_FRAME_WINDOW_UPDATE_STATE:
517 ret = handle_http_frame_window_update(client);
518 break;
519 case HTTP_SERVER_FRAME_RST_STREAM_STATE:
520 ret = handle_http_frame_rst_stream(client);
521 break;
522 case HTTP_SERVER_FRAME_GOAWAY_STATE:
523 ret = handle_http_frame_goaway(client);
524 break;
525 case HTTP_SERVER_FRAME_PRIORITY_STATE:
526 ret = handle_http_frame_priority(client);
527 break;
528 case HTTP_SERVER_FRAME_PADDING_STATE:
529 ret = handle_http_frame_padding(client);
530 break;
531 case HTTP_SERVER_DONE_STATE:
532 ret = handle_http_done(client);
533 break;
534 default:
535 ret = handle_http_done(client);
536 break;
537 }
538 } while (ret >= 0 && client->data_len > 0);
539
540 if (ret < 0 && ret != -EAGAIN) {
541 return ret;
542 }
543
544 if (client->data_len > 0) {
545 /* Move any remaining data in the buffer. */
546 memmove(client->buffer, client->cursor, client->data_len);
547 }
548
549 return 0;
550 }
551
http_server_run(struct http_server_ctx * ctx)552 static int http_server_run(struct http_server_ctx *ctx)
553 {
554 struct http_client_ctx *client;
555 const struct http_service_desc *service;
556 eventfd_t value;
557 bool found_slot;
558 int new_socket;
559 int ret, i, j;
560 int sock_error;
561 socklen_t optlen = sizeof(int);
562
563 value = 0;
564
565 while (1) {
566 ret = zsock_poll(ctx->fds, HTTP_SERVER_SOCK_COUNT, -1);
567 if (ret < 0) {
568 ret = -errno;
569 LOG_DBG("poll failed (%d)", ret);
570 goto closing;
571 }
572
573 if (ret == 0) {
574 /* should not happen because timeout is -1 */
575 break;
576 }
577
578 if (ret == 1 && ctx->fds[0].revents) {
579 eventfd_read(ctx->fds[0].fd, &value);
580 LOG_DBG("Received stop event. exiting ..");
581 ret = 0;
582 goto closing;
583 }
584
585 for (i = 1; i < ARRAY_SIZE(ctx->fds); i++) {
586 if (ctx->fds[i].fd < 0) {
587 continue;
588 }
589
590 if (ctx->fds[i].revents & ZSOCK_POLLHUP) {
591 if (i >= ctx->listen_fds) {
592 LOG_DBG("Client #%d has disconnected",
593 i - ctx->listen_fds);
594
595 client = &ctx->clients[i - ctx->listen_fds];
596 close_client_connection(client);
597 }
598
599 continue;
600 }
601
602 if (ctx->fds[i].revents & ZSOCK_POLLERR) {
603 (void)zsock_getsockopt(ctx->fds[i].fd, SOL_SOCKET,
604 SO_ERROR, &sock_error, &optlen);
605 LOG_DBG("Error on fd %d %d", ctx->fds[i].fd, sock_error);
606
607 if (i >= ctx->listen_fds) {
608 client = &ctx->clients[i - ctx->listen_fds];
609 close_client_connection(client);
610 continue;
611 }
612
613 /* Listening socket error, abort. */
614 LOG_ERR("Listening socket error, aborting.");
615 ret = -sock_error;
616 goto closing;
617
618 }
619
620 if (!(ctx->fds[i].revents & ZSOCK_POLLIN)) {
621 continue;
622 }
623
624 /* First check if we have something to accept */
625 if (i < ctx->listen_fds) {
626 service = lookup_service(ctx->fds[i].fd);
627 __ASSERT(NULL != service, "fd not associated with a service");
628
629 if (service->data->num_clients >= service->concurrent) {
630 ctx->fds[i].events = 0;
631 continue;
632 }
633
634 new_socket = accept_new_client(ctx->fds[i].fd);
635 if (new_socket < 0) {
636 ret = -errno;
637 LOG_DBG("accept: %d", ret);
638 continue;
639 }
640
641 found_slot = false;
642
643 for (j = ctx->listen_fds; j < ARRAY_SIZE(ctx->fds); j++) {
644 if (ctx->fds[j].fd != INVALID_SOCK) {
645 continue;
646 }
647
648 ctx->fds[j].fd = new_socket;
649 ctx->fds[j].events = ZSOCK_POLLIN;
650 ctx->fds[j].revents = 0;
651
652 service->data->num_clients++;
653
654 LOG_DBG("Init client #%d", j - ctx->listen_fds);
655
656 init_client_ctx(&ctx->clients[j - ctx->listen_fds], service,
657 new_socket);
658 found_slot = true;
659 break;
660 }
661
662 if (!found_slot) {
663 LOG_DBG("No free slot found.");
664 zsock_close(new_socket);
665 }
666
667 continue;
668 }
669
670 /* Client sock */
671 client = &ctx->clients[i - ctx->listen_fds];
672
673 ret = zsock_recv(client->fd, client->buffer + client->data_len,
674 sizeof(client->buffer) - client->data_len, 0);
675 if (ret <= 0) {
676 if (ret == 0) {
677 LOG_DBG("Connection closed by peer for client #%d",
678 i - ctx->listen_fds);
679 } else {
680 ret = -errno;
681 LOG_DBG("ERROR reading from socket (%d)", ret);
682 }
683
684 close_client_connection(client);
685 continue;
686 }
687
688 client->data_len += ret;
689
690 http_client_timer_restart(client);
691
692 ret = handle_http_request(client);
693 if (ret < 0 && ret != -EAGAIN) {
694 if (ret == -ENOTCONN) {
695 LOG_DBG("Client closed connection while handling request");
696 } else {
697 LOG_ERR("HTTP request handling error (%d)", ret);
698 }
699 close_client_connection(client);
700 } else if (client->data_len == sizeof(client->buffer)) {
701 /* If the RX buffer is still full after parsing,
702 * it means we won't be able to handle this request
703 * with the current buffer size.
704 */
705 LOG_ERR("RX buffer too small to handle request");
706 close_client_connection(client);
707 }
708 }
709 }
710
711 return 0;
712
713 closing:
714 /* Close all client connections and the server socket */
715 close_all_sockets(ctx);
716 return ret;
717 }
718
719 /* Compare a path and a resource string. The path string comes from the HTTP request and may be
720 * terminated by either '?' or '\0'. The resource string is registered along with the resource and
721 * may only be terminated by `\0`.
722 */
compare_strings(const char * path,const char * resource)723 static int compare_strings(const char *path, const char *resource)
724 {
725 while ((*path && *resource) && (*path == *resource) && (*path != '?')) {
726 path++;
727 resource++;
728 }
729
730 /* Check if both strings have reached their terminators */
731 if ((*path == '\0' || *path == '?') && (*resource == '\0')) {
732 return 0; /* Strings are equal */
733 }
734
735 return 1; /* Strings are not equal */
736 }
737
path_len_without_query(const char * path)738 static int path_len_without_query(const char *path)
739 {
740 int len = 0;
741
742 while ((path[len] != '\0') && (path[len] != '?')) {
743 len++;
744 }
745
746 return len;
747 }
748
skip_this(struct http_resource_desc * resource,bool is_websocket)749 static bool skip_this(struct http_resource_desc *resource, bool is_websocket)
750 {
751 struct http_resource_detail *detail;
752
753 detail = (struct http_resource_detail *)resource->detail;
754
755 if (is_websocket) {
756 if (detail->type != HTTP_RESOURCE_TYPE_WEBSOCKET) {
757 return true;
758 }
759 } else {
760 if (detail->type == HTTP_RESOURCE_TYPE_WEBSOCKET) {
761 return true;
762 }
763 }
764
765 return false;
766 }
767
get_resource_detail(const struct http_service_desc * service,const char * path,int * path_len,bool is_websocket)768 struct http_resource_detail *get_resource_detail(const struct http_service_desc *service,
769 const char *path, int *path_len, bool is_websocket)
770 {
771 HTTP_SERVICE_FOREACH_RESOURCE(service, resource) {
772 if (skip_this(resource, is_websocket)) {
773 continue;
774 }
775
776 if (IS_ENABLED(CONFIG_HTTP_SERVER_RESOURCE_WILDCARD)) {
777 int ret;
778
779 ret = fnmatch(resource->resource, path, (FNM_PATHNAME | FNM_LEADING_DIR));
780 if (ret == 0) {
781 *path_len = path_len_without_query(path);
782 return resource->detail;
783 }
784 }
785
786 if (compare_strings(path, resource->resource) == 0) {
787 NET_DBG("Got match for %s", resource->resource);
788
789 *path_len = strlen(resource->resource);
790 return resource->detail;
791 }
792 }
793
794 if (service->res_fallback != NULL) {
795 *path_len = path_len_without_query(path);
796 return service->res_fallback;
797 }
798
799 NET_DBG("No match for %s", path);
800
801 return NULL;
802 }
803
http_server_find_file(char * fname,size_t fname_size,size_t * file_size,uint8_t supported_compression,enum http_compression * chosen_compression)804 int http_server_find_file(char *fname, size_t fname_size, size_t *file_size,
805 uint8_t supported_compression, enum http_compression *chosen_compression)
806 {
807 struct fs_dirent dirent;
808 int ret;
809
810 if (IS_ENABLED(CONFIG_HTTP_SERVER_COMPRESSION)) {
811 const size_t len = strlen(fname);
812 *chosen_compression = HTTP_NONE;
813 if (IS_BIT_SET(supported_compression, HTTP_BR)) {
814 snprintk(fname + len, fname_size - len, ".br");
815 ret = fs_stat(fname, &dirent);
816 if (ret == 0) {
817 *chosen_compression = HTTP_BR;
818 goto return_filename;
819 }
820 }
821 if (IS_BIT_SET(supported_compression, HTTP_GZIP)) {
822 snprintk(fname + len, fname_size - len, ".gz");
823 ret = fs_stat(fname, &dirent);
824 if (ret == 0) {
825 *chosen_compression = HTTP_GZIP;
826 goto return_filename;
827 }
828 }
829 if (IS_BIT_SET(supported_compression, HTTP_ZSTD)) {
830 snprintk(fname + len, fname_size - len, ".zst");
831 ret = fs_stat(fname, &dirent);
832 if (ret == 0) {
833 *chosen_compression = HTTP_ZSTD;
834 goto return_filename;
835 }
836 }
837 if (IS_BIT_SET(supported_compression, HTTP_COMPRESS)) {
838 snprintk(fname + len, fname_size - len, ".lzw");
839 ret = fs_stat(fname, &dirent);
840 if (ret == 0) {
841 *chosen_compression = HTTP_COMPRESS;
842 goto return_filename;
843 }
844 }
845 if (IS_BIT_SET(supported_compression, HTTP_DEFLATE)) {
846 snprintk(fname + len, fname_size - len, ".zz");
847 ret = fs_stat(fname, &dirent);
848 if (ret == 0) {
849 *chosen_compression = HTTP_DEFLATE;
850 goto return_filename;
851 }
852 }
853 /* No compressed file found, try the original filename */
854 fname[len] = '\0';
855 }
856 ret = fs_stat(fname, &dirent);
857 if (ret != 0) {
858 return -ENOENT;
859 }
860
861 return_filename:
862 *file_size = dirent.size;
863 return ret;
864 }
865
http_server_get_content_type_from_extension(char * url,char * content_type,size_t content_type_size)866 void http_server_get_content_type_from_extension(char *url, char *content_type,
867 size_t content_type_size)
868 {
869 size_t url_len = strlen(url);
870
871 HTTP_SERVER_CONTENT_TYPE_FOREACH(ct) {
872 char *ext;
873
874 if (url_len <= ct->extension_len) {
875 continue;
876 }
877
878 ext = &url[url_len - ct->extension_len];
879
880 if (strncmp(ext, ct->extension, ct->extension_len) == 0) {
881 strncpy(content_type, ct->content_type, content_type_size);
882 return;
883 }
884 }
885 }
886
http_server_sendall(struct http_client_ctx * client,const void * buf,size_t len)887 int http_server_sendall(struct http_client_ctx *client, const void *buf, size_t len)
888 {
889 while (len) {
890 ssize_t out_len = zsock_send(client->fd, buf, len, 0);
891
892 if (out_len < 0) {
893 return -errno;
894 }
895
896 buf = (const char *)buf + out_len;
897 len -= out_len;
898
899 http_client_timer_restart(client);
900 }
901
902 return 0;
903 }
904
http_response_is_final(struct http_response_ctx * rsp,enum http_data_status status)905 bool http_response_is_final(struct http_response_ctx *rsp, enum http_data_status status)
906 {
907 if (status != HTTP_SERVER_DATA_FINAL) {
908 return false;
909 }
910
911 if (rsp->final_chunk ||
912 (rsp->status == 0 && rsp->header_count == 0 && rsp->body_len == 0)) {
913 return true;
914 }
915
916 return false;
917 }
918
http_response_is_provided(struct http_response_ctx * rsp)919 bool http_response_is_provided(struct http_response_ctx *rsp)
920 {
921 if (rsp->status != 0 || rsp->header_count > 0 || rsp->body_len > 0) {
922 return true;
923 }
924
925 return false;
926 }
927
populate_request_ctx(struct http_request_ctx * req_ctx,uint8_t * data,size_t len,struct http_header_capture_ctx * header_ctx)928 void populate_request_ctx(struct http_request_ctx *req_ctx, uint8_t *data, size_t len,
929 struct http_header_capture_ctx *header_ctx)
930 {
931 req_ctx->data = data;
932 req_ctx->data_len = len;
933
934 if (NULL == header_ctx || header_ctx->status == HTTP_HEADER_STATUS_NONE) {
935 req_ctx->headers = NULL;
936 req_ctx->header_count = 0;
937 req_ctx->headers_status = HTTP_HEADER_STATUS_NONE;
938 } else {
939 req_ctx->headers = header_ctx->headers;
940 req_ctx->header_count = header_ctx->count;
941 req_ctx->headers_status = header_ctx->status;
942 }
943 }
944
http_server_start(void)945 int http_server_start(void)
946 {
947 if (server_running) {
948 LOG_DBG("HTTP server already started");
949 return -EALREADY;
950 }
951
952 server_running = true;
953 k_sem_give(&server_start);
954
955 LOG_DBG("Starting HTTP server");
956
957 return 0;
958 }
959
http_server_stop(void)960 int http_server_stop(void)
961 {
962 if (!server_running) {
963 LOG_DBG("HTTP server already stopped");
964 return -EALREADY;
965 }
966
967 server_running = false;
968 k_sem_reset(&server_start);
969 eventfd_write(server_ctx.fds[0].fd, 1);
970
971 LOG_DBG("Stopping HTTP server");
972
973 return 0;
974 }
975
http_server_thread(void * p1,void * p2,void * p3)976 static void http_server_thread(void *p1, void *p2, void *p3)
977 {
978 int ret;
979
980 ARG_UNUSED(p1);
981 ARG_UNUSED(p2);
982 ARG_UNUSED(p3);
983
984 while (true) {
985 k_sem_take(&server_start, K_FOREVER);
986
987 while (server_running) {
988 ret = http_server_init(&server_ctx);
989 if (ret < 0) {
990 LOG_ERR("Failed to initialize HTTP2 server");
991 goto again;
992 }
993
994 ret = http_server_run(&server_ctx);
995 if (!server_running) {
996 continue;
997 }
998
999 again:
1000 LOG_INF("Re-starting server (%d)", ret);
1001 k_sleep(K_MSEC(CONFIG_HTTP_SERVER_RESTART_DELAY));
1002 }
1003 }
1004 }
1005
1006 K_THREAD_DEFINE(http_server_tid, CONFIG_HTTP_SERVER_STACK_SIZE,
1007 http_server_thread, NULL, NULL, NULL, THREAD_PRIORITY, 0, 0);
1008