From 43d5192f31e7a7907db44c11afef3195b7797508 Mon Sep 17 00:00:00 2001 From: Ar Nazeh Date: Wed, 31 Aug 2022 12:49:19 +0200 Subject: [PATCH] Deduplicate muxer for a given same stream. (#5) * docs: add documentation for iterating over channels * fix: deduplicate protomux instances for the same stream creating multiple channels on multiple muxers for the same stream closes channels accidently see [here](https://gist.github.com/Nazeh/a3f1d24b597913303afcb6c568f4b042) * fix: deduplicate muxers on the same stream opening multiple channels on multiple muxers causes channels to either close or reset, see [here](https://gist.github.com/Nazeh/a3f1d24b597913303afcb6c568f4b042) * use userData --- index.js | 3 +++ test.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/index.js b/index.js index a0424fc..0cbfdc7 100644 --- a/index.js +++ b/index.js @@ -245,6 +245,8 @@ class Channel { module.exports = class Protomux { constructor (stream, { alloc } = {}) { + if (stream.userData === null) stream.userData = this + this.isProtomux = true this.stream = stream this.corked = 0 @@ -271,6 +273,7 @@ module.exports = class Protomux { } static from (stream, opts) { + if (stream.userData && stream.userData.isProtomux) return stream.userData if (stream.isProtomux) return stream return new this(stream, opts) } diff --git a/test.js b/test.js index 6451194..d8a7f2d 100644 --- a/test.js +++ b/test.js @@ -345,6 +345,52 @@ test('alias', function (t) { bp.addMessage({ encoding: c.string }).send('hello world') }) +test('deduplicate muxers', function (t) { + const sa = new SecretStream(true) + const sb = new SecretStream(false) + + replicate({ stream: sa }, { stream: sb }) + + const a = Protomux.from(sa) + const foo = a.createChannel({ + protocol: 'foo', + onopen () { t.pass('a remote opened') } + }) + + foo.open() + + foo.addMessage({ + encoding: c.string, + onmessage (message) { t.is(message, 'hello foo') } + }) + + const bfoo = Protomux.from(sb).createChannel({ protocol: 'foo' }) + + // Another Protomux instance for another protocol + const a2 = Protomux.from(sa) + const bar = a2.createChannel({ + protocol: 'bar', + onopen () { t.pass('a remote opened') } + }) + + bar.open() + + bar.addMessage({ + encoding: c.string, + onmessage (message) { t.is(message, 'hello bar') } + }) + + const bbar = Protomux.from(sb).createChannel({ protocol: 'bar' }) + + t.plan(4) + + bfoo.open() + bfoo.addMessage({ encoding: c.string }).send('hello foo') + + bbar.open() + bbar.addMessage({ encoding: c.string }).send('hello bar') +}) + function replicate (a, b) { a.stream.rawStream.pipe(b.stream.rawStream).pipe(a.stream.rawStream) }