diff --git a/Cargo.lock b/Cargo.lock index 2a64fa4d..35679f1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -252,12 +252,9 @@ checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "log" -version = "0.4.17" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" @@ -391,7 +388,7 @@ dependencies = [ [[package]] name = "quic" -version = "1.3.9" +version = "1.3.10" dependencies = [ "boring", "napi", diff --git a/Cargo.toml b/Cargo.toml index 499e61b7..f288d5f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "quic" -version = "1.3.9" +version = "1.3.10" authors = ["Roger Qiu "] license-file = "LICENSE" edition = "2021" diff --git a/package-lock.json b/package-lock.json index 2858e26a..052ba4bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@matrixai/quic", - "version": "1.3.9", + "version": "1.3.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@matrixai/quic", - "version": "1.3.9", + "version": "1.3.10", "license": "Apache-2.0", "dependencies": { "@matrixai/async-cancellable": "^1.1.1", @@ -57,11 +57,11 @@ "typescript": "^5.1.6" }, "optionalDependencies": { - "@matrixai/quic-darwin-arm64": "1.3.9", - "@matrixai/quic-darwin-universal": "1.3.9", - "@matrixai/quic-darwin-x64": "1.3.9", - "@matrixai/quic-linux-x64": "1.3.9", - "@matrixai/quic-win32-x64": "1.3.9" + "@matrixai/quic-darwin-arm64": "1.3.10", + "@matrixai/quic-darwin-universal": "1.3.10", + "@matrixai/quic-darwin-x64": "1.3.10", + "@matrixai/quic-linux-x64": "1.3.10", + "@matrixai/quic-win32-x64": "1.3.10" } }, "node_modules/@aashutoshrathi/word-wrap": { diff --git a/package.json b/package.json index 82009cd4..17273598 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@matrixai/quic", - "version": "1.3.9", + "version": "1.3.10", "author": "Matrix AI", "contributors": [ { @@ -48,11 +48,11 @@ "ip-num": "^1.5.0" }, "optionalDependencies": { - "@matrixai/quic-darwin-arm64": "1.3.9", - "@matrixai/quic-darwin-universal": "1.3.9", - "@matrixai/quic-darwin-x64": "1.3.9", - "@matrixai/quic-linux-x64": "1.3.9", - "@matrixai/quic-win32-x64": "1.3.9" + "@matrixai/quic-darwin-arm64": "1.3.10", + "@matrixai/quic-darwin-universal": "1.3.10", + "@matrixai/quic-darwin-x64": "1.3.10", + "@matrixai/quic-linux-x64": "1.3.10", + "@matrixai/quic-win32-x64": "1.3.10" }, "devDependencies": { "@fast-check/jest": "^1.1.0", diff --git a/src/QUICConnection.ts b/src/QUICConnection.ts index 0b2c5a7a..7e1008fe 100644 --- a/src/QUICConnection.ts +++ b/src/QUICConnection.ts @@ -1029,30 +1029,47 @@ class QUICConnection { ); continue; } - - quicStream = QUICStream.createQUICStream({ - initiated: 'peer', - streamId, - config: this.config, - connection: this, - codeToReason: this.codeToReason, - reasonToCode: this.reasonToCode, - logger: this.logger.getChild(`${QUICStream.name} ${streamId}`), - }); - this.streamMap.set(quicStream.streamId, quicStream); - quicStream.addEventListener( - events.EventQUICStreamSend.name, - this.handleEventQUICStreamSend, - ); - quicStream.addEventListener( - events.EventQUICStreamDestroyed.name, - this.handleEventQUICStreamDestroyed, - { once: true }, - ); - quicStream.addEventListener(EventAll.name, this.handleEventQUICStream); - this.dispatchEvent( - new events.EventQUICConnectionStream({ detail: quicStream }), - ); + try { + this.conn.streamSend(streamId, Buffer.alloc(0), false); + utils.never( + 'We never expect the stream to be writable if it was created during the writable iterator', + ); + } catch (e) { + // If we got `FinalSize` during the writable iterator then we cleaned up an errant stream + if (e.message === 'FinalSize') continue; + if (utils.isStreamStopped(e) !== false) { + // In this case it was a stream that was created but errored out. We want to create a new stream for this one case. + quicStream = QUICStream.createQUICStream({ + initiated: 'peer', + streamId, + config: this.config, + connection: this, + codeToReason: this.codeToReason, + reasonToCode: this.reasonToCode, + logger: this.logger.getChild(`${QUICStream.name} ${streamId}`), + }); + this.streamMap.set(quicStream.streamId, quicStream); + quicStream.addEventListener( + events.EventQUICStreamSend.name, + this.handleEventQUICStreamSend, + ); + quicStream.addEventListener( + events.EventQUICStreamDestroyed.name, + this.handleEventQUICStreamDestroyed, + { once: true }, + ); + quicStream.addEventListener( + EventAll.name, + this.handleEventQUICStream, + ); + this.dispatchEvent( + new events.EventQUICConnectionStream({ detail: quicStream }), + ); + quicStream.write(); + continue; + } + utils.never(`Expected to throw "FinalSize", got ${e.message}`); + } } quicStream.write(); } diff --git a/src/errors.ts b/src/errors.ts index 6f839fc6..838e1506 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -6,6 +6,10 @@ class ErrorQUIC extends AbstractError { static description = 'QUIC error'; } +class ErrorQUICUndefinedBehaviour extends AbstractError { + static description = 'You should never see this error'; +} + class ErrorQUICHostInvalid extends AbstractError { static description = 'Host provided was not valid'; } @@ -293,6 +297,7 @@ class ErrorQUICStreamLimit extends ErrorQUICStream { export { ErrorQUIC, + ErrorQUICUndefinedBehaviour, ErrorQUICHostInvalid, ErrorQUICPortInvalid, ErrorQUICConfig, diff --git a/src/utils.ts b/src/utils.ts index 34404379..5b492a1a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -18,6 +18,10 @@ import * as errors from './errors'; const textEncoder = new TextEncoder(); const textDecoder = new TextDecoder('utf-8'); +function never(message: string): never { + throw new errors.ErrorQUICUndefinedBehaviour(message); +} + /** * Used to yield to the event loop to allow other micro tasks to process */ @@ -572,6 +576,7 @@ function setMaxListeners( export { textEncoder, textDecoder, + never, yieldMicro, promisify, promise, diff --git a/tests/QUICStream.test.ts b/tests/QUICStream.test.ts index 1c3f151e..313a8bbf 100644 --- a/tests/QUICStream.test.ts +++ b/tests/QUICStream.test.ts @@ -11,7 +11,7 @@ import * as testsUtils from './utils'; import { generateTLSConfig, sleep } from './utils'; describe(QUICStream.name, () => { - const logger = new Logger(`${QUICStream.name} Test`, LogLevel.WARN, [ + const logger = new Logger(`${QUICStream.name} Test`, LogLevel.INFO, [ new StreamHandler( formatting.format`${formatting.level}:${formatting.keys}:${formatting.msg}`, ),