diff --git a/common/include/tfe_http.h b/common/include/tfe_http.h index cffed8f..99480c6 100644 --- a/common/include/tfe_http.h +++ b/common/include/tfe_http.h @@ -166,6 +166,9 @@ enum tfe_http_std_field TFE_HTTP_LAST_MODIFIED }; +extern const char * __str_std_header_field_map[]; +extern const unsigned int __str_std_header_field_map_size; + enum http_ev_bit_number { REQ_HDR_BITNUM = 0, diff --git a/common/src/tfe_http.cpp b/common/src/tfe_http.cpp index 5ddf56f..e655299 100644 --- a/common/src/tfe_http.cpp +++ b/common/src/tfe_http.cpp @@ -4,7 +4,7 @@ #include #include -static const char * __str_std_header_field_map[] = +const char * __str_std_header_field_map[] = { [TFE_HTTP_UNKNOWN_FIELD] = NULL, [TFE_HTTP_HOST] = "Host", @@ -39,6 +39,7 @@ static const char * __str_std_header_field_map[] = [TFE_HTTP_IF_UNMODIFIED_SINCE] = "If-Unmodified-Since", [TFE_HTTP_LAST_MODIFIED] = "Last-Modified" }; +const unsigned int __str_std_header_field_map_size = sizeof(__str_std_header_field_map) / sizeof(__str_std_header_field_map[0]); static const char * __str_std_method_map[1024] = {}; void __str_std_method_map_init() __attribute__((constructor, used)); diff --git a/plugin/protocol/http/src/http_half.cpp b/plugin/protocol/http/src/http_half.cpp index fa133ea..87d78e7 100644 --- a/plugin/protocol/http/src/http_half.cpp +++ b/plugin/protocol/http/src/http_half.cpp @@ -15,46 +15,10 @@ #define __PARSER_TO_HF_PRIVATE(_parser) ((struct http_half_private *)(_parser->data)) -static const char * __str_std_header_field_map[] = - { - [TFE_HTTP_UNKNOWN_FIELD] = NULL, - [TFE_HTTP_HOST] = "Host", - [TFE_HTTP_REFERER] = "Referer", - [TFE_HTTP_USER_AGENT] = "User-Agent", - [TFE_HTTP_COOKIE] = "Cookie", - [TFE_HTTP_SET_COOKIE] = "Set-Cookie", - [TFE_HTTP_PROXY_AUTHORIZATION] = "Proxy-Authorization", - [TFE_HTTP_AUTHORIZATION] = "Authorization", - [TFE_HTTP_LOCATION] = "Location", - [TFE_HTTP_SERVER] = "Server", - [TFE_HTTP_ETAG] = "Etag", - [TFE_HTTP_DATE] = "Date", - [TFE_HTTP_TRAILER] = "Trailer", - [TFE_HTTP_TRANSFER_ENCODING] = "Transfer-Encoding", - [TFE_HTTP_VIA] = "Via", - [TFE_HTTP_PRAGMA] = "Pragma", - [TFE_HTTP_CONNECTION] = "Connection", - [TFE_HTTP_CONT_ENCODING] = "Content-Encoding", - [TFE_HTTP_CONT_LANGUAGE] = "Content-Language", - [TFE_HTTP_CONT_LOCATION] = "Content-Location", - [TFE_HTTP_CONT_RANGE] = "Content-Range", - [TFE_HTTP_CONT_LENGTH] = "Content-Length", - [TFE_HTTP_CONT_TYPE] = "Content-Type", - [TFE_HTTP_CONT_DISPOSITION] = "Content-Disposition", - [TFE_HTTP_EXPIRES] = "Expires", - [TFE_HTTP_ACCEPT_ENCODING] = "Accept-Encoding", - [TFE_HTTP_CACHE_CONTROL] = "Cache-Control", - [TFE_HTTP_IF_MATCH] = "If-Match", - [TFE_HTTP_IF_NONE_MATCH] = "If-None-Match", - [TFE_HTTP_IF_MODIFIED_SINCE] = "If-Modified-Since", - [TFE_HTTP_IF_UNMODIFIED_SINCE] = "If-Unmodified-Since", - [TFE_HTTP_LAST_MODIFIED] = "Last-Modified" - }; - static enum tfe_http_std_field __str_header_field_to_std_field_id(const char * str_field, size_t len) { /* TODO: store the header text in hash table or rbtree, or use AC multistring search algo. */ - for (unsigned int i = 0; i < TFE_DIM(__str_std_header_field_map); i++) + for (unsigned int i = 0; i < __str_std_header_field_map_size; i++) { const char * __std_header_field = __str_std_header_field_map[i]; if (__std_header_field == NULL) diff --git a/plugin/protocol/http2/include/internal/http2_common.h b/plugin/protocol/http2/include/internal/http2_common.h index fa6d787..5aba7df 100644 --- a/plugin/protocol/http2/include/internal/http2_common.h +++ b/plugin/protocol/http2/include/internal/http2_common.h @@ -49,6 +49,11 @@ val_to_str(unsigned int val, const struct value_string *vs); int str_to_val(const char *val, const struct value_string *vs); +const char* +http2_header_val_to_str(unsigned int val, const char * map[], unsigned int map_size); +int +http2_header_str_to_val(const char *str, const char * map[], unsigned int map_size); + #define BV(x) (1 << x) #define HTTP2_CONTENT_ENCODING_NONE 0 #define HTTP2_CONTENT_ENCODING_GZIP BV(1) diff --git a/plugin/protocol/http2/src/http2_common.cpp b/plugin/protocol/http2/src/http2_common.cpp index 2847ce5..b59f52b 100644 --- a/plugin/protocol/http2/src/http2_common.cpp +++ b/plugin/protocol/http2/src/http2_common.cpp @@ -35,6 +35,50 @@ Http2Plugin *http2_plugin() return &g_http2_plugin; } +int +http2_header_str_to_val(const char *str, const char * map[], unsigned int map_size) +{ + for (unsigned int i = 0; i < map_size; i++) + { + if (!strncasecmp(str, map[i], strlen(map[i]))) + { + return i; + } + } + + // in http [TFE_HTTP_UNKNOWN_FIELD] = NULL; [TFE_HTTP_HOST] = "Host", + // in http2 [TFE_HTTP_UNKNOWN_FIELD] = "unknown"; [TFE_HTTP_HOST] = ":authority" + if (!strncasecmp(str, ":authority", strlen(":authority"))) + { + return TFE_HTTP_HOST; + } else { + return TFE_HTTP_UNKNOWN_FIELD; + } +} + +const char* +http2_header_val_to_str(unsigned int val, const char * map[], unsigned int map_size) +{ + const static char * host = ":authority"; + const static char * unknown = "unknown"; + + if (val < map_size && val != TFE_HTTP_HOST && val != TFE_HTTP_UNKNOWN_FIELD) + { + return map[val]; + } + + // in http [TFE_HTTP_UNKNOWN_FIELD] = NULL; [TFE_HTTP_HOST] = "Host", + // in http2 [TFE_HTTP_UNKNOWN_FIELD] = "unknown"; [TFE_HTTP_HOST] = ":authority" + if (val == TFE_HTTP_HOST) + { + return host; + } + else + { + return unknown; + } +} + const char * try_val_to_str_idx(const unsigned int val, const struct value_string *vs, int *idx) { diff --git a/plugin/protocol/http2/src/http2_stream.cpp b/plugin/protocol/http2/src/http2_stream.cpp index 6c68c0c..d09d135 100644 --- a/plugin/protocol/http2/src/http2_stream.cpp +++ b/plugin/protocol/http2/src/http2_stream.cpp @@ -51,42 +51,6 @@ static const struct value_string method_vals[] = {NGHTTP2_METHOD_UNKNOWN, "unknown"}, }; -static const struct value_string header_vals[] = -{ - {TFE_HTTP_UNKNOWN_FIELD, "unkown"}, - {TFE_HTTP_HOST, ":authority"}, - {TFE_HTTP_REFERER, "referer"}, - {TFE_HTTP_USER_AGENT, "user-agent"}, - {TFE_HTTP_COOKIE, "cookie"}, - {TFE_HTTP_SET_COOKIE, "set-cookie"}, - {TFE_HTTP_PROXY_AUTHORIZATION, "proxy-authorization"}, - {TFE_HTTP_AUTHORIZATION, "authorization"}, - {TFE_HTTP_LOCATION, "location"}, - {TFE_HTTP_SERVER, "server"}, - {TFE_HTTP_ETAG, "etag"}, - {TFE_HTTP_DATE, "date"}, - {TFE_HTTP_TRAILER, "Trailer"}, - {TFE_HTTP_TRANSFER_ENCODING, "transfer-encoding"}, - {TFE_HTTP_VIA, "via"}, - {TFE_HTTP_PRAGMA, "pragma"}, - {TFE_HTTP_CONNECTION, "connection"}, - {TFE_HTTP_CONT_ENCODING, "content-encoding"}, - {TFE_HTTP_CONT_LANGUAGE, "content-language"}, - {TFE_HTTP_CONT_LOCATION, "content-location"}, - {TFE_HTTP_CONT_RANGE, "content-range"}, - {TFE_HTTP_CONT_LENGTH, "content-length"}, - {TFE_HTTP_CONT_TYPE, "content-type"}, - {TFE_HTTP_CONT_DISPOSITION, "content-disposition"}, - {TFE_HTTP_EXPIRES, "expires"}, - {TFE_HTTP_ACCEPT_ENCODING, "accept-encoding"}, - {TFE_HTTP_CACHE_CONTROL, "cache-control"}, - {TFE_HTTP_IF_MATCH, "if-match"}, - {TFE_HTTP_IF_NONE_MATCH, "if-none-match"}, - {TFE_HTTP_IF_MODIFIED_SINCE, "if-modified-since"}, - {TFE_HTTP_IF_UNMODIFIED_SINCE, "if-unmodified-since"}, - {TFE_HTTP_LAST_MODIFIED, "last-modified"}, -}; - typedef enum { NGHTTP2_USER_SEND = 0x0b, NGHTTP2_USER_COLSE = 0x0c, @@ -125,7 +89,7 @@ tfe_h2_header_add_field(struct tfe_h2_header *h2_header, const struct http_field peer_h2_field->nv.namelen = strlen(peer_h2_field->field->field_name); }else { - const char *std_name = val_to_str(field->field_id, header_vals); + const char *std_name = http2_header_val_to_str(field->field_id, __str_std_header_field_map, __str_std_header_field_map_size); peer_h2_field->nv.name = (uint8_t *)tfe_strdup((const char *)std_name); peer_h2_field->nv.namelen = strlen(std_name); } @@ -1498,19 +1462,19 @@ fill_resp_spec_from_handle(struct tfe_h2_half_private *half_private) struct tfe_http_resp_spec *resp_spec = &(half_private->half_public.resp_spec); TAILQ_FOREACH_SAFE(h2_field, &header->h2_field_list, next, peer_h2_field){ - if (!strncmp((char *)(h2_field->nv.name), ":status", strlen(":status"))){ + if (!strncasecmp((char *)(h2_field->nv.name), ":status", strlen(":status"))){ resp_spec->resp_code = atoi((const char *)h2_field->nv.value); continue; } - if (!strncmp((char *)(h2_field->nv.name), "content-type", strlen("content-type"))){ + if (!strncasecmp((char *)(h2_field->nv.name), "content-type", strlen("content-type"))){ resp_spec->content_type = tfe_strdup((const char *)(h2_field->nv.value));; continue; } - if (!strncmp((char *)(h2_field->nv.name), "content-encoding", strlen("content-encoding"))){ + if (!strncasecmp((char *)(h2_field->nv.name), "content-encoding", strlen("content-encoding"))){ resp_spec->content_encoding = tfe_strdup((const char *)(h2_field->nv.value));; continue; } - if (!strncmp((char *)(h2_field->nv.name), "content-length", strlen("content-length"))){ + if (!strncasecmp((char *)(h2_field->nv.name), "content-length", strlen("content-length"))){ resp_spec->content_length = tfe_strdup((const char *)(h2_field->nv.value));; continue; } @@ -1697,16 +1661,16 @@ static void fill_req_spec_from_handle(struct tfe_h2_half_private *half_private) struct tfe_http_req_spec *req_spec = &(half_private->half_public.req_spec); TAILQ_FOREACH_SAFE(h2_field, &header->h2_field_list, next, peer_h2_field){ - if (!strncmp((char *)(h2_field->nv.name), ":method", strlen(":method"))){ + if (!strncasecmp((char *)(h2_field->nv.name), ":method", strlen(":method"))){ req_spec->method = (enum tfe_http_std_method)str_to_val((const char *)(h2_field->nv.value), method_vals); continue; } - if (!strncmp((char *)(h2_field->nv.name), ":authority", strlen(":authority"))){ + if (!strncasecmp((char *)(h2_field->nv.name), ":authority", strlen(":authority"))){ req_spec->host = tfe_strdup((const char *)(h2_field->nv.value)); urllen += h2_field->nv.valuelen; continue; } - if (!strncmp((char *)(h2_field->nv.name), ":path", strlen(":path"))){ + if (!strncasecmp((char *)(h2_field->nv.name), ":path", strlen(":path"))){ req_spec->uri = tfe_strdup((const char*)(h2_field->nv.value)); urllen += h2_field->nv.valuelen; continue; @@ -1916,7 +1880,7 @@ nghttp2_fill_up_header(nghttp2_session *ngh2_session, const nghttp2_frame *frame struct tfe_h2_half_private *half = (dir == CONN_DIR_UPSTREAM) ? h2_session->resp : h2_session->req; struct http_field_name field; - field.field_id = (enum tfe_http_std_field)str_to_val((const char *)name, header_vals); + field.field_id = (enum tfe_http_std_field)http2_header_str_to_val((const char *)name, __str_std_header_field_map, __str_std_header_field_map_size); if (field.field_id == TFE_HTTP_UNKNOWN_FIELD) { field.field_name = (const char *)name; @@ -1950,7 +1914,7 @@ nghttp2_fill_up_promise(nghttp2_session *ngh2_session, const nghttp2_frame *fram } resp = h2_session->resp; struct http_field_name field; - field.field_id = (enum tfe_http_std_field)str_to_val((const char *)name, header_vals); + field.field_id = (enum tfe_http_std_field)http2_header_str_to_val((const char *)name, __str_std_header_field_map, __str_std_header_field_map_size); if (field.field_id == TFE_HTTP_UNKNOWN_FIELD) { field.field_name = (const char *)name;