| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1137,6 +1137,11 @@ reached. | |||
| 1137 | 1137 | An attempt was made to initiate a new push stream from within a push stream. | |
| 1138 | 1138 | Nested push streams are not permitted. | |
| 1139 | 1139 | ||
| 1140 | + <a id="ERR_HTTP2_NO_MEM"></a> | ||
| 1141 | + ### `ERR_HTTP2_NO_MEM` | ||
| 1142 | + | ||
| 1143 | + Out of memory when using the `http2session.setLocalWindowSize(windowSize)` API. | ||
| 1144 | + | ||
| 1140 | 1145 | <a id="ERR_HTTP2_NO_SOCKET_MANIPULATION"></a> | |
| 1141 | 1146 | ### `ERR_HTTP2_NO_SOCKET_MANIPULATION` | |
| 1142 | 1147 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -518,6 +518,29 @@ added: v8.4.0 | |||
| 518 | 518 | A prototype-less object describing the current remote settings of this | |
| 519 | 519 | `Http2Session`. The remote settings are set by the *connected* HTTP/2 peer. | |
| 520 | 520 | ||
| 521 | + #### `http2session.setLocalWindowSize(windowSize)` | ||
| 522 | + <!-- YAML | ||
| 523 | + added: REPLACEME | ||
| 524 | + --> | ||
| 525 | + | ||
| 526 | + * `windowSize` {number} | ||
| 527 | + | ||
| 528 | + Sets the local endpoint's window size. | ||
| 529 | + The `windowSize` is the total window size to set, not | ||
| 530 | + the delta. | ||
| 531 | + | ||
| 532 | + ```js | ||
| 533 | + const http2 = require('http2'); | ||
| 534 | + | ||
| 535 | + const server = http2.createServer(); | ||
| 536 | + const expectedWindowSize = 2 ** 20; | ||
| 537 | + server.on('connect', (session) => { | ||
| 538 | + | ||
| 539 | + // Set local window size to be 2 ** 20 | ||
| 540 | + session.setLocalWindowSize(expectedWindowSize); | ||
| 541 | + }); | ||
| 542 | + ``` | ||
| 543 | + | ||
| 521 | 544 | #### `http2session.setTimeout(msecs, callback)` | |
| 522 | 545 | <!-- YAML | |
| 523 | 546 | added: v8.4.0 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -917,6 +917,7 @@ E('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK', | |||
| 917 | 917 | 'Maximum number of pending settings acknowledgements', Error); | |
| 918 | 918 | E('ERR_HTTP2_NESTED_PUSH', | |
| 919 | 919 | 'A push stream cannot initiate another push stream.', Error); | |
| 920 | + E('ERR_HTTP2_NO_MEM', 'Out of memory', Error); | ||
| 920 | 921 | E('ERR_HTTP2_NO_SOCKET_MANIPULATION', | |
| 921 | 922 | 'HTTP/2 sockets should not be directly manipulated (e.g. read and written)', | |
| 922 | 923 | Error); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -71,6 +71,7 @@ const { | |||
| 71 | 71 | ERR_HTTP2_INVALID_STREAM, | |
| 72 | 72 | ERR_HTTP2_MAX_PENDING_SETTINGS_ACK, | |
| 73 | 73 | ERR_HTTP2_NESTED_PUSH, | |
| 74 | + ERR_HTTP2_NO_MEM, | ||
| 74 | 75 | ERR_HTTP2_NO_SOCKET_MANIPULATION, | |
| 75 | 76 | ERR_HTTP2_ORIGIN_LENGTH, | |
| 76 | 77 | ERR_HTTP2_OUT_OF_STREAMS, | |
@@ -104,6 +105,7 @@ const { | |||
| 104 | 105 | } = require('internal/errors'); | |
| 105 | 106 | const { | |
| 106 | 107 | isUint32, | |
| 108 | + validateInt32, | ||
| 107 | 109 | validateNumber, | |
| 108 | 110 | validateString, | |
| 109 | 111 | validateUint32, | |
@@ -252,6 +254,7 @@ const { | |||
| 252 | 254 | NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE, | |
| 253 | 255 | NGHTTP2_ERR_INVALID_ARGUMENT, | |
| 254 | 256 | NGHTTP2_ERR_STREAM_CLOSED, | |
| 257 | + NGHTTP2_ERR_NOMEM, | ||
| 255 | 258 | ||
| 256 | 259 | HTTP2_HEADER_AUTHORITY, | |
| 257 | 260 | HTTP2_HEADER_DATE, | |
@@ -1290,6 +1293,21 @@ class Http2Session extends EventEmitter { | |||
| 1290 | 1293 | this[kHandle].setNextStreamID(id); | |
| 1291 | 1294 | } | |
| 1292 | 1295 | ||
| 1296 | + // Sets the local window size (local endpoints's window size) | ||
| 1297 | + // Returns 0 if sucess or throw an exception if NGHTTP2_ERR_NOMEM | ||
| 1298 | + // if the window allocation fails | ||
| 1299 | + setLocalWindowSize(windowSize) { | ||
| 1300 | + if (this.destroyed) | ||
| 1301 | + throw new ERR_HTTP2_INVALID_SESSION(); | ||
| 1302 | + | ||
| 1303 | + validateInt32(windowSize, 'windowSize', 0); | ||
| 1304 | + const ret = this[kHandle].setLocalWindowSize(windowSize); | ||
| 1305 | + | ||
| 1306 | + if (ret === NGHTTP2_ERR_NOMEM) { | ||
| 1307 | + this.destroy(new ERR_HTTP2_NO_MEM()); | ||
| 1308 | + } | ||
| 1309 | + } | ||
| 1310 | + | ||
| 1293 | 1311 | // If ping is called while we are still connecting, or after close() has | |
| 1294 | 1312 | // been called, the ping callback will be invoked immediately with a ping | |
| 1295 | 1313 | // cancelled error and a duration of 0.0. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2433,6 +2433,25 @@ void Http2Session::SetNextStreamID(const FunctionCallbackInfo<Value>& args) { | |||
| 2433 | 2433 | Debug(session, "set next stream id to %d", id); | |
| 2434 | 2434 | } | |
| 2435 | 2435 | ||
| 2436 | + // Set local window size (local endpoints's window size) to the given | ||
| 2437 | + // window_size for the stream denoted by 0. | ||
| 2438 | + // This function returns 0 if it succeeds, or one of a negative codes | ||
| 2439 | + void Http2Session::SetLocalWindowSize( | ||
| 2440 | + const FunctionCallbackInfo<Value>& args) { | ||
| 2441 | + Environment* env = Environment::GetCurrent(args); | ||
| 2442 | + Http2Session* session; | ||
| 2443 | + ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder()); | ||
| 2444 | + | ||
| 2445 | + int32_t window_size = args[0]->Int32Value(env->context()).ToChecked(); | ||
| 2446 | + | ||
| 2447 | + int result = nghttp2_session_set_local_window_size( | ||
| 2448 | + session->session(), NGHTTP2_FLAG_NONE, 0, window_size); | ||
| 2449 | + | ||
| 2450 | + args.GetReturnValue().Set(result); | ||
| 2451 | + | ||
| 2452 | + Debug(session, "set local window size to %d", window_size); | ||
| 2453 | + } | ||
| 2454 | + | ||
| 2436 | 2455 | // A TypedArray instance is shared between C++ and JS land to contain the | |
| 2437 | 2456 | // SETTINGS (either remote or local). RefreshSettings updates the current | |
| 2438 | 2457 | // values established for each of the settings so those can be read in JS land. | |
@@ -3105,6 +3124,8 @@ void Initialize(Local<Object> target, | |||
| 3105 | 3124 | env->SetProtoMethod(session, "request", Http2Session::Request); | |
| 3106 | 3125 | env->SetProtoMethod(session, "setNextStreamID", | |
| 3107 | 3126 | Http2Session::SetNextStreamID); | |
| 3127 | + env->SetProtoMethod(session, "setLocalWindowSize", | ||
| 3128 | + Http2Session::SetLocalWindowSize); | ||
| 3108 | 3129 | env->SetProtoMethod(session, "updateChunksSent", | |
| 3109 | 3130 | Http2Session::UpdateChunksSent); | |
| 3110 | 3131 | env->SetProtoMethod(session, "refreshState", Http2Session::RefreshState); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -700,6 +700,8 @@ class Http2Session : public AsyncWrap, | |||
| 700 | 700 | static void Settings(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 701 | 701 | static void Request(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 702 | 702 | static void SetNextStreamID(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 703 | + static void SetLocalWindowSize( | ||
| 704 | + const v8::FunctionCallbackInfo<v8::Value>& args); | ||
| 703 | 705 | static void Goaway(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 704 | 706 | static void UpdateChunksSent(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 705 | 707 | static void RefreshState(const v8::FunctionCallbackInfo<v8::Value>& args); | |
@@ -1116,6 +1118,7 @@ class Origins { | |||
| 1116 | 1118 | V(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE) \ | |
| 1117 | 1119 | V(NGHTTP2_ERR_INVALID_ARGUMENT) \ | |
| 1118 | 1120 | V(NGHTTP2_ERR_STREAM_CLOSED) \ | |
| 1121 | + V(NGHTTP2_ERR_NOMEM) \ | ||
| 1119 | 1122 | V(STREAM_OPTION_EMPTY_PAYLOAD) \ | |
| 1120 | 1123 | V(STREAM_OPTION_GET_TRAILERS) | |
| 1121 | 1124 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -78,6 +78,7 @@ const Countdown = require('../common/countdown'); | |||
| 78 | 78 | }; | |
| 79 | 79 | ||
| 80 | 80 | assert.throws(() => client.setNextStreamID(), sessionError); | |
| 81 | + assert.throws(() => client.setLocalWindowSize(), sessionError); | ||
| 81 | 82 | assert.throws(() => client.ping(), sessionError); | |
| 82 | 83 | assert.throws(() => client.settings({}), sessionError); | |
| 83 | 84 | assert.throws(() => client.goaway(), sessionError); | |
@@ -88,6 +89,7 @@ const Countdown = require('../common/countdown'); | |||
| 88 | 89 | // so that state.destroyed is set to true | |
| 89 | 90 | setImmediate(() => { | |
| 90 | 91 | assert.throws(() => client.setNextStreamID(), sessionError); | |
| 92 | + assert.throws(() => client.setLocalWindowSize(), sessionError); | ||
| 91 | 93 | assert.throws(() => client.ping(), sessionError); | |
| 92 | 94 | assert.throws(() => client.settings({}), sessionError); | |
| 93 | 95 | assert.throws(() => client.goaway(), sessionError); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,121 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const common = require('../common'); | ||
| 4 | + if (!common.hasCrypto) | ||
| 5 | + common.skip('missing crypto'); | ||
| 6 | + | ||
| 7 | + const assert = require('assert'); | ||
| 8 | + const http2 = require('http2'); | ||
| 9 | + | ||
| 10 | + { | ||
| 11 | + const server = http2.createServer(); | ||
| 12 | + server.on('stream', common.mustNotCall((stream) => { | ||
| 13 | + stream.respond(); | ||
| 14 | + stream.end('ok'); | ||
| 15 | + })); | ||
| 16 | + | ||
| 17 | + const types = { | ||
| 18 | + boolean: true, | ||
| 19 | + function: () => {}, | ||
| 20 | + number: 1, | ||
| 21 | + object: {}, | ||
| 22 | + array: [], | ||
| 23 | + null: null, | ||
| 24 | + }; | ||
| 25 | + | ||
| 26 | + server.listen(0, common.mustCall(() => { | ||
| 27 | + const client = http2.connect(`http://localhost:${server.address().port}`); | ||
| 28 | + | ||
| 29 | + client.on('connect', common.mustCall(() => { | ||
| 30 | + const outOfRangeNum = 2 ** 32; | ||
| 31 | + assert.throws( | ||
| 32 | + () => client.setLocalWindowSize(outOfRangeNum), | ||
| 33 | + { | ||
| 34 | + name: 'RangeError', | ||
| 35 | + code: 'ERR_OUT_OF_RANGE', | ||
| 36 | + message: 'The value of "windowSize" is out of range.' + | ||
| 37 | + ' It must be >= 0 && <= 2147483647. Received ' + outOfRangeNum | ||
| 38 | + } | ||
| 39 | + ); | ||
| 40 | + | ||
| 41 | + // Throw if something other than number is passed to setLocalWindowSize | ||
| 42 | + Object.entries(types).forEach(([type, value]) => { | ||
| 43 | + if (type === 'number') { | ||
| 44 | + return; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + assert.throws( | ||
| 48 | + () => client.setLocalWindowSize(value), | ||
| 49 | + { | ||
| 50 | + name: 'TypeError', | ||
| 51 | + code: 'ERR_INVALID_ARG_TYPE', | ||
| 52 | + message: 'The "windowSize" argument must be of type number.' + | ||
| 53 | + common.invalidArgTypeHelper(value) | ||
| 54 | + } | ||
| 55 | + ); | ||
| 56 | + }); | ||
| 57 | + | ||
| 58 | + server.close(); | ||
| 59 | + client.close(); | ||
| 60 | + })); | ||
| 61 | + })); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + { | ||
| 65 | + const server = http2.createServer(); | ||
| 66 | + server.on('stream', common.mustNotCall((stream) => { | ||
| 67 | + stream.respond(); | ||
| 68 | + stream.end('ok'); | ||
| 69 | + })); | ||
| 70 | + | ||
| 71 | + server.listen(0, common.mustCall(() => { | ||
| 72 | + const client = http2.connect(`http://localhost:${server.address().port}`); | ||
| 73 | + | ||
| 74 | + client.on('connect', common.mustCall(() => { | ||
| 75 | + const windowSize = 2 ** 20; | ||
| 76 | + const defaultSetting = http2.getDefaultSettings(); | ||
| 77 | + client.setLocalWindowSize(windowSize); | ||
| 78 | + | ||
| 79 | + assert.strictEqual(client.state.effectiveLocalWindowSize, windowSize); | ||
| 80 | + assert.strictEqual(client.state.localWindowSize, windowSize); | ||
| 81 | + assert.strictEqual( | ||
| 82 | + client.state.remoteWindowSize, | ||
| 83 | + defaultSetting.initialWindowSize | ||
| 84 | + ); | ||
| 85 | + | ||
| 86 | + server.close(); | ||
| 87 | + client.close(); | ||
| 88 | + })); | ||
| 89 | + })); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + { | ||
| 93 | + const server = http2.createServer(); | ||
| 94 | + server.on('stream', common.mustNotCall((stream) => { | ||
| 95 | + stream.respond(); | ||
| 96 | + stream.end('ok'); | ||
| 97 | + })); | ||
| 98 | + | ||
| 99 | + server.listen(0, common.mustCall(() => { | ||
| 100 | + const client = http2.connect(`http://localhost:${server.address().port}`); | ||
| 101 | + | ||
| 102 | + client.on('connect', common.mustCall(() => { | ||
| 103 | + const windowSize = 20; | ||
| 104 | + const defaultSetting = http2.getDefaultSettings(); | ||
| 105 | + client.setLocalWindowSize(windowSize); | ||
| 106 | + | ||
| 107 | + assert.strictEqual(client.state.effectiveLocalWindowSize, windowSize); | ||
| 108 | + assert.strictEqual( | ||
| 109 | + client.state.localWindowSize, | ||
| 110 | + defaultSetting.initialWindowSize | ||
| 111 | + ); | ||
| 112 | + assert.strictEqual( | ||
| 113 | + client.state.remoteWindowSize, | ||
| 114 | + defaultSetting.initialWindowSize | ||
| 115 | + ); | ||
| 116 | + | ||
| 117 | + server.close(); | ||
| 118 | + client.close(); | ||
| 119 | + })); | ||
| 120 | + })); | ||
| 121 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,37 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const common = require('../common'); | ||
| 4 | + if (!common.hasCrypto) | ||
| 5 | + common.skip('missing crypto'); | ||
| 6 | + | ||
| 7 | + const assert = require('assert'); | ||
| 8 | + const http2 = require('http2'); | ||
| 9 | + | ||
| 10 | + const server = http2.createServer(); | ||
| 11 | + server.on('stream', common.mustCall((stream) => { | ||
| 12 | + stream.respond(); | ||
| 13 | + stream.end('ok'); | ||
| 14 | + })); | ||
| 15 | + server.on('session', common.mustCall((session) => { | ||
| 16 | + const windowSize = 2 ** 20; | ||
| 17 | + const defaultSetting = http2.getDefaultSettings(); | ||
| 18 | + session.setLocalWindowSize(windowSize); | ||
| 19 | + | ||
| 20 | + assert.strictEqual(session.state.effectiveLocalWindowSize, windowSize); | ||
| 21 | + assert.strictEqual(session.state.localWindowSize, windowSize); | ||
| 22 | + assert.strictEqual( | ||
| 23 | + session.state.remoteWindowSize, | ||
| 24 | + defaultSetting.initialWindowSize | ||
| 25 | + ); | ||
| 26 | + })); | ||
| 27 | + | ||
| 28 | + server.listen(0, common.mustCall(() => { | ||
| 29 | + const client = http2.connect(`http://localhost:${server.address().port}`); | ||
| 30 | + | ||
| 31 | + const req = client.request(); | ||
| 32 | + req.resume(); | ||
| 33 | + req.on('close', common.mustCall(() => { | ||
| 34 | + client.close(); | ||
| 35 | + server.close(); | ||
| 36 | + })); | ||
| 37 | + })); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments