39
39
40
40
#define MAX_HEADERS 13
41
41
#define MAX_ELEMENT_SIZE 2048
42
+ #define MAX_CHUNKS 16
42
43
43
44
#define MIN (a ,b ) ((a) < (b) ? (a) : (b))
44
45
@@ -65,6 +66,10 @@ struct message {
65
66
char headers [MAX_HEADERS ][2 ][MAX_ELEMENT_SIZE ];
66
67
int should_keep_alive ;
67
68
69
+ int num_chunks ;
70
+ int num_chunks_complete ;
71
+ int chunk_lengths [MAX_CHUNKS ];
72
+
68
73
const char * upgrade ; // upgraded body
69
74
70
75
unsigned short http_major ;
@@ -301,6 +306,8 @@ const struct message requests[] =
301
306
{ { "Transfer-Encoding" , "chunked" }
302
307
}
303
308
,.body = "all your base are belong to us"
309
+ ,.num_chunks_complete = 2
310
+ ,.chunk_lengths = { 0x1e }
304
311
}
305
312
306
313
#define TWO_CHUNKS_MULT_ZERO_END 9
@@ -327,6 +334,8 @@ const struct message requests[] =
327
334
{ { "Transfer-Encoding" , "chunked" }
328
335
}
329
336
,.body = "hello world"
337
+ ,.num_chunks_complete = 3
338
+ ,.chunk_lengths = { 5 , 6 }
330
339
}
331
340
332
341
#define CHUNKED_W_TRAILING_HEADERS 10
@@ -357,6 +366,8 @@ const struct message requests[] =
357
366
, { "Content-Type" , "text/plain" }
358
367
}
359
368
,.body = "hello world"
369
+ ,.num_chunks_complete = 3
370
+ ,.chunk_lengths = { 5 , 6 }
360
371
}
361
372
362
373
#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
@@ -383,6 +394,8 @@ const struct message requests[] =
383
394
{ { "Transfer-Encoding" , "chunked" }
384
395
}
385
396
,.body = "hello world"
397
+ ,.num_chunks_complete = 3
398
+ ,.chunk_lengths = { 5 , 6 }
386
399
}
387
400
388
401
#define WITH_QUOTES 12
@@ -1195,7 +1208,8 @@ const struct message responses[] =
1195
1208
,.body =
1196
1209
"This is the data in the first chunk\r\n"
1197
1210
"and this is the second one\r\n"
1198
-
1211
+ ,.num_chunks_complete = 3
1212
+ ,.chunk_lengths = { 0x25 , 0x1c }
1199
1213
}
1200
1214
1201
1215
#define NO_CARRIAGE_RET 5
@@ -1349,6 +1363,8 @@ const struct message responses[] =
1349
1363
, { "Connection" , "close" }
1350
1364
}
1351
1365
,.body = ""
1366
+ ,.num_chunks_complete = 1
1367
+ ,.chunk_lengths = {}
1352
1368
}
1353
1369
1354
1370
#define NON_ASCII_IN_STATUS_LINE 10
@@ -1531,6 +1547,7 @@ const struct message responses[] =
1531
1547
}
1532
1548
,.body_size = 0
1533
1549
,.body = ""
1550
+ ,.num_chunks_complete = 1
1534
1551
}
1535
1552
1536
1553
#if !HTTP_PARSER_STRICT
@@ -1604,6 +1621,8 @@ const struct message responses[] =
1604
1621
, { "Transfer-Encoding" , "chunked" }
1605
1622
}
1606
1623
,.body = "\n"
1624
+ ,.num_chunks_complete = 2
1625
+ ,.chunk_lengths = { 1 }
1607
1626
}
1608
1627
1609
1628
#define EMPTY_REASON_PHRASE_AFTER_SPACE 20
@@ -1839,6 +1858,35 @@ response_status_cb (http_parser *p, const char *buf, size_t len)
1839
1858
return 0 ;
1840
1859
}
1841
1860
1861
+ int
1862
+ chunk_header_cb (http_parser * p )
1863
+ {
1864
+ assert (p == parser );
1865
+ int chunk_idx = messages [num_messages ].num_chunks ;
1866
+ messages [num_messages ].num_chunks ++ ;
1867
+ if (chunk_idx < MAX_CHUNKS ) {
1868
+ messages [num_messages ].chunk_lengths [chunk_idx ] = p -> content_length ;
1869
+ }
1870
+
1871
+ return 0 ;
1872
+ }
1873
+
1874
+ int
1875
+ chunk_complete_cb (http_parser * p )
1876
+ {
1877
+ assert (p == parser );
1878
+
1879
+ /* Here we want to verify that each chunk_header_cb is matched by a
1880
+ * chunk_complete_cb, so not only should the total number of calls to
1881
+ * both callbacks be the same, but they also should be interleaved
1882
+ * properly */
1883
+ assert (messages [num_messages ].num_chunks ==
1884
+ messages [num_messages ].num_chunks_complete + 1 );
1885
+
1886
+ messages [num_messages ].num_chunks_complete ++ ;
1887
+ return 0 ;
1888
+ }
1889
+
1842
1890
/* These dontcall_* callbacks exist so that we can verify that when we're
1843
1891
* paused, no additional callbacks are invoked */
1844
1892
int
@@ -1907,6 +1955,23 @@ dontcall_response_status_cb (http_parser *p, const char *buf, size_t len)
1907
1955
abort ();
1908
1956
}
1909
1957
1958
+ int
1959
+ dontcall_chunk_header_cb (http_parser * p )
1960
+ {
1961
+ if (p ) { } // gcc
1962
+ fprintf (stderr , "\n\n*** on_chunk_header() called on paused parser ***\n\n" );
1963
+ exit (1 );
1964
+ }
1965
+
1966
+ int
1967
+ dontcall_chunk_complete_cb (http_parser * p )
1968
+ {
1969
+ if (p ) { } // gcc
1970
+ fprintf (stderr , "\n\n*** on_chunk_complete() "
1971
+ "called on paused parser ***\n\n" );
1972
+ exit (1 );
1973
+ }
1974
+
1910
1975
static http_parser_settings settings_dontcall =
1911
1976
{.on_message_begin = dontcall_message_begin_cb
1912
1977
,.on_header_field = dontcall_header_field_cb
@@ -1916,6 +1981,8 @@ static http_parser_settings settings_dontcall =
1916
1981
,.on_body = dontcall_body_cb
1917
1982
,.on_headers_complete = dontcall_headers_complete_cb
1918
1983
,.on_message_complete = dontcall_message_complete_cb
1984
+ ,.on_chunk_header = dontcall_chunk_header_cb
1985
+ ,.on_chunk_complete = dontcall_chunk_complete_cb
1919
1986
};
1920
1987
1921
1988
/* These pause_* callbacks always pause the parser and just invoke the regular
@@ -1986,6 +2053,22 @@ pause_response_status_cb (http_parser *p, const char *buf, size_t len)
1986
2053
return response_status_cb (p , buf , len );
1987
2054
}
1988
2055
2056
+ int
2057
+ pause_chunk_header_cb (http_parser * p )
2058
+ {
2059
+ http_parser_pause (p , 1 );
2060
+ * current_pause_parser = settings_dontcall ;
2061
+ return chunk_header_cb (p );
2062
+ }
2063
+
2064
+ int
2065
+ pause_chunk_complete_cb (http_parser * p )
2066
+ {
2067
+ http_parser_pause (p , 1 );
2068
+ * current_pause_parser = settings_dontcall ;
2069
+ return chunk_complete_cb (p );
2070
+ }
2071
+
1989
2072
static http_parser_settings settings_pause =
1990
2073
{.on_message_begin = pause_message_begin_cb
1991
2074
,.on_header_field = pause_header_field_cb
@@ -1995,6 +2078,8 @@ static http_parser_settings settings_pause =
1995
2078
,.on_body = pause_body_cb
1996
2079
,.on_headers_complete = pause_headers_complete_cb
1997
2080
,.on_message_complete = pause_message_complete_cb
2081
+ ,.on_chunk_header = pause_chunk_header_cb
2082
+ ,.on_chunk_complete = pause_chunk_complete_cb
1998
2083
};
1999
2084
2000
2085
static http_parser_settings settings =
@@ -2006,6 +2091,8 @@ static http_parser_settings settings =
2006
2091
,.on_body = body_cb
2007
2092
,.on_headers_complete = headers_complete_cb
2008
2093
,.on_message_complete = message_complete_cb
2094
+ ,.on_chunk_header = chunk_header_cb
2095
+ ,.on_chunk_complete = chunk_complete_cb
2009
2096
};
2010
2097
2011
2098
static http_parser_settings settings_count_body =
@@ -2017,6 +2104,8 @@ static http_parser_settings settings_count_body =
2017
2104
,.on_body = count_body_cb
2018
2105
,.on_headers_complete = headers_complete_cb
2019
2106
,.on_message_complete = message_complete_cb
2107
+ ,.on_chunk_header = chunk_header_cb
2108
+ ,.on_chunk_complete = chunk_complete_cb
2020
2109
};
2021
2110
2022
2111
static http_parser_settings settings_null =
@@ -2028,6 +2117,8 @@ static http_parser_settings settings_null =
2028
2117
,.on_body = 0
2029
2118
,.on_headers_complete = 0
2030
2119
,.on_message_complete = 0
2120
+ ,.on_chunk_header = 0
2121
+ ,.on_chunk_complete = 0
2031
2122
};
2032
2123
2033
2124
void
@@ -2196,6 +2287,12 @@ message_eq (int index, const struct message *expected)
2196
2287
MESSAGE_CHECK_STR_EQ (expected , m , body );
2197
2288
}
2198
2289
2290
+ assert (m -> num_chunks == m -> num_chunks_complete );
2291
+ MESSAGE_CHECK_NUM_EQ (expected , m , num_chunks_complete );
2292
+ for (i = 0 ; i < m -> num_chunks && i < MAX_CHUNKS ; i ++ ) {
2293
+ MESSAGE_CHECK_NUM_EQ (expected , m , chunk_lengths [i ]);
2294
+ }
2295
+
2199
2296
MESSAGE_CHECK_NUM_EQ (expected , m , num_headers );
2200
2297
2201
2298
int r ;
@@ -3488,7 +3585,11 @@ main (void)
3488
3585
, { "Content-Type" , "text/plain" }
3489
3586
}
3490
3587
,.body_size = 31337 * 1024
3588
+ ,.num_chunks_complete = 31338
3491
3589
};
3590
+ for (i = 0 ; i < MAX_CHUNKS ; i ++ ) {
3591
+ large_chunked .chunk_lengths [i ] = 1024 ;
3592
+ }
3492
3593
test_message_count_body (& large_chunked );
3493
3594
free (msg );
3494
3595
}
0 commit comments