diff --git a/hdtest/Makefile.am b/hdtest/Makefile.am index 1b1deb88..855bfc0f 100644 --- a/hdtest/Makefile.am +++ b/hdtest/Makefile.am @@ -31,9 +31,11 @@ LDADD = $(top_builddir)/lib/libnghttp2.la bin_PROGRAMS = inflatehd deflatehd -inflatehd_SOURCES = inflatehd.c +COMMON_SRCS = comp_helper.c comp_helper.h -deflatehd_SOURCES = deflatehd.c +inflatehd_SOURCES = inflatehd.c $(COMMON_SRCS) + +deflatehd_SOURCES = deflatehd.c $(COMMON_SRCS) endif # ENABLE_HDTEST diff --git a/hdtest/comp_helper.c b/hdtest/comp_helper.c new file mode 100644 index 00000000..ad948ce5 --- /dev/null +++ b/hdtest/comp_helper.c @@ -0,0 +1,67 @@ +/* + * nghttp2 - HTTP/2.0 C Library + * + * Copyright (c) 2013 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "comp_helper.h" + +void dump_val(json_t *jent, const char *key, uint8_t *val, size_t len) +{ + if(val == NULL) { + json_object_set_new(jent, key, json_string("**DEALLOCATED**")); + } else { + json_object_set_new(jent, key, json_pack("s#", val, len)); + } +} + +json_t* dump_header_table(nghttp2_hd_context *context) +{ + json_t *obj, *entries; + size_t i; + + obj = json_object(); + entries = json_array(); + for(i = 0; i < context->hd_table.len; ++i) { + nghttp2_hd_entry *ent = nghttp2_hd_table_get(context, i); + json_t *outent = json_object(); + json_object_set_new(outent, "index", json_integer(i)); + dump_val(outent, "name", ent->nv.name, ent->nv.namelen); + dump_val(outent, "value", ent->nv.value, ent->nv.valuelen); + json_object_set_new(outent, "referenced", + json_boolean(ent->flags & NGHTTP2_HD_FLAG_REFSET)); + json_object_set_new(outent, "size", + json_integer(ent->nv.namelen + ent->nv.valuelen + + NGHTTP2_HD_ENTRY_OVERHEAD)); + json_array_append_new(entries, outent); + } + json_object_set_new(obj, "entries", entries); + json_object_set_new(obj, "size", json_integer(context->hd_table_bufsize)); + json_object_set_new(obj, "maxSize", + json_integer(context->hd_table_bufsize_max)); + if(context->role == NGHTTP2_HD_ROLE_DEFLATE) { + json_object_set_new(obj, "localSize", + json_integer(context->local_hd_table_bufsize)); + json_object_set_new(obj, "localMaxSize", + json_integer(context->local_hd_table_bufsize_max)); + } + return obj; +} diff --git a/hdtest/comp_helper.h b/hdtest/comp_helper.h new file mode 100644 index 00000000..43d8fa6c --- /dev/null +++ b/hdtest/comp_helper.h @@ -0,0 +1,38 @@ +/* + * nghttp2 - HTTP/2.0 C Library + * + * Copyright (c) 2013 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef NGHTTP2_COMP_HELPER_H +#define NGHTTP2_COMP_HELPER_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +#include "nghttp2_hd.h" + +json_t* dump_header_table(nghttp2_hd_context *context); + +#endif /* NGHTTP2_COMP_HELPER_H */ diff --git a/hdtest/deflatehd.c b/hdtest/deflatehd.c index 5e5c456d..578f7b5c 100644 --- a/hdtest/deflatehd.c +++ b/hdtest/deflatehd.c @@ -11,11 +11,14 @@ #include "nghttp2_hd.h" #include "nghttp2_frame.h" +#include "comp_helper.h" + typedef struct { nghttp2_hd_side side; size_t table_size; size_t local_table_size; int http1text; + int dump_header_table; } deflate_config; static deflate_config config; @@ -29,7 +32,8 @@ static void to_hex(char *dest, const uint8_t *src, size_t len) } } -static void output_to_json(const uint8_t *buf, size_t len, size_t inputlen, +static void output_to_json(nghttp2_hd_context *deflater, + const uint8_t *buf, size_t len, size_t inputlen, int seq) { json_t *obj; @@ -47,7 +51,10 @@ static void output_to_json(const uint8_t *buf, size_t len, size_t inputlen, json_real((double)len / inputlen * 100)); to_hex(hex, buf, len); json_object_set_new(obj, "output", json_pack("s#", hex, len * 2)); - json_dumpf(obj, stdout, JSON_PRESERVE_ORDER); + if(config.dump_header_table) { + json_object_set_new(obj, "headerTable", dump_header_table(deflater)); + } + json_dumpf(obj, stdout, JSON_PRESERVE_ORDER | JSON_INDENT(2)); printf("\n"); json_decref(obj); } @@ -63,7 +70,7 @@ static void deflate_hd(nghttp2_hd_context *deflater, fprintf(stderr, "deflate failed with error code %zd at %d\n", rv, seq); exit(EXIT_FAILURE); } - output_to_json(buf, rv, inputlen, seq); + output_to_json(deflater, buf, rv, inputlen, seq); nghttp2_hd_end_headers(deflater); free(buf); } @@ -260,21 +267,16 @@ static void print_help(void) " Each header set is delimited by single empty\n" " line.\n" " -s, --table-size=\n" - " Set dynamic table size. This value is the\n" - " buffer size the decoder uses. In the HPACK\n" + " Set dynamic table size. In the HPACK\n" " specification, this value is denoted by\n" " SETTINGS_HEADER_TABLE_SIZE.\n" " Default: 4096\n" " -S, --local-table-size=\n" - " Set effective dynamic table size when\n" - " encoding headers. Although a decoder uses\n" - " the value specified in -s option, encoder\n" - " can use smaller buffer size than that. This\n" - " option specifies it. Therefore it is\n" - " meaningless to specify the value equals to\n" - " or greater than the value given in -s\n" - " option.\n" - " Default: 4096\n"); + " Use first N bytes of dynamic header table\n" + " buffer.\n" + " Default: 4096\n" + " -d, --dump-header-table\n" + " Output dynamic header table.\n"); } static struct option long_options[] = { @@ -282,6 +284,7 @@ static struct option long_options[] = { {"http1text", no_argument, NULL, 't'}, {"table-size", required_argument, NULL, 's'}, {"local-table-size", required_argument, NULL, 'S'}, + {"dump-header-table", no_argument, NULL, 'd'}, {NULL, 0, NULL, 0 } }; @@ -294,9 +297,10 @@ int main(int argc, char **argv) config.table_size = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; config.local_table_size = NGHTTP2_HD_DEFAULT_LOCAL_MAX_BUFFER_SIZE; config.http1text = 0; + config.dump_header_table = 0; while(1) { int option_index = 0; - int c = getopt_long(argc, argv, "S:hrs:t", long_options, &option_index); + int c = getopt_long(argc, argv, "S:dhrs:t", long_options, &option_index); if(c == -1) { break; } @@ -328,6 +332,10 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } break; + case 'd': + /* --dump-header-table */ + config.dump_header_table = 1; + break; case '?': exit(EXIT_FAILURE); default: diff --git a/hdtest/inflatehd.c b/hdtest/inflatehd.c index 38021cee..eb3693d8 100644 --- a/hdtest/inflatehd.c +++ b/hdtest/inflatehd.c @@ -11,9 +11,12 @@ #include "nghttp2_hd.h" #include "nghttp2_frame.h" +#include "comp_helper.h" + typedef struct { nghttp2_hd_side side; size_t table_size; + int dump_header_table; } inflate_config; static inflate_config config; @@ -37,7 +40,8 @@ static void decode_hex(uint8_t *dest, const char *src, size_t len) } } -static void nva_to_json(const nghttp2_nv *nva, size_t nvlen, int seq) +static void nva_to_json(nghttp2_hd_context *inflater, + const nghttp2_nv *nva, size_t nvlen, int seq) { size_t i; json_t *obj; @@ -53,6 +57,9 @@ static void nva_to_json(const nghttp2_nv *nva, size_t nvlen, int seq) json_array_append_new(nv_pair, json_pack("s#", nv->value, nv->valuelen)); json_array_append_new(headers, nv_pair); } + if(config.dump_header_table) { + json_object_set_new(obj, "headerTable", dump_header_table(inflater)); + } json_dumpf(obj, stdout, JSON_INDENT(2) | JSON_PRESERVE_ORDER); json_decref(obj); printf("\n"); @@ -88,7 +95,7 @@ static int inflate_hd(json_t *obj, nghttp2_hd_context *inflater, int seq) resnvlen, seq); exit(EXIT_FAILURE); } - nva_to_json(resnva, resnvlen, seq); + nva_to_json(inflater, resnva, resnvlen, seq); nghttp2_hd_end_headers(inflater); nghttp2_nv_array_del(resnva); return 0; @@ -155,16 +162,18 @@ static void print_help(void) " -r, --response Use response compression context instead of\n" " request.\n" " -s, --table-size=\n" - " Set dynamic table size. This value is the\n" - " buffer size the decoder uses. In the HPACK\n" + " Set dynamic table size. In the HPACK\n" " specification, this value is denoted by\n" " SETTINGS_HEADER_TABLE_SIZE.\n" - " Default: 4096\n"); + " Default: 4096\n" + " -d, --dump-header-table\n" + " Output dynamic header table.\n"); } static struct option long_options[] = { {"response", no_argument, NULL, 'r'}, {"table-size", required_argument, NULL, 's'}, + {"dump-header-table", no_argument, NULL, 'd'}, {NULL, 0, NULL, 0 } }; @@ -173,9 +182,10 @@ int main(int argc, char **argv) char *end; config.side = NGHTTP2_HD_SIDE_REQUEST; config.table_size = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; + config.dump_header_table = 0; while(1) { int option_index = 0; - int c = getopt_long(argc, argv, "hrs:", long_options, &option_index); + int c = getopt_long(argc, argv, "dhrs:", long_options, &option_index); if(c == -1) { break; } @@ -195,6 +205,10 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } break; + case 'd': + /* --dump-header-table */ + config.dump_header_table = 1; + break; case '?': exit(EXIT_FAILURE); default: