Compare commits

...

16 Commits

Author SHA1 Message Date
Derrick Hammer e7aa69a59b
*make message encoding/decoding async for use with the kernel 2023-04-08 21:18:14 -04:00
Derrick Hammer bbe30a3de5
*prettier 2023-04-05 03:36:37 -04:00
Derrick Hammer ce12140ac0
*add prettier 2023-04-05 03:35:15 -04:00
Nina Breznik 6dfa4f32ca
update readme with mux.pair and mux.opened (#9)
* update readme with mux.pair and mux.opened

* add opts to .pair, .unpair and .opened
2023-02-06 18:43:05 +01:00
Mathias Buus 131fce63d7 3.4.1 2023-01-13 14:08:42 +01:00
Mathias Buus 78e83bbfa9 failing test 2023-01-13 14:08:34 +01:00
Lucas b9ff6b50b7
Add test: open + send + close on same tick (#8) 2022-11-08 22:13:32 +01:00
Lucas 69ae35ca8b
Update README.md (#6) 2022-11-03 10:39:15 +01:00
Mathias Buus d47fd52836 3.4.0 2022-08-31 12:49:40 +02:00
Ar Nazeh 43d5192f31
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
2022-08-31 12:49:19 +02:00
Mathias Buus fcdc0db1e1 move to brittle 3 2022-08-15 23:51:56 +02:00
Mathias Buus e00098b294 3.3.0 2022-08-13 00:54:18 +02:00
Kasper Isager Dalsgarð 88df528516
Add `aliases` option (#4)
* Add `aliases` option

* Clear aliases on GC
2022-08-13 00:52:34 +02:00
Mathias Buus 699dbed87d 3.2.2 2022-07-06 14:39:16 +02:00
Mathias Buus 5606c5ef85 auto split corks if they get too big 2022-07-06 14:39:04 +02:00
Ar Nazeh 3a2c88c5cb
docs: add documentation for iterating over channels (#3) 2022-04-06 11:48:35 +02:00
5 changed files with 649 additions and 365 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
node_modules
package-lock.json
sandbox.js
sandbox.mjs
sandbox

View File

@ -46,10 +46,9 @@ const two = cool.addMessage({
}
})
// open the channels
// open the channel
one.open()
two.open()
cool.open()
// And send some data
@ -109,13 +108,25 @@ __NOTE__: `mux.createChannel` returns `null` if the channel should not be opened
If you want multiple sessions with the same `protocol` and `id`, set `unique: false` as an option.
#### `const opened = mux.opened({ protocol, id })`
Boolean that indicates if the channel is opened.
#### `mux.pair({ protocol, id }, callback)`
Register a callback to be called everytime a new channel is requested.
#### `mux.unpair({ protocol, id })`
Unregisters the pair callback.
#### `channel.open([handshake])`
Open the channel.
#### `const m = channel.addMessage(opts)`
Add a message. Options include:
Add/register a message type for a certain encoding. Options include:
``` js
{
@ -159,6 +170,10 @@ Same as `channel.cork` but on the muxer instance.
Same as `channel.uncork` but on the muxer instance.
#### `for (const channel of muxer) { ... }`
The muxer instance is iterable, so you can iterate over all the channels.
## License
MIT

818
index.js

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "protomux",
"version": "3.2.1",
"version": "3.4.1",
"description": "Multiplex multiple message oriented protocols over a stream",
"main": "index.js",
"dependencies": {
@ -10,8 +10,9 @@
"safety-catch": "^1.0.1"
},
"devDependencies": {
"@hyperswarm/secret-stream": "^5.1.4",
"brittle": "^2.0.1",
"@hyperswarm/secret-stream": "^6.0.0",
"brittle": "^3.0.0",
"prettier": "^2.8.7",
"standard": "^16.0.4"
},
"scripts": {

165
test.js
View File

@ -2,6 +2,7 @@ const Protomux = require('./')
const SecretStream = require('@hyperswarm/secret-stream')
const test = require('brittle')
const c = require('compact-encoding')
const b4a = require('b4a')
test('basic', function (t) {
const a = new Protomux(new SecretStream(true))
@ -189,6 +190,52 @@ test('corks', function (t) {
}
})
test('mega cork', function (t) {
const a = new Protomux(new SecretStream(true))
a.cork()
const ap = a.createChannel({
protocol: 'mega'
})
ap.open()
const a1 = ap.addMessage({ encoding: c.buffer })
const b = new Protomux(new SecretStream(false))
const bp = b.createChannel({
protocol: 'mega'
})
bp.open()
const b1 = bp.addMessage({ encoding: c.buffer })
replicate(a, b)
t.plan(32 + 4)
const buf = b4a.alloc(1024 * 1024)
const expected = []
for (let i = 0; i < 32; i++) {
a1.send(buf)
expected.push(buf)
}
a.uncork()
b.stream.on('data', function (data) {
t.ok(data.byteLength > 8000000, 'got big message')
})
b1.onmessage = function (message) {
t.alike(message, expected.shift())
}
})
test('handshake', function (t) {
const a = new Protomux(new SecretStream(true))
const b = new Protomux(new SecretStream(false))
@ -265,6 +312,124 @@ test('pipeline close and rejections', function (t) {
}
})
test('alias', function (t) {
const a = new Protomux(new SecretStream(true))
const b = new Protomux(new SecretStream(false))
replicate(a, b)
const p = a.createChannel({
protocol: 'foo',
aliases: ['bar'],
onopen () {
t.pass('a remote opened')
}
})
p.open()
p.addMessage({
encoding: c.string,
onmessage (message) {
t.is(message, 'hello world')
}
})
const bp = b.createChannel({
protocol: 'bar'
})
t.plan(2)
bp.open()
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')
})
test('open + send + close on same tick', async function (t) {
t.plan(4)
const a = new Protomux(new SecretStream(true))
const b = new Protomux(new SecretStream(false))
replicate(a, b)
const ac = a.createChannel({
protocol: 'foo',
onopen () {
t.pass('a opened')
},
onclose () {
t.pass('a closed')
}
})
ac.open()
ac.addMessage({
encoding: c.string,
onmessage (message) { t.is(message, 'hello') }
})
const bc = b.createChannel({
protocol: 'foo',
onopen () {
t.fail('b opened')
},
onclose () {
t.pass('b closed')
}
})
bc.open()
bc.addMessage({ encoding: c.string }).send('hello')
bc.close()
})
function replicate (a, b) {
a.stream.rawStream.pipe(b.stream.rawStream).pipe(a.stream.rawStream)
}