diff options
author | cjihrig <cjihrig@gmail.com> | 2019-06-26 10:15:52 -0400 |
---|---|---|
committer | cjihrig <cjihrig@gmail.com> | 2019-06-28 15:20:29 -0400 |
commit | f9632041dc744f1ac982f7345f1716449afec2ee (patch) | |
tree | 766beb2577d632dbd93377028c8287a580585d0c | |
parent | bf7edaa3c9075b58352a618f1a60785a481902f7 (diff) | |
download | android-node-v8-f9632041dc744f1ac982f7345f1716449afec2ee.tar.gz android-node-v8-f9632041dc744f1ac982f7345f1716449afec2ee.tar.bz2 android-node-v8-f9632041dc744f1ac982f7345f1716449afec2ee.zip |
http2: propagate session destroy code to streams
Currently, when an HTTP2 session is destroyed with a code, that
code is not propagated to the destroy() call of the session's
streams. This commit forwards any code used to destroy a session
to its corresponding streams.
PR-URL: https://github.com/nodejs/node/pull/28435
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
-rw-r--r-- | lib/internal/http2/core.js | 9 | ||||
-rw-r--r-- | test/parallel/test-http2-propagate-session-destroy-code.js | 54 |
2 files changed, 61 insertions, 2 deletions
diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 63f9da5564..fefb04d03d 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -942,6 +942,7 @@ class Http2Session extends EventEmitter { socket[kSession] = this; this[kState] = { + destroyCode: NGHTTP2_NO_ERROR, flags: SESSION_FLAGS_PENDING, goawayCode: null, goawayLastStreamID: null, @@ -1206,6 +1207,7 @@ class Http2Session extends EventEmitter { const state = this[kState]; state.flags |= SESSION_FLAGS_DESTROYED; + state.destroyCode = code; // Clear timeout and remove timeout listeners this.setTimeout(0); @@ -1937,10 +1939,13 @@ class Http2Stream extends Duplex { debug(`Http2Stream ${this[kID] || '<pending>'} [Http2Session ` + `${sessionName(session[kType])}]: destroying stream`); + const state = this[kState]; + const sessionCode = session[kState].goawayCode || + session[kState].destroyCode; const code = err != null ? - NGHTTP2_INTERNAL_ERROR : (state.rstCode || NGHTTP2_NO_ERROR); - + sessionCode || NGHTTP2_INTERNAL_ERROR : + state.rstCode || sessionCode; const hasHandle = handle !== undefined; if (!this.closed) diff --git a/test/parallel/test-http2-propagate-session-destroy-code.js b/test/parallel/test-http2-propagate-session-destroy-code.js new file mode 100644 index 0000000000..a23bcfd07c --- /dev/null +++ b/test/parallel/test-http2-propagate-session-destroy-code.js @@ -0,0 +1,54 @@ +'use strict'; +const common = require('../common'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const http2 = require('http2'); +const server = http2.createServer(); +const errRegEx = /Session closed with error code 7/; +const destroyCode = http2.constants.NGHTTP2_REFUSED_STREAM; + +server.on('error', common.mustNotCall()); + +server.on('session', (session) => { + session.on('close', common.mustCall()); + session.on('error', common.mustCall((err) => { + assert(errRegEx.test(err)); + assert.strictEqual(session.closed, false); + assert.strictEqual(session.destroyed, true); + })); + + session.on('stream', common.mustCall((stream) => { + stream.on('error', common.mustCall((err) => { + assert.strictEqual(session.closed, false); + assert.strictEqual(session.destroyed, true); + assert(errRegEx.test(err)); + assert.strictEqual(stream.rstCode, destroyCode); + })); + + session.destroy(destroyCode); + })); +}); + +server.listen(0, common.mustCall(() => { + const session = http2.connect(`http://localhost:${server.address().port}`); + + session.on('error', common.mustCall((err) => { + assert(errRegEx.test(err)); + assert.strictEqual(session.closed, false); + assert.strictEqual(session.destroyed, true); + })); + + const stream = session.request({ [http2.constants.HTTP2_HEADER_PATH]: '/' }); + + stream.on('error', common.mustCall((err) => { + assert(errRegEx.test(err)); + assert.strictEqual(stream.rstCode, destroyCode); + })); + + stream.on('close', common.mustCall(() => { + server.close(); + })); +})); |