12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2013 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#ifdef HAVE_CONFIG_H 262c593315Sopenharmony_ci# include <config.h> 272c593315Sopenharmony_ci#endif // HAVE_CONFIG_H 282c593315Sopenharmony_ci 292c593315Sopenharmony_ci#ifdef HAVE_UNISTD_H 302c593315Sopenharmony_ci# include <unistd.h> 312c593315Sopenharmony_ci#endif // HAVE_UNISTD_H 322c593315Sopenharmony_ci#include <getopt.h> 332c593315Sopenharmony_ci 342c593315Sopenharmony_ci#include <cstdio> 352c593315Sopenharmony_ci#include <cstring> 362c593315Sopenharmony_ci#include <cassert> 372c593315Sopenharmony_ci#include <cerrno> 382c593315Sopenharmony_ci#include <cstdlib> 392c593315Sopenharmony_ci#include <vector> 402c593315Sopenharmony_ci#include <iostream> 412c593315Sopenharmony_ci 422c593315Sopenharmony_ci#include <jansson.h> 432c593315Sopenharmony_ci 442c593315Sopenharmony_ci#include <nghttp2/nghttp2.h> 452c593315Sopenharmony_ci 462c593315Sopenharmony_ci#include "template.h" 472c593315Sopenharmony_ci#include "comp_helper.h" 482c593315Sopenharmony_ci#include "util.h" 492c593315Sopenharmony_ci 502c593315Sopenharmony_cinamespace nghttp2 { 512c593315Sopenharmony_ci 522c593315Sopenharmony_citypedef struct { 532c593315Sopenharmony_ci size_t table_size; 542c593315Sopenharmony_ci size_t deflate_table_size; 552c593315Sopenharmony_ci int http1text; 562c593315Sopenharmony_ci int dump_header_table; 572c593315Sopenharmony_ci} deflate_config; 582c593315Sopenharmony_ci 592c593315Sopenharmony_cistatic deflate_config config; 602c593315Sopenharmony_ci 612c593315Sopenharmony_cistatic size_t input_sum; 622c593315Sopenharmony_cistatic size_t output_sum; 632c593315Sopenharmony_ci 642c593315Sopenharmony_cistatic char to_hex_digit(uint8_t n) { 652c593315Sopenharmony_ci if (n > 9) { 662c593315Sopenharmony_ci return n - 10 + 'a'; 672c593315Sopenharmony_ci } 682c593315Sopenharmony_ci return n + '0'; 692c593315Sopenharmony_ci} 702c593315Sopenharmony_ci 712c593315Sopenharmony_cistatic void to_hex(char *dest, const uint8_t *src, size_t len) { 722c593315Sopenharmony_ci size_t i; 732c593315Sopenharmony_ci for (i = 0; i < len; ++i) { 742c593315Sopenharmony_ci *dest++ = to_hex_digit(src[i] >> 4); 752c593315Sopenharmony_ci *dest++ = to_hex_digit(src[i] & 0xf); 762c593315Sopenharmony_ci } 772c593315Sopenharmony_ci} 782c593315Sopenharmony_ci 792c593315Sopenharmony_cistatic void output_to_json(nghttp2_hd_deflater *deflater, const uint8_t *buf, 802c593315Sopenharmony_ci size_t buflen, size_t inputlen, 812c593315Sopenharmony_ci const std::vector<nghttp2_nv> &nva, int seq) { 822c593315Sopenharmony_ci auto hex = std::vector<char>(buflen * 2); 832c593315Sopenharmony_ci auto obj = json_object(); 842c593315Sopenharmony_ci auto comp_ratio = inputlen == 0 ? 0.0 : (double)buflen / inputlen * 100; 852c593315Sopenharmony_ci 862c593315Sopenharmony_ci json_object_set_new(obj, "seq", json_integer(seq)); 872c593315Sopenharmony_ci json_object_set_new(obj, "input_length", json_integer(inputlen)); 882c593315Sopenharmony_ci json_object_set_new(obj, "output_length", json_integer(buflen)); 892c593315Sopenharmony_ci json_object_set_new(obj, "percentage_of_original_size", 902c593315Sopenharmony_ci json_real(comp_ratio)); 912c593315Sopenharmony_ci 922c593315Sopenharmony_ci if (buflen == 0) { 932c593315Sopenharmony_ci json_object_set_new(obj, "wire", json_string("")); 942c593315Sopenharmony_ci } else { 952c593315Sopenharmony_ci to_hex(hex.data(), buf, buflen); 962c593315Sopenharmony_ci json_object_set_new(obj, "wire", json_pack("s#", hex.data(), hex.size())); 972c593315Sopenharmony_ci } 982c593315Sopenharmony_ci json_object_set_new(obj, "headers", dump_headers(nva.data(), nva.size())); 992c593315Sopenharmony_ci if (seq == 0) { 1002c593315Sopenharmony_ci // We only change the header table size only once at the beginning 1012c593315Sopenharmony_ci json_object_set_new(obj, "header_table_size", 1022c593315Sopenharmony_ci json_integer(config.table_size)); 1032c593315Sopenharmony_ci } 1042c593315Sopenharmony_ci if (config.dump_header_table) { 1052c593315Sopenharmony_ci json_object_set_new(obj, "header_table", 1062c593315Sopenharmony_ci dump_deflate_header_table(deflater)); 1072c593315Sopenharmony_ci } 1082c593315Sopenharmony_ci json_dumpf(obj, stdout, JSON_PRESERVE_ORDER | JSON_INDENT(2)); 1092c593315Sopenharmony_ci printf("\n"); 1102c593315Sopenharmony_ci json_decref(obj); 1112c593315Sopenharmony_ci} 1122c593315Sopenharmony_ci 1132c593315Sopenharmony_cistatic void deflate_hd(nghttp2_hd_deflater *deflater, 1142c593315Sopenharmony_ci const std::vector<nghttp2_nv> &nva, size_t inputlen, 1152c593315Sopenharmony_ci int seq) { 1162c593315Sopenharmony_ci ssize_t rv; 1172c593315Sopenharmony_ci std::array<uint8_t, 64_k> buf; 1182c593315Sopenharmony_ci 1192c593315Sopenharmony_ci rv = nghttp2_hd_deflate_hd(deflater, buf.data(), buf.size(), 1202c593315Sopenharmony_ci (nghttp2_nv *)nva.data(), nva.size()); 1212c593315Sopenharmony_ci if (rv < 0) { 1222c593315Sopenharmony_ci fprintf(stderr, "deflate failed with error code %zd at %d\n", rv, seq); 1232c593315Sopenharmony_ci exit(EXIT_FAILURE); 1242c593315Sopenharmony_ci } 1252c593315Sopenharmony_ci 1262c593315Sopenharmony_ci input_sum += inputlen; 1272c593315Sopenharmony_ci output_sum += rv; 1282c593315Sopenharmony_ci 1292c593315Sopenharmony_ci output_to_json(deflater, buf.data(), rv, inputlen, nva, seq); 1302c593315Sopenharmony_ci} 1312c593315Sopenharmony_ci 1322c593315Sopenharmony_cistatic int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, 1332c593315Sopenharmony_ci int seq) { 1342c593315Sopenharmony_ci size_t inputlen = 0; 1352c593315Sopenharmony_ci 1362c593315Sopenharmony_ci auto js = json_object_get(obj, "headers"); 1372c593315Sopenharmony_ci if (js == nullptr) { 1382c593315Sopenharmony_ci fprintf(stderr, "'headers' key is missing at %d\n", seq); 1392c593315Sopenharmony_ci return -1; 1402c593315Sopenharmony_ci } 1412c593315Sopenharmony_ci if (!json_is_array(js)) { 1422c593315Sopenharmony_ci fprintf(stderr, "The value of 'headers' key must be an array at %d\n", seq); 1432c593315Sopenharmony_ci return -1; 1442c593315Sopenharmony_ci } 1452c593315Sopenharmony_ci 1462c593315Sopenharmony_ci auto len = json_array_size(js); 1472c593315Sopenharmony_ci auto nva = std::vector<nghttp2_nv>(len); 1482c593315Sopenharmony_ci 1492c593315Sopenharmony_ci for (size_t i = 0; i < len; ++i) { 1502c593315Sopenharmony_ci auto nv_pair = json_array_get(js, i); 1512c593315Sopenharmony_ci const char *name; 1522c593315Sopenharmony_ci json_t *value; 1532c593315Sopenharmony_ci 1542c593315Sopenharmony_ci if (!json_is_object(nv_pair) || json_object_size(nv_pair) != 1) { 1552c593315Sopenharmony_ci fprintf(stderr, "bad formatted name/value pair object at %d\n", seq); 1562c593315Sopenharmony_ci return -1; 1572c593315Sopenharmony_ci } 1582c593315Sopenharmony_ci 1592c593315Sopenharmony_ci json_object_foreach(nv_pair, name, value) { 1602c593315Sopenharmony_ci nva[i].name = (uint8_t *)name; 1612c593315Sopenharmony_ci nva[i].namelen = strlen(name); 1622c593315Sopenharmony_ci 1632c593315Sopenharmony_ci if (!json_is_string(value)) { 1642c593315Sopenharmony_ci fprintf(stderr, "value is not string at %d\n", seq); 1652c593315Sopenharmony_ci return -1; 1662c593315Sopenharmony_ci } 1672c593315Sopenharmony_ci 1682c593315Sopenharmony_ci nva[i].value = (uint8_t *)json_string_value(value); 1692c593315Sopenharmony_ci nva[i].valuelen = strlen(json_string_value(value)); 1702c593315Sopenharmony_ci 1712c593315Sopenharmony_ci nva[i].flags = NGHTTP2_NV_FLAG_NONE; 1722c593315Sopenharmony_ci } 1732c593315Sopenharmony_ci 1742c593315Sopenharmony_ci inputlen += nva[i].namelen + nva[i].valuelen; 1752c593315Sopenharmony_ci } 1762c593315Sopenharmony_ci 1772c593315Sopenharmony_ci deflate_hd(deflater, nva, inputlen, seq); 1782c593315Sopenharmony_ci 1792c593315Sopenharmony_ci return 0; 1802c593315Sopenharmony_ci} 1812c593315Sopenharmony_ci 1822c593315Sopenharmony_cistatic nghttp2_hd_deflater *init_deflater() { 1832c593315Sopenharmony_ci nghttp2_hd_deflater *deflater; 1842c593315Sopenharmony_ci nghttp2_hd_deflate_new(&deflater, config.deflate_table_size); 1852c593315Sopenharmony_ci if (config.table_size != NGHTTP2_DEFAULT_HEADER_TABLE_SIZE) { 1862c593315Sopenharmony_ci nghttp2_hd_deflate_change_table_size(deflater, config.table_size); 1872c593315Sopenharmony_ci } 1882c593315Sopenharmony_ci return deflater; 1892c593315Sopenharmony_ci} 1902c593315Sopenharmony_ci 1912c593315Sopenharmony_cistatic void deinit_deflater(nghttp2_hd_deflater *deflater) { 1922c593315Sopenharmony_ci nghttp2_hd_deflate_del(deflater); 1932c593315Sopenharmony_ci} 1942c593315Sopenharmony_ci 1952c593315Sopenharmony_cistatic int perform(void) { 1962c593315Sopenharmony_ci json_error_t error; 1972c593315Sopenharmony_ci 1982c593315Sopenharmony_ci auto json = json_loadf(stdin, 0, &error); 1992c593315Sopenharmony_ci 2002c593315Sopenharmony_ci if (json == nullptr) { 2012c593315Sopenharmony_ci fprintf(stderr, "JSON loading failed\n"); 2022c593315Sopenharmony_ci exit(EXIT_FAILURE); 2032c593315Sopenharmony_ci } 2042c593315Sopenharmony_ci 2052c593315Sopenharmony_ci auto cases = json_object_get(json, "cases"); 2062c593315Sopenharmony_ci 2072c593315Sopenharmony_ci if (cases == nullptr) { 2082c593315Sopenharmony_ci fprintf(stderr, "Missing 'cases' key in root object\n"); 2092c593315Sopenharmony_ci exit(EXIT_FAILURE); 2102c593315Sopenharmony_ci } 2112c593315Sopenharmony_ci 2122c593315Sopenharmony_ci if (!json_is_array(cases)) { 2132c593315Sopenharmony_ci fprintf(stderr, "'cases' must be JSON array\n"); 2142c593315Sopenharmony_ci exit(EXIT_FAILURE); 2152c593315Sopenharmony_ci } 2162c593315Sopenharmony_ci 2172c593315Sopenharmony_ci auto deflater = init_deflater(); 2182c593315Sopenharmony_ci output_json_header(); 2192c593315Sopenharmony_ci auto len = json_array_size(cases); 2202c593315Sopenharmony_ci 2212c593315Sopenharmony_ci for (size_t i = 0; i < len; ++i) { 2222c593315Sopenharmony_ci auto obj = json_array_get(cases, i); 2232c593315Sopenharmony_ci if (!json_is_object(obj)) { 2242c593315Sopenharmony_ci fprintf(stderr, "Unexpected JSON type at %zu. It should be object.\n", i); 2252c593315Sopenharmony_ci continue; 2262c593315Sopenharmony_ci } 2272c593315Sopenharmony_ci if (deflate_hd_json(obj, deflater, i) != 0) { 2282c593315Sopenharmony_ci continue; 2292c593315Sopenharmony_ci } 2302c593315Sopenharmony_ci if (i + 1 < len) { 2312c593315Sopenharmony_ci printf(",\n"); 2322c593315Sopenharmony_ci } 2332c593315Sopenharmony_ci } 2342c593315Sopenharmony_ci output_json_footer(); 2352c593315Sopenharmony_ci deinit_deflater(deflater); 2362c593315Sopenharmony_ci json_decref(json); 2372c593315Sopenharmony_ci return 0; 2382c593315Sopenharmony_ci} 2392c593315Sopenharmony_ci 2402c593315Sopenharmony_cistatic int perform_from_http1text(void) { 2412c593315Sopenharmony_ci char line[1 << 14]; 2422c593315Sopenharmony_ci int seq = 0; 2432c593315Sopenharmony_ci 2442c593315Sopenharmony_ci auto deflater = init_deflater(); 2452c593315Sopenharmony_ci output_json_header(); 2462c593315Sopenharmony_ci for (;;) { 2472c593315Sopenharmony_ci std::vector<nghttp2_nv> nva; 2482c593315Sopenharmony_ci int end = 0; 2492c593315Sopenharmony_ci size_t inputlen = 0; 2502c593315Sopenharmony_ci 2512c593315Sopenharmony_ci for (;;) { 2522c593315Sopenharmony_ci char *rv = fgets(line, sizeof(line), stdin); 2532c593315Sopenharmony_ci char *val, *val_end; 2542c593315Sopenharmony_ci if (rv == nullptr) { 2552c593315Sopenharmony_ci end = 1; 2562c593315Sopenharmony_ci break; 2572c593315Sopenharmony_ci } else if (line[0] == '\n') { 2582c593315Sopenharmony_ci break; 2592c593315Sopenharmony_ci } 2602c593315Sopenharmony_ci 2612c593315Sopenharmony_ci nva.emplace_back(); 2622c593315Sopenharmony_ci auto &nv = nva.back(); 2632c593315Sopenharmony_ci 2642c593315Sopenharmony_ci val = strchr(line + 1, ':'); 2652c593315Sopenharmony_ci if (val == nullptr) { 2662c593315Sopenharmony_ci fprintf(stderr, "Bad HTTP/1 header field format at %d.\n", seq); 2672c593315Sopenharmony_ci exit(EXIT_FAILURE); 2682c593315Sopenharmony_ci } 2692c593315Sopenharmony_ci *val = '\0'; 2702c593315Sopenharmony_ci ++val; 2712c593315Sopenharmony_ci for (; *val && (*val == ' ' || *val == '\t'); ++val) 2722c593315Sopenharmony_ci ; 2732c593315Sopenharmony_ci for (val_end = val; *val_end && (*val_end != '\r' && *val_end != '\n'); 2742c593315Sopenharmony_ci ++val_end) 2752c593315Sopenharmony_ci ; 2762c593315Sopenharmony_ci *val_end = '\0'; 2772c593315Sopenharmony_ci 2782c593315Sopenharmony_ci nv.namelen = strlen(line); 2792c593315Sopenharmony_ci nv.valuelen = strlen(val); 2802c593315Sopenharmony_ci nv.name = (uint8_t *)strdup(line); 2812c593315Sopenharmony_ci nv.value = (uint8_t *)strdup(val); 2822c593315Sopenharmony_ci nv.flags = NGHTTP2_NV_FLAG_NONE; 2832c593315Sopenharmony_ci 2842c593315Sopenharmony_ci inputlen += nv.namelen + nv.valuelen; 2852c593315Sopenharmony_ci } 2862c593315Sopenharmony_ci 2872c593315Sopenharmony_ci if (!end) { 2882c593315Sopenharmony_ci if (seq > 0) { 2892c593315Sopenharmony_ci printf(",\n"); 2902c593315Sopenharmony_ci } 2912c593315Sopenharmony_ci deflate_hd(deflater, nva, inputlen, seq); 2922c593315Sopenharmony_ci } 2932c593315Sopenharmony_ci 2942c593315Sopenharmony_ci for (auto &nv : nva) { 2952c593315Sopenharmony_ci free(nv.name); 2962c593315Sopenharmony_ci free(nv.value); 2972c593315Sopenharmony_ci } 2982c593315Sopenharmony_ci 2992c593315Sopenharmony_ci if (end) 3002c593315Sopenharmony_ci break; 3012c593315Sopenharmony_ci ++seq; 3022c593315Sopenharmony_ci } 3032c593315Sopenharmony_ci output_json_footer(); 3042c593315Sopenharmony_ci deinit_deflater(deflater); 3052c593315Sopenharmony_ci return 0; 3062c593315Sopenharmony_ci} 3072c593315Sopenharmony_ci 3082c593315Sopenharmony_cistatic void print_help(void) { 3092c593315Sopenharmony_ci std::cout << R"(HPACK HTTP/2 header encoder 3102c593315Sopenharmony_ciUsage: deflatehd [OPTIONS] < INPUT 3112c593315Sopenharmony_ci 3122c593315Sopenharmony_ciReads JSON data or HTTP/1-style header fields from stdin and outputs 3132c593315Sopenharmony_cideflated header block in JSON array. 3142c593315Sopenharmony_ci 3152c593315Sopenharmony_ciFor the JSON input, the root JSON object must contain "context" key, 3162c593315Sopenharmony_ciwhich indicates which compression context is used. If it is 3172c593315Sopenharmony_ci"request", request compression context is used. Otherwise, response 3182c593315Sopenharmony_cicompression context is used. The value of "cases" key contains the 3192c593315Sopenharmony_cisequence of input header set. They share the same compression context 3202c593315Sopenharmony_ciand are processed in the order they appear. Each item in the sequence 3212c593315Sopenharmony_ciis a JSON object and it must have at least "headers" key. Its value 3222c593315Sopenharmony_ciis an array of a JSON object containing exactly one name/value pair. 3232c593315Sopenharmony_ci 3242c593315Sopenharmony_ciExample: 3252c593315Sopenharmony_ci{ 3262c593315Sopenharmony_ci "context": "request", 3272c593315Sopenharmony_ci "cases": 3282c593315Sopenharmony_ci [ 3292c593315Sopenharmony_ci { 3302c593315Sopenharmony_ci "headers": [ 3312c593315Sopenharmony_ci { ":method": "GET" }, 3322c593315Sopenharmony_ci { ":path": "/" } 3332c593315Sopenharmony_ci ] 3342c593315Sopenharmony_ci }, 3352c593315Sopenharmony_ci { 3362c593315Sopenharmony_ci "headers": [ 3372c593315Sopenharmony_ci { ":method": "POST" }, 3382c593315Sopenharmony_ci { ":path": "/" } 3392c593315Sopenharmony_ci ] 3402c593315Sopenharmony_ci } 3412c593315Sopenharmony_ci ] 3422c593315Sopenharmony_ci} 3432c593315Sopenharmony_ci 3442c593315Sopenharmony_ciWith -t option, the program can accept more familiar HTTP/1 style 3452c593315Sopenharmony_ciheader field block. Each header set must be followed by one empty 3462c593315Sopenharmony_ciline: 3472c593315Sopenharmony_ci 3482c593315Sopenharmony_ciExample: 3492c593315Sopenharmony_ci 3502c593315Sopenharmony_ci:method: GET 3512c593315Sopenharmony_ci:scheme: https 3522c593315Sopenharmony_ci:path: / 3532c593315Sopenharmony_ci 3542c593315Sopenharmony_ci:method: POST 3552c593315Sopenharmony_ciuser-agent: nghttp2 3562c593315Sopenharmony_ci 3572c593315Sopenharmony_ciThe output of this program can be used as input for inflatehd. 3582c593315Sopenharmony_ci 3592c593315Sopenharmony_ciOPTIONS: 3602c593315Sopenharmony_ci -t, --http1text Use HTTP/1 style header field text as input. 3612c593315Sopenharmony_ci Each header set is delimited by single empty 3622c593315Sopenharmony_ci line. 3632c593315Sopenharmony_ci -s, --table-size=<N> 3642c593315Sopenharmony_ci Set dynamic table size. In the HPACK 3652c593315Sopenharmony_ci specification, this value is denoted by 3662c593315Sopenharmony_ci SETTINGS_HEADER_TABLE_SIZE. 3672c593315Sopenharmony_ci Default: 4096 3682c593315Sopenharmony_ci -S, --deflate-table-size=<N> 3692c593315Sopenharmony_ci Use first N bytes of dynamic header table 3702c593315Sopenharmony_ci buffer. 3712c593315Sopenharmony_ci Default: 4096 3722c593315Sopenharmony_ci -d, --dump-header-table 3732c593315Sopenharmony_ci Output dynamic header table.)" 3742c593315Sopenharmony_ci << std::endl; 3752c593315Sopenharmony_ci} 3762c593315Sopenharmony_ci 3772c593315Sopenharmony_ciconstexpr static struct option long_options[] = { 3782c593315Sopenharmony_ci {"http1text", no_argument, nullptr, 't'}, 3792c593315Sopenharmony_ci {"table-size", required_argument, nullptr, 's'}, 3802c593315Sopenharmony_ci {"deflate-table-size", required_argument, nullptr, 'S'}, 3812c593315Sopenharmony_ci {"dump-header-table", no_argument, nullptr, 'd'}, 3822c593315Sopenharmony_ci {nullptr, 0, nullptr, 0}}; 3832c593315Sopenharmony_ci 3842c593315Sopenharmony_ciint main(int argc, char **argv) { 3852c593315Sopenharmony_ci config.table_size = 4_k; 3862c593315Sopenharmony_ci config.deflate_table_size = 4_k; 3872c593315Sopenharmony_ci config.http1text = 0; 3882c593315Sopenharmony_ci config.dump_header_table = 0; 3892c593315Sopenharmony_ci while (1) { 3902c593315Sopenharmony_ci int option_index = 0; 3912c593315Sopenharmony_ci int c = getopt_long(argc, argv, "S:dhs:t", long_options, &option_index); 3922c593315Sopenharmony_ci if (c == -1) { 3932c593315Sopenharmony_ci break; 3942c593315Sopenharmony_ci } 3952c593315Sopenharmony_ci switch (c) { 3962c593315Sopenharmony_ci case 'h': 3972c593315Sopenharmony_ci print_help(); 3982c593315Sopenharmony_ci exit(EXIT_SUCCESS); 3992c593315Sopenharmony_ci case 't': 4002c593315Sopenharmony_ci // --http1text 4012c593315Sopenharmony_ci config.http1text = 1; 4022c593315Sopenharmony_ci break; 4032c593315Sopenharmony_ci case 's': { 4042c593315Sopenharmony_ci // --table-size 4052c593315Sopenharmony_ci auto n = util::parse_uint(optarg); 4062c593315Sopenharmony_ci if (n == -1) { 4072c593315Sopenharmony_ci fprintf(stderr, "-s: Bad option value\n"); 4082c593315Sopenharmony_ci exit(EXIT_FAILURE); 4092c593315Sopenharmony_ci } 4102c593315Sopenharmony_ci config.table_size = n; 4112c593315Sopenharmony_ci break; 4122c593315Sopenharmony_ci } 4132c593315Sopenharmony_ci case 'S': { 4142c593315Sopenharmony_ci // --deflate-table-size 4152c593315Sopenharmony_ci auto n = util::parse_uint(optarg); 4162c593315Sopenharmony_ci if (n == -1) { 4172c593315Sopenharmony_ci fprintf(stderr, "-S: Bad option value\n"); 4182c593315Sopenharmony_ci exit(EXIT_FAILURE); 4192c593315Sopenharmony_ci } 4202c593315Sopenharmony_ci config.deflate_table_size = n; 4212c593315Sopenharmony_ci break; 4222c593315Sopenharmony_ci } 4232c593315Sopenharmony_ci case 'd': 4242c593315Sopenharmony_ci // --dump-header-table 4252c593315Sopenharmony_ci config.dump_header_table = 1; 4262c593315Sopenharmony_ci break; 4272c593315Sopenharmony_ci case '?': 4282c593315Sopenharmony_ci exit(EXIT_FAILURE); 4292c593315Sopenharmony_ci default: 4302c593315Sopenharmony_ci break; 4312c593315Sopenharmony_ci } 4322c593315Sopenharmony_ci } 4332c593315Sopenharmony_ci if (config.http1text) { 4342c593315Sopenharmony_ci perform_from_http1text(); 4352c593315Sopenharmony_ci } else { 4362c593315Sopenharmony_ci perform(); 4372c593315Sopenharmony_ci } 4382c593315Sopenharmony_ci 4392c593315Sopenharmony_ci auto comp_ratio = input_sum == 0 ? 0.0 : (double)output_sum / input_sum; 4402c593315Sopenharmony_ci 4412c593315Sopenharmony_ci fprintf(stderr, "Overall: input=%zu output=%zu ratio=%.02f\n", input_sum, 4422c593315Sopenharmony_ci output_sum, comp_ratio); 4432c593315Sopenharmony_ci return 0; 4442c593315Sopenharmony_ci} 4452c593315Sopenharmony_ci 4462c593315Sopenharmony_ci} // namespace nghttp2 4472c593315Sopenharmony_ci 4482c593315Sopenharmony_ciint main(int argc, char **argv) { 4492c593315Sopenharmony_ci return nghttp2::run_app(nghttp2::main, argc, argv); 4502c593315Sopenharmony_ci} 451