Skip to content

Commit 9db2dc4

Browse files
rlubosnashif
authored andcommitted
net: lib: http_server: Move stream-specific flags to stream context
The information about replied headers or END_OF_STREAM flag are stream-specific and not general for a client. Hence, need to move them to the stream context. For the upgrade case, we need to allocate a new stream now when HTTP1 request /w upgrade field is received. The stream ID in such case is assumed to be 1 according to RFC. Signed-off-by: Robert Lubos <[email protected]>
1 parent 0e1c0a7 commit 9db2dc4

File tree

4 files changed

+69
-24
lines changed

4 files changed

+69
-24
lines changed

include/zephyr/net/http/server.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,12 @@ struct http2_stream_ctx {
276276
int stream_id; /**< Stream identifier. */
277277
enum http2_stream_state stream_state; /**< Stream state. */
278278
int window_size; /**< Stream-level window size. */
279+
280+
/** Flag indicating that headers were sent in the reply. */
281+
bool headers_sent : 1;
282+
283+
/** Flag indicating that END_STREAM flag was sent. */
284+
bool end_stream_sent : 1;
279285
};
280286

281287
/** @brief HTTP/2 frame representation. */
@@ -315,6 +321,9 @@ struct http_client_ctx {
315321
/** Currently processed resource detail. */
316322
struct http_resource_detail *current_detail;
317323

324+
/** Currently processed stream. */
325+
struct http2_stream_ctx *current_stream;
326+
318327
/** HTTP/2 header parser context. */
319328
struct http_hpack_header_buf header_field;
320329

@@ -360,13 +369,6 @@ struct http_client_ctx {
360369
IF_ENABLED(CONFIG_WEBSOCKET, (uint8_t ws_sec_key[HTTP_SERVER_WS_MAX_SEC_KEY_LEN]));
361370
/** @endcond */
362371

363-
/* TODO those two are stream-specific, move them. */
364-
/** Flag indicating that headers were sent in the reply. */
365-
bool headers_sent : 1;
366-
367-
/** Flag indicating that END_STREAM flag was sent. */
368-
bool end_stream_sent : 1;
369-
370372
/** Flag indicating that HTTP2 preface was sent. */
371373
bool preface_sent : 1;
372374

subsys/net/lib/http/http_server_core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@ static void init_client_ctx(struct http_client_ctx *client, int new_socket)
364364
client->streams[i].stream_state = HTTP2_STREAM_IDLE;
365365
client->streams[i].stream_id = 0;
366366
}
367+
368+
client->current_stream = NULL;
367369
}
368370

369371
static int handle_http_preface(struct http_client_ctx *client)

subsys/net/lib/http/http_server_http1.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,17 @@ static int dynamic_post_req(struct http_resource_detail_dynamic *dynamic_detail,
193193
return -ENOENT;
194194
}
195195

196-
if (!client->headers_sent) {
196+
if (client->current_stream == NULL) {
197+
return -ENOENT;
198+
}
199+
200+
if (!client->current_stream->headers_sent) {
197201
ret = SEND_RESPONSE(RESPONSE_TEMPLATE_CHUNKED,
198202
dynamic_detail->common.content_type);
199203
if (ret < 0) {
200204
return ret;
201205
}
202-
client->headers_sent = true;
206+
client->current_stream->headers_sent = true;
203207
}
204208

205209
copy_len = MIN(remaining, dynamic_detail->data_buffer_len);

subsys/net/lib/http/http_server_http2.c

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ static struct http2_stream_ctx *allocate_http_stream_context(
8282
client->streams[i].stream_state = HTTP2_STREAM_OPEN;
8383
client->streams[i].window_size =
8484
HTTP_SERVER_INITIAL_WINDOW_SIZE;
85+
client->streams[i].headers_sent = false;
86+
client->streams[i].end_stream_sent = false;
8587
return &client->streams[i];
8688
}
8789
}
@@ -339,6 +341,10 @@ static int handle_http2_static_resource(
339341
return -ENOTSUP;
340342
}
341343

344+
if (client->current_stream == NULL) {
345+
return -ENOENT;
346+
}
347+
342348
content_200 = static_detail->static_data;
343349
content_len = static_detail->static_data_len;
344350

@@ -349,7 +355,7 @@ static int handle_http2_static_resource(
349355
goto out;
350356
}
351357

352-
client->headers_sent = true;
358+
client->current_stream->headers_sent = true;
353359

354360
ret = send_data_frame(client, content_200, content_len,
355361
frame->stream_identifier,
@@ -359,7 +365,7 @@ static int handle_http2_static_resource(
359365
goto out;
360366
}
361367

362-
client->end_stream_sent = true;
368+
client->current_stream->end_stream_sent = true;
363369

364370
out:
365371
return ret;
@@ -372,14 +378,18 @@ static int dynamic_get_req_v2(struct http_resource_detail_dynamic *dynamic_detai
372378
int ret, remaining, offset = dynamic_detail->common.path_len;
373379
char *ptr;
374380

381+
if (client->current_stream == NULL) {
382+
return -ENOENT;
383+
}
384+
375385
ret = send_headers_frame(client, HTTP_200_OK, frame->stream_identifier,
376386
&dynamic_detail->common, 0);
377387
if (ret < 0) {
378388
LOG_DBG("Cannot write to socket (%d)", ret);
379389
return ret;
380390
}
381391

382-
client->headers_sent = true;
392+
client->current_stream->headers_sent = true;
383393

384394
remaining = strlen(&client->url_buffer[dynamic_detail->common.path_len]);
385395

@@ -428,7 +438,7 @@ static int dynamic_get_req_v2(struct http_resource_detail_dynamic *dynamic_detai
428438
LOG_DBG("Cannot send last frame (%d)", ret);
429439
}
430440

431-
client->end_stream_sent = true;
441+
client->current_stream->end_stream_sent = true;
432442

433443
dynamic_detail->holder = NULL;
434444

@@ -450,6 +460,10 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta
450460
return -ENOENT;
451461
}
452462

463+
if (client->current_stream == NULL) {
464+
return -ENOENT;
465+
}
466+
453467
data_len = MIN(frame->length, client->data_len);
454468
copy_len = MIN(data_len, dynamic_detail->data_buffer_len);
455469

@@ -481,7 +495,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta
481495
if (send_len > 0) {
482496
uint8_t flags = 0;
483497

484-
if (!client->headers_sent) {
498+
if (!client->current_stream->headers_sent) {
485499
ret = send_headers_frame(
486500
client, HTTP_200_OK, frame->stream_identifier,
487501
&dynamic_detail->common, 0);
@@ -490,7 +504,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta
490504
return ret;
491505
}
492506

493-
client->headers_sent = true;
507+
client->current_stream->headers_sent = true;
494508
}
495509

496510
/* 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
499513
if (frame->length == 0 &&
500514
is_header_flag_set(frame->flags, HTTP2_FLAG_END_STREAM)) {
501515
flags = HTTP2_FLAG_END_STREAM;
502-
client->end_stream_sent = true;
516+
client->current_stream->end_stream_sent = true;
503517
}
504518

505519
ret = send_data_frame(client,
@@ -518,7 +532,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta
518532

519533
if (frame->length == 0 &&
520534
is_header_flag_set(frame->flags, HTTP2_FLAG_END_STREAM)) {
521-
if (!client->headers_sent) {
535+
if (!client->current_stream->headers_sent) {
522536
/* The callback did not report any data to send, therefore send
523537
* headers frame now, including END_STREAM flag.
524538
*/
@@ -531,8 +545,8 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta
531545
return ret;
532546
}
533547

534-
client->headers_sent = true;
535-
client->end_stream_sent = true;
548+
client->current_stream->headers_sent = true;
549+
client->current_stream->end_stream_sent = true;
536550
}
537551

538552
dynamic_detail->holder = NULL;
@@ -659,6 +673,7 @@ static int enter_http_frame_data_state(struct http_client_ctx *client)
659673
stream->window_size -= frame->length;
660674
client->window_size -= frame->length;
661675
client->server_state = HTTP_SERVER_FRAME_DATA_STATE;
676+
client->current_stream = stream;
662677

663678
return 0;
664679
}
@@ -680,6 +695,8 @@ static int enter_http_frame_headers_state(struct http_client_ctx *client)
680695
}
681696
}
682697

698+
client->current_stream = stream;
699+
683700
if (!is_header_flag_set(frame->flags, HTTP2_FLAG_END_HEADERS)) {
684701
client->expect_continuation = true;
685702
} else {
@@ -756,6 +773,8 @@ int handle_http_frame_header(struct http_client_ctx *client)
756773
return -EBADMSG;
757774
}
758775

776+
client->current_stream = NULL;
777+
759778
switch (client->current_frame.type) {
760779
case HTTP2_DATA_FRAME:
761780
return enter_http_frame_data_state(client);
@@ -792,6 +811,7 @@ int handle_http1_to_http2_upgrade(struct http_client_ctx *client)
792811
"\r\n";
793812
struct http2_frame *frame = &client->current_frame;
794813
struct http_resource_detail *detail;
814+
struct http2_stream_ctx *stream;
795815
int path_len;
796816
int ret;
797817

@@ -808,6 +828,18 @@ int handle_http1_to_http2_upgrade(struct http_client_ctx *client)
808828
frame->flags = 0;
809829
}
810830

831+
/* Allocate stream. */
832+
stream = find_http_stream_context(client, frame->stream_identifier);
833+
if (stream == NULL) {
834+
stream = allocate_http_stream_context(client, frame->stream_identifier);
835+
if (!stream) {
836+
LOG_DBG("No available stream slots. Connection closed.");
837+
return -ENOMEM;
838+
}
839+
}
840+
841+
client->current_stream = stream;
842+
811843
if (!client->preface_sent) {
812844
ret = http_server_sendall(client, switching_protocols,
813845
sizeof(switching_protocols) - 1);
@@ -866,6 +898,7 @@ int handle_http1_to_http2_upgrade(struct http_client_ctx *client)
866898
* to HTTP2.
867899
*/
868900
if (client->parser_state == HTTP1_MESSAGE_COMPLETE_STATE) {
901+
release_http_stream_context(client, frame->stream_identifier);
869902
client->current_detail = NULL;
870903
client->server_state = HTTP_SERVER_PREFACE_STATE;
871904
client->cursor += client->data_len;
@@ -1121,6 +1154,10 @@ static int handle_http_frame_headers_end_stream(struct http_client_ctx *client)
11211154
goto out;
11221155
}
11231156

1157+
if (client->current_stream == NULL) {
1158+
return -ENOENT;
1159+
}
1160+
11241161
if (client->current_detail->type == HTTP_RESOURCE_TYPE_DYNAMIC) {
11251162
struct http_resource_detail_dynamic *dynamic_detail =
11261163
(struct http_resource_detail_dynamic *)client->current_detail;
@@ -1130,7 +1167,7 @@ static int handle_http_frame_headers_end_stream(struct http_client_ctx *client)
11301167
dynamic_detail->data_buffer, 0,
11311168
dynamic_detail->user_data);
11321169
if (send_len > 0) {
1133-
if (!client->headers_sent) {
1170+
if (!client->current_stream->headers_sent) {
11341171
ret = send_headers_frame(
11351172
client, HTTP_200_OK, frame->stream_identifier,
11361173
client->current_detail, 0);
@@ -1139,7 +1176,7 @@ static int handle_http_frame_headers_end_stream(struct http_client_ctx *client)
11391176
goto out;
11401177
}
11411178

1142-
client->headers_sent = true;
1179+
client->current_stream->headers_sent = true;
11431180
}
11441181

11451182
ret = send_data_frame(client,
@@ -1151,21 +1188,21 @@ static int handle_http_frame_headers_end_stream(struct http_client_ctx *client)
11511188
goto out;
11521189
}
11531190

1154-
client->end_stream_sent = true;
1191+
client->current_stream->end_stream_sent = true;
11551192
}
11561193

11571194
dynamic_detail->holder = NULL;
11581195
}
11591196

1160-
if (!client->headers_sent) {
1197+
if (!client->current_stream->headers_sent) {
11611198
ret = send_headers_frame(
11621199
client, HTTP_200_OK, frame->stream_identifier,
11631200
client->current_detail, HTTP2_FLAG_END_STREAM);
11641201
if (ret < 0) {
11651202
LOG_DBG("Cannot write to socket (%d)", ret);
11661203
goto out;
11671204
}
1168-
} else if (!client->end_stream_sent) {
1205+
} else if (!client->current_stream->end_stream_sent) {
11691206
ret = send_data_frame(client, NULL, 0, frame->stream_identifier,
11701207
HTTP2_FLAG_END_STREAM);
11711208
if (ret < 0) {

0 commit comments

Comments
 (0)