mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
http2: add new connectionWindowSize option
Signed-off-by: Tim Perry <pimterry@gmail.com> PR-URL: https://github.com/nodejs/node/pull/65619 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
This commit is contained in:
1 parent
8c9d14118b
commit
b12688c6e6
8 files changed
+218
-47
No files matched your search
+43
-1
@@ -669,10 +669,16 @@ added:
|
||||
|
||||
* `windowSize` {number}
|
||||
|
||||
Sets the local endpoint's window size.
|
||||
Sets the local endpoint's connection-level window size.
|
||||
The `windowSize` is the total window size to set, not
|
||||
the delta.
|
||||
|
||||
Increases take effect immediately, but decreases only apply as the window
|
||||
already advertised to the peer is consumed, since a window that has been
|
||||
advertised cannot be retracted. To use a window smaller than the default from
|
||||
the start of the connection, set the `connectionWindowSize` option when
|
||||
creating the server or client session instead.
|
||||
|
||||
```mjs
|
||||
import { createServer } from 'node:http2';
|
||||
|
||||
@@ -2844,6 +2850,9 @@ Throws `ERR_INVALID_ARG_TYPE` for invalid `settings` argument.
|
||||
<!-- YAML
|
||||
added: v8.4.0
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/65619
|
||||
description: Added the `connectionWindowSize` option.
|
||||
- version:
|
||||
- v25.7.0
|
||||
- v24.15.0
|
||||
@@ -2961,6 +2970,13 @@ changes:
|
||||
error that should tell the peer to not open any more streams, continuing
|
||||
to open streams is therefore regarded as a sign of a misbehaving peer.
|
||||
**Default:** `100`.
|
||||
* `connectionWindowSize` {number} Sets the initial flow control window for
|
||||
each session, in bytes. This is the total amount of data the remote peer
|
||||
may send across all streams before it has to wait for a `WINDOW_UPDATE`.
|
||||
The equivalent per-stream limit is `settings.initialWindowSize`. The
|
||||
minimum allowed value is `1` and the maximum is 2<sup>31</sup>-1. Values
|
||||
below 65535 will not take effect until the initial protocol-default
|
||||
window of 65535 has been used.
|
||||
* `settings` {HTTP/2 Settings Object} The initial settings to send to the
|
||||
remote peer upon connection.
|
||||
* `streamResetBurst` {number} and `streamResetRate` {number} Sets the rate
|
||||
@@ -3072,6 +3088,9 @@ server.listen(8000);
|
||||
<!-- YAML
|
||||
added: v8.4.0
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/65619
|
||||
description: Added the `connectionWindowSize` option.
|
||||
- version:
|
||||
- v25.7.0
|
||||
- v24.15.0
|
||||
@@ -3180,6 +3199,14 @@ changes:
|
||||
error that should tell the peer to not open any more streams, continuing
|
||||
to open streams is therefore regarded as a sign of a misbehaving peer.
|
||||
**Default:** `100`.
|
||||
* `connectionWindowSize` {number} Sets the initial flow control window for
|
||||
each session, in bytes. This is the total amount of data the remote peer
|
||||
may send across all streams before it has to wait for a `WINDOW_UPDATE`.
|
||||
The equivalent per-stream limit is `settings.initialWindowSize`. The
|
||||
minimum allowed value is `1` and the maximum is 2<sup>31</sup>-1. Values
|
||||
below 65535 will not take effect until the initial protocol-default
|
||||
window of 65535 has been used.
|
||||
**Default:** `33554432`.
|
||||
* `settings` {HTTP/2 Settings Object} The initial settings to send to the
|
||||
remote peer upon connection.
|
||||
* `streamResetBurst` {number} and `streamResetRate` {number} Sets the rate
|
||||
@@ -3276,6 +3303,9 @@ server.listen(8443);
|
||||
<!-- YAML
|
||||
added: v8.4.0
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/65619
|
||||
description: Added the `connectionWindowSize` option.
|
||||
- version:
|
||||
- v15.10.0
|
||||
- v14.16.0
|
||||
@@ -3363,6 +3393,14 @@ changes:
|
||||
* `protocol` {string} The protocol to connect with, if not set in the
|
||||
`authority`. Value may be either `'http:'` or `'https:'`. **Default:**
|
||||
`'https:'`
|
||||
* `connectionWindowSize` {number} Sets the initial flow control window for
|
||||
this session, in bytes. This is the total amount of data the remote peer
|
||||
may send across all streams before it has to wait for a `WINDOW_UPDATE`.
|
||||
The equivalent per-stream limit is `settings.initialWindowSize`. The
|
||||
minimum allowed value is `1` and the maximum is 2<sup>31</sup>-1. Values
|
||||
below 65535 will not take effect until the initial protocol-default
|
||||
window of 65535 has been used.
|
||||
**Default:** `33554432`.
|
||||
* `settings` {HTTP/2 Settings Object} The initial settings to send to the
|
||||
remote peer upon connection.
|
||||
* `remoteCustomSettings` {Array} The array of integer values determines the
|
||||
@@ -3795,6 +3833,9 @@ properties.
|
||||
* `initialWindowSize` {number} Specifies the _sender's_ initial window size in
|
||||
bytes for stream-level flow control. The minimum allowed value is 0. The
|
||||
maximum allowed value is 2<sup>32</sup>-1. **Default:** `4194304`.
|
||||
This is a per-stream limit; the window for the connection as a whole is
|
||||
configured separately with the `connectionWindowSize` option of
|
||||
[`http2.createServer()`][] or [`http2.connect()`][].
|
||||
* `maxFrameSize` {number} Specifies the size in bytes of the largest frame
|
||||
payload. The minimum allowed value is 16,384. The maximum allowed value is
|
||||
2<sup>24</sup>-1. **Default:** `16384`.
|
||||
@@ -5258,6 +5299,7 @@ you need to implement any fall-back behavior yourself.
|
||||
[`http.createServer()`]: http.md#httpcreateserveroptions-requestlistener
|
||||
[`http2.SecureServer`]: #class-http2secureserver
|
||||
[`http2.Server`]: #class-http2server
|
||||
[`http2.connect()`]: #http2connectauthority-options-listener
|
||||
[`http2.createSecureServer()`]: #http2createsecureserveroptions-onrequesthandler
|
||||
[`http2.createServer()`]: #http2createserveroptions-onrequesthandler
|
||||
[`http2stream.pushStream()`]: #http2streampushstreamheaders-options-callback
|
||||
|
||||
+28
-31
@@ -241,6 +241,8 @@ function debugSessionObj(session, message, ...args) {
|
||||
const kMaxFrameSize = (2 ** 24) - 1;
|
||||
const kMaxInt = (2 ** 32) - 1;
|
||||
const kMaxInitialWindowSize = (2 ** 31) - 1; // HTTP/2 spec maximum
|
||||
// A connection window of 0 stalls the connection
|
||||
const kMinConnectionWindowSize = 1;
|
||||
const kMaxStreams = (2 ** 32) - 1;
|
||||
const kMaxALTSVC = (2 ** 14) - 2;
|
||||
|
||||
@@ -3590,12 +3592,8 @@ function connectionListener(socket) {
|
||||
this.emit('session', session);
|
||||
}
|
||||
|
||||
function initializeOptions(options) {
|
||||
assertIsObject(options, 'options');
|
||||
options = { ...options };
|
||||
assertIsObject(options.settings, 'options.settings');
|
||||
options.settings = { ...options.settings };
|
||||
|
||||
// Validates the session options that apply to both client and server sessions
|
||||
function validateSessionOptions(options) {
|
||||
assertIsArray(options.remoteCustomSettings, 'options.remoteCustomSettings');
|
||||
if (options.remoteCustomSettings) {
|
||||
options.remoteCustomSettings = [ ...options.remoteCustomSettings ];
|
||||
@@ -3603,6 +3601,29 @@ function initializeOptions(options) {
|
||||
throw new ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS();
|
||||
}
|
||||
|
||||
if (options.strictSingleValueFields !== undefined) {
|
||||
validateBoolean(
|
||||
options.strictSingleValueFields,
|
||||
'options.strictSingleValueFields',
|
||||
);
|
||||
} else {
|
||||
options.strictSingleValueFields = true;
|
||||
}
|
||||
|
||||
if (options.connectionWindowSize !== undefined) {
|
||||
validateInt32(options.connectionWindowSize, 'options.connectionWindowSize',
|
||||
kMinConnectionWindowSize, kMaxInitialWindowSize);
|
||||
}
|
||||
}
|
||||
|
||||
function initializeOptions(options) {
|
||||
assertIsObject(options, 'options');
|
||||
options = { ...options };
|
||||
assertIsObject(options.settings, 'options.settings');
|
||||
options.settings = { ...options.settings };
|
||||
|
||||
validateSessionOptions(options);
|
||||
|
||||
if (options.maxSessionInvalidFrames !== undefined)
|
||||
validateUint32(options.maxSessionInvalidFrames, 'options.maxSessionInvalidFrames');
|
||||
|
||||
@@ -3619,16 +3640,6 @@ function initializeOptions(options) {
|
||||
// TODO(danbev): is this a good default value?
|
||||
options.unknownProtocolTimeout = 10000;
|
||||
|
||||
if (options.strictSingleValueFields !== undefined) {
|
||||
validateBoolean(
|
||||
options.strictSingleValueFields,
|
||||
'options.strictSingleValueFields',
|
||||
);
|
||||
} else {
|
||||
options.strictSingleValueFields = true;
|
||||
}
|
||||
|
||||
|
||||
// Initialize http1Options bag for HTTP/1 fallback when allowHTTP1 is true.
|
||||
// This bag is passed to storeHTTPOptions() to configure HTTP/1 server
|
||||
// behavior (timeouts, IncomingMessage/ServerResponse classes, etc.).
|
||||
@@ -3840,21 +3851,7 @@ function connect(authority, options, listener) {
|
||||
maxOriginSetSize = 128;
|
||||
}
|
||||
|
||||
assertIsArray(options.remoteCustomSettings, 'options.remoteCustomSettings');
|
||||
if (options.remoteCustomSettings) {
|
||||
options.remoteCustomSettings = [ ...options.remoteCustomSettings ];
|
||||
if (options.remoteCustomSettings.length > MAX_ADDITIONAL_SETTINGS)
|
||||
throw new ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS();
|
||||
}
|
||||
|
||||
if (options.strictSingleValueFields !== undefined) {
|
||||
validateBoolean(
|
||||
options.strictSingleValueFields,
|
||||
'options.strictSingleValueFields',
|
||||
);
|
||||
} else {
|
||||
options.strictSingleValueFields = true;
|
||||
}
|
||||
validateSessionOptions(options);
|
||||
|
||||
if (typeof authority === 'string')
|
||||
authority = new URL(authority);
|
||||
|
||||
@@ -233,7 +233,8 @@ const IDX_OPTIONS_MAX_SETTINGS = 9;
|
||||
const IDX_OPTIONS_STREAM_RESET_RATE = 10;
|
||||
const IDX_OPTIONS_STREAM_RESET_BURST = 11;
|
||||
const IDX_OPTIONS_STRICT_HTTP_FIELD_WHITESPACE_VALIDATION = 12;
|
||||
const IDX_OPTIONS_FLAGS = 13;
|
||||
const IDX_OPTIONS_CONNECTION_WINDOW_SIZE = 13;
|
||||
const IDX_OPTIONS_FLAGS = 14;
|
||||
|
||||
function updateOptionsBuffer(options) {
|
||||
let flags = 0;
|
||||
@@ -303,6 +304,11 @@ function updateOptionsBuffer(options) {
|
||||
optionsBuffer[IDX_OPTIONS_STRICT_HTTP_FIELD_WHITESPACE_VALIDATION] =
|
||||
options.strictFieldWhitespaceValidation === true ? 0 : 1;
|
||||
}
|
||||
if (typeof options.connectionWindowSize === 'number') {
|
||||
flags |= (1 << IDX_OPTIONS_CONNECTION_WINDOW_SIZE);
|
||||
optionsBuffer[IDX_OPTIONS_CONNECTION_WINDOW_SIZE] =
|
||||
options.connectionWindowSize;
|
||||
}
|
||||
|
||||
optionsBuffer[IDX_OPTIONS_FLAGS] = flags;
|
||||
}
|
||||
|
||||
+11
-8
@@ -217,6 +217,11 @@ Http2Options::Http2Options(Http2State* http2_state, SessionType type) {
|
||||
static_cast<size_t>(buffer[IDX_OPTIONS_MAX_SETTINGS]));
|
||||
}
|
||||
|
||||
if (flags & (1 << IDX_OPTIONS_CONNECTION_WINDOW_SIZE)) {
|
||||
set_connection_window_size(
|
||||
static_cast<int32_t>(buffer[IDX_OPTIONS_CONNECTION_WINDOW_SIZE]));
|
||||
}
|
||||
|
||||
if ((flags & (1 << IDX_OPTIONS_STREAM_RESET_BURST)) &&
|
||||
(flags & (1 << IDX_OPTIONS_STREAM_RESET_RATE))) {
|
||||
nghttp2_option_set_stream_reset_rate_limit(
|
||||
@@ -612,15 +617,13 @@ Http2Session::Http2Session(Http2State* http2_state,
|
||||
&alloc_info), 0);
|
||||
session_.reset(session);
|
||||
|
||||
// Increase the default local connection window to improve throughput
|
||||
// on high-latency connections. The default 64KB window limits throughput
|
||||
// to window_size / RTT. With a 32MB connection window, throughput is
|
||||
// significantly improved. See https://github.com/nodejs/node/issues/38426
|
||||
// The default connection window is larger than the 64KB required by the
|
||||
// spec to improve throughput on high-latency connections, where throughput
|
||||
// is limited to window_size / RTT. User settings have to be applied here
|
||||
// initially rather than updating later as windows cannot be shrunk after
|
||||
// they've been advertised.
|
||||
CHECK_EQ(nghttp2_session_set_local_window_size(
|
||||
session,
|
||||
NGHTTP2_FLAG_NONE,
|
||||
0,
|
||||
DEFAULT_SETTINGS_LOCAL_CONNECTION_WINDOW_SIZE),
|
||||
session, NGHTTP2_FLAG_NONE, 0, opts.connection_window_size()),
|
||||
0);
|
||||
|
||||
outgoing_storage_.reserve(1024);
|
||||
|
||||
+11
-4
@@ -39,6 +39,10 @@ constexpr size_t kDefaultMaxSettings = 10;
|
||||
// Default maximum total memory cap for Http2Session.
|
||||
constexpr uint64_t kDefaultMaxSessionMemory = 10000000;
|
||||
|
||||
// Default connection-level flow control window (32MB) to improve throughput
|
||||
// on high-latency connections. See https://github.com/nodejs/node/issues/38426
|
||||
constexpr int32_t kDefaultConnectionWindowSize = 33554432;
|
||||
|
||||
// These are the standard HTTP/2 defaults as specified by the RFC
|
||||
constexpr uint32_t DEFAULT_SETTINGS_HEADER_TABLE_SIZE = 4096;
|
||||
constexpr uint32_t DEFAULT_SETTINGS_ENABLE_PUSH = 1;
|
||||
@@ -51,10 +55,6 @@ constexpr uint32_t MAX_MAX_FRAME_SIZE = 16777215;
|
||||
constexpr uint32_t MIN_MAX_FRAME_SIZE = DEFAULT_SETTINGS_MAX_FRAME_SIZE;
|
||||
constexpr uint32_t MAX_INITIAL_WINDOW_SIZE = 2147483647;
|
||||
|
||||
// Default local connection window size (32MB) to improve throughput
|
||||
// on high-latency connections. See https://github.com/nodejs/node/issues/38426
|
||||
constexpr uint32_t DEFAULT_SETTINGS_LOCAL_CONNECTION_WINDOW_SIZE = 33554432;
|
||||
|
||||
// Stream is not going to have any DATA frames
|
||||
constexpr int STREAM_OPTION_EMPTY_PAYLOAD = 0x1;
|
||||
|
||||
@@ -245,9 +245,16 @@ class Http2Options {
|
||||
return max_session_memory_;
|
||||
}
|
||||
|
||||
void set_connection_window_size(int32_t size) {
|
||||
connection_window_size_ = size;
|
||||
}
|
||||
|
||||
int32_t connection_window_size() const { return connection_window_size_; }
|
||||
|
||||
private:
|
||||
Nghttp2OptionPointer options_;
|
||||
uint64_t max_session_memory_ = kDefaultMaxSessionMemory;
|
||||
int32_t connection_window_size_ = kDefaultConnectionWindowSize;
|
||||
uint32_t max_header_pairs_ = DEFAULT_MAX_HEADER_LIST_PAIRS;
|
||||
PaddingStrategy padding_strategy_ = PADDING_STRATEGY_NONE;
|
||||
size_t max_outstanding_pings_ = kDefaultMaxPings;
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace http2 {
|
||||
IDX_OPTIONS_STREAM_RESET_RATE,
|
||||
IDX_OPTIONS_STREAM_RESET_BURST,
|
||||
IDX_OPTIONS_STRICT_HTTP_FIELD_WHITESPACE_VALIDATION,
|
||||
IDX_OPTIONS_CONNECTION_WINDOW_SIZE,
|
||||
IDX_OPTIONS_FLAGS
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const http2 = require('http2');
|
||||
|
||||
const DEFAULT_WINDOW = 33554432;
|
||||
const SPEC_DEFAULT_WINDOW = 65535;
|
||||
|
||||
// Set client & server's windows (or default if undefined) and validate that
|
||||
// the both peers see the remote value as expected.
|
||||
function check(serverWindow, clientWindow) {
|
||||
const server = http2.createServer({ connectionWindowSize: serverWindow });
|
||||
serverWindow ??= DEFAULT_WINDOW;
|
||||
clientWindow ??= DEFAULT_WINDOW;
|
||||
|
||||
server.on('session', common.mustCall((session) => {
|
||||
assert.strictEqual(session.state.effectiveLocalWindowSize, serverWindow);
|
||||
}));
|
||||
|
||||
server.on('stream', common.mustCall((stream) => {
|
||||
assert.strictEqual(stream.session.state.remoteWindowSize, clientWindow);
|
||||
stream.respond({ ':status': 200 }, { endStream: true });
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const client = http2.connect(`http://localhost:${server.address().port}`,
|
||||
{ connectionWindowSize: clientWindow });
|
||||
|
||||
client.on('connect', common.mustCall(() => {
|
||||
assert.strictEqual(client.state.effectiveLocalWindowSize, clientWindow);
|
||||
}));
|
||||
|
||||
const req = client.request();
|
||||
req.resume();
|
||||
req.on('close', common.mustCall(() => {
|
||||
assert.strictEqual(client.state.remoteWindowSize, serverWindow);
|
||||
client.close();
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
check(undefined, undefined);
|
||||
|
||||
// The option shrinks the window below the default, which setLocalWindowSize()
|
||||
// cannot do once the connection has been established.
|
||||
check(SPEC_DEFAULT_WINDOW, SPEC_DEFAULT_WINDOW);
|
||||
|
||||
// Each end of the connection is configured independently.
|
||||
check(2 ** 20, 2 ** 21);
|
||||
|
||||
// A window below the peer's fixed initial 65535 is the only case that shrinks
|
||||
// the window nghttp2 has already accounted for, leaving a reduction to pay off
|
||||
// before any WINDOW_UPDATE can be sent again. Larger windows, including the
|
||||
// default, only ever grow it. Send more than the window to prove the
|
||||
// connection still resumes rather than stalling once the reduction is paid.
|
||||
{
|
||||
const windowSize = 16384;
|
||||
const payload = Buffer.alloc(2 ** 18, 'x');
|
||||
const server = http2.createServer({ connectionWindowSize: windowSize });
|
||||
|
||||
server.on('stream', common.mustCall((stream) => {
|
||||
let received = 0;
|
||||
stream.on('data', (chunk) => { received += chunk.length; });
|
||||
stream.on('end', common.mustCall(() => {
|
||||
assert.strictEqual(received, payload.length);
|
||||
stream.respond({ ':status': 200 }, { endStream: true });
|
||||
}));
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const client = http2.connect(`http://localhost:${server.address().port}`,
|
||||
{ connectionWindowSize: windowSize });
|
||||
const req = client.request({ ':method': 'POST', ':path': '/' });
|
||||
req.resume();
|
||||
req.end(payload);
|
||||
req.on('close', common.mustCall(() => {
|
||||
client.close();
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
for (const connectionWindowSize of [-1, 0, 2 ** 31, 1.5]) {
|
||||
assert.throws(() => http2.createServer({ connectionWindowSize }),
|
||||
{ code: 'ERR_OUT_OF_RANGE' });
|
||||
assert.throws(() => http2.createSecureServer({ connectionWindowSize }),
|
||||
{ code: 'ERR_OUT_OF_RANGE' });
|
||||
assert.throws(() => http2.connect('http://localhost:80', { connectionWindowSize }),
|
||||
{ code: 'ERR_OUT_OF_RANGE' });
|
||||
}
|
||||
|
||||
// Windows below the peer's fixed initial 65535 are permitted: they cannot
|
||||
// shrink that first burst, but they do throttle everything after it.
|
||||
for (const connectionWindowSize of [1, 1024, 65534]) {
|
||||
http2.createServer({ connectionWindowSize }).close();
|
||||
}
|
||||
|
||||
for (const connectionWindowSize of ['1024', null, {}]) {
|
||||
assert.throws(() => http2.createServer({ connectionWindowSize }),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' });
|
||||
assert.throws(() => http2.connect('http://localhost:80', { connectionWindowSize }),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' });
|
||||
}
|
||||
@@ -26,7 +26,8 @@ const IDX_OPTIONS_MAX_SETTINGS = 9;
|
||||
const IDX_OPTIONS_STREAM_RESET_RATE = 10;
|
||||
const IDX_OPTIONS_STREAM_RESET_BURST = 11;
|
||||
const IDX_OPTIONS_STRICT_HTTP_FIELD_WHITESPACE_VALIDATION = 12;
|
||||
const IDX_OPTIONS_FLAGS = 13;
|
||||
const IDX_OPTIONS_CONNECTION_WINDOW_SIZE = 13;
|
||||
const IDX_OPTIONS_FLAGS = 14;
|
||||
|
||||
{
|
||||
updateOptionsBuffer({
|
||||
@@ -42,7 +43,8 @@ const IDX_OPTIONS_FLAGS = 13;
|
||||
maxSettings: 10,
|
||||
streamResetRate: 11,
|
||||
streamResetBurst: 12,
|
||||
strictFieldWhitespaceValidation: false
|
||||
strictFieldWhitespaceValidation: false,
|
||||
connectionWindowSize: 13
|
||||
});
|
||||
|
||||
assert.strictEqual(optionsBuffer[IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE], 1);
|
||||
@@ -58,6 +60,7 @@ const IDX_OPTIONS_FLAGS = 13;
|
||||
assert.strictEqual(optionsBuffer[IDX_OPTIONS_STREAM_RESET_RATE], 11);
|
||||
assert.strictEqual(optionsBuffer[IDX_OPTIONS_STREAM_RESET_BURST], 12);
|
||||
assert.strictEqual(optionsBuffer[IDX_OPTIONS_STRICT_HTTP_FIELD_WHITESPACE_VALIDATION], 1);
|
||||
assert.strictEqual(optionsBuffer[IDX_OPTIONS_CONNECTION_WINDOW_SIZE], 13);
|
||||
|
||||
const flags = optionsBuffer[IDX_OPTIONS_FLAGS];
|
||||
|
||||
@@ -73,11 +76,13 @@ const IDX_OPTIONS_FLAGS = 13;
|
||||
assert.ok(flags & (1 << IDX_OPTIONS_STREAM_RESET_RATE));
|
||||
assert.ok(flags & (1 << IDX_OPTIONS_STREAM_RESET_BURST));
|
||||
assert.ok(flags & (1 << IDX_OPTIONS_STRICT_HTTP_FIELD_WHITESPACE_VALIDATION));
|
||||
assert.ok(flags & (1 << IDX_OPTIONS_CONNECTION_WINDOW_SIZE));
|
||||
}
|
||||
|
||||
{
|
||||
optionsBuffer[IDX_OPTIONS_MAX_SEND_HEADER_BLOCK_LENGTH] = 0;
|
||||
optionsBuffer[IDX_OPTIONS_MAX_OUTSTANDING_PINGS] = 0;
|
||||
optionsBuffer[IDX_OPTIONS_CONNECTION_WINDOW_SIZE] = 0;
|
||||
|
||||
updateOptionsBuffer({
|
||||
maxDeflateDynamicTableSize: 1,
|
||||
@@ -94,6 +99,7 @@ const IDX_OPTIONS_FLAGS = 13;
|
||||
assert.strictEqual(optionsBuffer[IDX_OPTIONS_MAX_HEADER_LIST_PAIRS], 6);
|
||||
assert.strictEqual(optionsBuffer[IDX_OPTIONS_MAX_SEND_HEADER_BLOCK_LENGTH], 0);
|
||||
assert.strictEqual(optionsBuffer[IDX_OPTIONS_MAX_OUTSTANDING_PINGS], 0);
|
||||
assert.strictEqual(optionsBuffer[IDX_OPTIONS_CONNECTION_WINDOW_SIZE], 0);
|
||||
|
||||
const flags = optionsBuffer[IDX_OPTIONS_FLAGS];
|
||||
|
||||
@@ -105,4 +111,5 @@ const IDX_OPTIONS_FLAGS = 13;
|
||||
|
||||
assert.ok(!(flags & (1 << IDX_OPTIONS_MAX_SEND_HEADER_BLOCK_LENGTH)));
|
||||
assert.ok(!(flags & (1 << IDX_OPTIONS_MAX_OUTSTANDING_PINGS)));
|
||||
assert.ok(!(flags & (1 << IDX_OPTIONS_CONNECTION_WINDOW_SIZE)));
|
||||
}
|
||||
Reference in new issue
Block a user