diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index 826a9aafc0f3b6f..fb6b965f4405b7a 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -276,6 +276,12 @@ struct http2_stream_ctx { int stream_id; /**< Stream identifier. */ enum http2_stream_state stream_state; /**< Stream state. */ int window_size; /**< Stream-level window size. */ + + /** Flag indicating that headers were sent in the reply. */ + bool headers_sent : 1; + + /** Flag indicating that END_STREAM flag was sent. */ + bool end_stream_sent : 1; }; /** @brief HTTP/2 frame representation. */ @@ -315,6 +321,9 @@ struct http_client_ctx { /** Currently processed resource detail. */ struct http_resource_detail *current_detail; + /** Currently processed stream. */ + struct http2_stream_ctx *current_stream; + /** HTTP/2 header parser context. */ struct http_hpack_header_buf header_field; @@ -360,13 +369,6 @@ struct http_client_ctx { IF_ENABLED(CONFIG_WEBSOCKET, (uint8_t ws_sec_key[HTTP_SERVER_WS_MAX_SEC_KEY_LEN])); /** @endcond */ - /* TODO those two are stream-specific, move them. */ - /** Flag indicating that headers were sent in the reply. */ - bool headers_sent : 1; - - /** Flag indicating that END_STREAM flag was sent. */ - bool end_stream_sent : 1; - /** Flag indicating that HTTP2 preface was sent. */ bool preface_sent : 1; diff --git a/subsys/net/lib/http/http_server_core.c b/subsys/net/lib/http/http_server_core.c index 004cf857c3ce5e4..01e6131538b4f33 100644 --- a/subsys/net/lib/http/http_server_core.c +++ b/subsys/net/lib/http/http_server_core.c @@ -364,6 +364,8 @@ static void init_client_ctx(struct http_client_ctx *client, int new_socket) client->streams[i].stream_state = HTTP2_STREAM_IDLE; client->streams[i].stream_id = 0; } + + client->current_stream = NULL; } static int handle_http_preface(struct http_client_ctx *client) diff --git a/subsys/net/lib/http/http_server_http1.c b/subsys/net/lib/http/http_server_http1.c index de5c3d01bc4d231..bbf15926ba78c47 100644 --- a/subsys/net/lib/http/http_server_http1.c +++ b/subsys/net/lib/http/http_server_http1.c @@ -193,13 +193,17 @@ static int dynamic_post_req(struct http_resource_detail_dynamic *dynamic_detail, return -ENOENT; } - if (!client->headers_sent) { + if (client->current_stream == NULL) { + return -ENOENT; + } + + if (!client->current_stream->headers_sent) { ret = SEND_RESPONSE(RESPONSE_TEMPLATE_CHUNKED, dynamic_detail->common.content_type); if (ret < 0) { return ret; } - client->headers_sent = true; + client->current_stream->headers_sent = true; } copy_len = MIN(remaining, dynamic_detail->data_buffer_len); diff --git a/subsys/net/lib/http/http_server_http2.c b/subsys/net/lib/http/http_server_http2.c index 8cd208695cada2f..f2a1fde25dcac97 100644 --- a/subsys/net/lib/http/http_server_http2.c +++ b/subsys/net/lib/http/http_server_http2.c @@ -82,6 +82,8 @@ static struct http2_stream_ctx *allocate_http_stream_context( client->streams[i].stream_state = HTTP2_STREAM_OPEN; client->streams[i].window_size = HTTP_SERVER_INITIAL_WINDOW_SIZE; + client->streams[i].headers_sent = false; + client->streams[i].end_stream_sent = false; return &client->streams[i]; } } @@ -339,6 +341,10 @@ static int handle_http2_static_resource( return -ENOTSUP; } + if (client->current_stream == NULL) { + return -ENOENT; + } + content_200 = static_detail->static_data; content_len = static_detail->static_data_len; @@ -349,7 +355,7 @@ static int handle_http2_static_resource( goto out; } - client->headers_sent = true; + client->current_stream->headers_sent = true; ret = send_data_frame(client, content_200, content_len, frame->stream_identifier, @@ -359,7 +365,7 @@ static int handle_http2_static_resource( goto out; } - client->end_stream_sent = true; + client->current_stream->end_stream_sent = true; out: return ret; @@ -372,6 +378,10 @@ static int dynamic_get_req_v2(struct http_resource_detail_dynamic *dynamic_detai int ret, remaining, offset = dynamic_detail->common.path_len; char *ptr; + if (client->current_stream == NULL) { + return -ENOENT; + } + ret = send_headers_frame(client, HTTP_200_OK, frame->stream_identifier, &dynamic_detail->common, 0); if (ret < 0) { @@ -379,7 +389,7 @@ static int dynamic_get_req_v2(struct http_resource_detail_dynamic *dynamic_detai return ret; } - client->headers_sent = true; + client->current_stream->headers_sent = true; remaining = strlen(&client->url_buffer[dynamic_detail->common.path_len]); @@ -428,7 +438,7 @@ static int dynamic_get_req_v2(struct http_resource_detail_dynamic *dynamic_detai LOG_DBG("Cannot send last frame (%d)", ret); } - client->end_stream_sent = true; + client->current_stream->end_stream_sent = true; dynamic_detail->holder = NULL; @@ -450,6 +460,10 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta return -ENOENT; } + if (client->current_stream == NULL) { + return -ENOENT; + } + data_len = MIN(frame->length, client->data_len); copy_len = MIN(data_len, dynamic_detail->data_buffer_len); @@ -481,7 +495,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta if (send_len > 0) { uint8_t flags = 0; - if (!client->headers_sent) { + if (!client->current_stream->headers_sent) { ret = send_headers_frame( client, HTTP_200_OK, frame->stream_identifier, &dynamic_detail->common, 0); @@ -490,7 +504,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta return ret; } - client->headers_sent = true; + client->current_stream->headers_sent = true; } /* In case no more data is available, that was the last @@ -499,7 +513,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta if (frame->length == 0 && is_header_flag_set(frame->flags, HTTP2_FLAG_END_STREAM)) { flags = HTTP2_FLAG_END_STREAM; - client->end_stream_sent = true; + client->current_stream->end_stream_sent = true; } ret = send_data_frame(client, @@ -518,7 +532,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta if (frame->length == 0 && is_header_flag_set(frame->flags, HTTP2_FLAG_END_STREAM)) { - if (!client->headers_sent) { + if (!client->current_stream->headers_sent) { /* The callback did not report any data to send, therefore send * headers frame now, including END_STREAM flag. */ @@ -531,8 +545,8 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta return ret; } - client->headers_sent = true; - client->end_stream_sent = true; + client->current_stream->headers_sent = true; + client->current_stream->end_stream_sent = true; } dynamic_detail->holder = NULL; @@ -659,6 +673,7 @@ static int enter_http_frame_data_state(struct http_client_ctx *client) stream->window_size -= frame->length; client->window_size -= frame->length; client->server_state = HTTP_SERVER_FRAME_DATA_STATE; + client->current_stream = stream; return 0; } @@ -680,6 +695,8 @@ static int enter_http_frame_headers_state(struct http_client_ctx *client) } } + client->current_stream = stream; + if (!is_header_flag_set(frame->flags, HTTP2_FLAG_END_HEADERS)) { client->expect_continuation = true; } else { @@ -756,6 +773,8 @@ int handle_http_frame_header(struct http_client_ctx *client) return -EBADMSG; } + client->current_stream = NULL; + switch (client->current_frame.type) { case HTTP2_DATA_FRAME: return enter_http_frame_data_state(client); @@ -1121,6 +1140,10 @@ static int handle_http_frame_headers_end_stream(struct http_client_ctx *client) goto out; } + if (client->current_stream == NULL) { + return -ENOENT; + } + if (client->current_detail->type == HTTP_RESOURCE_TYPE_DYNAMIC) { struct http_resource_detail_dynamic *dynamic_detail = (struct http_resource_detail_dynamic *)client->current_detail; @@ -1130,7 +1153,7 @@ static int handle_http_frame_headers_end_stream(struct http_client_ctx *client) dynamic_detail->data_buffer, 0, dynamic_detail->user_data); if (send_len > 0) { - if (!client->headers_sent) { + if (!client->current_stream->headers_sent) { ret = send_headers_frame( client, HTTP_200_OK, frame->stream_identifier, client->current_detail, 0); @@ -1139,7 +1162,7 @@ static int handle_http_frame_headers_end_stream(struct http_client_ctx *client) goto out; } - client->headers_sent = true; + client->current_stream->headers_sent = true; } ret = send_data_frame(client, @@ -1151,13 +1174,13 @@ static int handle_http_frame_headers_end_stream(struct http_client_ctx *client) goto out; } - client->end_stream_sent = true; + client->current_stream->end_stream_sent = true; } dynamic_detail->holder = NULL; } - if (!client->headers_sent) { + if (!client->current_stream->headers_sent) { ret = send_headers_frame( client, HTTP_200_OK, frame->stream_identifier, client->current_detail, HTTP2_FLAG_END_STREAM); @@ -1165,7 +1188,7 @@ static int handle_http_frame_headers_end_stream(struct http_client_ctx *client) LOG_DBG("Cannot write to socket (%d)", ret); goto out; } - } else if (!client->end_stream_sent) { + } else if (!client->current_stream->end_stream_sent) { ret = send_data_frame(client, NULL, 0, frame->stream_identifier, HTTP2_FLAG_END_STREAM); if (ret < 0) {