diff --git a/src/HttpServer.cc b/src/HttpServer.cc index 10582c62..df903e3a 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -109,6 +109,8 @@ Config::Config() num_worker(1), max_concurrent_streams(100), header_table_size(-1), + window_bits(-1), + connection_window_bits(-1), port(0), verbose(false), daemon(false), @@ -845,11 +847,28 @@ int Http2Handler::connection_made() { entry[niv].value = config->header_table_size; ++niv; } + + if (config->window_bits != -1) { + entry[niv].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; + entry[niv].value = (1 << config->window_bits) - 1; + ++niv; + } + r = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(), niv); if (r != 0) { return r; } + if (config->connection_window_bits != -1) { + r = nghttp2_submit_window_update( + session_, NGHTTP2_FLAG_NONE, 0, + (1 << config->connection_window_bits) - 1 - + NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE); + if (r != 0) { + return r; + } + } + ev_timer_start(sessions_->get_loop(), &settings_timerev_); if (ssl_ && !nghttp2::ssl::check_http2_requirement(ssl_)) { diff --git a/src/HttpServer.h b/src/HttpServer.h index ff2b844f..151bae71 100644 --- a/src/HttpServer.h +++ b/src/HttpServer.h @@ -67,6 +67,8 @@ struct Config { size_t num_worker; size_t max_concurrent_streams; ssize_t header_table_size; + int window_bits; + int connection_window_bits; uint16_t port; bool verbose; bool daemon; diff --git a/src/nghttpd.cc b/src/nghttpd.cc index 8add1951..a2921e88 100644 --- a/src/nghttpd.cc +++ b/src/nghttpd.cc @@ -143,6 +143,11 @@ Options: Default: 1 -e, --error-gzip Make error response gzipped. + -w, --window-bits= + Sets the stream level initial window size to 2**-1. + -W, --connection-window-bits= + Sets the connection level initial window size to + 2**-1. --dh-param-file= Path to file that contains DH parameters in PEM format. Without this option, DHE cipher suites are not @@ -202,6 +207,8 @@ int main(int argc, char **argv) { {"max-concurrent-streams", required_argument, nullptr, 'm'}, {"workers", required_argument, nullptr, 'n'}, {"error-gzip", no_argument, nullptr, 'e'}, + {"window-bits", required_argument, nullptr, 'w'}, + {"connection-window-bits", required_argument, nullptr, 'W'}, {"no-tls", no_argument, &flag, 1}, {"color", no_argument, &flag, 2}, {"version", no_argument, &flag, 3}, @@ -214,7 +221,7 @@ int main(int argc, char **argv) { {"no-content-length", no_argument, &flag, 10}, {nullptr, 0, nullptr, 0}}; int option_index = 0; - int c = getopt_long(argc, argv, "DVb:c:d:ehm:n:p:va:", long_options, + int c = getopt_long(argc, argv, "DVb:c:d:ehm:n:p:va:w:W:", long_options, &option_index); char *end; if (c == -1) { @@ -281,6 +288,26 @@ int main(int argc, char **argv) { std::cerr << "-p: Bad option value: " << optarg << std::endl; } break; + case 'w': + case 'W': { + char *endptr; + errno = 0; + auto n = strtoul(optarg, &endptr, 10); + if (errno != 0 || *endptr != '\0' || n >= 31) { + std::cerr << "-" << static_cast(c) + << ": specify the integer in the range [0, 30], inclusive" + << std::endl; + exit(EXIT_FAILURE); + } + + if (c == 'w') { + config.window_bits = n; + } else { + config.connection_window_bits = n; + } + + break; + } case '?': util::show_candidates(argv[optind - 1], long_options); exit(EXIT_FAILURE);