|
|
@ -289,11 +289,9 @@ function onSessionRead(nread, buf, handle) { |
|
|
|
_unrefActive(this); // Reset the session timeout timer
|
|
|
|
_unrefActive(stream); // Reset the stream timeout timer
|
|
|
|
|
|
|
|
if (nread >= 0) { |
|
|
|
if (nread >= 0 && !stream.destroyed) { |
|
|
|
if (!stream.push(buf)) { |
|
|
|
assert(this.streamReadStop(id) === undefined, |
|
|
|
`HTTP/2 Stream ${id} does not exist. Please report this as ' +
|
|
|
|
'a bug in Node.js`);
|
|
|
|
this.streamReadStop(id); |
|
|
|
state.reading = false; |
|
|
|
} |
|
|
|
} else { |
|
|
@ -1475,44 +1473,48 @@ class Http2Stream extends Duplex { |
|
|
|
this.once('ready', this._destroy.bind(this, err, callback)); |
|
|
|
return; |
|
|
|
} |
|
|
|
debug(`[${sessionName(session[kType])}] destroying stream ${this[kID]}`); |
|
|
|
|
|
|
|
// Submit RST-STREAM frame if one hasn't been sent already and the
|
|
|
|
// stream hasn't closed normally...
|
|
|
|
if (!this[kState].rst) { |
|
|
|
const code = |
|
|
|
err instanceof Error ? |
|
|
|
NGHTTP2_INTERNAL_ERROR : NGHTTP2_NO_ERROR; |
|
|
|
this[kSession].rstStream(this, code); |
|
|
|
} |
|
|
|
|
|
|
|
process.nextTick(() => { |
|
|
|
debug(`[${sessionName(session[kType])}] destroying stream ${this[kID]}`); |
|
|
|
|
|
|
|
// Submit RST-STREAM frame if one hasn't been sent already and the
|
|
|
|
// stream hasn't closed normally...
|
|
|
|
if (!this[kState].rst && !session.destroyed) { |
|
|
|
const code = |
|
|
|
err instanceof Error ? |
|
|
|
NGHTTP2_INTERNAL_ERROR : NGHTTP2_NO_ERROR; |
|
|
|
this[kSession].rstStream(this, code); |
|
|
|
} |
|
|
|
|
|
|
|
// Remove the close handler on the session
|
|
|
|
session.removeListener('close', this[kState].closeHandler); |
|
|
|
// Remove the close handler on the session
|
|
|
|
session.removeListener('close', this[kState].closeHandler); |
|
|
|
|
|
|
|
// Unenroll the timer
|
|
|
|
unenroll(this); |
|
|
|
// Unenroll the timer
|
|
|
|
unenroll(this); |
|
|
|
|
|
|
|
setImmediate(finishStreamDestroy.bind(this, handle)); |
|
|
|
session[kState].streams.delete(this[kID]); |
|
|
|
delete this[kSession]; |
|
|
|
setImmediate(finishStreamDestroy.bind(this, handle)); |
|
|
|
|
|
|
|
// All done
|
|
|
|
const rst = this[kState].rst; |
|
|
|
const code = rst ? this[kState].rstCode : NGHTTP2_NO_ERROR; |
|
|
|
if (code !== NGHTTP2_NO_ERROR) { |
|
|
|
const err = new errors.Error('ERR_HTTP2_STREAM_ERROR', code); |
|
|
|
process.nextTick(() => this.emit('error', err)); |
|
|
|
} |
|
|
|
process.nextTick(emit.bind(this, 'streamClosed', code)); |
|
|
|
debug(`[${sessionName(session[kType])}] stream ${this[kID]} destroyed`); |
|
|
|
callback(err); |
|
|
|
// All done
|
|
|
|
const rst = this[kState].rst; |
|
|
|
const code = rst ? this[kState].rstCode : NGHTTP2_NO_ERROR; |
|
|
|
if (code !== NGHTTP2_NO_ERROR) { |
|
|
|
const err = new errors.Error('ERR_HTTP2_STREAM_ERROR', code); |
|
|
|
process.nextTick(() => this.emit('error', err)); |
|
|
|
} |
|
|
|
process.nextTick(emit.bind(this, 'streamClosed', code)); |
|
|
|
debug(`[${sessionName(session[kType])}] stream ${this[kID]} destroyed`); |
|
|
|
callback(err); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function finishStreamDestroy(handle) { |
|
|
|
const id = this[kID]; |
|
|
|
const session = this[kSession]; |
|
|
|
session[kState].streams.delete(id); |
|
|
|
delete this[kSession]; |
|
|
|
if (handle !== undefined) |
|
|
|
handle.destroyStream(this[kID]); |
|
|
|
handle.destroyStream(id); |
|
|
|
this.emit('destroy'); |
|
|
|
} |
|
|
|
|
|
|
|
function processHeaders(headers) { |
|
|
|