From b8c3336f5de4c84890388fb92ba65c461cea3639 Mon Sep 17 00:00:00 2001 From: Cliff Frey Date: Wed, 26 May 2010 19:30:13 -0700 Subject: [PATCH] add support for HTTP_BOTH This is good for analyzing raw streams of data when one is not sure which direction it will be in. --- http_parser.c | 40 ++++++++++++++- http_parser.h | 2 +- test.c | 134 +++++++++++++++++++++++++------------------------- 3 files changed, 108 insertions(+), 68 deletions(-) diff --git a/http_parser.c b/http_parser.c index 8ecc94c..c2df0cc 100644 --- a/http_parser.c +++ b/http_parser.c @@ -132,6 +132,8 @@ static const uint32_t usual[] = { enum state { s_dead = 1 /* important that this is > 0 */ + , s_start_res_or_resp + , s_res_or_resp_H , s_start_res , s_res_H , s_res_HT @@ -326,6 +328,42 @@ size_t http_parser_execute (http_parser *parser, */ goto error; + case s_start_res_or_resp: + { + if (ch == CR || ch == LF) + break; + parser->flags = 0; + parser->content_length = -1; + + CALLBACK2(message_begin); + + if (ch == 'H') + state = s_res_or_resp_H; + else { + parser->type = HTTP_REQUEST; + if (ch < 'A' || 'Z' < ch) goto error; + parser->buffer[0] = ch; + index = 0; + state = s_req_method; + } + break; + } + + case s_res_or_resp_H: + if (ch == 'T') { + parser->type = HTTP_RESPONSE; + state = s_res_HT; + } else { + if (ch < 'A' || 'Z' < ch) goto error; + parser->type = HTTP_REQUEST; + parser->method = (enum http_method) 0; + parser->buffer[0] = 'H'; + parser->buffer[1] = ch; + index = 1; + state = s_req_method; + } + break; + case s_start_res: { parser->flags = 0; @@ -1547,7 +1585,7 @@ void http_parser_init (http_parser *parser, enum http_parser_type t) { parser->type = t; - parser->state = (t == HTTP_REQUEST ? s_start_req : s_start_res); + parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_res_or_resp)); parser->nread = 0; parser->upgrade = 0; diff --git a/http_parser.h b/http_parser.h index 977ecdf..4f5a420 100644 --- a/http_parser.h +++ b/http_parser.h @@ -89,7 +89,7 @@ enum http_method }; -enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE }; +enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; struct http_parser { diff --git a/test.c b/test.c index 03a98ff..4866a51 100644 --- a/test.c +++ b/test.c @@ -1207,82 +1207,84 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess int total_len = strlen(total); - int total_ops = (total_len - 1) * (total_len - 2) / 2; + int total_ops = 2 * (total_len - 1) * (total_len - 2) / 2; int ops = 0 ; size_t buf1_len, buf2_len, buf3_len; - int i,j; - for (j = 2; j < total_len; j ++ ) { - for (i = 1; i < j; i ++ ) { - - if (ops % 1000 == 0) { - printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops); - fflush(stdout); - } - ops += 1; - - parser_init(r1->type); - - buf1_len = i; - strncpy(buf1, total, buf1_len); - buf1[buf1_len] = 0; - - buf2_len = j - i; - strncpy(buf2, total+i, buf2_len); - buf2[buf2_len] = 0; - - buf3_len = total_len - j; - strncpy(buf3, total+j, buf3_len); - buf3[buf3_len] = 0; - - read = parse(buf1, buf1_len); - if (read != buf1_len) { - print_error(buf1, read); - goto error; - } - - read = parse(buf2, buf2_len); - if (read != buf2_len) { - print_error(buf2, read); - goto error; - } - - read = parse(buf3, buf3_len); - if (read != buf3_len) { - print_error(buf3, read); - goto error; + int i,j,type_both; + for (type_both = 0; type_both < 2; type_both ++ ) { + for (j = 2; j < total_len; j ++ ) { + for (i = 1; i < j; i ++ ) { + + if (ops % 1000 == 0) { + printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops); + fflush(stdout); + } + ops += 1; + + parser_init(type_both ? HTTP_BOTH : r1->type); + + buf1_len = i; + strncpy(buf1, total, buf1_len); + buf1[buf1_len] = 0; + + buf2_len = j - i; + strncpy(buf2, total+i, buf2_len); + buf2[buf2_len] = 0; + + buf3_len = total_len - j; + strncpy(buf3, total+j, buf3_len); + buf3[buf3_len] = 0; + + read = parse(buf1, buf1_len); + if (read != buf1_len) { + print_error(buf1, read); + goto error; + } + + read = parse(buf2, buf2_len); + if (read != buf2_len) { + print_error(buf2, read); + goto error; + } + + read = parse(buf3, buf3_len); + if (read != buf3_len) { + print_error(buf3, read); + goto error; + } + + parse(NULL, 0); + + if (3 != num_messages) { + fprintf(stderr, "\n\nParser didn't see 3 messages only %d\n", num_messages); + goto error; + } + + if (!message_eq(0, r1)) { + fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n"); + goto error; + } + + if (!message_eq(1, r2)) { + fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n"); + goto error; + } + + if (!message_eq(2, r3)) { + fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n"); + goto error; + } + + parser_free(); } - - parse(NULL, 0); - - if (3 != num_messages) { - fprintf(stderr, "\n\nParser didn't see 3 messages only %d\n", num_messages); - goto error; - } - - if (!message_eq(0, r1)) { - fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n"); - goto error; - } - - if (!message_eq(1, r2)) { - fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n"); - goto error; - } - - if (!message_eq(2, r3)) { - fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n"); - goto error; - } - - parser_free(); } } puts("\b\b\b\b100%"); return; -error: + error: fprintf(stderr, "i=%d j=%d\n", i, j); fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1); fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2);