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/http/server.h>
21 
22 LOG_MODULE_DECLARE(net_http_server, CONFIG_NET_HTTP_SERVER_LOG_LEVEL);
23 
24 #include "headers/server_internal.h"
25 
26 static const char content_404[] = {
27 #ifdef INCLUDE_HTML_CONTENT
28 #include "not_found_page.html.gz.inc"
29 #endif
30 };
31 
is_header_flag_set(uint8_t flags,uint8_t mask)32 static bool is_header_flag_set(uint8_t flags, uint8_t mask)
33 {
34 	return (flags & mask) != 0;
35 }
36 
clear_header_flag(uint8_t * flags,uint8_t mask)37 static void clear_header_flag(uint8_t *flags, uint8_t mask)
38 {
39 	*flags &= ~mask;
40 }
41 
print_http_frames(struct http_client_ctx * client)42 static void print_http_frames(struct http_client_ctx *client)
43 {
44 #if defined(PRINT_COLOR)
45 	const char *bold = "\033[1m";
46 	const char *reset = "\033[0m";
47 	const char *green = "\033[32m";
48 	const char *blue = "\033[34m";
49 #else
50 	const char *bold = "";
51 	const char *reset = "";
52 	const char *green = "";
53 	const char *blue = "";
54 #endif
55 
56 	struct http2_frame *frame = &client->current_frame;
57 
58 	LOG_DBG("%s=====================================%s", green, reset);
59 	LOG_DBG("%sReceived %s Frame :%s", bold, get_frame_type_name(frame->type), reset);
60 	LOG_DBG("  %sLength:%s %u", blue, reset, frame->length);
61 	LOG_DBG("  %sType:%s %u (%s)", blue, reset, frame->type, get_frame_type_name(frame->type));
62 	LOG_DBG("  %sFlags:%s %u", blue, reset, frame->flags);
63 	LOG_DBG("  %sStream Identifier:%s %u", blue, reset, frame->stream_identifier);
64 	LOG_DBG("%s=====================================%s", green, reset);
65 }
66 
find_http_stream_context(struct http_client_ctx * client,uint32_t stream_id)67 static struct http2_stream_ctx *find_http_stream_context(
68 			struct http_client_ctx *client, uint32_t stream_id)
69 {
70 	ARRAY_FOR_EACH(client->streams, i) {
71 		if (client->streams[i].stream_id == stream_id) {
72 			return &client->streams[i];
73 		}
74 	}
75 
76 	return NULL;
77 }
78 
allocate_http_stream_context(struct http_client_ctx * client,uint32_t stream_id)79 static struct http2_stream_ctx *allocate_http_stream_context(
80 			struct http_client_ctx *client, uint32_t stream_id)
81 {
82 	ARRAY_FOR_EACH(client->streams, i) {
83 		if (client->streams[i].stream_state == HTTP2_STREAM_IDLE) {
84 			client->streams[i].stream_id = stream_id;
85 			client->streams[i].stream_state = HTTP2_STREAM_OPEN;
86 			client->streams[i].window_size =
87 				HTTP_SERVER_INITIAL_WINDOW_SIZE;
88 			client->streams[i].headers_sent = false;
89 			client->streams[i].end_stream_sent = false;
90 			return &client->streams[i];
91 		}
92 	}
93 
94 	return NULL;
95 }
96 
release_http_stream_context(struct http_client_ctx * client,uint32_t stream_id)97 static void release_http_stream_context(struct http_client_ctx *client,
98 					uint32_t stream_id)
99 {
100 	ARRAY_FOR_EACH(client->streams, i) {
101 		if (client->streams[i].stream_id == stream_id) {
102 			client->streams[i].stream_id = 0;
103 			client->streams[i].stream_state = HTTP2_STREAM_IDLE;
104 			client->streams[i].current_detail = NULL;
105 			break;
106 		}
107 	}
108 }
109 
add_header_field(struct http_client_ctx * client,uint8_t ** buf,size_t * buflen,const char * name,const char * value)110 static int add_header_field(struct http_client_ctx *client, uint8_t **buf,
111 			    size_t *buflen, const char *name, const char *value)
112 {
113 	int ret;
114 
115 	client->header_field.name = name;
116 	client->header_field.name_len = strlen(name);
117 	client->header_field.value = value;
118 	client->header_field.value_len = strlen(value);
119 
120 	ret = http_hpack_encode_header(*buf, *buflen, &client->header_field);
121 	if (ret < 0) {
122 		LOG_DBG("Failed to encode header, err %d", ret);
123 		return ret;
124 	}
125 
126 	*buf += ret;
127 	*buflen -= ret;
128 
129 	return 0;
130 }
131 
encode_frame_header(uint8_t * buf,uint32_t payload_len,enum http2_frame_type frame_type,uint8_t flags,uint32_t stream_id)132 static void encode_frame_header(uint8_t *buf, uint32_t payload_len,
133 				enum http2_frame_type frame_type,
134 				uint8_t flags, uint32_t stream_id)
135 {
136 	sys_put_be24(payload_len, &buf[HTTP2_FRAME_LENGTH_OFFSET]);
137 	buf[HTTP2_FRAME_TYPE_OFFSET] = frame_type;
138 	buf[HTTP2_FRAME_FLAGS_OFFSET] = flags;
139 	sys_put_be32(stream_id, &buf[HTTP2_FRAME_STREAM_ID_OFFSET]);
140 }
141 
send_headers_frame(struct http_client_ctx * client,enum http_status status,uint32_t stream_id,struct http_resource_detail * detail_common,uint8_t flags,const struct http_header * extra_headers,size_t extra_headers_count)142 static int send_headers_frame(struct http_client_ctx *client, enum http_status status,
143 			      uint32_t stream_id, struct http_resource_detail *detail_common,
144 			      uint8_t flags, const struct http_header *extra_headers,
145 			      size_t extra_headers_count)
146 {
147 	uint8_t headers_frame[CONFIG_HTTP_SERVER_HTTP2_MAX_HEADER_FRAME_LEN];
148 	uint8_t status_str[4];
149 	uint8_t *buf = headers_frame + HTTP2_FRAME_HEADER_SIZE;
150 	size_t buflen = sizeof(headers_frame) - HTTP2_FRAME_HEADER_SIZE;
151 	bool content_encoding_sent = false;
152 	bool content_type_sent = false;
153 	size_t payload_len;
154 	int ret;
155 
156 	ret = snprintf(status_str, sizeof(status_str), "%d", status);
157 	if (ret > sizeof(status_str) - 1) {
158 		return -EINVAL;
159 	}
160 
161 	ret = add_header_field(client, &buf, &buflen, ":status", status_str);
162 	if (ret < 0) {
163 		return ret;
164 	}
165 
166 	for (size_t i = 0; i < extra_headers_count; i++) {
167 		const struct http_header *hdr = &extra_headers[i];
168 
169 		if (strcasecmp(hdr->name, "content-encoding") == 0) {
170 			content_encoding_sent = true;
171 		}
172 
173 		if (strcasecmp(hdr->name, "content-type") == 0) {
174 			content_type_sent = true;
175 		}
176 
177 		ret = add_header_field(client, &buf, &buflen, hdr->name, hdr->value);
178 		if (ret < 0) {
179 			return ret;
180 		}
181 	}
182 
183 	if (!content_encoding_sent && detail_common && detail_common->content_encoding != NULL) {
184 		ret = add_header_field(client, &buf, &buflen, "content-encoding",
185 				       detail_common->content_encoding);
186 		if (ret < 0) {
187 			return ret;
188 		}
189 	}
190 
191 	if (!content_type_sent && detail_common && detail_common->content_type != NULL) {
192 		ret = add_header_field(client, &buf, &buflen, "content-type",
193 				       detail_common->content_type);
194 		if (ret < 0) {
195 			return ret;
196 		}
197 	}
198 
199 	payload_len = sizeof(headers_frame) - buflen - HTTP2_FRAME_HEADER_SIZE;
200 	flags |= HTTP2_FLAG_END_HEADERS;
201 
202 	encode_frame_header(headers_frame, payload_len, HTTP2_HEADERS_FRAME,
203 			    flags, stream_id);
204 
205 	ret = http_server_sendall(client, headers_frame,
206 				  payload_len + HTTP2_FRAME_HEADER_SIZE);
207 	if (ret < 0) {
208 		LOG_DBG("Cannot write to socket (%d)", ret);
209 		return ret;
210 	}
211 
212 	client->current_stream->headers_sent = true;
213 
214 	return 0;
215 }
216 
send_data_frame(struct http_client_ctx * client,const char * payload,size_t length,uint32_t stream_id,uint8_t flags)217 static int send_data_frame(struct http_client_ctx *client, const char *payload,
218 			   size_t length, uint32_t stream_id, uint8_t flags)
219 {
220 	uint8_t frame_header[HTTP2_FRAME_HEADER_SIZE];
221 	int ret;
222 
223 	encode_frame_header(frame_header, length, HTTP2_DATA_FRAME,
224 			    is_header_flag_set(flags, HTTP2_FLAG_END_STREAM) ?
225 			    HTTP2_FLAG_END_STREAM : 0,
226 			    stream_id);
227 
228 	ret = http_server_sendall(client, frame_header, sizeof(frame_header));
229 	if (ret < 0) {
230 		LOG_DBG("Cannot write to socket (%d)", ret);
231 	} else {
232 		if (payload != NULL && length > 0) {
233 			ret = http_server_sendall(client, payload, length);
234 			if (ret < 0) {
235 				LOG_DBG("Cannot write to socket (%d)", ret);
236 			}
237 		}
238 	}
239 
240 	return ret;
241 }
242 
send_settings_frame(struct http_client_ctx * client,bool ack)243 int send_settings_frame(struct http_client_ctx *client, bool ack)
244 {
245 	uint8_t settings_frame[HTTP2_FRAME_HEADER_SIZE +
246 			       2 * sizeof(struct http2_settings_field)];
247 	struct http2_settings_field *setting;
248 	size_t len;
249 	int ret;
250 
251 	if (ack) {
252 		encode_frame_header(settings_frame, 0,
253 				    HTTP2_SETTINGS_FRAME,
254 				    HTTP2_FLAG_SETTINGS_ACK, 0);
255 		len = HTTP2_FRAME_HEADER_SIZE;
256 	} else {
257 		encode_frame_header(settings_frame,
258 				    2 * sizeof(struct http2_settings_field),
259 				    HTTP2_SETTINGS_FRAME, 0, 0);
260 
261 		setting = (struct http2_settings_field *)
262 			(settings_frame + HTTP2_FRAME_HEADER_SIZE);
263 		UNALIGNED_PUT(htons(HTTP2_SETTINGS_HEADER_TABLE_SIZE),
264 			      &setting->id);
265 		UNALIGNED_PUT(0, &setting->value);
266 
267 		setting++;
268 		UNALIGNED_PUT(htons(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS),
269 			      &setting->id);
270 		UNALIGNED_PUT(htonl(CONFIG_HTTP_SERVER_MAX_STREAMS),
271 			      &setting->value);
272 
273 		len = HTTP2_FRAME_HEADER_SIZE +
274 		      2 * sizeof(struct http2_settings_field);
275 	}
276 
277 	ret = http_server_sendall(client, settings_frame, len);
278 	if (ret < 0) {
279 		LOG_DBG("Cannot write to socket (%d)", ret);
280 		return ret;
281 	}
282 
283 	return 0;
284 }
285 
send_window_update_frame(struct http_client_ctx * client,struct http2_stream_ctx * stream)286 int send_window_update_frame(struct http_client_ctx *client,
287 			     struct http2_stream_ctx *stream)
288 {
289 	uint8_t window_update_frame[HTTP2_FRAME_HEADER_SIZE +
290 				    sizeof(uint32_t)];
291 	uint32_t window_update;
292 	uint32_t stream_id;
293 	int ret;
294 
295 	if (stream != NULL) {
296 		window_update = HTTP_SERVER_INITIAL_WINDOW_SIZE - stream->window_size;
297 		stream->window_size = HTTP_SERVER_INITIAL_WINDOW_SIZE;
298 		stream_id = stream->stream_id;
299 	} else {
300 		window_update = HTTP_SERVER_INITIAL_WINDOW_SIZE - client->window_size;
301 		client->window_size = HTTP_SERVER_INITIAL_WINDOW_SIZE;
302 		stream_id = 0;
303 	}
304 
305 	encode_frame_header(window_update_frame, sizeof(uint32_t),
306 			    HTTP2_WINDOW_UPDATE_FRAME,
307 			    0, stream_id);
308 	sys_put_be32(window_update,
309 		     window_update_frame + HTTP2_FRAME_HEADER_SIZE);
310 
311 	ret = http_server_sendall(client, window_update_frame,
312 				  sizeof(window_update_frame));
313 	if (ret < 0) {
314 		LOG_DBG("Cannot write to socket (%d)", ret);
315 		return ret;
316 	}
317 
318 	return 0;
319 }
320 
send_http2_404(struct http_client_ctx * client,struct http2_frame * frame)321 static int send_http2_404(struct http_client_ctx *client,
322 			  struct http2_frame *frame)
323 {
324 	int ret;
325 
326 	ret = send_headers_frame(client, HTTP_404_NOT_FOUND, frame->stream_identifier, NULL, 0,
327 				 NULL, 0);
328 	if (ret < 0) {
329 		LOG_DBG("Cannot write to socket (%d)", ret);
330 		return ret;
331 	}
332 
333 	ret = send_data_frame(client, content_404, sizeof(content_404),
334 			      frame->stream_identifier,
335 			      HTTP2_FLAG_END_STREAM);
336 	if (ret < 0) {
337 		LOG_DBG("Cannot write to socket (%d)", ret);
338 	}
339 
340 	return ret;
341 }
342 
send_http2_405(struct http_client_ctx * client,struct http2_frame * frame)343 static int send_http2_405(struct http_client_ctx *client,
344 			  struct http2_frame *frame)
345 {
346 	int ret;
347 
348 	ret = send_headers_frame(client, HTTP_405_METHOD_NOT_ALLOWED,
349 				 frame->stream_identifier, NULL,
350 				 HTTP2_FLAG_END_STREAM, NULL, 0);
351 	if (ret < 0) {
352 		LOG_DBG("Cannot write to socket (%d)", ret);
353 		return ret;
354 	}
355 
356 	return ret;
357 }
358 
send_http2_409(struct http_client_ctx * client,struct http2_frame * frame)359 static int send_http2_409(struct http_client_ctx *client,
360 			  struct http2_frame *frame)
361 {
362 	int ret;
363 
364 	ret = send_headers_frame(client, HTTP_409_CONFLICT, frame->stream_identifier, NULL,
365 				 HTTP2_FLAG_END_STREAM, NULL, 0);
366 	if (ret < 0) {
367 		LOG_DBG("Cannot write to socket (%d)", ret);
368 	}
369 
370 	return ret;
371 }
372 
send_http2_500(struct http_client_ctx * client,struct http2_frame * frame,int error_code)373 static void send_http2_500(struct http_client_ctx *client,
374 			   struct http2_frame *frame, int error_code)
375 {
376 #define HTTP_500_RESPONSE_TEMPLATE "Internal Server Error%s%s"
377 #define MAX_ERROR_DESC_LEN 32
378 
379 	char error_str[] = "xxx";
380 	char http_response[sizeof(HTTP_500_RESPONSE_TEMPLATE) +
381 			   MAX_ERROR_DESC_LEN + 1]; /* For the error description */
382 	const char *error_desc;
383 	const char *desc_separator;
384 
385 	if (IS_ENABLED(CONFIG_HTTP_SERVER_REPORT_FAILURE_REASON)) {
386 		/* Try to fetch error description, fallback to error number if
387 		 * not available
388 		 */
389 		error_desc = strerror(error_code);
390 		if (strlen(error_desc) == 0) {
391 			/* Cast error value to uint8_t to avoid truncation warnings. */
392 			(void)snprintk(error_str, sizeof(error_str), "%u",
393 				       (uint8_t)error_code);
394 			error_desc = error_str;
395 		}
396 		desc_separator = ": ";
397 	} else {
398 		error_desc = "";
399 		desc_separator = "";
400 	}
401 
402 	if (send_headers_frame(client, HTTP_500_INTERNAL_SERVER_ERROR,
403 			       frame->stream_identifier, NULL, 0, NULL, 0) < 0) {
404 		return;
405 	}
406 
407 	(void)snprintk(http_response, sizeof(http_response),
408 		       HTTP_500_RESPONSE_TEMPLATE, desc_separator, error_desc);
409 	(void)send_data_frame(client, http_response, strlen(http_response),
410 			      frame->stream_identifier, HTTP2_FLAG_END_STREAM);
411 }
412 
handle_http2_static_resource(struct http_resource_detail_static * static_detail,struct http2_frame * frame,struct http_client_ctx * client)413 static int handle_http2_static_resource(
414 	struct http_resource_detail_static *static_detail,
415 	struct http2_frame *frame, struct http_client_ctx *client)
416 {
417 	const char *content_200;
418 	size_t content_len;
419 	int ret;
420 
421 	if (client->method != HTTP_GET) {
422 		return send_http2_405(client, frame);
423 	}
424 
425 	if (client->current_stream == NULL) {
426 		return -ENOENT;
427 	}
428 
429 	content_200 = static_detail->static_data;
430 	content_len = static_detail->static_data_len;
431 
432 	ret = send_headers_frame(client, HTTP_200_OK, frame->stream_identifier,
433 				 &static_detail->common, 0, NULL, 0);
434 	if (ret < 0) {
435 		LOG_DBG("Cannot write to socket (%d)", ret);
436 		goto out;
437 	}
438 
439 	ret = send_data_frame(client, content_200, content_len,
440 			      frame->stream_identifier,
441 			      HTTP2_FLAG_END_STREAM);
442 	if (ret < 0) {
443 		LOG_DBG("Cannot write to socket (%d)", ret);
444 		goto out;
445 	}
446 
447 	client->current_stream->end_stream_sent = true;
448 
449 out:
450 	return ret;
451 }
452 
453 #if defined(CONFIG_FILE_SYSTEM)
handle_http2_static_fs_resource(struct http_resource_detail_static_fs * static_fs_detail,struct http2_frame * frame,struct http_client_ctx * client)454 static int handle_http2_static_fs_resource(struct http_resource_detail_static_fs *static_fs_detail,
455 					   struct http2_frame *frame,
456 					   struct http_client_ctx *client)
457 {
458 	int ret;
459 	struct fs_file_t file;
460 	char fname[HTTP_SERVER_MAX_URL_LENGTH];
461 	char content_type[HTTP_SERVER_MAX_CONTENT_TYPE_LEN] = "text/html";
462 	struct http_resource_detail res_detail = {
463 		.bitmask_of_supported_http_methods =
464 			static_fs_detail->common.bitmask_of_supported_http_methods,
465 		.content_type = content_type,
466 		.path_len = static_fs_detail->common.path_len,
467 		.type = static_fs_detail->common.type,
468 	};
469 	enum http_compression chosen_compression = 0;
470 	int len;
471 	int remaining;
472 	char tmp[64];
473 
474 	if (client->method != HTTP_GET) {
475 		return send_http2_405(client, frame);
476 	}
477 
478 	if (client->current_stream == NULL) {
479 		return -ENOENT;
480 	}
481 
482 	/* get filename and content-type from url */
483 	len = strlen(client->url_buffer);
484 	if (len == 1) {
485 		/* url is just the leading slash, use index.html as filename */
486 		snprintk(fname, sizeof(fname), "%s/index.html", static_fs_detail->fs_path);
487 	} else {
488 		http_server_get_content_type_from_extension(client->url_buffer, content_type,
489 							    sizeof(content_type));
490 		snprintk(fname, sizeof(fname), "%s%s", static_fs_detail->fs_path,
491 			 client->url_buffer);
492 	}
493 
494 	/* open file, if it exists */
495 #ifdef CONFIG_HTTP_SERVER_COMPRESSION
496 	ret = http_server_find_file(fname, sizeof(fname), &client->data_len,
497 					client->supported_compression, &chosen_compression);
498 #else
499 	ret = http_server_find_file(fname, sizeof(fname), &client->data_len, 0, NULL);
500 #endif /* CONFIG_HTTP_SERVER_COMPRESSION */
501 	if (ret < 0) {
502 		LOG_ERR("fs_stat %s: %d", fname, ret);
503 
504 		ret = send_headers_frame(client, HTTP_404_NOT_FOUND, frame->stream_identifier, NULL,
505 					 0, NULL, 0);
506 		if (ret < 0) {
507 			LOG_DBG("Cannot write to socket (%d)", ret);
508 		}
509 		return ret;
510 	}
511 	fs_file_t_init(&file);
512 	ret = fs_open(&file, fname, FS_O_READ);
513 	if (ret < 0) {
514 		LOG_ERR("fs_open %s: %d", fname, ret);
515 		if (ret < 0) {
516 			return ret;
517 		}
518 	}
519 
520 	/* send headers */
521 	if (IS_ENABLED(CONFIG_HTTP_SERVER_COMPRESSION)) {
522 		res_detail.content_encoding = http_compression_text(chosen_compression);
523 	}
524 	ret = send_headers_frame(client, HTTP_200_OK, frame->stream_identifier, &res_detail, 0,
525 				 NULL, 0);
526 	if (ret < 0) {
527 		LOG_DBG("Cannot write to socket (%d)", ret);
528 		goto out;
529 	}
530 
531 	/* read and send file */
532 	remaining = client->data_len;
533 	while (remaining > 0) {
534 		len = fs_read(&file, tmp, sizeof(tmp));
535 		if (len < 0) {
536 			LOG_ERR("Filesystem read error (%d)", len);
537 			goto out;
538 		}
539 
540 		remaining -= len;
541 		ret = send_data_frame(client, tmp, len, frame->stream_identifier,
542 				      (remaining > 0) ? 0 : HTTP2_FLAG_END_STREAM);
543 		if (ret < 0) {
544 			LOG_DBG("Cannot write to socket (%d)", ret);
545 			goto out;
546 		}
547 	}
548 
549 	client->current_stream->end_stream_sent = true;
550 
551 out:
552 	/* close file */
553 	fs_close(&file);
554 
555 	return ret;
556 }
557 #endif /* CONFIG_FILE_SYSTEM */
558 
http2_dynamic_response(struct http_client_ctx * client,struct http2_frame * frame,struct http_response_ctx * rsp,enum http_data_status data_status,struct http_resource_detail_dynamic * dynamic_detail)559 static int http2_dynamic_response(struct http_client_ctx *client, struct http2_frame *frame,
560 				  struct http_response_ctx *rsp, enum http_data_status data_status,
561 				  struct http_resource_detail_dynamic *dynamic_detail)
562 {
563 	int ret;
564 	uint8_t flags = 0;
565 	bool final_response = http_response_is_final(rsp, data_status);
566 
567 	if (client->current_stream->headers_sent && (rsp->header_count > 0 || rsp->status != 0)) {
568 		LOG_WRN("Already sent headers, dropping new headers and/or response code");
569 	}
570 
571 	/* Send headers and response code if not already sent */
572 	if (!client->current_stream->headers_sent) {
573 		/* Use '200 OK' status if not specified by application */
574 		if (rsp->status == 0) {
575 			rsp->status = 200;
576 		}
577 
578 		if (rsp->status < HTTP_100_CONTINUE ||
579 		    rsp->status > HTTP_511_NETWORK_AUTHENTICATION_REQUIRED) {
580 			LOG_DBG("Invalid HTTP status code: %d", rsp->status);
581 			return -EINVAL;
582 		}
583 
584 		if (rsp->headers == NULL && rsp->header_count > 0) {
585 			LOG_DBG("NULL headers, but count is > 0");
586 			return -EINVAL;
587 		}
588 
589 		if (final_response && rsp->body_len == 0) {
590 			flags |= HTTP2_FLAG_END_STREAM;
591 			client->current_stream->end_stream_sent = true;
592 		}
593 
594 		ret = send_headers_frame(client, rsp->status, frame->stream_identifier,
595 					 (struct http_resource_detail *)dynamic_detail, flags,
596 					 rsp->headers, rsp->header_count);
597 		if (ret < 0) {
598 			return ret;
599 		}
600 	}
601 
602 	/* Send body data if provided */
603 	if (rsp->body != NULL && rsp->body_len > 0) {
604 		if (final_response) {
605 			flags |= HTTP2_FLAG_END_STREAM;
606 			client->current_stream->end_stream_sent = true;
607 		}
608 
609 		ret = send_data_frame(client, rsp->body, rsp->body_len, frame->stream_identifier,
610 				      flags);
611 		if (ret < 0) {
612 			return ret;
613 		}
614 	}
615 
616 	return 0;
617 }
618 
dynamic_get_del_req_v2(struct http_resource_detail_dynamic * dynamic_detail,struct http_client_ctx * client)619 static int dynamic_get_del_req_v2(struct http_resource_detail_dynamic *dynamic_detail,
620 				  struct http_client_ctx *client)
621 {
622 	int ret, len;
623 	char *ptr;
624 	struct http2_frame *frame = &client->current_frame;
625 	enum http_data_status status;
626 	struct http_request_ctx request_ctx;
627 	struct http_response_ctx response_ctx;
628 
629 	if (client->current_stream == NULL) {
630 		return -ENOENT;
631 	}
632 
633 	/* Start of GET params */
634 	ptr = &client->url_buffer[dynamic_detail->common.path_len];
635 	len = strlen(ptr);
636 	status = HTTP_SERVER_DATA_FINAL;
637 
638 	do {
639 		memset(&response_ctx, 0, sizeof(response_ctx));
640 		populate_request_ctx(&request_ctx, ptr, len, &client->header_capture_ctx);
641 
642 		ret = dynamic_detail->cb(client, status, &request_ctx, &response_ctx,
643 					 dynamic_detail->user_data);
644 		if (ret < 0) {
645 			return ret;
646 		}
647 
648 		ret = http2_dynamic_response(client, frame, &response_ctx, status, dynamic_detail);
649 		if (ret < 0) {
650 			return ret;
651 		}
652 
653 		/* URL params are passed in the first cb only */
654 		len = 0;
655 	} while (!http_response_is_final(&response_ctx, status));
656 
657 	if (!client->current_stream->end_stream_sent) {
658 		client->current_stream->end_stream_sent = true;
659 		ret = send_data_frame(client, NULL, 0, frame->stream_identifier,
660 				      HTTP2_FLAG_END_STREAM);
661 		if (ret < 0) {
662 			LOG_DBG("Cannot send last frame (%d)", ret);
663 		}
664 	}
665 
666 	dynamic_detail->holder = NULL;
667 
668 	return ret;
669 }
670 
dynamic_post_put_req_v2(struct http_resource_detail_dynamic * dynamic_detail,struct http_client_ctx * client,bool headers_only)671 static int dynamic_post_put_req_v2(struct http_resource_detail_dynamic *dynamic_detail,
672 				   struct http_client_ctx *client, bool headers_only)
673 {
674 	int ret = 0;
675 	char *ptr = client->cursor;
676 	size_t data_len;
677 	enum http_data_status status;
678 	struct http2_frame *frame = &client->current_frame;
679 	struct http_request_ctx request_ctx;
680 	struct http_response_ctx response_ctx;
681 	struct http_header_capture_ctx *request_headers_ctx =
682 		headers_only ? &client->header_capture_ctx : NULL;
683 
684 	if (dynamic_detail == NULL) {
685 		return -ENOENT;
686 	}
687 
688 	if (client->current_stream == NULL) {
689 		return -ENOENT;
690 	}
691 
692 	if (headers_only) {
693 		data_len = 0;
694 	} else {
695 		data_len = MIN(frame->length, client->data_len);
696 		frame->length -= data_len;
697 		client->cursor += data_len;
698 		client->data_len -= data_len;
699 	}
700 
701 	if (frame->length == 0 && is_header_flag_set(frame->flags, HTTP2_FLAG_END_STREAM) &&
702 	    !headers_only) {
703 		status = HTTP_SERVER_DATA_FINAL;
704 	} else {
705 		status = HTTP_SERVER_DATA_MORE;
706 	}
707 
708 	memset(&response_ctx, 0, sizeof(response_ctx));
709 	populate_request_ctx(&request_ctx, ptr, data_len, request_headers_ctx);
710 
711 	ret = dynamic_detail->cb(client, status, &request_ctx, &response_ctx,
712 				 dynamic_detail->user_data);
713 	if (ret < 0) {
714 		return ret;
715 	}
716 
717 	/* For POST the application might not send a response until all data has been received.
718 	 * Don't send a default response until the application has had a chance to respond.
719 	 */
720 	if (http_response_is_provided(&response_ctx)) {
721 		ret = http2_dynamic_response(client, frame, &response_ctx, status, dynamic_detail);
722 		if (ret < 0) {
723 			return ret;
724 		}
725 	}
726 
727 	/* Once all data is transferred to application, repeat cb until response is complete */
728 	while (!http_response_is_final(&response_ctx, status) && status == HTTP_SERVER_DATA_FINAL) {
729 		memset(&response_ctx, 0, sizeof(response_ctx));
730 		populate_request_ctx(&request_ctx, ptr, 0, request_headers_ctx);
731 
732 		ret = dynamic_detail->cb(client, status, &request_ctx, &response_ctx,
733 					 dynamic_detail->user_data);
734 		if (ret < 0) {
735 			return ret;
736 		}
737 
738 		ret = http2_dynamic_response(client, frame, &response_ctx, status, dynamic_detail);
739 		if (ret < 0) {
740 			return ret;
741 		}
742 	}
743 
744 	/* At end of stream, ensure response is sent and terminated */
745 	if (frame->length == 0 && !client->current_stream->end_stream_sent &&
746 	    is_header_flag_set(frame->flags, HTTP2_FLAG_END_STREAM)) {
747 		if (client->current_stream->headers_sent) {
748 			ret = send_data_frame(client, NULL, 0, frame->stream_identifier,
749 					      HTTP2_FLAG_END_STREAM);
750 		} else {
751 			memset(&response_ctx, 0, sizeof(response_ctx));
752 			response_ctx.final_chunk = true;
753 			ret = http2_dynamic_response(client, frame, &response_ctx,
754 						     HTTP_SERVER_DATA_FINAL, dynamic_detail);
755 		}
756 
757 		if (ret < 0) {
758 			LOG_DBG("Cannot send last frame (%d)", ret);
759 		}
760 
761 		client->current_stream->end_stream_sent = true;
762 		dynamic_detail->holder = NULL;
763 	}
764 
765 	return ret;
766 }
767 
handle_http2_dynamic_resource(struct http_resource_detail_dynamic * dynamic_detail,struct http2_frame * frame,struct http_client_ctx * client)768 static int handle_http2_dynamic_resource(
769 	struct http_resource_detail_dynamic *dynamic_detail,
770 	struct http2_frame *frame, struct http_client_ctx *client)
771 {
772 	uint32_t user_method;
773 	int ret;
774 
775 	if (dynamic_detail->cb == NULL) {
776 		return -ESRCH;
777 	}
778 
779 	user_method = dynamic_detail->common.bitmask_of_supported_http_methods;
780 
781 	if (!(BIT(client->method) & user_method)) {
782 		return send_http2_405(client, frame);
783 	}
784 
785 	if (dynamic_detail->holder != NULL && dynamic_detail->holder != client) {
786 		ret = send_http2_409(client, frame);
787 		if (ret < 0) {
788 			return ret;
789 		}
790 
791 		return enter_http_done_state(client);
792 	}
793 
794 	dynamic_detail->holder = client;
795 
796 	switch (client->method) {
797 	case HTTP_GET:
798 	case HTTP_DELETE:
799 		if (user_method & BIT(client->method)) {
800 			return dynamic_get_del_req_v2(dynamic_detail, client);
801 		}
802 
803 		goto not_supported;
804 
805 	case HTTP_POST:
806 	case HTTP_PUT:
807 	case HTTP_PATCH:
808 		/* The data will come in DATA frames. Remember the detail ptr
809 		 * which needs to be known when passing data to application.
810 		 */
811 		if (user_method & BIT(client->method)) {
812 			client->current_stream->current_detail =
813 				(struct http_resource_detail *)dynamic_detail;
814 
815 			/* If there are any header fields to pass to the application, call the
816 			 * dynamic handler now with the header data so that this may be cleared to
817 			 * re-use for any other concurrent streams
818 			 */
819 			if (IS_ENABLED(CONFIG_HTTP_SERVER_CAPTURE_HEADERS)) {
820 				ret = dynamic_post_put_req_v2(dynamic_detail, client, true);
821 				if (ret < 0) {
822 					return ret;
823 				}
824 			}
825 			break;
826 		}
827 
828 		goto not_supported;
829 
830 not_supported:
831 	default:
832 		LOG_DBG("HTTP method %s (%d) not supported.",
833 			http_method_str(client->method),
834 			client->method);
835 
836 		return -ENOTSUP;
837 	}
838 
839 	return 0;
840 }
841 
enter_http2_request(struct http_client_ctx * client)842 int enter_http2_request(struct http_client_ctx *client)
843 {
844 	int ret;
845 
846 	client->server_state = HTTP_SERVER_FRAME_HEADER_STATE;
847 	client->data_len -= sizeof(HTTP2_PREFACE) - 1;
848 	client->cursor += sizeof(HTTP2_PREFACE) - 1;
849 
850 	/* HTTP/2 client preface received, send server preface
851 	 * (settings frame).
852 	 */
853 	if (!client->preface_sent) {
854 		ret = send_settings_frame(client, false);
855 		if (ret < 0) {
856 			return ret;
857 		}
858 
859 		client->preface_sent = true;
860 	}
861 
862 	return 0;
863 }
864 
enter_http_frame_settings_state(struct http_client_ctx * client)865 static int enter_http_frame_settings_state(struct http_client_ctx *client)
866 {
867 	client->server_state = HTTP_SERVER_FRAME_SETTINGS_STATE;
868 
869 	return 0;
870 }
871 
enter_http_frame_data_state(struct http_client_ctx * client)872 static int enter_http_frame_data_state(struct http_client_ctx *client)
873 {
874 	struct http2_frame *frame = &client->current_frame;
875 	struct http2_stream_ctx *stream;
876 
877 	if (frame->stream_identifier == 0) {
878 		LOG_DBG("Stream ID 0 is forbidden for data frames.");
879 		return -EBADMSG;
880 	}
881 
882 	stream = find_http_stream_context(client, frame->stream_identifier);
883 	if (stream == NULL) {
884 		LOG_DBG("No stream context found for ID %d",
885 			frame->stream_identifier);
886 		return -EBADMSG;
887 	}
888 
889 	if (stream->stream_state != HTTP2_STREAM_OPEN &&
890 	    stream->stream_state != HTTP2_STREAM_HALF_CLOSED_REMOTE) {
891 		LOG_DBG("Stream ID %d in a wrong state %d", stream->stream_id,
892 			stream->stream_state);
893 		return -EBADMSG;
894 	}
895 
896 	stream->window_size -= frame->length;
897 	client->window_size -= frame->length;
898 	client->server_state = HTTP_SERVER_FRAME_DATA_STATE;
899 	client->current_stream = stream;
900 
901 	return 0;
902 }
903 
enter_http_frame_headers_state(struct http_client_ctx * client)904 static int enter_http_frame_headers_state(struct http_client_ctx *client)
905 {
906 	struct http2_frame *frame = &client->current_frame;
907 	struct http2_stream_ctx *stream;
908 
909 	stream = find_http_stream_context(client, frame->stream_identifier);
910 	if (!stream) {
911 		LOG_DBG("|| stream ID ||  %d", frame->stream_identifier);
912 
913 		stream = allocate_http_stream_context(client, frame->stream_identifier);
914 		if (!stream) {
915 			LOG_DBG("No available stream slots. Connection closed.");
916 
917 			return -ENOMEM;
918 		}
919 	}
920 
921 	client->current_stream = stream;
922 
923 	if (!is_header_flag_set(frame->flags, HTTP2_FLAG_END_HEADERS)) {
924 		client->expect_continuation = true;
925 	} else {
926 		client->expect_continuation = false;
927 	}
928 
929 	if (IS_ENABLED(CONFIG_HTTP_SERVER_CAPTURE_HEADERS)) {
930 		/* Reset header capture state for new headers frame */
931 		client->header_capture_ctx.count = 0;
932 		client->header_capture_ctx.cursor = 0;
933 		client->header_capture_ctx.status = HTTP_HEADER_STATUS_OK;
934 		client->header_capture_ctx.current_stream = stream;
935 	}
936 
937 	client->server_state = HTTP_SERVER_FRAME_HEADERS_STATE;
938 
939 	return 0;
940 }
941 
enter_http_frame_continuation_state(struct http_client_ctx * client)942 static int enter_http_frame_continuation_state(struct http_client_ctx *client)
943 {
944 	struct http2_frame *frame = &client->current_frame;
945 
946 	if (!is_header_flag_set(frame->flags, HTTP2_FLAG_END_HEADERS)) {
947 		client->expect_continuation = true;
948 	} else {
949 		client->expect_continuation = false;
950 	}
951 
952 	client->server_state = HTTP_SERVER_FRAME_CONTINUATION_STATE;
953 
954 	return 0;
955 }
956 
enter_http_frame_window_update_state(struct http_client_ctx * client)957 static int enter_http_frame_window_update_state(struct http_client_ctx *client)
958 {
959 	client->server_state = HTTP_SERVER_FRAME_WINDOW_UPDATE_STATE;
960 
961 	return 0;
962 }
963 
enter_http_frame_priority_state(struct http_client_ctx * client)964 static int enter_http_frame_priority_state(struct http_client_ctx *client)
965 {
966 	client->server_state = HTTP_SERVER_FRAME_PRIORITY_STATE;
967 
968 	return 0;
969 }
970 
enter_http_frame_rst_stream_state(struct http_client_ctx * client)971 static int enter_http_frame_rst_stream_state(struct http_client_ctx *client)
972 {
973 	client->server_state = HTTP_SERVER_FRAME_RST_STREAM_STATE;
974 
975 	return 0;
976 }
977 
enter_http_frame_goaway_state(struct http_client_ctx * client)978 static int enter_http_frame_goaway_state(struct http_client_ctx *client)
979 {
980 	client->server_state = HTTP_SERVER_FRAME_GOAWAY_STATE;
981 
982 	return 0;
983 }
984 
handle_http_frame_header(struct http_client_ctx * client)985 int handle_http_frame_header(struct http_client_ctx *client)
986 {
987 	int ret;
988 
989 	LOG_DBG("HTTP_SERVER_FRAME_HEADER");
990 
991 	ret = parse_http_frame_header(client, client->cursor, client->data_len);
992 	if (ret < 0) {
993 		return ret;
994 	}
995 
996 	client->cursor += HTTP2_FRAME_HEADER_SIZE;
997 	client->data_len -= HTTP2_FRAME_HEADER_SIZE;
998 
999 	print_http_frames(client);
1000 
1001 	if (client->expect_continuation &&
1002 	    client->current_frame.type != HTTP2_CONTINUATION_FRAME) {
1003 		LOG_ERR("Continuation frame expected");
1004 		return -EBADMSG;
1005 	}
1006 
1007 	client->current_stream = NULL;
1008 
1009 	switch (client->current_frame.type) {
1010 	case HTTP2_DATA_FRAME:
1011 		return enter_http_frame_data_state(client);
1012 	case HTTP2_HEADERS_FRAME:
1013 		return enter_http_frame_headers_state(client);
1014 	case HTTP2_CONTINUATION_FRAME:
1015 		return enter_http_frame_continuation_state(client);
1016 	case HTTP2_SETTINGS_FRAME:
1017 		return enter_http_frame_settings_state(client);
1018 	case HTTP2_WINDOW_UPDATE_FRAME:
1019 		return enter_http_frame_window_update_state(client);
1020 	case HTTP2_RST_STREAM_FRAME:
1021 		return enter_http_frame_rst_stream_state(client);
1022 	case HTTP2_GOAWAY_FRAME:
1023 		return enter_http_frame_goaway_state(client);
1024 	case HTTP2_PRIORITY_FRAME:
1025 		return enter_http_frame_priority_state(client);
1026 	default:
1027 		return enter_http_done_state(client);
1028 	}
1029 
1030 	return 0;
1031 }
1032 
1033 /* This feature is theoretically obsoleted in RFC9113, but curl for instance
1034  * still uses it, so implement as described in RFC7540.
1035  */
handle_http1_to_http2_upgrade(struct http_client_ctx * client)1036 int handle_http1_to_http2_upgrade(struct http_client_ctx *client)
1037 {
1038 	static const char switching_protocols[] =
1039 		"HTTP/1.1 101 Switching Protocols\r\n"
1040 		"Connection: Upgrade\r\n"
1041 		"Upgrade: h2c\r\n"
1042 		"\r\n";
1043 	struct http2_frame *frame = &client->current_frame;
1044 	struct http_resource_detail *detail;
1045 	struct http2_stream_ctx *stream;
1046 	int path_len;
1047 	int ret;
1048 
1049 	/* Create an artificial Data frame, so that we can proceed with HTTP2
1050 	 * processing. The HTTP/1.1 request that is sent prior to upgrade is
1051 	 * assigned a stream identifier of 1.
1052 	 */
1053 	frame->stream_identifier = 1;
1054 	frame->type = HTTP2_DATA_FRAME;
1055 	frame->length = client->http1_frag_data_len;
1056 	if (client->parser_state == HTTP1_MESSAGE_COMPLETE_STATE) {
1057 		frame->flags = HTTP2_FLAG_END_STREAM;
1058 	} else {
1059 		frame->flags = 0;
1060 	}
1061 
1062 	/* Allocate stream. */
1063 	stream = find_http_stream_context(client, frame->stream_identifier);
1064 	if (stream == NULL) {
1065 		stream = allocate_http_stream_context(client, frame->stream_identifier);
1066 		if (!stream) {
1067 			LOG_DBG("No available stream slots. Connection closed.");
1068 			return -ENOMEM;
1069 		}
1070 	}
1071 
1072 	client->current_stream = stream;
1073 
1074 	if (!client->preface_sent) {
1075 		ret = http_server_sendall(client, switching_protocols,
1076 					  sizeof(switching_protocols) - 1);
1077 		if (ret < 0) {
1078 			return ret;
1079 		}
1080 
1081 		client->http1_headers_sent = true;
1082 
1083 		/* The first HTTP/2 frame sent by the server MUST be a server connection
1084 		 * preface.
1085 		 */
1086 		ret = send_settings_frame(client, false);
1087 		if (ret < 0) {
1088 			goto error;
1089 		}
1090 
1091 		client->preface_sent = true;
1092 	}
1093 
1094 	detail = get_resource_detail(client->service, client->url_buffer, &path_len, false);
1095 	if (detail != NULL) {
1096 		detail->path_len = path_len;
1097 
1098 		if (detail->type == HTTP_RESOURCE_TYPE_STATIC) {
1099 			ret = handle_http2_static_resource(
1100 				(struct http_resource_detail_static *)detail,
1101 				frame, client);
1102 			if (ret < 0) {
1103 				goto error;
1104 			}
1105 #if defined(CONFIG_FILE_SYSTEM)
1106 		} else if (detail->type == HTTP_RESOURCE_TYPE_STATIC_FS) {
1107 			ret = handle_http2_static_fs_resource(
1108 				(struct http_resource_detail_static_fs *)detail, frame, client);
1109 			if (ret < 0) {
1110 				goto error;
1111 			}
1112 #endif
1113 		} else if (detail->type == HTTP_RESOURCE_TYPE_DYNAMIC) {
1114 			ret = handle_http2_dynamic_resource(
1115 				(struct http_resource_detail_dynamic *)detail,
1116 				frame, client);
1117 			if (ret < 0) {
1118 				goto error;
1119 			}
1120 
1121 			if (client->method == HTTP_POST ||
1122 			    client->method == HTTP_PUT ||
1123 			    client->method == HTTP_PATCH) {
1124 				ret = dynamic_post_put_req_v2(
1125 					(struct http_resource_detail_dynamic *)detail, client,
1126 					false);
1127 				if (ret < 0) {
1128 					goto error;
1129 				}
1130 			}
1131 
1132 		}
1133 	} else {
1134 		ret = send_http2_404(client, frame);
1135 		if (ret < 0) {
1136 			goto error;
1137 		}
1138 	}
1139 
1140 	/* Only after the complete HTTP1 payload has been processed, switch
1141 	 * to HTTP2.
1142 	 */
1143 	if (client->parser_state == HTTP1_MESSAGE_COMPLETE_STATE) {
1144 		release_http_stream_context(client, frame->stream_identifier);
1145 		client->current_detail = NULL;
1146 		client->server_state = HTTP_SERVER_PREFACE_STATE;
1147 		client->cursor += client->data_len;
1148 		client->data_len = 0;
1149 	}
1150 
1151 	return 0;
1152 
1153 error:
1154 	if (ret != -EAGAIN && client->current_stream &&
1155 	    !client->current_stream->headers_sent) {
1156 		send_http2_500(client, frame, -ret);
1157 	}
1158 
1159 	return ret;
1160 }
1161 
parse_http_frame_padded_field(struct http_client_ctx * client)1162 static int parse_http_frame_padded_field(struct http_client_ctx *client)
1163 {
1164 	struct http2_frame *frame = &client->current_frame;
1165 
1166 	if (client->data_len == 0) {
1167 		return -EAGAIN;
1168 	}
1169 
1170 	frame->padding_len = *client->cursor;
1171 	client->cursor++;
1172 	client->data_len--;
1173 	frame->length--;
1174 
1175 	if (frame->length <= frame->padding_len) {
1176 		return -EBADMSG;
1177 	}
1178 
1179 	/* Subtract the padding length from frame length now to simplify
1180 	 * payload processing. Padding will be handled based on
1181 	 * frame->padding_len in a separate state.
1182 	 */
1183 	frame->length -= frame->padding_len;
1184 
1185 	/* Clear the padded flag, this indicates that padding field was
1186 	 * already parsed.
1187 	 */
1188 	clear_header_flag(&frame->flags, HTTP2_FLAG_PADDED);
1189 
1190 	return 0;
1191 }
1192 
parse_http_frame_priority_field(struct http_client_ctx * client)1193 static int parse_http_frame_priority_field(struct http_client_ctx *client)
1194 {
1195 	struct http2_frame *frame = &client->current_frame;
1196 
1197 	if (client->data_len < HTTP2_HEADERS_FRAME_PRIORITY_LEN) {
1198 		return -EAGAIN;
1199 	}
1200 
1201 	/* Priority signalling is deprecated by RFC 9113, however it still
1202 	 * should be expected to receive, just drop the bytes.
1203 	 */
1204 	client->cursor += HTTP2_HEADERS_FRAME_PRIORITY_LEN;
1205 	client->data_len -= HTTP2_HEADERS_FRAME_PRIORITY_LEN;
1206 	frame->length -= HTTP2_HEADERS_FRAME_PRIORITY_LEN;
1207 
1208 	/* Clear the priority flag, this indicates that priority field was
1209 	 * already parsed.
1210 	 */
1211 	clear_header_flag(&frame->flags, HTTP2_FLAG_PRIORITY);
1212 
1213 	return 0;
1214 }
1215 
handle_http_frame_data(struct http_client_ctx * client)1216 int handle_http_frame_data(struct http_client_ctx *client)
1217 {
1218 	struct http2_frame *frame = &client->current_frame;
1219 	int ret;
1220 
1221 	LOG_DBG("HTTP_SERVER_FRAME_DATA_STATE");
1222 
1223 	if (client->current_stream->current_detail == NULL) {
1224 		/* There is no handler */
1225 		LOG_DBG("No dynamic handler found.");
1226 		(void)send_http2_404(client, frame);
1227 		ret = -ENOENT;
1228 		goto error;
1229 	}
1230 
1231 	if (is_header_flag_set(frame->flags, HTTP2_FLAG_PADDED)) {
1232 		ret = parse_http_frame_padded_field(client);
1233 		if (ret < 0) {
1234 			goto error;
1235 		}
1236 	}
1237 
1238 	ret = dynamic_post_put_req_v2(
1239 		(struct http_resource_detail_dynamic *)client->current_stream->current_detail,
1240 		client, false);
1241 	if (ret < 0 && ret == -ENOENT) {
1242 		ret = send_http2_404(client, frame);
1243 	}
1244 
1245 	if (ret < 0) {
1246 		goto error;
1247 	}
1248 
1249 	if (frame->length == 0) {
1250 		struct http2_stream_ctx *stream =
1251 			find_http_stream_context(client, frame->stream_identifier);
1252 
1253 		if (stream == NULL) {
1254 			LOG_DBG("No stream context found for ID %d",
1255 				frame->stream_identifier);
1256 			ret = -EBADMSG;
1257 			goto error;
1258 		}
1259 
1260 		ret = send_window_update_frame(client, stream);
1261 		if (ret < 0) {
1262 			goto error;
1263 		}
1264 
1265 		ret = send_window_update_frame(client, NULL);
1266 		if (ret < 0) {
1267 			goto error;
1268 		}
1269 
1270 		if (is_header_flag_set(frame->flags, HTTP2_FLAG_END_STREAM)) {
1271 			client->current_stream->current_detail = NULL;
1272 			release_http_stream_context(client, frame->stream_identifier);
1273 		}
1274 
1275 		/* Whole frame consumed, expect next one. */
1276 		if (frame->padding_len > 0) {
1277 			client->server_state = HTTP_SERVER_FRAME_PADDING_STATE;
1278 		} else {
1279 			client->server_state = HTTP_SERVER_FRAME_HEADER_STATE;
1280 		}
1281 	}
1282 
1283 	return 0;
1284 
1285 error:
1286 	if (ret != -EAGAIN && client->current_stream &&
1287 	    !client->current_stream->headers_sent) {
1288 		send_http2_500(client, frame, -ret);
1289 	}
1290 
1291 	return ret;
1292 }
1293 
check_user_request_headers_http2(struct http_header_capture_ctx * ctx,struct http_hpack_header_buf * hdr_buf)1294 static void check_user_request_headers_http2(struct http_header_capture_ctx *ctx,
1295 					     struct http_hpack_header_buf *hdr_buf)
1296 {
1297 	size_t required_len;
1298 	char *dest = &ctx->buffer[ctx->cursor];
1299 	size_t remaining = sizeof(ctx->buffer) - ctx->cursor;
1300 	struct http_header *current_header = &ctx->headers[ctx->count];
1301 
1302 	STRUCT_SECTION_FOREACH(http_header_name, header) {
1303 		required_len = hdr_buf->name_len + hdr_buf->value_len + 2;
1304 
1305 		if (hdr_buf->name_len == strlen(header->name) &&
1306 		    (strncasecmp(hdr_buf->name, header->name, hdr_buf->name_len) == 0)) {
1307 			if (ctx->count == ARRAY_SIZE(ctx->headers)) {
1308 				LOG_DBG("Header '%s' dropped: not enough slots", header->name);
1309 				ctx->status = HTTP_HEADER_STATUS_DROPPED;
1310 				break;
1311 			}
1312 
1313 			if (remaining < required_len) {
1314 				LOG_DBG("Header '%s' dropped: buffer too small", header->name);
1315 				ctx->status = HTTP_HEADER_STATUS_DROPPED;
1316 				break;
1317 			}
1318 
1319 			/* Copy header name from user-registered header to make HTTP1/HTTP2
1320 			 * transparent to the user - they do not need a case-insensitive comparison
1321 			 * to check which header was matched.
1322 			 */
1323 			memcpy(dest, header->name, hdr_buf->name_len);
1324 			dest[hdr_buf->name_len] = '\0';
1325 			current_header->name = dest;
1326 			ctx->cursor += (hdr_buf->name_len + 1);
1327 			dest += (hdr_buf->name_len + 1);
1328 
1329 			/* Copy header value */
1330 			memcpy(dest, hdr_buf->value, hdr_buf->value_len);
1331 			dest[hdr_buf->value_len] = '\0';
1332 			current_header->value = dest;
1333 			ctx->cursor += (hdr_buf->value_len + 1);
1334 
1335 			ctx->count++;
1336 			break;
1337 		}
1338 	}
1339 }
1340 
process_header(struct http_client_ctx * client,struct http_hpack_header_buf * header)1341 static int process_header(struct http_client_ctx *client,
1342 			  struct http_hpack_header_buf *header)
1343 {
1344 	if (IS_ENABLED(CONFIG_HTTP_SERVER_CAPTURE_HEADERS)) {
1345 		check_user_request_headers_http2(&client->header_capture_ctx, header);
1346 	}
1347 
1348 	if (header->name_len == (sizeof(":method") - 1) &&
1349 	    memcmp(header->name, ":method", header->name_len) == 0) {
1350 		const enum http_method supported_methods[] = {
1351 			HTTP_GET, HTTP_DELETE, HTTP_POST, HTTP_PUT, HTTP_PATCH
1352 		};
1353 
1354 		for (int i = 0; i < ARRAY_SIZE(supported_methods); i++) {
1355 			if ((header->value_len ==
1356 			     strlen(http_method_str(supported_methods[i]))) &&
1357 			    (memcmp(header->value,
1358 				    http_method_str(supported_methods[i]),
1359 				    header->value_len) == 0)) {
1360 				client->method = supported_methods[i];
1361 				goto out;
1362 			}
1363 		}
1364 
1365 		/* Unknown method */
1366 		return -EBADMSG;
1367 	} else if (header->name_len == (sizeof(":path") - 1) &&
1368 		   memcmp(header->name, ":path", header->name_len) == 0) {
1369 		if (header->value_len > sizeof(client->url_buffer) - 1) {
1370 			/* URL too long to handle */
1371 			return -ENOBUFS;
1372 		}
1373 
1374 		memcpy(client->url_buffer, header->value, header->value_len);
1375 		client->url_buffer[header->value_len] = '\0';
1376 	} else if (header->name_len == (sizeof("content-type") - 1) &&
1377 		   memcmp(header->name, "content-type", header->name_len) == 0) {
1378 		if (header->value_len > sizeof(client->content_type) - 1) {
1379 			/* Content-type too long to handle */
1380 			return -ENOBUFS;
1381 		}
1382 
1383 		memcpy(client->content_type, header->value, header->value_len);
1384 		client->content_type[header->value_len] = '\0';
1385 	} else if (header->name_len == (sizeof("content-length") - 1) &&
1386 		   memcmp(header->name, "content-length", header->name_len) == 0) {
1387 		char len_str[16] = { 0 };
1388 		char *endptr;
1389 		unsigned long len;
1390 
1391 		memcpy(len_str, header->value, MIN(sizeof(len_str), header->value_len));
1392 		len_str[sizeof(len_str) - 1] = '\0';
1393 
1394 		len = strtoul(len_str, &endptr, 10);
1395 		if (*endptr != '\0') {
1396 			return -EINVAL;
1397 		}
1398 
1399 		client->content_len = (size_t)len;
1400 	}
1401 #ifdef CONFIG_HTTP_SERVER_COMPRESSION
1402 	else if (header->name_len == (sizeof("accept-encoding") - 1) &&
1403 		 memcmp(header->name, "accept-encoding", header->name_len) == 0) {
1404 		http_compression_parse_accept_encoding(header->value, header->value_len,
1405 						       &client->supported_compression);
1406 	}
1407 #endif /* CONFIG_HTTP_SERVER_COMPRESSION */
1408 	else {
1409 		/* Just ignore for now. */
1410 		LOG_DBG("Ignoring field %.*s", (int)header->name_len, header->name);
1411 	}
1412 
1413 out:
1414 	return 0;
1415 }
1416 
handle_incomplete_http_header(struct http_client_ctx * client)1417 static int handle_incomplete_http_header(struct http_client_ctx *client)
1418 {
1419 	struct http2_frame *frame = &client->current_frame;
1420 	size_t extra_len, prev_frame_len;
1421 	int ret;
1422 
1423 	if (client->data_len < frame->length) {
1424 		/* Still did not receive entire frame content */
1425 		return -EAGAIN;
1426 	}
1427 
1428 	if (!client->expect_continuation) {
1429 		/* Failed to parse header field while the frame is complete
1430 		 * and no continuation frame is expected - report protocol
1431 		 * error.
1432 		 */
1433 		LOG_ERR("Incomplete header field");
1434 		return -EBADMSG;
1435 	}
1436 
1437 	/* A header field can be split between two frames, i. e. header and
1438 	 * continuation or two continuation frames. Because of this, the
1439 	 * continuation frame header can be present in the stream in between
1440 	 * header field data, so in such case we need to check for header here
1441 	 * and remove it from the stream to unblock further processing of the
1442 	 * header field.
1443 	 */
1444 	prev_frame_len = frame->length;
1445 	extra_len = client->data_len - frame->length;
1446 	ret = parse_http_frame_header(client, client->cursor + prev_frame_len,
1447 				      extra_len);
1448 	if (ret < 0) {
1449 		return -EAGAIN;
1450 	}
1451 
1452 	/* Continuation frame expected. */
1453 	if (frame->type != HTTP2_CONTINUATION_FRAME) {
1454 		LOG_ERR("Continuation frame expected");
1455 		return -EBADMSG;
1456 	}
1457 
1458 	print_http_frames(client);
1459 	/* Now remove continuation frame header from the stream, and proceed
1460 	 * with processing.
1461 	 */
1462 	extra_len -= HTTP2_FRAME_HEADER_SIZE;
1463 	client->data_len -= HTTP2_FRAME_HEADER_SIZE;
1464 	frame->length += prev_frame_len;
1465 	memmove(client->cursor + prev_frame_len,
1466 		client->cursor + prev_frame_len + HTTP2_FRAME_HEADER_SIZE,
1467 		extra_len);
1468 
1469 	return enter_http_frame_continuation_state(client);
1470 }
1471 
handle_http_frame_headers_end_stream(struct http_client_ctx * client)1472 static int handle_http_frame_headers_end_stream(struct http_client_ctx *client)
1473 {
1474 	struct http2_frame *frame = &client->current_frame;
1475 	struct http_request_ctx request_ctx;
1476 	struct http_response_ctx response_ctx;
1477 	int ret = 0;
1478 
1479 	if (client->current_stream == NULL) {
1480 		return -ENOENT;
1481 	}
1482 
1483 	if (client->current_stream->current_detail == NULL) {
1484 		goto out;
1485 	}
1486 
1487 	if (client->current_stream->current_detail->type == HTTP_RESOURCE_TYPE_DYNAMIC) {
1488 		struct http_resource_detail_dynamic *dynamic_detail =
1489 			(struct http_resource_detail_dynamic *)
1490 				client->current_stream->current_detail;
1491 
1492 		memset(&response_ctx, 0, sizeof(response_ctx));
1493 		populate_request_ctx(&request_ctx, NULL, 0, NULL);
1494 
1495 		ret = dynamic_detail->cb(client, HTTP_SERVER_DATA_FINAL, &request_ctx,
1496 					 &response_ctx, dynamic_detail->user_data);
1497 		if (ret < 0) {
1498 			dynamic_detail->holder = NULL;
1499 			goto out;
1500 		}
1501 
1502 		/* Force end stream */
1503 		response_ctx.final_chunk = true;
1504 
1505 		ret = http2_dynamic_response(client, frame, &response_ctx, HTTP_SERVER_DATA_FINAL,
1506 					     dynamic_detail);
1507 		dynamic_detail->holder = NULL;
1508 
1509 		if (ret < 0) {
1510 			goto out;
1511 		}
1512 	}
1513 
1514 	if (!client->current_stream->headers_sent) {
1515 		ret = send_headers_frame(client, HTTP_200_OK, frame->stream_identifier,
1516 					 client->current_stream->current_detail,
1517 					 HTTP2_FLAG_END_STREAM, NULL, 0);
1518 		if (ret < 0) {
1519 			LOG_DBG("Cannot write to socket (%d)", ret);
1520 			goto out;
1521 		}
1522 	} else if (!client->current_stream->end_stream_sent) {
1523 		ret = send_data_frame(client, NULL, 0, frame->stream_identifier,
1524 				      HTTP2_FLAG_END_STREAM);
1525 		if (ret < 0) {
1526 			LOG_DBG("Cannot send last frame (%d)", ret);
1527 		}
1528 	}
1529 
1530 	client->current_stream->current_detail = NULL;
1531 
1532 out:
1533 	release_http_stream_context(client, frame->stream_identifier);
1534 
1535 	return ret;
1536 }
1537 
handle_http_frame_headers(struct http_client_ctx * client)1538 int handle_http_frame_headers(struct http_client_ctx *client)
1539 {
1540 	struct http2_frame *frame = &client->current_frame;
1541 	struct http_resource_detail *detail;
1542 	int ret, path_len;
1543 
1544 	LOG_DBG("HTTP_SERVER_FRAME_HEADERS");
1545 
1546 	if (is_header_flag_set(frame->flags, HTTP2_FLAG_PADDED)) {
1547 		ret = parse_http_frame_padded_field(client);
1548 		if (ret < 0) {
1549 			goto error;
1550 		}
1551 	}
1552 
1553 	if (is_header_flag_set(frame->flags, HTTP2_FLAG_PRIORITY)) {
1554 		ret = parse_http_frame_priority_field(client);
1555 		if (ret < 0) {
1556 			goto error;
1557 		}
1558 	}
1559 
1560 	while (frame->length > 0) {
1561 		struct http_hpack_header_buf *header = &client->header_field;
1562 		size_t datalen = MIN(client->data_len, frame->length);
1563 
1564 		ret = http_hpack_decode_header(client->cursor, datalen, header);
1565 		if (ret <= 0) {
1566 			if (ret == -EAGAIN) {
1567 				ret = handle_incomplete_http_header(client);
1568 			} else if (ret == 0) {
1569 				ret = -EBADMSG;
1570 			}
1571 
1572 			if (ret < 0) {
1573 				goto error;
1574 			}
1575 
1576 			return 0;
1577 		}
1578 
1579 		if (ret > frame->length) {
1580 			LOG_ERR("Protocol error, frame length exceeded");
1581 			ret = -EBADMSG;
1582 			goto error;
1583 		}
1584 
1585 		frame->length -= ret;
1586 		client->cursor += ret;
1587 		client->data_len -= ret;
1588 
1589 		LOG_DBG("Parsed header: %.*s %.*s", (int)header->name_len,
1590 			header->name, (int)header->value_len, header->value);
1591 
1592 		ret = process_header(client, header);
1593 		if (ret < 0) {
1594 			goto error;
1595 		}
1596 	}
1597 
1598 	if (client->expect_continuation) {
1599 		/* More headers to come in the continuation frame. */
1600 		client->server_state = HTTP_SERVER_FRAME_HEADER_STATE;
1601 		return 0;
1602 	}
1603 
1604 	detail = get_resource_detail(client->service, client->url_buffer, &path_len, false);
1605 	if (detail != NULL) {
1606 		detail->path_len = path_len;
1607 
1608 		if (detail->type == HTTP_RESOURCE_TYPE_STATIC) {
1609 			ret = handle_http2_static_resource(
1610 				(struct http_resource_detail_static *)detail,
1611 				frame, client);
1612 			if (ret < 0) {
1613 				goto error;
1614 			}
1615 #if defined(CONFIG_FILE_SYSTEM)
1616 		} else if (detail->type == HTTP_RESOURCE_TYPE_STATIC_FS) {
1617 			ret = handle_http2_static_fs_resource(
1618 				(struct http_resource_detail_static_fs *)detail, frame, client);
1619 			if (ret < 0) {
1620 				goto error;
1621 			}
1622 #endif
1623 		} else if (detail->type == HTTP_RESOURCE_TYPE_DYNAMIC) {
1624 			ret = handle_http2_dynamic_resource(
1625 				(struct http_resource_detail_dynamic *)detail,
1626 				frame, client);
1627 			if (ret < 0) {
1628 				goto error;
1629 			}
1630 		}
1631 
1632 	} else {
1633 		ret = send_http2_404(client, frame);
1634 		if (ret < 0) {
1635 			goto error;
1636 		}
1637 	}
1638 
1639 	if (is_header_flag_set(frame->flags, HTTP2_FLAG_END_STREAM)) {
1640 		ret = handle_http_frame_headers_end_stream(client);
1641 		if (ret < 0) {
1642 			goto error;
1643 		}
1644 	}
1645 
1646 	if (frame->padding_len > 0) {
1647 		client->server_state = HTTP_SERVER_FRAME_PADDING_STATE;
1648 	} else {
1649 		client->server_state = HTTP_SERVER_FRAME_HEADER_STATE;
1650 	}
1651 
1652 	return 0;
1653 
1654 error:
1655 	if (ret != -EAGAIN && client->current_stream &&
1656 	    !client->current_stream->headers_sent) {
1657 		send_http2_500(client, frame, -ret);
1658 	}
1659 
1660 	return ret;
1661 }
1662 
handle_http_frame_priority(struct http_client_ctx * client)1663 int handle_http_frame_priority(struct http_client_ctx *client)
1664 {
1665 	struct http2_frame *frame = &client->current_frame;
1666 
1667 	LOG_DBG("HTTP_SERVER_FRAME_PRIORITY_STATE");
1668 
1669 	if (frame->length != HTTP2_PRIORITY_FRAME_LEN) {
1670 		return -EBADMSG;
1671 	}
1672 
1673 	if (client->data_len < frame->length) {
1674 		return -EAGAIN;
1675 	}
1676 
1677 	/* Priority signalling is deprecated by RFC 9113, however it still
1678 	 * should be expected to receive, just drop the bytes.
1679 	 */
1680 	client->data_len -= HTTP2_PRIORITY_FRAME_LEN;
1681 	client->cursor += HTTP2_PRIORITY_FRAME_LEN;
1682 
1683 	client->server_state = HTTP_SERVER_FRAME_HEADER_STATE;
1684 
1685 	return 0;
1686 }
1687 
handle_http_frame_rst_stream(struct http_client_ctx * client)1688 int handle_http_frame_rst_stream(struct http_client_ctx *client)
1689 {
1690 	struct http2_frame *frame = &client->current_frame;
1691 	struct http2_stream_ctx *stream_ctx;
1692 	uint32_t error_code;
1693 
1694 	LOG_DBG("FRAME_RST_STREAM");
1695 
1696 	if (frame->length != HTTP2_RST_STREAM_FRAME_LEN) {
1697 		return -EBADMSG;
1698 	}
1699 
1700 	if (client->data_len < frame->length) {
1701 		return -EAGAIN;
1702 	}
1703 
1704 	if (frame->stream_identifier == 0) {
1705 		return -EBADMSG;
1706 	}
1707 
1708 	stream_ctx = find_http_stream_context(client, frame->stream_identifier);
1709 	if (stream_ctx == NULL) {
1710 		return -EBADMSG;
1711 	}
1712 
1713 	error_code = sys_get_be32(client->cursor);
1714 
1715 	LOG_DBG("Stream %u reset with error code %u", stream_ctx->stream_id,
1716 		error_code);
1717 
1718 	release_http_stream_context(client, stream_ctx->stream_id);
1719 
1720 	client->data_len -= HTTP2_RST_STREAM_FRAME_LEN;
1721 	client->cursor += HTTP2_RST_STREAM_FRAME_LEN;
1722 
1723 	client->server_state = HTTP_SERVER_FRAME_HEADER_STATE;
1724 
1725 	return 0;
1726 }
1727 
handle_http_frame_settings(struct http_client_ctx * client)1728 int handle_http_frame_settings(struct http_client_ctx *client)
1729 {
1730 	struct http2_frame *frame = &client->current_frame;
1731 	int bytes_consumed;
1732 
1733 	LOG_DBG("HTTP_SERVER_FRAME_SETTINGS");
1734 
1735 	if (client->data_len < frame->length) {
1736 		return -EAGAIN;
1737 	}
1738 
1739 	bytes_consumed = client->current_frame.length;
1740 	client->data_len -= bytes_consumed;
1741 	client->cursor += bytes_consumed;
1742 
1743 	if (!is_header_flag_set(frame->flags, HTTP2_FLAG_SETTINGS_ACK)) {
1744 		int ret;
1745 
1746 		ret = send_settings_frame(client, true);
1747 		if (ret < 0) {
1748 			LOG_DBG("Cannot write to socket (%d)", ret);
1749 			return ret;
1750 		}
1751 	}
1752 
1753 	client->server_state = HTTP_SERVER_FRAME_HEADER_STATE;
1754 
1755 	return 0;
1756 }
1757 
handle_http_frame_goaway(struct http_client_ctx * client)1758 int handle_http_frame_goaway(struct http_client_ctx *client)
1759 {
1760 	struct http2_frame *frame = &client->current_frame;
1761 	int bytes_consumed;
1762 
1763 	LOG_DBG("HTTP_SERVER_FRAME_GOAWAY");
1764 
1765 	if (client->data_len < frame->length) {
1766 		return -EAGAIN;
1767 	}
1768 
1769 	bytes_consumed = client->current_frame.length;
1770 	client->data_len -= bytes_consumed;
1771 	client->cursor += bytes_consumed;
1772 
1773 	enter_http_done_state(client);
1774 
1775 	return 0;
1776 }
1777 
handle_http_frame_window_update(struct http_client_ctx * client)1778 int handle_http_frame_window_update(struct http_client_ctx *client)
1779 {
1780 	struct http2_frame *frame = &client->current_frame;
1781 	int bytes_consumed;
1782 
1783 	LOG_DBG("HTTP_SERVER_FRAME_WINDOW_UPDATE");
1784 
1785 	/* TODO Implement flow control, for now just ignore. */
1786 
1787 	if (client->data_len < frame->length) {
1788 		return -EAGAIN;
1789 	}
1790 
1791 	bytes_consumed = client->current_frame.length;
1792 	client->data_len -= bytes_consumed;
1793 	client->cursor += bytes_consumed;
1794 
1795 	client->server_state = HTTP_SERVER_FRAME_HEADER_STATE;
1796 
1797 	return 0;
1798 }
1799 
handle_http_frame_continuation(struct http_client_ctx * client)1800 int handle_http_frame_continuation(struct http_client_ctx *client)
1801 {
1802 	LOG_DBG("HTTP_SERVER_FRAME_CONTINUATION_STATE");
1803 	client->server_state = HTTP_SERVER_FRAME_HEADERS_STATE;
1804 
1805 	return 0;
1806 }
1807 
handle_http_frame_padding(struct http_client_ctx * client)1808 int handle_http_frame_padding(struct http_client_ctx *client)
1809 {
1810 	struct http2_frame *frame = &client->current_frame;
1811 	size_t bytes_consumed;
1812 
1813 	if (client->data_len == 0) {
1814 		return -EAGAIN;
1815 	}
1816 
1817 	bytes_consumed = MIN(client->data_len, frame->padding_len);
1818 	client->data_len -= bytes_consumed;
1819 	client->cursor += bytes_consumed;
1820 	frame->padding_len -= bytes_consumed;
1821 
1822 	if (frame->padding_len == 0) {
1823 		client->server_state = HTTP_SERVER_FRAME_HEADER_STATE;
1824 	}
1825 
1826 	return 0;
1827 }
1828 
get_frame_type_name(enum http2_frame_type type)1829 const char *get_frame_type_name(enum http2_frame_type type)
1830 {
1831 	switch (type) {
1832 	case HTTP2_DATA_FRAME:
1833 		return "DATA";
1834 	case HTTP2_HEADERS_FRAME:
1835 		return "HEADERS";
1836 	case HTTP2_PRIORITY_FRAME:
1837 		return "PRIORITY";
1838 	case HTTP2_RST_STREAM_FRAME:
1839 		return "RST_STREAM";
1840 	case HTTP2_SETTINGS_FRAME:
1841 		return "SETTINGS";
1842 	case HTTP2_PUSH_PROMISE_FRAME:
1843 		return "PUSH_PROMISE";
1844 	case HTTP2_PING_FRAME:
1845 		return "PING";
1846 	case HTTP2_GOAWAY_FRAME:
1847 		return "GOAWAY";
1848 	case HTTP2_WINDOW_UPDATE_FRAME:
1849 		return "WINDOW_UPDATE";
1850 	case HTTP2_CONTINUATION_FRAME:
1851 		return "CONTINUATION";
1852 	default:
1853 		return "UNKNOWN";
1854 	}
1855 }
1856 
parse_http_frame_header(struct http_client_ctx * client,const uint8_t * buffer,size_t buflen)1857 int parse_http_frame_header(struct http_client_ctx *client, const uint8_t *buffer,
1858 			    size_t buflen)
1859 {
1860 	struct http2_frame *frame = &client->current_frame;
1861 
1862 	if (buflen < HTTP2_FRAME_HEADER_SIZE) {
1863 		return -EAGAIN;
1864 	}
1865 
1866 	frame->length = sys_get_be24(&buffer[HTTP2_FRAME_LENGTH_OFFSET]);
1867 	frame->type = buffer[HTTP2_FRAME_TYPE_OFFSET];
1868 	frame->flags = buffer[HTTP2_FRAME_FLAGS_OFFSET];
1869 	frame->stream_identifier = sys_get_be32(
1870 				&buffer[HTTP2_FRAME_STREAM_ID_OFFSET]);
1871 	frame->stream_identifier &= HTTP2_FRAME_STREAM_ID_MASK;
1872 	frame->padding_len = 0;
1873 
1874 	LOG_DBG("Frame len %d type 0x%02x flags 0x%02x id %d",
1875 		frame->length, frame->type, frame->flags, frame->stream_identifier);
1876 
1877 	return 0;
1878 }
1879