summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2019-06-26 10:15:52 -0400
committercjihrig <cjihrig@gmail.com>2019-06-28 15:20:29 -0400
commitf9632041dc744f1ac982f7345f1716449afec2ee (patch)
tree766beb2577d632dbd93377028c8287a580585d0c
parentbf7edaa3c9075b58352a618f1a60785a481902f7 (diff)
downloadandroid-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.js9
-rw-r--r--test/parallel/test-http2-propagate-session-destroy-code.js54
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();
+ }));
+}));