src: Compile defaltehd and inflatehd with c++
This commit also fixes defaltehd always reports output length is 0.
This commit is contained in:
parent
34581d830d
commit
f011bda377
|
@ -141,8 +141,8 @@ bin_PROGRAMS += inflatehd deflatehd
|
|||
|
||||
HPACK_TOOLS_COMMON_SRCS = comp_helper.c comp_helper.h
|
||||
|
||||
inflatehd_SOURCES = inflatehd.c $(HPACK_TOOLS_COMMON_SRCS)
|
||||
inflatehd_SOURCES = inflatehd.cc $(HPACK_TOOLS_COMMON_SRCS)
|
||||
|
||||
deflatehd_SOURCES = deflatehd.c $(HPACK_TOOLS_COMMON_SRCS)
|
||||
deflatehd_SOURCES = deflatehd.cc $(HPACK_TOOLS_COMMON_SRCS)
|
||||
|
||||
endif # ENABLE_HPACK_TOOLS
|
||||
|
|
|
@ -26,21 +26,28 @@
|
|||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "nghttp2_hd.h"
|
||||
#include "nghttp2_frame.h"
|
||||
|
||||
#include "comp_helper.h"
|
||||
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
size_t table_size;
|
||||
size_t deflate_table_size;
|
||||
|
@ -73,31 +80,22 @@ static void to_hex(char *dest, const uint8_t *src, size_t len)
|
|||
|
||||
static void output_to_json(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_bufs *bufs, size_t inputlen,
|
||||
nghttp2_nv *nva, size_t nvlen,
|
||||
const std::vector<nghttp2_nv> nva,
|
||||
int seq)
|
||||
{
|
||||
json_t *obj;
|
||||
char *hex = NULL, *hexp;
|
||||
size_t len;
|
||||
nghttp2_buf_chain *ci;
|
||||
nghttp2_buf *buf;
|
||||
auto len = nghttp2_bufs_len(bufs);
|
||||
auto hex = std::vector<char>(len * 2);
|
||||
auto obj = json_object();
|
||||
|
||||
len = nghttp2_bufs_len(bufs);
|
||||
|
||||
if(len > 0) {
|
||||
hex = malloc(len * 2);
|
||||
}
|
||||
|
||||
obj = json_object();
|
||||
json_object_set_new(obj, "seq", json_integer(seq));
|
||||
json_object_set_new(obj, "input_length", json_integer(inputlen));
|
||||
json_object_set_new(obj, "output_length", json_integer(len));
|
||||
json_object_set_new(obj, "percentage_of_original_size",
|
||||
json_real((double)len / inputlen * 100));
|
||||
|
||||
hexp = hex;
|
||||
for(ci = bufs->head; ci; ci = ci->next) {
|
||||
buf = &ci->buf;
|
||||
auto hexp = hex.data();
|
||||
for(auto ci = bufs->head; ci; ci = ci->next) {
|
||||
auto buf = &ci->buf;
|
||||
to_hex(hexp, buf->pos, nghttp2_buf_len(buf));
|
||||
hexp += nghttp2_buf_len(buf);
|
||||
}
|
||||
|
@ -105,9 +103,9 @@ static void output_to_json(nghttp2_hd_deflater *deflater,
|
|||
if(len == 0) {
|
||||
json_object_set_new(obj, "wire", json_string(""));
|
||||
} else {
|
||||
json_object_set_new(obj, "wire", json_pack("s#", hex, len * 2));
|
||||
json_object_set_new(obj, "wire", json_pack("s#", hex.data(), hex.size()));
|
||||
}
|
||||
json_object_set_new(obj, "headers", dump_headers(nva, nvlen));
|
||||
json_object_set_new(obj, "headers", dump_headers(nva.data(), nva.size()));
|
||||
if(seq == 0) {
|
||||
/* We only change the header table size only once at the beginning */
|
||||
json_object_set_new(obj, "header_table_size",
|
||||
|
@ -120,40 +118,37 @@ static void output_to_json(nghttp2_hd_deflater *deflater,
|
|||
json_dumpf(obj, stdout, JSON_PRESERVE_ORDER | JSON_INDENT(2));
|
||||
printf("\n");
|
||||
json_decref(obj);
|
||||
free(hex);
|
||||
}
|
||||
|
||||
static void deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_nv *nva, size_t nvlen, size_t inputlen, int seq)
|
||||
const std::vector<nghttp2_nv>& nva,
|
||||
size_t inputlen, int seq)
|
||||
{
|
||||
ssize_t rv;
|
||||
nghttp2_bufs bufs;
|
||||
|
||||
nghttp2_bufs_init2(&bufs, 4096, 16, 0);
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(deflater, &bufs, nva, nvlen);
|
||||
rv = nghttp2_hd_deflate_hd(deflater, &bufs,
|
||||
(nghttp2_nv*)nva.data(), nva.size());
|
||||
if(rv < 0) {
|
||||
fprintf(stderr, "deflate failed with error code %zd at %d\n", rv, seq);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
input_sum += inputlen;
|
||||
output_sum += rv;
|
||||
output_sum += nghttp2_bufs_len(&bufs);
|
||||
|
||||
output_to_json(deflater, &bufs, inputlen, nva, nvlen, seq);
|
||||
output_to_json(deflater, &bufs, inputlen, nva, seq);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
}
|
||||
|
||||
static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, int seq)
|
||||
{
|
||||
json_t *js;
|
||||
nghttp2_nv nva[128];
|
||||
size_t len;
|
||||
size_t i;
|
||||
size_t inputlen = 0;
|
||||
|
||||
js = json_object_get(obj, "headers");
|
||||
if(js == NULL) {
|
||||
auto js = json_object_get(obj, "headers");
|
||||
if(js == nullptr) {
|
||||
fprintf(stderr, "'headers' key is missing at %d\n", seq);
|
||||
return -1;
|
||||
}
|
||||
|
@ -162,20 +157,20 @@ static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, int seq)
|
|||
"The value of 'headers' key must be an array at %d\n", seq);
|
||||
return -1;
|
||||
}
|
||||
len = json_array_size(js);
|
||||
if(len > sizeof(nva)/sizeof(nva[0])) {
|
||||
fprintf(stderr, "Too many headers (> %zu) at %d\n",
|
||||
sizeof(nva)/sizeof(nva[0]), seq);
|
||||
return -1;
|
||||
}
|
||||
for(i = 0; i < len; ++i) {
|
||||
json_t *nv_pair = json_array_get(js, i);
|
||||
|
||||
auto len = json_array_size(js);
|
||||
auto nva = std::vector<nghttp2_nv>(len);
|
||||
|
||||
for(size_t i = 0; i < len; ++i) {
|
||||
auto nv_pair = json_array_get(js, i);
|
||||
const char *name;
|
||||
json_t *value;
|
||||
|
||||
if(!json_is_object(nv_pair) || json_object_size(nv_pair) != 1) {
|
||||
fprintf(stderr, "bad formatted name/value pair object at %d\n", seq);
|
||||
return -1;
|
||||
}
|
||||
|
||||
json_object_foreach(nv_pair, name, value) {
|
||||
nva[i].name = (uint8_t*)name;
|
||||
nva[i].namelen = strlen(name);
|
||||
|
@ -184,12 +179,16 @@ static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, int seq)
|
|||
fprintf(stderr, "value is not string at %d\n", seq);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nva[i].value = (uint8_t*)json_string_value(value);
|
||||
nva[i].valuelen = strlen(json_string_value(value));
|
||||
}
|
||||
|
||||
inputlen += nva[i].namelen + nva[i].valuelen;
|
||||
}
|
||||
deflate_hd(deflater, nva, len, inputlen, seq);
|
||||
|
||||
deflate_hd(deflater, nva, inputlen, seq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -207,31 +206,34 @@ static void deinit_deflater(nghttp2_hd_deflater *deflater)
|
|||
|
||||
static int perform(void)
|
||||
{
|
||||
size_t i;
|
||||
json_t *json, *cases;
|
||||
json_error_t error;
|
||||
size_t len;
|
||||
nghttp2_hd_deflater deflater;
|
||||
|
||||
json = json_loadf(stdin, 0, &error);
|
||||
if(json == NULL) {
|
||||
auto json = json_loadf(stdin, 0, &error);
|
||||
|
||||
if(json == nullptr) {
|
||||
fprintf(stderr, "JSON loading failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cases = json_object_get(json, "cases");
|
||||
if(cases == NULL) {
|
||||
|
||||
auto cases = json_object_get(json, "cases");
|
||||
|
||||
if(cases == nullptr) {
|
||||
fprintf(stderr, "Missing 'cases' key in root object\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(!json_is_array(cases)) {
|
||||
fprintf(stderr, "'cases' must be JSON array\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
init_deflater(&deflater);
|
||||
output_json_header();
|
||||
len = json_array_size(cases);
|
||||
for(i = 0; i < len; ++i) {
|
||||
json_t *obj = json_array_get(cases, i);
|
||||
auto len = json_array_size(cases);
|
||||
|
||||
for(size_t i = 0; i < len; ++i) {
|
||||
auto obj = json_array_get(cases, i);
|
||||
if(!json_is_object(obj)) {
|
||||
fprintf(stderr, "Unexpected JSON type at %zu. It should be object.\n",
|
||||
i);
|
||||
|
@ -253,7 +255,7 @@ static int perform(void)
|
|||
static int perform_from_http1text(void)
|
||||
{
|
||||
char line[1 << 14];
|
||||
nghttp2_nv nva[256];
|
||||
std::vector<nghttp2_nv> nva;
|
||||
int seq = 0;
|
||||
nghttp2_hd_deflater deflater;
|
||||
init_deflater(&deflater);
|
||||
|
@ -267,16 +269,18 @@ static int perform_from_http1text(void)
|
|||
nghttp2_nv *nv;
|
||||
char *rv = fgets(line, sizeof(line), stdin);
|
||||
char *val, *val_end;
|
||||
if(rv == NULL) {
|
||||
if(rv == nullptr) {
|
||||
end = 1;
|
||||
break;
|
||||
} else if(line[0] == '\n') {
|
||||
break;
|
||||
}
|
||||
assert(nvlen < sizeof(nva)/sizeof(nva[0]));
|
||||
|
||||
nva.resize(nvlen);
|
||||
|
||||
nv = &nva[nvlen];
|
||||
val = strchr(line+1, ':');
|
||||
if(val == NULL) {
|
||||
if(val == nullptr) {
|
||||
fprintf(stderr, "Bad HTTP/1 header field format at %d.\n", seq);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -299,7 +303,7 @@ static int perform_from_http1text(void)
|
|||
if(seq > 0) {
|
||||
printf(",\n");
|
||||
}
|
||||
deflate_hd(&deflater, nva, nvlen, inputlen, seq);
|
||||
deflate_hd(&deflater, nva, inputlen, seq);
|
||||
}
|
||||
|
||||
for(i = 0; i < nvlen; ++i) {
|
||||
|
@ -316,81 +320,82 @@ static int perform_from_http1text(void)
|
|||
|
||||
static void print_help(void)
|
||||
{
|
||||
printf("HPACK HTTP/2 header encoder\n"
|
||||
"Usage: deflatehd [OPTIONS] < INPUT\n"
|
||||
"\n"
|
||||
"Reads JSON data or HTTP/1-style header fields from stdin and\n"
|
||||
"outputs deflated header block in JSON array.\n"
|
||||
"\n"
|
||||
"For the JSON input, the root JSON object must contain \"context\"\n"
|
||||
"key, which indicates which compression context is used. If it is\n"
|
||||
"\"request\", request compression context is used. Otherwise,\n"
|
||||
"response compression context is used. The value of \"cases\" key\n"
|
||||
"contains the sequence of input header set. They share the same\n"
|
||||
"compression context and are processed in the order they appear.\n"
|
||||
"Each item in the sequence is a JSON object and it must have at\n"
|
||||
"least \"headers\" key. Its value is an array of a JSON object\n"
|
||||
"containing exactly one name/value pair.\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
"{\n"
|
||||
" \"context\": \"request\",\n"
|
||||
" \"cases\":\n"
|
||||
" [\n"
|
||||
" {\n"
|
||||
" \"headers\": [\n"
|
||||
" { \":method\": \"GET\" },\n"
|
||||
" { \":path\": \"/\" }\n"
|
||||
" ]\n"
|
||||
" },\n"
|
||||
" {\n"
|
||||
" \"headers\": [\n"
|
||||
" { \":method\": \"POST\" },\n"
|
||||
" { \":path\": \"/\" }\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"With -t option, the program can accept more familiar HTTP/1 style\n"
|
||||
"header field block. Each header set must be followed by one empty\n"
|
||||
"line:\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
":method: GET\n"
|
||||
":scheme: https\n"
|
||||
":path: /\n"
|
||||
"\n"
|
||||
":method: POST\n"
|
||||
"user-agent: nghttp2\n"
|
||||
"\n"
|
||||
"The output of this program can be used as input for inflatehd.\n"
|
||||
"\n"
|
||||
"OPTIONS:\n"
|
||||
" -t, --http1text Use HTTP/1 style header field text as input.\n"
|
||||
" Each header set is delimited by single empty\n"
|
||||
" line.\n"
|
||||
" -s, --table-size=<N>\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, --deflate-table-size=<N>\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"
|
||||
" -c, --no-refset Don't use reference set.\n");
|
||||
std::cout << R"(HPACK HTTP/2 header encoder
|
||||
Usage: deflatehd [OPTIONS] < INPUT
|
||||
|
||||
Reads JSON data or HTTP/1-style header fields from stdin and outputs
|
||||
deflated header block in JSON array.
|
||||
|
||||
For the JSON input, the root JSON object must contain "context" key,
|
||||
which indicates which compression context is used. If it is
|
||||
"request", request compression context is used. Otherwise, response
|
||||
compression context is used. The value of "cases" key contains the
|
||||
sequence of input header set. They share the same compression context
|
||||
and are processed in the order they appear. Each item in the sequence
|
||||
is a JSON object and it must have at least "headers" key. Its value
|
||||
is an array of a JSON object containing exactly one name/value pair.
|
||||
|
||||
Example:
|
||||
{
|
||||
"context": "request",
|
||||
"cases":
|
||||
[
|
||||
{
|
||||
"headers": [
|
||||
{ ":method": "GET" },
|
||||
{ ":path": "/" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"headers": [
|
||||
{ ":method": "POST" },
|
||||
{ ":path": "/" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
With -t option, the program can accept more familiar HTTP/1 style
|
||||
header field block. Each header set must be followed by one empty
|
||||
line:
|
||||
|
||||
Example:
|
||||
|
||||
:method: GET
|
||||
:scheme: https
|
||||
:path: /
|
||||
|
||||
:method: POST
|
||||
user-agent: nghttp2
|
||||
|
||||
The output of this program can be used as input for inflatehd.
|
||||
|
||||
OPTIONS:
|
||||
-t, --http1text Use HTTP/1 style header field text as input.
|
||||
Each header set is delimited by single empty
|
||||
line.
|
||||
-s, --table-size=<N>
|
||||
Set dynamic table size. In the HPACK
|
||||
specification, this value is denoted by
|
||||
SETTINGS_HEADER_TABLE_SIZE.
|
||||
Default: 4096
|
||||
-S, --deflate-table-size=<N>
|
||||
Use first N bytes of dynamic header table
|
||||
buffer.
|
||||
Default: 4096
|
||||
-d, --dump-header-table
|
||||
Output dynamic header table.
|
||||
-c, --no-refset Don't use reference set.)"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"http1text", no_argument, NULL, 't'},
|
||||
{"table-size", required_argument, NULL, 's'},
|
||||
{"deflate-table-size", required_argument, NULL, 'S'},
|
||||
{"dump-header-table", no_argument, NULL, 'd'},
|
||||
{"no-refset", no_argument, NULL, 'c'},
|
||||
{NULL, 0, NULL, 0 }
|
||||
{"http1text", no_argument, nullptr, 't'},
|
||||
{"table-size", required_argument, nullptr, 's'},
|
||||
{"deflate-table-size", required_argument, nullptr, 'S'},
|
||||
{"dump-header-table", no_argument, nullptr, 'd'},
|
||||
{"no-refset", no_argument, nullptr, 'c'},
|
||||
{nullptr, 0, nullptr, 0 }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
|
@ -26,21 +26,28 @@
|
|||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "nghttp2_hd.h"
|
||||
#include "nghttp2_frame.h"
|
||||
|
||||
#include "comp_helper.h"
|
||||
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int dump_header_table;
|
||||
} inflate_config;
|
||||
|
@ -70,9 +77,7 @@ static void to_json(nghttp2_hd_inflater *inflater,
|
|||
json_t *headers, json_t *wire, int seq,
|
||||
size_t old_settings_table_size)
|
||||
{
|
||||
json_t *obj;
|
||||
|
||||
obj = json_object();
|
||||
auto obj = json_object();
|
||||
json_object_set_new(obj, "seq", json_integer(seq));
|
||||
json_object_set(obj, "wire", wire);
|
||||
json_object_set(obj, "headers", headers);
|
||||
|
@ -91,21 +96,20 @@ static void to_json(nghttp2_hd_inflater *inflater,
|
|||
|
||||
static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
|
||||
{
|
||||
json_t *wire, *table_size, *headers;
|
||||
size_t inputlen;
|
||||
uint8_t *buf, *p;
|
||||
size_t buflen;
|
||||
ssize_t rv;
|
||||
nghttp2_nv nv;
|
||||
int inflate_flags;
|
||||
size_t old_settings_table_size = inflater->settings_hd_table_bufsize_max;
|
||||
|
||||
wire = json_object_get(obj, "wire");
|
||||
if(wire == NULL) {
|
||||
auto wire = json_object_get(obj, "wire");
|
||||
|
||||
if(wire == nullptr) {
|
||||
fprintf(stderr, "'wire' key is missing at %d\n", seq);
|
||||
return -1;
|
||||
}
|
||||
table_size = json_object_get(obj, "header_table_size");
|
||||
|
||||
auto table_size = json_object_get(obj, "header_table_size");
|
||||
|
||||
if(table_size) {
|
||||
if(!json_is_integer(table_size)) {
|
||||
fprintf(stderr,
|
||||
|
@ -122,18 +126,22 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
inputlen = strlen(json_string_value(wire));
|
||||
|
||||
auto inputlen = strlen(json_string_value(wire));
|
||||
|
||||
if(inputlen & 1) {
|
||||
fprintf(stderr, "Badly formatted output value at %d\n", seq);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
buflen = inputlen / 2;
|
||||
buf = malloc(buflen);
|
||||
decode_hex(buf, json_string_value(wire), inputlen);
|
||||
|
||||
headers = json_array();
|
||||
auto buflen = inputlen / 2;
|
||||
auto buf = std::vector<uint8_t>(buflen);
|
||||
|
||||
p = buf;
|
||||
decode_hex(buf.data(), json_string_value(wire), inputlen);
|
||||
|
||||
auto headers = json_array();
|
||||
|
||||
auto p = buf.data();
|
||||
for(;;) {
|
||||
inflate_flags = 0;
|
||||
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, p, buflen, 1);
|
||||
|
@ -155,37 +163,40 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
|
|||
nghttp2_hd_inflate_end_headers(inflater);
|
||||
to_json(inflater, headers, wire, seq, old_settings_table_size);
|
||||
json_decref(headers);
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int perform(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
size_t i;
|
||||
json_t *json, *cases;
|
||||
json_error_t error;
|
||||
size_t len;
|
||||
|
||||
json = json_loadf(stdin, 0, &error);
|
||||
if(json == NULL) {
|
||||
auto json = json_loadf(stdin, 0, &error);
|
||||
|
||||
if(json == nullptr) {
|
||||
fprintf(stderr, "JSON loading failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cases = json_object_get(json, "cases");
|
||||
if(cases == NULL) {
|
||||
|
||||
auto cases = json_object_get(json, "cases");
|
||||
|
||||
if(cases == nullptr) {
|
||||
fprintf(stderr, "Missing 'cases' key in root object\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(!json_is_array(cases)) {
|
||||
fprintf(stderr, "'cases' must be JSON array\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
output_json_header();
|
||||
len = json_array_size(cases);
|
||||
for(i = 0; i < len; ++i) {
|
||||
json_t *obj = json_array_get(cases, i);
|
||||
auto len = json_array_size(cases);
|
||||
|
||||
for(size_t i = 0; i < len; ++i) {
|
||||
auto obj = json_array_get(cases, i);
|
||||
if(!json_is_object(obj)) {
|
||||
fprintf(stderr, "Unexpected JSON type at %zu. It should be object.\n",
|
||||
i);
|
||||
|
@ -201,47 +212,49 @@ static int perform(void)
|
|||
output_json_footer();
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
json_decref(json);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_help(void)
|
||||
{
|
||||
printf("HPACK HTTP/2 header decoder\n"
|
||||
"Usage: inflatehd [OPTIONS] < INPUT\n"
|
||||
"\n"
|
||||
"Reads JSON data from stdin and outputs inflated name/value pairs\n"
|
||||
"in JSON.\n"
|
||||
"\n"
|
||||
"The root JSON object must contain \"context\" key, which indicates\n"
|
||||
"which compression context is used. If it is \"request\", request\n"
|
||||
"compression context is used. Otherwise, response compression\n"
|
||||
"context is used. The value of \"cases\" key contains the sequence\n"
|
||||
"of compressed header block. They share the same compression\n"
|
||||
"context and are processed in the order they appear. Each item in\n"
|
||||
"the sequence is a JSON object and it must have at least \"wire\"\n"
|
||||
"key. Its value is a string containing compressed header block in\n"
|
||||
"hex string.\n"
|
||||
"\n"
|
||||
"Example:\n"
|
||||
"{\n"
|
||||
" \"context\": \"request\",\n"
|
||||
" \"cases\":\n"
|
||||
" [\n"
|
||||
" { \"wire\": \"0284f77778ff\" },\n"
|
||||
" { \"wire\": \"0185fafd3c3c7f81\" }\n"
|
||||
" ]\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"The output of this program can be used as input for deflatehd.\n"
|
||||
"\n"
|
||||
"OPTIONS:\n"
|
||||
" -d, --dump-header-table\n"
|
||||
" Output dynamic header table.\n");
|
||||
std::cout << R"(HPACK HTTP/2 header decoder
|
||||
Usage: inflatehd [OPTIONS] < INPUT
|
||||
|
||||
Reads JSON data from stdin and outputs inflated name/value pairs in
|
||||
JSON.
|
||||
|
||||
The root JSON object must contain "context" key, which indicates which
|
||||
compression context is used. If it is "request", request compression
|
||||
context is used. Otherwise, response compression context is used.
|
||||
The value of "cases" key contains the sequence of compressed header
|
||||
block. They share the same compression context and are processed in
|
||||
the order they appear. Each item in the sequence is a JSON object and
|
||||
it must have at least "wire" key. Its value is a string containing
|
||||
compressed header block in hex string.
|
||||
|
||||
Example:
|
||||
|
||||
{
|
||||
"context": "request",
|
||||
"cases":
|
||||
[
|
||||
{ "wire": "0284f77778ff" },
|
||||
{ "wire": "0185fafd3c3c7f81" }
|
||||
]
|
||||
}
|
||||
|
||||
The output of this program can be used as input for deflatehd.
|
||||
|
||||
OPTIONS:
|
||||
-d, --dump-header-table
|
||||
Output dynamic header table.)"
|
||||
<< std::endl;;
|
||||
}
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"dump-header-table", no_argument, NULL, 'd'},
|
||||
{NULL, 0, NULL, 0 }
|
||||
{"dump-header-table", no_argument, nullptr, 'd'},
|
||||
{nullptr, 0, nullptr, 0 }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
Loading…
Reference in New Issue