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