From fe5dfe533fd9d2e1701e398c3cd6ebd557f5c70f Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 1 Jul 2012 18:37:12 +0900 Subject: [PATCH] Updated htparse --- examples/htparse/htparse.c | 76 +++++++++++++++++++++++--------- examples/htparse/htparse.h | 20 +++++---- examples/shrpx_downstream.cc | 1 + examples/shrpx_https_upstream.cc | 1 + 4 files changed, 67 insertions(+), 31 deletions(-) diff --git a/examples/htparse/htparse.c b/examples/htparse/htparse.c index fe313439..88b4f45d 100644 --- a/examples/htparse/htparse.c +++ b/examples/htparse/htparse.c @@ -45,7 +45,9 @@ enum eval_hdr_val { eval_hdr_val_connection, eval_hdr_val_proxy_connection, eval_hdr_val_content_length, - eval_hdr_val_transfer_encoding + eval_hdr_val_transfer_encoding, + eval_hdr_val_hostname, + eval_hdr_val_content_type }; enum parser_flags { @@ -109,6 +111,7 @@ struct htparser { htp_scheme scheme; htp_method method; + unsigned char multipart; unsigned char major; unsigned char minor; uint64_t content_len; @@ -258,6 +261,7 @@ __HTPARSE_GENDHOOK(uri); __HTPARSE_GENDHOOK(hdr_key); __HTPARSE_GENDHOOK(hdr_val); __HTPARSE_GENDHOOK(body); +__HTPARSE_GENDHOOK(hostname); static inline uint64_t @@ -395,6 +399,11 @@ htparser_get_minor(htparser * p) { return p->minor; } +unsigned char +htparser_get_multipart(htparser * p) { + return p->multipart; +} + void * htparser_get_userdata(htparser * p) { return p->userdata; @@ -1137,9 +1146,9 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len) case s_status: /* http response status code */ if (ch == ' ') { - if (p->status) { - p->state = s_status_text; - } + if (p->status) { + p->state = s_status_text; + } break; } @@ -1262,11 +1271,21 @@ hdrline_start: p->heval = eval_hdr_val_none; switch (p->buf_idx + 1) { + case 5: + if (!strcasecmp(p->buf, "host")) { + p->heval = eval_hdr_val_hostname; + } + break; case 11: if (!strcasecmp(p->buf, "connection")) { p->heval = eval_hdr_val_connection; } break; + case 13: + if (!strcasecmp(p->buf, "content-type")) { + p->heval = eval_hdr_val_content_type; + } + break; case 15: if (!strcasecmp(p->buf, "content-length")) { p->heval = eval_hdr_val_content_length; @@ -1336,8 +1355,11 @@ hdrline_start: switch (p->heval) { case eval_hdr_val_none: break; + case eval_hdr_val_hostname: + res = hook_hostname_run(p, hooks, p->buf, p->buf_idx); + break; case eval_hdr_val_content_length: - p->content_len = str_to_uint64(p->buf, p->buf_idx, &err); + p->content_len = str_to_uint64(p->buf, p->buf_idx, &err); if (err == 1) { p->error = htparse_error_too_big; @@ -1366,6 +1388,13 @@ hdrline_start: p->flags |= parser_flag_chunked; } + break; + case eval_hdr_val_content_type: + if (p->buf[0] == 'm' || p->buf[0] == 'M') { + if (_str8cmp((p->buf + 1), 'u', 'l', 't', 'i', 'p', 'a', 'r', 't')) { + p->multipart = 1; + } + } break; default: break; @@ -1421,6 +1450,13 @@ hdrline_start: switch (ch) { case CR: p->state = s_hdrline_almost_done; + res = hook_on_hdrs_complete_run(p, hooks); + + if (res) { + p->error = htparse_error_user; + return i + 1; + } + break; case LF: /* got LFLF? is this valid? */ @@ -1432,7 +1468,7 @@ hdrline_start: p->state = s_hdrline_hdr_key; break; - } + } /* switch */ break; case s_hdrline_almost_done: htparse_log_debug("[%p] s_hdrline_almost_done", p); @@ -1444,24 +1480,20 @@ hdrline_start: p->buf_idx = 0; htparse_log_debug("[%p] HERE", p); - res = hook_on_hdrs_complete_run(p, hooks); - - if (!res) { - if (p->flags & parser_flag_trailing) { - res = hook_on_msg_complete_run(p, hooks); - p->state = s_start; - } else if (p->flags & parser_flag_chunked) { - p->state = s_chunk_size_start; - } else if (p->content_len > 0) { - p->state = s_body_read; - } else if (p->content_len == 0) { - res = hook_on_msg_complete_run(p, hooks); - p->state = s_start; - } - } else { - p->state = s_hdrline_done; + if (p->flags & parser_flag_trailing) { + res = hook_on_msg_complete_run(p, hooks); + p->state = s_start; + } else if (p->flags & parser_flag_chunked) { + p->state = s_chunk_size_start; + } else if (p->content_len > 0) { + p->state = s_body_read; + } else if (p->content_len == 0) { + res = hook_on_msg_complete_run(p, hooks); + p->state = s_start; } + p->state = s_hdrline_done; + if (res) { p->error = htparse_error_user; return i + 1; diff --git a/examples/htparse/htparse.h b/examples/htparse/htparse.h index 827c8dc9..b4f7fa6c 100644 --- a/examples/htparse/htparse.h +++ b/examples/htparse/htparse.h @@ -67,19 +67,20 @@ typedef int (*htparse_data_hook)(htparser *, const char *, size_t); struct htparse_hooks { htparse_hook on_msg_begin; htparse_data_hook method; - htparse_data_hook scheme; /* called if scheme is found */ - htparse_data_hook host; /* called if a host was in the request scheme */ - htparse_data_hook port; /* called if a port was in the request scheme */ - htparse_data_hook path; /* only the path of the uri */ - htparse_data_hook args; /* only the arguments of the uri */ - htparse_data_hook uri; /* the entire uri including path/args */ + htparse_data_hook scheme; /* called if scheme is found */ + htparse_data_hook host; /* called if a host was in the request scheme */ + htparse_data_hook port; /* called if a port was in the request scheme */ + htparse_data_hook path; /* only the path of the uri */ + htparse_data_hook args; /* only the arguments of the uri */ + htparse_data_hook uri; /* the entire uri including path/args */ htparse_hook on_hdrs_begin; htparse_data_hook hdr_key; htparse_data_hook hdr_val; + htparse_data_hook hostname; htparse_hook on_hdrs_complete; - htparse_hook on_new_chunk; /* called after parsed chunk octet */ - htparse_hook on_chunk_complete; /* called after single parsed chunk */ - htparse_hook on_chunks_complete; /* called after all parsed chunks processed */ + htparse_hook on_new_chunk; /* called after parsed chunk octet */ + htparse_hook on_chunk_complete; /* called after single parsed chunk */ + htparse_hook on_chunks_complete; /* called after all parsed chunks processed */ htparse_data_hook body; htparse_hook on_msg_complete; }; @@ -94,6 +95,7 @@ void htparser_set_major(htparser *, unsigned char); void htparser_set_minor(htparser *, unsigned char); unsigned char htparser_get_major(htparser *); unsigned char htparser_get_minor(htparser *); +unsigned char htparser_get_multipart(htparser *); unsigned int htparser_get_status(htparser *); uint64_t htparser_get_content_length(htparser *); uint64_t htparser_get_bytes_read(htparser *); diff --git a/examples/shrpx_downstream.cc b/examples/shrpx_downstream.cc index 89496d66..ecd71583 100644 --- a/examples/shrpx_downstream.cc +++ b/examples/shrpx_downstream.cc @@ -500,6 +500,7 @@ htparse_hooks htp_hooks = { 0, /* htparse_hook on_hdrs_begin; */ htp_hdr_keycb, /* htparse_data_hook hdr_key; */ htp_hdr_valcb, /* htparse_data_hook hdr_val; */ + 0, /* htparse_data_hook hostname; */ htp_hdrs_completecb, /* htparse_hook on_hdrs_complete; */ 0, /*htparse_hook on_new_chunk;*/ 0, /*htparse_hook on_chunk_complete;*/ diff --git a/examples/shrpx_https_upstream.cc b/examples/shrpx_https_upstream.cc index f6c233bf..b037c642 100644 --- a/examples/shrpx_https_upstream.cc +++ b/examples/shrpx_https_upstream.cc @@ -222,6 +222,7 @@ htparse_hooks htp_hooks = { htp_hdrs_begincb, /* htparse_hook on_hdrs_begin; */ htp_hdr_keycb, /* htparse_data_hook hdr_key; */ htp_hdr_valcb, /* htparse_data_hook hdr_val; */ + 0, /* htparse_data_hook hostname; */ htp_hdrs_completecb, /* htparse_hook on_hdrs_complete; */ 0, /*htparse_hook on_new_chunk;*/ 0, /*htparse_hook on_chunk_complete;*/