@@ -2173,6 +2173,20 @@ pause_chunk_complete_cb (http_parser *p) |
2173 | 2173 | return chunk_complete_cb(p); |
2174 | 2174 | } |
2175 | 2175 |
|
| 2176 | +int |
| 2177 | +connect_headers_complete_cb (http_parser *p) |
| 2178 | +{ |
| 2179 | + headers_complete_cb(p); |
| 2180 | + return 1; |
| 2181 | +} |
| 2182 | + |
| 2183 | +int |
| 2184 | +connect_message_complete_cb (http_parser *p) |
| 2185 | +{ |
| 2186 | + messages[num_messages].should_keep_alive = http_should_keep_alive(parser); |
| 2187 | + return message_complete_cb(p); |
| 2188 | +} |
| 2189 | + |
2176 | 2190 | static http_parser_settings settings_pause = |
2177 | 2191 | {.on_message_begin = pause_message_begin_cb |
2178 | 2192 | ,.on_header_field = pause_header_field_cb |
@@ -2212,6 +2226,19 @@ static http_parser_settings settings_count_body = |
2212 | 2226 | ,.on_chunk_complete = chunk_complete_cb |
2213 | 2227 | }; |
2214 | 2228 |
|
| 2229 | +static http_parser_settings settings_connect = |
| 2230 | + {.on_message_begin = message_begin_cb |
| 2231 | + ,.on_header_field = header_field_cb |
| 2232 | + ,.on_header_value = header_value_cb |
| 2233 | + ,.on_url = request_url_cb |
| 2234 | + ,.on_status = response_status_cb |
| 2235 | + ,.on_body = dontcall_body_cb |
| 2236 | + ,.on_headers_complete = connect_headers_complete_cb |
| 2237 | + ,.on_message_complete = connect_message_complete_cb |
| 2238 | + ,.on_chunk_header = chunk_header_cb |
| 2239 | + ,.on_chunk_complete = chunk_complete_cb |
| 2240 | + }; |
| 2241 | + |
2215 | 2242 | static http_parser_settings settings_null = |
2216 | 2243 | {.on_message_begin = 0 |
2217 | 2244 | ,.on_header_field = 0 |
@@ -2275,6 +2302,14 @@ size_t parse_pause (const char *buf, size_t len) |
2275 | 2302 | return nparsed; |
2276 | 2303 | } |
2277 | 2304 |
|
| 2305 | +size_t parse_connect (const char *buf, size_t len) |
| 2306 | +{ |
| 2307 | + size_t nparsed; |
| 2308 | + currently_parsing_eof = (len == 0); |
| 2309 | + nparsed = http_parser_execute(parser, &settings_connect, buf, len); |
| 2310 | + return nparsed; |
| 2311 | +} |
| 2312 | + |
2278 | 2313 | static inline int |
2279 | 2314 | check_str_eq (const struct message *m, |
2280 | 2315 | const char *prop, |
@@ -2331,7 +2366,7 @@ do { \ |
2331 | 2366 | } while(0) |
2332 | 2367 |
|
2333 | 2368 | int |
2334 | | -message_eq (int index, const struct message *expected) |
| 2369 | +message_eq (int index, int connect, const struct message *expected) |
2335 | 2370 | { |
2336 | 2371 | int i; |
2337 | 2372 | struct message *m = &messages[index]; |
@@ -2346,8 +2381,10 @@ message_eq (int index, const struct message *expected) |
2346 | 2381 | MESSAGE_CHECK_STR_EQ(expected, m, response_status); |
2347 | 2382 | } |
2348 | 2383 |
|
2349 | | - MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive); |
2350 | | - MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof); |
| 2384 | + if (!connect) { |
| 2385 | + MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive); |
| 2386 | + MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof); |
| 2387 | + } |
2351 | 2388 |
|
2352 | 2389 | assert(m->message_begin_cb_called); |
2353 | 2390 | assert(m->headers_complete_cb_called); |
@@ -2385,16 +2422,22 @@ message_eq (int index, const struct message *expected) |
2385 | 2422 | MESSAGE_CHECK_NUM_EQ(expected, m, port); |
2386 | 2423 | } |
2387 | 2424 |
|
2388 | | - if (expected->body_size) { |
| 2425 | + if (connect) { |
| 2426 | + check_num_eq(m, "body_size", 0, m->body_size); |
| 2427 | + } else if (expected->body_size) { |
2389 | 2428 | MESSAGE_CHECK_NUM_EQ(expected, m, body_size); |
2390 | 2429 | } else { |
2391 | 2430 | MESSAGE_CHECK_STR_EQ(expected, m, body); |
2392 | 2431 | } |
2393 | 2432 |
|
2394 | | - assert(m->num_chunks == m->num_chunks_complete); |
2395 | | - MESSAGE_CHECK_NUM_EQ(expected, m, num_chunks_complete); |
2396 | | - for (i = 0; i < m->num_chunks && i < MAX_CHUNKS; i++) { |
2397 | | - MESSAGE_CHECK_NUM_EQ(expected, m, chunk_lengths[i]); |
| 2433 | + if (connect) { |
| 2434 | + check_num_eq(m, "num_chunks_complete", 0, m->num_chunks_complete); |
| 2435 | + } else { |
| 2436 | + assert(m->num_chunks == m->num_chunks_complete); |
| 2437 | + MESSAGE_CHECK_NUM_EQ(expected, m, num_chunks_complete); |
| 2438 | + for (i = 0; i < m->num_chunks && i < MAX_CHUNKS; i++) { |
| 2439 | + MESSAGE_CHECK_NUM_EQ(expected, m, chunk_lengths[i]); |
| 2440 | + } |
2398 | 2441 | } |
2399 | 2442 |
|
2400 | 2443 | MESSAGE_CHECK_NUM_EQ(expected, m, num_headers); |
@@ -3201,7 +3244,7 @@ test_message (const struct message *message) |
3201 | 3244 | abort(); |
3202 | 3245 | } |
3203 | 3246 |
|
3204 | | - if(!message_eq(0, message)) abort(); |
| 3247 | + if(!message_eq(0, 0, message)) abort(); |
3205 | 3248 |
|
3206 | 3249 | parser_free(); |
3207 | 3250 | } |
@@ -3238,7 +3281,7 @@ test_message_count_body (const struct message *message) |
3238 | 3281 | abort(); |
3239 | 3282 | } |
3240 | 3283 |
|
3241 | | - if(!message_eq(0, message)) abort(); |
| 3284 | + if(!message_eq(0, 0, message)) abort(); |
3242 | 3285 |
|
3243 | 3286 | parser_free(); |
3244 | 3287 | } |
@@ -3589,9 +3632,9 @@ test_multiple3 (const struct message *r1, const struct message *r2, const struct |
3589 | 3632 | abort(); |
3590 | 3633 | } |
3591 | 3634 |
|
3592 | | - if (!message_eq(0, r1)) abort(); |
3593 | | - if (message_count > 1 && !message_eq(1, r2)) abort(); |
3594 | | - if (message_count > 2 && !message_eq(2, r3)) abort(); |
| 3635 | + if (!message_eq(0, 0, r1)) abort(); |
| 3636 | + if (message_count > 1 && !message_eq(1, 0, r2)) abort(); |
| 3637 | + if (message_count > 2 && !message_eq(2, 0, r3)) abort(); |
3595 | 3638 |
|
3596 | 3639 | parser_free(); |
3597 | 3640 | } |
@@ -3687,17 +3730,17 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess |
3687 | 3730 | goto error; |
3688 | 3731 | } |
3689 | 3732 |
|
3690 | | - if (!message_eq(0, r1)) { |
| 3733 | + if (!message_eq(0, 0, r1)) { |
3691 | 3734 | fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n"); |
3692 | 3735 | goto error; |
3693 | 3736 | } |
3694 | 3737 |
|
3695 | | - if (message_count > 1 && !message_eq(1, r2)) { |
| 3738 | + if (message_count > 1 && !message_eq(1, 0, r2)) { |
3696 | 3739 | fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n"); |
3697 | 3740 | goto error; |
3698 | 3741 | } |
3699 | 3742 |
|
3700 | | - if (message_count > 2 && !message_eq(2, r3)) { |
| 3743 | + if (message_count > 2 && !message_eq(2, 0, r3)) { |
3701 | 3744 | fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n"); |
3702 | 3745 | goto error; |
3703 | 3746 | } |
@@ -3796,7 +3839,29 @@ test_message_pause (const struct message *msg) |
3796 | 3839 | abort(); |
3797 | 3840 | } |
3798 | 3841 |
|
3799 | | - if(!message_eq(0, msg)) abort(); |
| 3842 | + if(!message_eq(0, 0, msg)) abort(); |
| 3843 | + |
| 3844 | + parser_free(); |
| 3845 | +} |
| 3846 | + |
| 3847 | +/* Verify that body and next message won't be parsed in responses to CONNECT */ |
| 3848 | +void |
| 3849 | +test_message_connect (const struct message *msg) |
| 3850 | +{ |
| 3851 | + char *buf = (char*) msg->raw; |
| 3852 | + size_t buflen = strlen(msg->raw); |
| 3853 | + size_t nread; |
| 3854 | + |
| 3855 | + parser_init(msg->type); |
| 3856 | + |
| 3857 | + nread = parse_connect(buf, buflen); |
| 3858 | + |
| 3859 | + if (num_messages != 1) { |
| 3860 | + printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name); |
| 3861 | + abort(); |
| 3862 | + } |
| 3863 | + |
| 3864 | + if(!message_eq(0, 1, msg)) abort(); |
3800 | 3865 |
|
3801 | 3866 | parser_free(); |
3802 | 3867 | } |
@@ -3867,6 +3932,10 @@ main (void) |
3867 | 3932 | test_message_pause(&responses[i]); |
3868 | 3933 | } |
3869 | 3934 |
|
| 3935 | + for (i = 0; i < response_count; i++) { |
| 3936 | + test_message_connect(&responses[i]); |
| 3937 | + } |
| 3938 | + |
3870 | 3939 | for (i = 0; i < response_count; i++) { |
3871 | 3940 | if (!responses[i].should_keep_alive) continue; |
3872 | 3941 | for (j = 0; j < response_count; j++) { |
|