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/zvfs/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 	net_socklen_t len;
80 	int fd, af, i;
81 	struct net_sockaddr_storage addr_storage;
82 	const union {
83 		struct net_sockaddr *addr;
84 		struct net_sockaddr_in *addr4;
85 		struct net_sockaddr_in6 *addr6;
86 	} addr = {
87 		.addr = (struct net_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 = zvfs_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 / NET_INADDR_ANY are all 0) */
114 		memset(&addr_storage, 0, sizeof(struct net_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(NET_AF_INET6, svc->host, &addr.addr6->sin6_addr) == 1) {
119 			af = NET_AF_INET6;
120 			len = sizeof(*addr.addr6);
121 
122 			addr.addr6->sin6_family = NET_AF_INET6;
123 			addr.addr6->sin6_port = net_htons(*svc->port);
124 		} else if (IS_ENABLED(CONFIG_NET_IPV4) && svc->host != NULL &&
125 			   zsock_inet_pton(NET_AF_INET, svc->host, &addr.addr4->sin_addr) == 1) {
126 			af = NET_AF_INET;
127 			len = sizeof(*addr.addr4);
128 
129 			addr.addr4->sin_family = NET_AF_INET;
130 			addr.addr4->sin_port = net_htons(*svc->port);
131 		} else if (IS_ENABLED(CONFIG_NET_IPV6)) {
132 			/* prefer IPv6 if both IPv6 and IPv4 are supported */
133 			af = NET_AF_INET6;
134 			len = sizeof(*addr.addr6);
135 
136 			addr.addr6->sin6_family = NET_AF_INET6;
137 			addr.addr6->sin6_port = net_htons(*svc->port);
138 		} else if (IS_ENABLED(CONFIG_NET_IPV4)) {
139 			af = NET_AF_INET;
140 			len = sizeof(*addr.addr4);
141 
142 			addr.addr4->sin_family = NET_AF_INET;
143 			addr.addr4->sin_port = net_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 = NET_IPPROTO_TLS_1_2;
155 		} else {
156 			proto = NET_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, NET_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, NET_IPPROTO_IPV6, ZSOCK_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, ZSOCK_SOL_TLS, ZSOCK_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, ZSOCK_SOL_TLS, ZSOCK_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, ZSOCK_SOL_TLS, ZSOCK_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, ZSOCK_SOL_SOCKET, ZSOCK_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 = net_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 	net_socklen_t addrlen;
267 	struct net_sockaddr_storage sa;
268 
269 	memset(&sa, 0, sizeof(sa));
270 	addrlen = sizeof(sa);
271 
272 	new_socket = zsock_accept(server_fd, (struct net_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 net_sockaddr *)&sa)->sin_addr);
281 	LOG_DBG("New client from %s:%d", addrstr != NULL ? addrstr : "<unknown>",
282 		net_ntohs(net_sin((struct net_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 	if (fd >= 0) {
387 		http_server_release_client(client);
388 
389 		(void)zsock_close(fd);
390 	}
391 }
392 
client_timeout(struct k_work * work)393 static void client_timeout(struct k_work *work)
394 {
395 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
396 	struct http_client_ctx *client =
397 		CONTAINER_OF(dwork, struct http_client_ctx, inactivity_timer);
398 
399 	LOG_DBG("Client %p timeout", client);
400 
401 	/* Shutdown the socket. This will be detected by poll() and a proper
402 	 * cleanup will proceed.
403 	 */
404 	(void)zsock_shutdown(client->fd, ZSOCK_SHUT_RD);
405 }
406 
http_client_timer_restart(struct http_client_ctx * client)407 void http_client_timer_restart(struct http_client_ctx *client)
408 {
409 	__ASSERT_NO_MSG(IS_ARRAY_ELEMENT(server_ctx.clients, client));
410 
411 	k_work_reschedule(&client->inactivity_timer, INACTIVITY_TIMEOUT);
412 }
413 
lookup_service(int server_fd)414 static const struct http_service_desc *lookup_service(int server_fd)
415 {
416 	HTTP_SERVICE_FOREACH(svc) {
417 		if (*svc->fd == server_fd) {
418 			return svc;
419 		}
420 	}
421 
422 	return NULL;
423 }
424 
init_client_ctx(struct http_client_ctx * client,const struct http_service_desc * svc,int new_socket)425 static void init_client_ctx(struct http_client_ctx *client, const struct http_service_desc *svc,
426 			    int new_socket)
427 {
428 	client->fd = new_socket;
429 	client->service = svc;
430 	client->data_len = 0;
431 	client->server_state = HTTP_SERVER_PREFACE_STATE;
432 	client->has_upgrade_header = false;
433 	client->preface_sent = false;
434 	client->window_size = HTTP_SERVER_INITIAL_WINDOW_SIZE;
435 
436 	memset(client->buffer, 0, sizeof(client->buffer));
437 	memset(client->url_buffer, 0, sizeof(client->url_buffer));
438 	k_work_init_delayable(&client->inactivity_timer, client_timeout);
439 	http_client_timer_restart(client);
440 
441 	ARRAY_FOR_EACH(client->streams, i) {
442 		client->streams[i].stream_state = HTTP2_STREAM_IDLE;
443 		client->streams[i].stream_id = 0;
444 	}
445 
446 	client->current_stream = NULL;
447 }
448 
handle_http_preface(struct http_client_ctx * client)449 static int handle_http_preface(struct http_client_ctx *client)
450 {
451 	LOG_DBG("HTTP_SERVER_PREFACE_STATE.");
452 
453 	if (client->data_len < sizeof(HTTP2_PREFACE) - 1) {
454 		/* We don't have full preface yet, get more data. */
455 		return -EAGAIN;
456 	}
457 
458 	if (IS_ENABLED(CONFIG_HTTP_SERVER_CAPTURE_HEADERS)) {
459 		client->header_capture_ctx.count = 0;
460 		client->header_capture_ctx.cursor = 0;
461 		client->header_capture_ctx.status = HTTP_HEADER_STATUS_OK;
462 	}
463 
464 	if (strncmp(client->cursor, HTTP2_PREFACE, sizeof(HTTP2_PREFACE) - 1) != 0) {
465 		return enter_http1_request(client);
466 	}
467 
468 	return enter_http2_request(client);
469 }
470 
handle_http_done(struct http_client_ctx * client)471 static int handle_http_done(struct http_client_ctx *client)
472 {
473 	LOG_DBG("HTTP_SERVER_DONE_STATE");
474 
475 	close_client_connection(client);
476 
477 	return -EAGAIN;
478 }
479 
enter_http_done_state(struct http_client_ctx * client)480 int enter_http_done_state(struct http_client_ctx *client)
481 {
482 	close_client_connection(client);
483 
484 	client->server_state = HTTP_SERVER_DONE_STATE;
485 
486 	return -EAGAIN;
487 }
488 
handle_http_request(struct http_client_ctx * client)489 static int handle_http_request(struct http_client_ctx *client)
490 {
491 	int ret = -EINVAL;
492 
493 	client->cursor = client->buffer;
494 
495 	do {
496 		switch (client->server_state) {
497 		case HTTP_SERVER_FRAME_DATA_STATE:
498 			ret = handle_http_frame_data(client);
499 			break;
500 		case HTTP_SERVER_PREFACE_STATE:
501 			ret = handle_http_preface(client);
502 			break;
503 		case HTTP_SERVER_REQUEST_STATE:
504 			ret = handle_http1_request(client);
505 			break;
506 		case HTTP_SERVER_FRAME_HEADER_STATE:
507 			ret = handle_http_frame_header(client);
508 			break;
509 		case HTTP_SERVER_FRAME_HEADERS_STATE:
510 			ret = handle_http_frame_headers(client);
511 			break;
512 		case HTTP_SERVER_FRAME_CONTINUATION_STATE:
513 			ret = handle_http_frame_continuation(client);
514 			break;
515 		case HTTP_SERVER_FRAME_SETTINGS_STATE:
516 			ret = handle_http_frame_settings(client);
517 			break;
518 		case HTTP_SERVER_FRAME_WINDOW_UPDATE_STATE:
519 			ret = handle_http_frame_window_update(client);
520 			break;
521 		case HTTP_SERVER_FRAME_RST_STREAM_STATE:
522 			ret = handle_http_frame_rst_stream(client);
523 			break;
524 		case HTTP_SERVER_FRAME_GOAWAY_STATE:
525 			ret = handle_http_frame_goaway(client);
526 			break;
527 		case HTTP_SERVER_FRAME_PRIORITY_STATE:
528 			ret = handle_http_frame_priority(client);
529 			break;
530 		case HTTP_SERVER_FRAME_PADDING_STATE:
531 			ret = handle_http_frame_padding(client);
532 			break;
533 		case HTTP_SERVER_DONE_STATE:
534 			ret = handle_http_done(client);
535 			break;
536 		default:
537 			ret = handle_http_done(client);
538 			break;
539 		}
540 	} while (ret >= 0 && client->data_len > 0);
541 
542 	if (ret < 0 && ret != -EAGAIN) {
543 		return ret;
544 	}
545 
546 	if (client->data_len > 0) {
547 		/* Move any remaining data in the buffer. */
548 		memmove(client->buffer, client->cursor, client->data_len);
549 	}
550 
551 	return 0;
552 }
553 
http_server_run(struct http_server_ctx * ctx)554 static int http_server_run(struct http_server_ctx *ctx)
555 {
556 	struct http_client_ctx *client;
557 	const struct http_service_desc *service;
558 	zvfs_eventfd_t value;
559 	bool found_slot;
560 	int new_socket;
561 	int ret, i, j;
562 	int sock_error;
563 	net_socklen_t optlen = sizeof(int);
564 
565 	value = 0;
566 
567 	while (1) {
568 		ret = zsock_poll(ctx->fds, HTTP_SERVER_SOCK_COUNT, -1);
569 		if (ret < 0) {
570 			ret = -errno;
571 			LOG_DBG("poll failed (%d)", ret);
572 			goto closing;
573 		}
574 
575 		if (ret == 0) {
576 			/* should not happen because timeout is -1 */
577 			break;
578 		}
579 
580 		if (ret == 1 && ctx->fds[0].revents) {
581 			zvfs_eventfd_read(ctx->fds[0].fd, &value);
582 			LOG_DBG("Received stop event. exiting ..");
583 			ret = 0;
584 			goto closing;
585 		}
586 
587 		for (i = 1; i < ARRAY_SIZE(ctx->fds); i++) {
588 			if (ctx->fds[i].fd < 0) {
589 				continue;
590 			}
591 
592 			if (ctx->fds[i].revents & ZSOCK_POLLHUP) {
593 				if (i >= ctx->listen_fds) {
594 					LOG_DBG("Client #%d has disconnected",
595 						i - ctx->listen_fds);
596 
597 					client = &ctx->clients[i - ctx->listen_fds];
598 					close_client_connection(client);
599 				}
600 
601 				continue;
602 			}
603 
604 			if (ctx->fds[i].revents & ZSOCK_POLLERR) {
605 				(void)zsock_getsockopt(ctx->fds[i].fd, ZSOCK_SOL_SOCKET,
606 						       ZSOCK_SO_ERROR, &sock_error, &optlen);
607 				LOG_DBG("Error on fd %d %d", ctx->fds[i].fd, sock_error);
608 
609 				if (i >= ctx->listen_fds) {
610 					client = &ctx->clients[i - ctx->listen_fds];
611 					close_client_connection(client);
612 					continue;
613 				}
614 
615 				ret = -sock_error;
616 
617 				if (ret == -ENETDOWN) {
618 					LOG_INF("Network is down");
619 				} else {
620 					LOG_ERR("Listening socket error, aborting. (%d)", ret);
621 				}
622 
623 				goto closing;
624 
625 			}
626 
627 			if (!(ctx->fds[i].revents & ZSOCK_POLLIN)) {
628 				continue;
629 			}
630 
631 			/* First check if we have something to accept */
632 			if (i < ctx->listen_fds) {
633 				service = lookup_service(ctx->fds[i].fd);
634 				__ASSERT(NULL != service, "fd not associated with a service");
635 
636 				if (service->data->num_clients >= service->concurrent) {
637 					ctx->fds[i].events = 0;
638 					continue;
639 				}
640 
641 				new_socket = accept_new_client(ctx->fds[i].fd);
642 				if (new_socket < 0) {
643 					ret = -errno;
644 					LOG_DBG("accept: %d", ret);
645 					continue;
646 				}
647 
648 				found_slot = false;
649 
650 				for (j = ctx->listen_fds; j < ARRAY_SIZE(ctx->fds); j++) {
651 					if (ctx->fds[j].fd != INVALID_SOCK) {
652 						continue;
653 					}
654 
655 					ctx->fds[j].fd = new_socket;
656 					ctx->fds[j].events = ZSOCK_POLLIN;
657 					ctx->fds[j].revents = 0;
658 
659 					service->data->num_clients++;
660 
661 					LOG_DBG("Init client #%d", j - ctx->listen_fds);
662 
663 					init_client_ctx(&ctx->clients[j - ctx->listen_fds], service,
664 							new_socket);
665 					found_slot = true;
666 					break;
667 				}
668 
669 				if (!found_slot) {
670 					LOG_DBG("No free slot found.");
671 					zsock_close(new_socket);
672 				}
673 
674 				continue;
675 			}
676 
677 			/* Client sock */
678 			client = &ctx->clients[i - ctx->listen_fds];
679 
680 			ret = zsock_recv(client->fd, client->buffer + client->data_len,
681 					 sizeof(client->buffer) - client->data_len, 0);
682 			if (ret <= 0) {
683 				if (ret == 0) {
684 					LOG_DBG("Connection closed by peer for client #%d",
685 						i - ctx->listen_fds);
686 				} else {
687 					ret = -errno;
688 					LOG_DBG("ERROR reading from socket (%d)", ret);
689 				}
690 
691 				close_client_connection(client);
692 				continue;
693 			}
694 
695 			client->data_len += ret;
696 
697 			http_client_timer_restart(client);
698 
699 			ret = handle_http_request(client);
700 			if (ret < 0 && ret != -EAGAIN) {
701 				if (ret == -ENOTCONN) {
702 					LOG_DBG("Client closed connection while handling request");
703 				} else {
704 					LOG_ERR("HTTP request handling error (%d)", ret);
705 				}
706 				close_client_connection(client);
707 			} else if (client->data_len == sizeof(client->buffer)) {
708 				/* If the RX buffer is still full after parsing,
709 				 * it means we won't be able to handle this request
710 				 * with the current buffer size.
711 				 */
712 				LOG_ERR("RX buffer too small to handle request");
713 				close_client_connection(client);
714 			}
715 		}
716 	}
717 
718 	return 0;
719 
720 closing:
721 	/* Close all client connections and the server socket */
722 	close_all_sockets(ctx);
723 	return ret;
724 }
725 
726 /* Compare a path and a resource string. The path string comes from the HTTP request and may be
727  * terminated by either '?' or '\0'. The resource string is registered along with the resource and
728  * may only be terminated by `\0`.
729  */
compare_strings(const char * path,const char * resource)730 static int compare_strings(const char *path, const char *resource)
731 {
732 	while ((*path && *resource) && (*path == *resource) && (*path != '?')) {
733 		path++;
734 		resource++;
735 	}
736 
737 	/* Check if both strings have reached their terminators */
738 	if ((*path == '\0' || *path == '?') && (*resource == '\0')) {
739 		return 0; /* Strings are equal */
740 	}
741 
742 	return 1; /* Strings are not equal */
743 }
744 
path_len_without_query(const char * path)745 static int path_len_without_query(const char *path)
746 {
747 	int len = 0;
748 
749 	while ((path[len] != '\0') && (path[len] != '?')) {
750 		len++;
751 	}
752 
753 	return len;
754 }
755 
skip_this(struct http_resource_desc * resource,bool is_websocket)756 static bool skip_this(struct http_resource_desc *resource, bool is_websocket)
757 {
758 	struct http_resource_detail *detail;
759 
760 	detail = (struct http_resource_detail *)resource->detail;
761 
762 	if (is_websocket) {
763 		if (detail->type != HTTP_RESOURCE_TYPE_WEBSOCKET) {
764 			return true;
765 		}
766 	} else {
767 		if (detail->type == HTTP_RESOURCE_TYPE_WEBSOCKET) {
768 			return true;
769 		}
770 	}
771 
772 	return false;
773 }
774 
get_resource_detail(const struct http_service_desc * service,const char * path,int * path_len,bool is_websocket)775 struct http_resource_detail *get_resource_detail(const struct http_service_desc *service,
776 						 const char *path, int *path_len, bool is_websocket)
777 {
778 	HTTP_SERVICE_FOREACH_RESOURCE(service, resource) {
779 		if (skip_this(resource, is_websocket)) {
780 			continue;
781 		}
782 
783 		if (IS_ENABLED(CONFIG_HTTP_SERVER_RESOURCE_WILDCARD)) {
784 			int ret;
785 
786 			ret = fnmatch(resource->resource, path, (FNM_PATHNAME | FNM_LEADING_DIR));
787 			if (ret == 0) {
788 				*path_len = path_len_without_query(path);
789 				return resource->detail;
790 			}
791 		}
792 
793 		if (compare_strings(path, resource->resource) == 0) {
794 			NET_DBG("Got match for %s", resource->resource);
795 
796 			*path_len = strlen(resource->resource);
797 			return resource->detail;
798 		}
799 	}
800 
801 	if (service->res_fallback != NULL) {
802 		*path_len = path_len_without_query(path);
803 		return service->res_fallback;
804 	}
805 
806 	NET_DBG("No match for %s", path);
807 
808 	return NULL;
809 }
810 
http_server_find_file(char * fname,size_t fname_size,size_t * file_size,uint8_t supported_compression,enum http_compression * chosen_compression)811 int http_server_find_file(char *fname, size_t fname_size, size_t *file_size,
812 			  uint8_t supported_compression, enum http_compression *chosen_compression)
813 {
814 	struct fs_dirent dirent;
815 	int ret;
816 
817 	if (IS_ENABLED(CONFIG_HTTP_SERVER_COMPRESSION)) {
818 		const size_t len = strlen(fname);
819 		*chosen_compression = HTTP_NONE;
820 		if (IS_BIT_SET(supported_compression, HTTP_BR)) {
821 			snprintk(fname + len, fname_size - len, ".br");
822 			ret = fs_stat(fname, &dirent);
823 			if (ret == 0) {
824 				*chosen_compression = HTTP_BR;
825 				goto return_filename;
826 			}
827 		}
828 		if (IS_BIT_SET(supported_compression, HTTP_GZIP)) {
829 			snprintk(fname + len, fname_size - len, ".gz");
830 			ret = fs_stat(fname, &dirent);
831 			if (ret == 0) {
832 				*chosen_compression = HTTP_GZIP;
833 				goto return_filename;
834 			}
835 		}
836 		if (IS_BIT_SET(supported_compression, HTTP_ZSTD)) {
837 			snprintk(fname + len, fname_size - len, ".zst");
838 			ret = fs_stat(fname, &dirent);
839 			if (ret == 0) {
840 				*chosen_compression = HTTP_ZSTD;
841 				goto return_filename;
842 			}
843 		}
844 		if (IS_BIT_SET(supported_compression, HTTP_COMPRESS)) {
845 			snprintk(fname + len, fname_size - len, ".lzw");
846 			ret = fs_stat(fname, &dirent);
847 			if (ret == 0) {
848 				*chosen_compression = HTTP_COMPRESS;
849 				goto return_filename;
850 			}
851 		}
852 		if (IS_BIT_SET(supported_compression, HTTP_DEFLATE)) {
853 			snprintk(fname + len, fname_size - len, ".zz");
854 			ret = fs_stat(fname, &dirent);
855 			if (ret == 0) {
856 				*chosen_compression = HTTP_DEFLATE;
857 				goto return_filename;
858 			}
859 		}
860 		/* No compressed file found, try the original filename */
861 		fname[len] = '\0';
862 	}
863 	ret = fs_stat(fname, &dirent);
864 	if (ret != 0) {
865 		return -ENOENT;
866 	}
867 
868 return_filename:
869 	*file_size = dirent.size;
870 	return ret;
871 }
872 
http_server_get_content_type_from_extension(char * url,char * content_type,size_t content_type_size)873 void http_server_get_content_type_from_extension(char *url, char *content_type,
874 						 size_t content_type_size)
875 {
876 	size_t url_len = strlen(url);
877 
878 	HTTP_SERVER_CONTENT_TYPE_FOREACH(ct) {
879 		char *ext;
880 
881 		if (url_len <= ct->extension_len) {
882 			continue;
883 		}
884 
885 		ext = &url[url_len - ct->extension_len];
886 
887 		if (strncmp(ext, ct->extension, ct->extension_len) == 0) {
888 			strncpy(content_type, ct->content_type, content_type_size);
889 			return;
890 		}
891 	}
892 }
893 
http_server_sendall(struct http_client_ctx * client,const void * buf,size_t len)894 int http_server_sendall(struct http_client_ctx *client, const void *buf, size_t len)
895 {
896 	while (len) {
897 		ssize_t out_len = zsock_send(client->fd, buf, len, 0);
898 
899 		if (out_len < 0) {
900 			return -errno;
901 		}
902 
903 		buf = (const char *)buf + out_len;
904 		len -= out_len;
905 
906 		http_client_timer_restart(client);
907 	}
908 
909 	return 0;
910 }
911 
http_response_is_final(struct http_response_ctx * rsp,enum http_data_status status)912 bool http_response_is_final(struct http_response_ctx *rsp, enum http_data_status status)
913 {
914 	if (status != HTTP_SERVER_DATA_FINAL) {
915 		return false;
916 	}
917 
918 	if (rsp->final_chunk ||
919 	    (rsp->status == 0 && rsp->header_count == 0 && rsp->body_len == 0)) {
920 		return true;
921 	}
922 
923 	return false;
924 }
925 
http_response_is_provided(struct http_response_ctx * rsp)926 bool http_response_is_provided(struct http_response_ctx *rsp)
927 {
928 	if (rsp->status != 0 || rsp->header_count > 0 || rsp->body_len > 0) {
929 		return true;
930 	}
931 
932 	return false;
933 }
934 
populate_request_ctx(struct http_request_ctx * req_ctx,uint8_t * data,size_t len,struct http_header_capture_ctx * header_ctx)935 void populate_request_ctx(struct http_request_ctx *req_ctx, uint8_t *data, size_t len,
936 			  struct http_header_capture_ctx *header_ctx)
937 {
938 	req_ctx->data = data;
939 	req_ctx->data_len = len;
940 
941 	if (NULL == header_ctx || header_ctx->status == HTTP_HEADER_STATUS_NONE) {
942 		req_ctx->headers = NULL;
943 		req_ctx->header_count = 0;
944 		req_ctx->headers_status = HTTP_HEADER_STATUS_NONE;
945 	} else {
946 		req_ctx->headers = header_ctx->headers;
947 		req_ctx->header_count = header_ctx->count;
948 		req_ctx->headers_status = header_ctx->status;
949 	}
950 }
951 
http_server_start(void)952 int http_server_start(void)
953 {
954 	if (server_running) {
955 		LOG_DBG("HTTP server already started");
956 		return -EALREADY;
957 	}
958 
959 	server_running = true;
960 	k_sem_give(&server_start);
961 
962 	LOG_DBG("Starting HTTP server");
963 
964 	return 0;
965 }
966 
http_server_stop(void)967 int http_server_stop(void)
968 {
969 	if (!server_running) {
970 		LOG_DBG("HTTP server already stopped");
971 		return -EALREADY;
972 	}
973 
974 	server_running = false;
975 	k_sem_reset(&server_start);
976 	zvfs_eventfd_write(server_ctx.fds[0].fd, 1);
977 
978 	LOG_DBG("Stopping HTTP server");
979 
980 	return 0;
981 }
982 
http_server_thread(void * p1,void * p2,void * p3)983 static void http_server_thread(void *p1, void *p2, void *p3)
984 {
985 	int ret;
986 
987 	ARG_UNUSED(p1);
988 	ARG_UNUSED(p2);
989 	ARG_UNUSED(p3);
990 
991 	while (true) {
992 		k_sem_take(&server_start, K_FOREVER);
993 
994 		while (server_running) {
995 			ret = http_server_init(&server_ctx);
996 			if (ret < 0) {
997 				LOG_ERR("Failed to initialize HTTP2 server");
998 				goto again;
999 			}
1000 
1001 			ret = http_server_run(&server_ctx);
1002 			if (!server_running) {
1003 				continue;
1004 			}
1005 
1006 again:
1007 			LOG_INF("Re-starting server (%d)", ret);
1008 			k_sleep(K_MSEC(CONFIG_HTTP_SERVER_RESTART_DELAY));
1009 		}
1010 	}
1011 }
1012 
1013 K_THREAD_DEFINE(http_server_tid, CONFIG_HTTP_SERVER_STACK_SIZE,
1014 		http_server_thread, NULL, NULL, NULL, THREAD_PRIORITY, 0, 0);
1015