@@ -670,13 +670,27 @@ static int enter_http_frame_headers_state(struct http_client_ctx *client)
670
670
}
671
671
}
672
672
673
+ if (!is_header_flag_set (frame -> flags , HTTP2_FLAG_END_HEADERS )) {
674
+ client -> expect_continuation = true;
675
+ } else {
676
+ client -> expect_continuation = false;
677
+ }
678
+
673
679
client -> server_state = HTTP_SERVER_FRAME_HEADERS_STATE ;
674
680
675
681
return 0 ;
676
682
}
677
683
678
684
static int enter_http_frame_continuation_state (struct http_client_ctx * client )
679
685
{
686
+ struct http2_frame * frame = & client -> current_frame ;
687
+
688
+ if (!is_header_flag_set (frame -> flags , HTTP2_FLAG_END_HEADERS )) {
689
+ client -> expect_continuation = true;
690
+ } else {
691
+ client -> expect_continuation = false;
692
+ }
693
+
680
694
client -> server_state = HTTP_SERVER_FRAME_CONTINUATION_STATE ;
681
695
682
696
return 0 ;
@@ -712,25 +726,26 @@ static int enter_http_frame_goaway_state(struct http_client_ctx *client)
712
726
713
727
int handle_http_frame_header (struct http_client_ctx * client )
714
728
{
715
- int bytes_consumed ;
716
- int parse_result ;
729
+ int ret ;
717
730
718
731
LOG_DBG ("HTTP_SERVER_FRAME_HEADER" );
719
732
720
- parse_result = parse_http_frame_header (client );
721
- if (parse_result == 0 ) {
722
- return - EAGAIN ;
723
- } else if (parse_result < 0 ) {
724
- return parse_result ;
733
+ ret = parse_http_frame_header (client , client -> cursor , client -> data_len );
734
+ if (ret < 0 ) {
735
+ return ret ;
725
736
}
726
737
727
- bytes_consumed = HTTP2_FRAME_HEADER_SIZE ;
728
-
729
- client -> cursor += bytes_consumed ;
730
- client -> data_len -= bytes_consumed ;
738
+ client -> cursor += HTTP2_FRAME_HEADER_SIZE ;
739
+ client -> data_len -= HTTP2_FRAME_HEADER_SIZE ;
731
740
732
741
print_http_frames (client );
733
742
743
+ if (client -> expect_continuation &&
744
+ client -> current_frame .type != HTTP2_CONTINUATION_FRAME ) {
745
+ LOG_ERR ("Continuation frame expected" );
746
+ return - EBADMSG ;
747
+ }
748
+
734
749
switch (client -> current_frame .type ) {
735
750
case HTTP2_DATA_FRAME :
736
751
return enter_http_frame_data_state (client );
@@ -1032,6 +1047,61 @@ static int process_header(struct http_client_ctx *client,
1032
1047
return 0 ;
1033
1048
}
1034
1049
1050
+ static int handle_incomplete_http_header (struct http_client_ctx * client )
1051
+ {
1052
+ struct http2_frame * frame = & client -> current_frame ;
1053
+ size_t extra_len , prev_frame_len ;
1054
+ int ret ;
1055
+
1056
+ if (client -> data_len < frame -> length ) {
1057
+ /* Still did not receive entire frame content */
1058
+ return - EAGAIN ;
1059
+ }
1060
+
1061
+ if (!client -> expect_continuation ) {
1062
+ /* Failed to parse header field while the frame is complete
1063
+ * and no continuation frame is expected - report protocol
1064
+ * error.
1065
+ */
1066
+ LOG_ERR ("Incomplete header field" );
1067
+ return - EBADMSG ;
1068
+ }
1069
+
1070
+ /* A header field can be split between two frames, i. e. header and
1071
+ * continuation or two continuation frames. Because of this, the
1072
+ * continuation frame header can be present in the stream in between
1073
+ * header field data, so in such case we need to check for header here
1074
+ * and remove it from the stream to unblock further processing of the
1075
+ * header field.
1076
+ */
1077
+ prev_frame_len = frame -> length ;
1078
+ extra_len = client -> data_len - frame -> length ;
1079
+ ret = parse_http_frame_header (client , client -> cursor + prev_frame_len ,
1080
+ extra_len );
1081
+ if (ret < 0 ) {
1082
+ return - EAGAIN ;
1083
+ }
1084
+
1085
+ /* Continuation frame expected. */
1086
+ if (frame -> type != HTTP2_CONTINUATION_FRAME ) {
1087
+ LOG_ERR ("Continuation frame expected" );
1088
+ return - EBADMSG ;
1089
+ }
1090
+
1091
+ print_http_frames (client );
1092
+ /* Now remove continuation frame header from the stream, and proceed
1093
+ * with processing.
1094
+ */
1095
+ extra_len -= HTTP2_FRAME_HEADER_SIZE ;
1096
+ client -> data_len -= HTTP2_FRAME_HEADER_SIZE ;
1097
+ frame -> length += prev_frame_len ;
1098
+ memmove (client -> cursor + prev_frame_len ,
1099
+ client -> cursor + prev_frame_len + HTTP2_FRAME_HEADER_SIZE ,
1100
+ extra_len );
1101
+
1102
+ return enter_http_frame_continuation_state (client );
1103
+ }
1104
+
1035
1105
int handle_http_frame_headers (struct http_client_ctx * client )
1036
1106
{
1037
1107
struct http2_frame * frame = & client -> current_frame ;
@@ -1056,11 +1126,16 @@ int handle_http_frame_headers(struct http_client_ctx *client)
1056
1126
1057
1127
while (frame -> length > 0 ) {
1058
1128
struct http_hpack_header_buf * header = & client -> header_field ;
1129
+ size_t datalen = MIN (client -> data_len , frame -> length );
1059
1130
1060
- ret = http_hpack_decode_header (client -> cursor , client -> data_len ,
1061
- header );
1131
+ ret = http_hpack_decode_header (client -> cursor , datalen , header );
1062
1132
if (ret <= 0 ) {
1063
- ret = (ret == 0 ) ? - EBADMSG : ret ;
1133
+ if (ret == - EAGAIN ) {
1134
+ ret = handle_incomplete_http_header (client );
1135
+ } else if (ret == 0 ) {
1136
+ ret = - EBADMSG ;
1137
+ }
1138
+
1064
1139
return ret ;
1065
1140
}
1066
1141
@@ -1082,12 +1157,9 @@ int handle_http_frame_headers(struct http_client_ctx *client)
1082
1157
}
1083
1158
}
1084
1159
1085
- if (! is_header_flag_set ( frame -> flags , HTTP2_FLAG_END_HEADERS ) ) {
1160
+ if (client -> expect_continuation ) {
1086
1161
/* More headers to come in the continuation frame. */
1087
1162
client -> server_state = HTTP_SERVER_FRAME_HEADER_STATE ;
1088
-
1089
- /* TODO Implement continuation frame processing. */
1090
-
1091
1163
return 0 ;
1092
1164
}
1093
1165
@@ -1325,16 +1397,13 @@ const char *get_frame_type_name(enum http2_frame_type type)
1325
1397
}
1326
1398
}
1327
1399
1328
- int parse_http_frame_header (struct http_client_ctx * client )
1400
+ int parse_http_frame_header (struct http_client_ctx * client , const uint8_t * buffer ,
1401
+ size_t buflen )
1329
1402
{
1330
- uint8_t * buffer = client -> cursor ;
1331
1403
struct http2_frame * frame = & client -> current_frame ;
1332
1404
1333
- frame -> length = 0 ;
1334
- frame -> stream_identifier = 0 ;
1335
-
1336
- if (client -> data_len < HTTP2_FRAME_HEADER_SIZE ) {
1337
- return 0 ;
1405
+ if (buflen < HTTP2_FRAME_HEADER_SIZE ) {
1406
+ return - EAGAIN ;
1338
1407
}
1339
1408
1340
1409
frame -> length = sys_get_be24 (& buffer [HTTP2_FRAME_LENGTH_OFFSET ]);
@@ -1348,5 +1417,5 @@ int parse_http_frame_header(struct http_client_ctx *client)
1348
1417
LOG_DBG ("Frame len %d type 0x%02x flags 0x%02x id %d" ,
1349
1418
frame -> length , frame -> type , frame -> flags , frame -> stream_identifier );
1350
1419
1351
- return 1 ;
1420
+ return 0 ;
1352
1421
}
0 commit comments