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 
26 LOG_MODULE_REGISTER(net_http_server, CONFIG_NET_HTTP_SERVER_LOG_LEVEL);
27 
28 #include "../../ip/net_private.h"
29 #include "headers/server_internal.h"
30 
31 #if defined(CONFIG_NET_TC_THREAD_COOPERATIVE)
32 /* Lowest priority cooperative thread */
33 #define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)
34 #else
35 #define THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1)
36 #endif
37 
38 #define INVALID_SOCK -1
39 #define INACTIVITY_TIMEOUT K_SECONDS(CONFIG_HTTP_SERVER_CLIENT_INACTIVITY_TIMEOUT)
40 
41 #define HTTP_SERVER_MAX_SERVICES CONFIG_HTTP_SERVER_NUM_SERVICES
42 #define HTTP_SERVER_MAX_CLIENTS  CONFIG_HTTP_SERVER_MAX_CLIENTS
43 #define HTTP_SERVER_SOCK_COUNT (1 + HTTP_SERVER_MAX_SERVICES + HTTP_SERVER_MAX_CLIENTS)
44 
45 struct http_server_ctx {
46 	int num_clients;
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 		fd = zsock_socket(af, SOCK_STREAM, proto);
160 		if (fd < 0) {
161 			LOG_ERR("socket: %d", errno);
162 			failed++;
163 			continue;
164 		}
165 
166 		/* If IPv4-to-IPv6 mapping is enabled, then turn off V6ONLY option
167 		 * so that IPv6 socket can serve IPv4 connections.
168 		 */
169 		if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) {
170 			int optval = 0;
171 
172 			(void)zsock_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval,
173 					       sizeof(optval));
174 		}
175 
176 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
177 		if (svc->sec_tag_list != NULL) {
178 			if (zsock_setsockopt(fd, SOL_TLS, TLS_SEC_TAG_LIST,
179 					     svc->sec_tag_list,
180 					     svc->sec_tag_list_size) < 0) {
181 				LOG_ERR("setsockopt: %d", errno);
182 				zsock_close(fd);
183 				continue;
184 			}
185 
186 			if (zsock_setsockopt(fd, SOL_TLS, TLS_HOSTNAME, "localhost",
187 					     sizeof("localhost")) < 0) {
188 				LOG_ERR("setsockopt: %d", errno);
189 				zsock_close(fd);
190 				continue;
191 			}
192 
193 #if defined(CONFIG_HTTP_SERVER_TLS_USE_ALPN)
194 			if (zsock_setsockopt(fd, SOL_TLS, TLS_ALPN_LIST, alpn_list,
195 					     sizeof(alpn_list)) < 0) {
196 				LOG_ERR("setsockopt: %d", errno);
197 				zsock_close(fd);
198 				continue;
199 			}
200 #endif /* defined(CONFIG_HTTP_SERVER_TLS_USE_ALPN) */
201 		}
202 #endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */
203 
204 		if (zsock_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1},
205 				     sizeof(int)) < 0) {
206 			LOG_ERR("setsockopt: %d", errno);
207 			zsock_close(fd);
208 			continue;
209 		}
210 
211 		if (zsock_bind(fd, addr.addr, len) < 0) {
212 			LOG_ERR("bind: %d", errno);
213 			failed++;
214 			zsock_close(fd);
215 			continue;
216 		}
217 
218 		if (*svc->port == 0) {
219 			/* ephemeral port - read back the port number */
220 			len = sizeof(addr_storage);
221 			if (zsock_getsockname(fd, addr.addr, &len) < 0) {
222 				LOG_ERR("getsockname: %d", errno);
223 				zsock_close(fd);
224 				continue;
225 			}
226 
227 			*svc->port = ntohs(addr.addr4->sin_port);
228 		}
229 
230 		if (zsock_listen(fd, HTTP_SERVER_MAX_CLIENTS) < 0) {
231 			LOG_ERR("listen: %d", errno);
232 			failed++;
233 			zsock_close(fd);
234 			continue;
235 		}
236 
237 		LOG_DBG("Initialized HTTP Service %s:%u",
238 			svc->host ? svc->host : "<any>", *svc->port);
239 
240 		ctx->fds[count].fd = fd;
241 		ctx->fds[count].events = ZSOCK_POLLIN;
242 		count++;
243 	}
244 
245 	if (failed >= svc_count) {
246 		LOG_ERR("All services failed (%d)", failed);
247 		/* Close eventfd socket */
248 		zsock_close(ctx->fds[0].fd);
249 		return -ESRCH;
250 	}
251 
252 	ctx->listen_fds = count;
253 	ctx->num_clients = 0;
254 
255 	return 0;
256 }
257 
accept_new_client(int server_fd)258 static int accept_new_client(int server_fd)
259 {
260 	int new_socket;
261 	socklen_t addrlen;
262 	struct sockaddr_storage sa;
263 
264 	memset(&sa, 0, sizeof(sa));
265 	addrlen = sizeof(sa);
266 
267 	new_socket = zsock_accept(server_fd, (struct sockaddr *)&sa, &addrlen);
268 	if (new_socket < 0) {
269 		new_socket = -errno;
270 		LOG_DBG("[%d] accept failed (%d)", server_fd, new_socket);
271 		return new_socket;
272 	}
273 
274 	LOG_DBG("New client from %s:%d",
275 		net_sprint_addr(sa.ss_family, &net_sin((struct sockaddr *)&sa)->sin_addr),
276 		ntohs(net_sin((struct sockaddr *)&sa)->sin_port));
277 
278 	return new_socket;
279 }
280 
close_all_sockets(struct http_server_ctx * ctx)281 static void close_all_sockets(struct http_server_ctx *ctx)
282 {
283 	zsock_close(ctx->fds[0].fd); /* close eventfd */
284 	ctx->fds[0].fd = -1;
285 
286 	for (int i = 1; i < ARRAY_SIZE(ctx->fds); i++) {
287 		if (ctx->fds[i].fd < 0) {
288 			continue;
289 		}
290 
291 		if (i < ctx->listen_fds) {
292 			zsock_close(ctx->fds[i].fd);
293 		} else {
294 			struct http_client_ctx *client =
295 				&server_ctx.clients[i - ctx->listen_fds];
296 
297 			close_client_connection(client);
298 		}
299 
300 		ctx->fds[i].fd = -1;
301 	}
302 }
303 
client_release_resources(struct http_client_ctx * client)304 static void client_release_resources(struct http_client_ctx *client)
305 {
306 	struct http_resource_detail *detail;
307 	struct http_resource_detail_dynamic *dynamic_detail;
308 	struct http_request_ctx request_ctx;
309 	struct http_response_ctx response_ctx;
310 
311 	HTTP_SERVICE_FOREACH(service) {
312 		HTTP_SERVICE_FOREACH_RESOURCE(service, resource) {
313 			detail = resource->detail;
314 
315 			if (detail->type != HTTP_RESOURCE_TYPE_DYNAMIC) {
316 				continue;
317 			}
318 
319 			dynamic_detail = (struct http_resource_detail_dynamic *)detail;
320 
321 			if (dynamic_detail->holder != client) {
322 				continue;
323 			}
324 
325 			/* If the client still holds the resource at this point,
326 			 * it means the transaction was not complete. Release
327 			 * the resource and notify application.
328 			 */
329 			dynamic_detail->holder = NULL;
330 
331 			if (dynamic_detail->cb == NULL) {
332 				continue;
333 			}
334 
335 			populate_request_ctx(&request_ctx, NULL, 0, NULL);
336 
337 			dynamic_detail->cb(client, HTTP_SERVER_DATA_ABORTED, &request_ctx,
338 					   &response_ctx, dynamic_detail->user_data);
339 		}
340 	}
341 }
342 
http_server_release_client(struct http_client_ctx * client)343 void http_server_release_client(struct http_client_ctx *client)
344 {
345 	int i;
346 	struct k_work_sync sync;
347 
348 	__ASSERT_NO_MSG(IS_ARRAY_ELEMENT(server_ctx.clients, client));
349 
350 	k_work_cancel_delayable_sync(&client->inactivity_timer, &sync);
351 	client_release_resources(client);
352 
353 	server_ctx.num_clients--;
354 
355 	for (i = server_ctx.listen_fds; i < ARRAY_SIZE(server_ctx.fds); i++) {
356 		if (server_ctx.fds[i].fd == client->fd) {
357 			server_ctx.fds[i].fd = INVALID_SOCK;
358 			break;
359 		}
360 	}
361 
362 	memset(client, 0, sizeof(struct http_client_ctx));
363 	client->fd = INVALID_SOCK;
364 }
365 
close_client_connection(struct http_client_ctx * client)366 static void close_client_connection(struct http_client_ctx *client)
367 {
368 	int fd = client->fd;
369 
370 	http_server_release_client(client);
371 
372 	(void)zsock_close(fd);
373 }
374 
client_timeout(struct k_work * work)375 static void client_timeout(struct k_work *work)
376 {
377 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
378 	struct http_client_ctx *client =
379 		CONTAINER_OF(dwork, struct http_client_ctx, inactivity_timer);
380 
381 	LOG_DBG("Client %p timeout", client);
382 
383 	/* Shutdown the socket. This will be detected by poll() and a proper
384 	 * cleanup will proceed.
385 	 */
386 	(void)zsock_shutdown(client->fd, ZSOCK_SHUT_RD);
387 }
388 
http_client_timer_restart(struct http_client_ctx * client)389 void http_client_timer_restart(struct http_client_ctx *client)
390 {
391 	__ASSERT_NO_MSG(IS_ARRAY_ELEMENT(server_ctx.clients, client));
392 
393 	k_work_reschedule(&client->inactivity_timer, INACTIVITY_TIMEOUT);
394 }
395 
init_client_ctx(struct http_client_ctx * client,int new_socket)396 static void init_client_ctx(struct http_client_ctx *client, int new_socket)
397 {
398 	client->fd = new_socket;
399 	client->data_len = 0;
400 	client->server_state = HTTP_SERVER_PREFACE_STATE;
401 	client->has_upgrade_header = false;
402 	client->preface_sent = false;
403 	client->window_size = HTTP_SERVER_INITIAL_WINDOW_SIZE;
404 
405 	memset(client->buffer, 0, sizeof(client->buffer));
406 	memset(client->url_buffer, 0, sizeof(client->url_buffer));
407 	k_work_init_delayable(&client->inactivity_timer, client_timeout);
408 	http_client_timer_restart(client);
409 
410 	ARRAY_FOR_EACH(client->streams, i) {
411 		client->streams[i].stream_state = HTTP2_STREAM_IDLE;
412 		client->streams[i].stream_id = 0;
413 	}
414 
415 	client->current_stream = NULL;
416 }
417 
handle_http_preface(struct http_client_ctx * client)418 static int handle_http_preface(struct http_client_ctx *client)
419 {
420 	LOG_DBG("HTTP_SERVER_PREFACE_STATE.");
421 
422 	if (client->data_len < sizeof(HTTP2_PREFACE) - 1) {
423 		/* We don't have full preface yet, get more data. */
424 		return -EAGAIN;
425 	}
426 
427 	if (IS_ENABLED(CONFIG_HTTP_SERVER_CAPTURE_HEADERS)) {
428 		client->header_capture_ctx.count = 0;
429 		client->header_capture_ctx.cursor = 0;
430 		client->header_capture_ctx.status = HTTP_HEADER_STATUS_OK;
431 	}
432 
433 	if (strncmp(client->cursor, HTTP2_PREFACE, sizeof(HTTP2_PREFACE) - 1) != 0) {
434 		return enter_http1_request(client);
435 	}
436 
437 	return enter_http2_request(client);
438 }
439 
handle_http_done(struct http_client_ctx * client)440 static int handle_http_done(struct http_client_ctx *client)
441 {
442 	LOG_DBG("HTTP_SERVER_DONE_STATE");
443 
444 	close_client_connection(client);
445 
446 	return -EAGAIN;
447 }
448 
enter_http_done_state(struct http_client_ctx * client)449 int enter_http_done_state(struct http_client_ctx *client)
450 {
451 	close_client_connection(client);
452 
453 	client->server_state = HTTP_SERVER_DONE_STATE;
454 
455 	return -EAGAIN;
456 }
457 
handle_http_request(struct http_client_ctx * client)458 static int handle_http_request(struct http_client_ctx *client)
459 {
460 	int ret = -EINVAL;
461 
462 	client->cursor = client->buffer;
463 
464 	do {
465 		switch (client->server_state) {
466 		case HTTP_SERVER_FRAME_DATA_STATE:
467 			ret = handle_http_frame_data(client);
468 			break;
469 		case HTTP_SERVER_PREFACE_STATE:
470 			ret = handle_http_preface(client);
471 			break;
472 		case HTTP_SERVER_REQUEST_STATE:
473 			ret = handle_http1_request(client);
474 			break;
475 		case HTTP_SERVER_FRAME_HEADER_STATE:
476 			ret = handle_http_frame_header(client);
477 			break;
478 		case HTTP_SERVER_FRAME_HEADERS_STATE:
479 			ret = handle_http_frame_headers(client);
480 			break;
481 		case HTTP_SERVER_FRAME_CONTINUATION_STATE:
482 			ret = handle_http_frame_continuation(client);
483 			break;
484 		case HTTP_SERVER_FRAME_SETTINGS_STATE:
485 			ret = handle_http_frame_settings(client);
486 			break;
487 		case HTTP_SERVER_FRAME_WINDOW_UPDATE_STATE:
488 			ret = handle_http_frame_window_update(client);
489 			break;
490 		case HTTP_SERVER_FRAME_RST_STREAM_STATE:
491 			ret = handle_http_frame_rst_stream(client);
492 			break;
493 		case HTTP_SERVER_FRAME_GOAWAY_STATE:
494 			ret = handle_http_frame_goaway(client);
495 			break;
496 		case HTTP_SERVER_FRAME_PRIORITY_STATE:
497 			ret = handle_http_frame_priority(client);
498 			break;
499 		case HTTP_SERVER_FRAME_PADDING_STATE:
500 			ret = handle_http_frame_padding(client);
501 			break;
502 		case HTTP_SERVER_DONE_STATE:
503 			ret = handle_http_done(client);
504 			break;
505 		default:
506 			ret = handle_http_done(client);
507 			break;
508 		}
509 	} while (ret >= 0 && client->data_len > 0);
510 
511 	if (ret < 0 && ret != -EAGAIN) {
512 		return ret;
513 	}
514 
515 	if (client->data_len > 0) {
516 		/* Move any remaining data in the buffer. */
517 		memmove(client->buffer, client->cursor, client->data_len);
518 	}
519 
520 	return 0;
521 }
522 
http_server_run(struct http_server_ctx * ctx)523 static int http_server_run(struct http_server_ctx *ctx)
524 {
525 	struct http_client_ctx *client;
526 	eventfd_t value;
527 	bool found_slot;
528 	int new_socket;
529 	int ret, i, j;
530 	int sock_error;
531 	socklen_t optlen = sizeof(int);
532 
533 	value = 0;
534 
535 	while (1) {
536 		ret = zsock_poll(ctx->fds, HTTP_SERVER_SOCK_COUNT, -1);
537 		if (ret < 0) {
538 			ret = -errno;
539 			LOG_DBG("poll failed (%d)", ret);
540 			goto closing;
541 		}
542 
543 		if (ret == 0) {
544 			/* should not happen because timeout is -1 */
545 			break;
546 		}
547 
548 		if (ret == 1 && ctx->fds[0].revents) {
549 			eventfd_read(ctx->fds[0].fd, &value);
550 			LOG_DBG("Received stop event. exiting ..");
551 			ret = 0;
552 			goto closing;
553 		}
554 
555 		for (i = 1; i < ARRAY_SIZE(ctx->fds); i++) {
556 			if (ctx->fds[i].fd < 0) {
557 				continue;
558 			}
559 
560 			if (ctx->fds[i].revents & ZSOCK_POLLHUP) {
561 				if (i >= ctx->listen_fds) {
562 					LOG_DBG("Client #%d has disconnected",
563 						i - ctx->listen_fds);
564 
565 					client = &ctx->clients[i - ctx->listen_fds];
566 					close_client_connection(client);
567 				}
568 
569 				continue;
570 			}
571 
572 			if (ctx->fds[i].revents & ZSOCK_POLLERR) {
573 				(void)zsock_getsockopt(ctx->fds[i].fd, SOL_SOCKET,
574 						       SO_ERROR, &sock_error, &optlen);
575 				LOG_DBG("Error on fd %d %d", ctx->fds[i].fd, sock_error);
576 
577 				if (i >= ctx->listen_fds) {
578 					client = &ctx->clients[i - ctx->listen_fds];
579 					close_client_connection(client);
580 					continue;
581 				}
582 
583 				/* Listening socket error, abort. */
584 				LOG_ERR("Listening socket error, aborting.");
585 				ret = -sock_error;
586 				goto closing;
587 
588 			}
589 
590 			if (!(ctx->fds[i].revents & ZSOCK_POLLIN)) {
591 				continue;
592 			}
593 
594 			/* First check if we have something to accept */
595 			if (i < ctx->listen_fds) {
596 				new_socket = accept_new_client(ctx->fds[i].fd);
597 				if (new_socket < 0) {
598 					ret = -errno;
599 					LOG_DBG("accept: %d", ret);
600 					continue;
601 				}
602 
603 				found_slot = false;
604 
605 				for (j = ctx->listen_fds; j < ARRAY_SIZE(ctx->fds); j++) {
606 					if (ctx->fds[j].fd != INVALID_SOCK) {
607 						continue;
608 					}
609 
610 					ctx->fds[j].fd = new_socket;
611 					ctx->fds[j].events = ZSOCK_POLLIN;
612 					ctx->fds[j].revents = 0;
613 
614 					ctx->num_clients++;
615 
616 					LOG_DBG("Init client #%d", j - ctx->listen_fds);
617 
618 					init_client_ctx(&ctx->clients[j - ctx->listen_fds],
619 							new_socket);
620 					found_slot = true;
621 					break;
622 				}
623 
624 				if (!found_slot) {
625 					LOG_DBG("No free slot found.");
626 					zsock_close(new_socket);
627 				}
628 
629 				continue;
630 			}
631 
632 			/* Client sock */
633 			client = &ctx->clients[i - ctx->listen_fds];
634 
635 			ret = zsock_recv(client->fd, client->buffer + client->data_len,
636 					 sizeof(client->buffer) - client->data_len, 0);
637 			if (ret <= 0) {
638 				if (ret == 0) {
639 					LOG_DBG("Connection closed by peer for client #%d",
640 						i - ctx->listen_fds);
641 				} else {
642 					ret = -errno;
643 					LOG_DBG("ERROR reading from socket (%d)", ret);
644 				}
645 
646 				close_client_connection(client);
647 				continue;
648 			}
649 
650 			client->data_len += ret;
651 
652 			http_client_timer_restart(client);
653 
654 			ret = handle_http_request(client);
655 			if (ret < 0 && ret != -EAGAIN) {
656 				if (ret == -ENOTCONN) {
657 					LOG_DBG("Client closed connection while handling request");
658 				} else {
659 					LOG_ERR("HTTP request handling error (%d)", ret);
660 				}
661 				close_client_connection(client);
662 			} else if (client->data_len == sizeof(client->buffer)) {
663 				/* If the RX buffer is still full after parsing,
664 				 * it means we won't be able to handle this request
665 				 * with the current buffer size.
666 				 */
667 				LOG_ERR("RX buffer too small to handle request");
668 				close_client_connection(client);
669 			}
670 		}
671 	}
672 
673 	return 0;
674 
675 closing:
676 	/* Close all client connections and the server socket */
677 	close_all_sockets(ctx);
678 	return ret;
679 }
680 
681 /* Compare two strings where the terminator is either "\0" or "?" */
compare_strings(const char * s1,const char * s2)682 static int compare_strings(const char *s1, const char *s2)
683 {
684 	while ((*s1 && *s2) && (*s1 == *s2) && (*s1 != '?')) {
685 		s1++;
686 		s2++;
687 	}
688 
689 	/* Check if both strings have reached their terminators or '?' */
690 	if ((*s1 == '\0' || *s1 == '?') && (*s2 == '\0' || *s2 == '?')) {
691 		return 0; /* Strings are equal */
692 	}
693 
694 	return 1; /* Strings are not equal */
695 }
696 
skip_this(struct http_resource_desc * resource,bool is_websocket)697 static bool skip_this(struct http_resource_desc *resource, bool is_websocket)
698 {
699 	struct http_resource_detail *detail;
700 
701 	detail = (struct http_resource_detail *)resource->detail;
702 
703 	if (is_websocket) {
704 		if (detail->type != HTTP_RESOURCE_TYPE_WEBSOCKET) {
705 			return true;
706 		}
707 	} else {
708 		if (detail->type == HTTP_RESOURCE_TYPE_WEBSOCKET) {
709 			return true;
710 		}
711 	}
712 
713 	return false;
714 }
715 
get_resource_detail(const char * path,int * path_len,bool is_websocket)716 struct http_resource_detail *get_resource_detail(const char *path,
717 						 int *path_len,
718 						 bool is_websocket)
719 {
720 	HTTP_SERVICE_FOREACH(service) {
721 		HTTP_SERVICE_FOREACH_RESOURCE(service, resource) {
722 			if (skip_this(resource, is_websocket)) {
723 				continue;
724 			}
725 
726 			if (IS_ENABLED(CONFIG_HTTP_SERVER_RESOURCE_WILDCARD)) {
727 				int ret;
728 
729 				ret = fnmatch(resource->resource, path,
730 					      (FNM_PATHNAME | FNM_LEADING_DIR));
731 				if (ret == 0) {
732 					*path_len = strlen(resource->resource);
733 					return resource->detail;
734 				}
735 			}
736 
737 			if (compare_strings(path, resource->resource) == 0) {
738 				NET_DBG("Got match for %s", resource->resource);
739 
740 				*path_len = strlen(resource->resource);
741 				return resource->detail;
742 			}
743 		}
744 	}
745 
746 	NET_DBG("No match for %s", path);
747 
748 	return NULL;
749 }
750 
http_server_find_file(char * fname,size_t fname_size,size_t * file_size,bool * gzipped)751 int http_server_find_file(char *fname, size_t fname_size, size_t *file_size, bool *gzipped)
752 {
753 	struct fs_dirent dirent;
754 	size_t len;
755 	int ret;
756 
757 	ret = fs_stat(fname, &dirent);
758 	if (ret < 0) {
759 		len = strlen(fname);
760 		snprintk(fname + len, fname_size - len, ".gz");
761 		ret = fs_stat(fname, &dirent);
762 		*gzipped = (ret == 0);
763 	}
764 
765 	if (ret == 0) {
766 		*file_size = dirent.size;
767 		return ret;
768 	}
769 
770 	return -ENOENT;
771 }
772 
http_server_get_content_type_from_extension(char * url,char * content_type,size_t content_type_size)773 void http_server_get_content_type_from_extension(char *url, char *content_type,
774 						 size_t content_type_size)
775 {
776 	size_t url_len = strlen(url);
777 
778 	HTTP_SERVER_CONTENT_TYPE_FOREACH(ct) {
779 		char *ext;
780 
781 		if (url_len <= ct->extension_len) {
782 			continue;
783 		}
784 
785 		ext = &url[url_len - ct->extension_len];
786 
787 		if (strncmp(ext, ct->extension, ct->extension_len) == 0) {
788 			strncpy(content_type, ct->content_type, content_type_size);
789 			return;
790 		}
791 	}
792 }
793 
http_server_sendall(struct http_client_ctx * client,const void * buf,size_t len)794 int http_server_sendall(struct http_client_ctx *client, const void *buf, size_t len)
795 {
796 	while (len) {
797 		ssize_t out_len = zsock_send(client->fd, buf, len, 0);
798 
799 		if (out_len < 0) {
800 			return -errno;
801 		}
802 
803 		buf = (const char *)buf + out_len;
804 		len -= out_len;
805 
806 		http_client_timer_restart(client);
807 	}
808 
809 	return 0;
810 }
811 
http_response_is_final(struct http_response_ctx * rsp,enum http_data_status status)812 bool http_response_is_final(struct http_response_ctx *rsp, enum http_data_status status)
813 {
814 	if (status != HTTP_SERVER_DATA_FINAL) {
815 		return false;
816 	}
817 
818 	if (rsp->final_chunk ||
819 	    (rsp->status == 0 && rsp->header_count == 0 && rsp->body_len == 0)) {
820 		return true;
821 	}
822 
823 	return false;
824 }
825 
http_response_is_provided(struct http_response_ctx * rsp)826 bool http_response_is_provided(struct http_response_ctx *rsp)
827 {
828 	if (rsp->status != 0 || rsp->header_count > 0 || rsp->body_len > 0) {
829 		return true;
830 	}
831 
832 	return false;
833 }
834 
populate_request_ctx(struct http_request_ctx * req_ctx,uint8_t * data,size_t len,struct http_header_capture_ctx * header_ctx)835 void populate_request_ctx(struct http_request_ctx *req_ctx, uint8_t *data, size_t len,
836 			  struct http_header_capture_ctx *header_ctx)
837 {
838 	req_ctx->data = data;
839 	req_ctx->data_len = len;
840 
841 	if (NULL == header_ctx || header_ctx->status == HTTP_HEADER_STATUS_NONE) {
842 		req_ctx->headers = NULL;
843 		req_ctx->header_count = 0;
844 		req_ctx->headers_status = HTTP_HEADER_STATUS_NONE;
845 	} else {
846 		req_ctx->headers = header_ctx->headers;
847 		req_ctx->header_count = header_ctx->count;
848 		req_ctx->headers_status = header_ctx->status;
849 	}
850 }
851 
http_server_start(void)852 int http_server_start(void)
853 {
854 	if (server_running) {
855 		LOG_DBG("HTTP server already started");
856 		return -EALREADY;
857 	}
858 
859 	server_running = true;
860 	k_sem_give(&server_start);
861 
862 	LOG_DBG("Starting HTTP server");
863 
864 	return 0;
865 }
866 
http_server_stop(void)867 int http_server_stop(void)
868 {
869 	if (!server_running) {
870 		LOG_DBG("HTTP server already stopped");
871 		return -EALREADY;
872 	}
873 
874 	server_running = false;
875 	k_sem_reset(&server_start);
876 	eventfd_write(server_ctx.fds[0].fd, 1);
877 
878 	LOG_DBG("Stopping HTTP server");
879 
880 	return 0;
881 }
882 
http_server_thread(void * p1,void * p2,void * p3)883 static void http_server_thread(void *p1, void *p2, void *p3)
884 {
885 	int ret;
886 
887 	ARG_UNUSED(p1);
888 	ARG_UNUSED(p2);
889 	ARG_UNUSED(p3);
890 
891 	while (true) {
892 		k_sem_take(&server_start, K_FOREVER);
893 
894 		while (server_running) {
895 			ret = http_server_init(&server_ctx);
896 			if (ret < 0) {
897 				LOG_ERR("Failed to initialize HTTP2 server");
898 				goto again;
899 			}
900 
901 			ret = http_server_run(&server_ctx);
902 			if (!server_running) {
903 				continue;
904 			}
905 
906 again:
907 			LOG_INF("Re-starting server (%d)", ret);
908 			k_sleep(K_MSEC(CONFIG_HTTP_SERVER_RESTART_DELAY));
909 		}
910 	}
911 }
912 
913 K_THREAD_DEFINE(http_server_tid, CONFIG_HTTP_SERVER_STACK_SIZE,
914 		http_server_thread, NULL, NULL, NULL, THREAD_PRIORITY, 0, 0);
915