Protomux
Multiplex multiple framed protocols over one transport stream.
Protomux multiplexes multiple message-oriented subprotocols over one framed stream. It is typically layered on top of Secretstream and uses Compact encoding for message schemas. For source and releases, see the Protomux repository.
Install
npm i protomuxQuickstart
import Protomux from 'protomux'
import cenc from 'compact-encoding'
const mux = new Protomux(aFramedEncryptedStream)
const channel = mux.createChannel({
protocol: 'chat',
onopen() {
console.log('chat channel opened')
}
})
const message = channel.addMessage({
encoding: cenc.string,
onmessage(text) {
console.log(text)
}
})
channel.open()
message.send('hello')API Reference
Constructor and mux helpers
mux = new Protomux(stream, [options])
Make a new instance. stream should be a framed stream, preserving the messages written.
| Parameter | Type | Default | Description |
|---|---|---|---|
stream | object | — | — |
options | ProtomuxOptions | {} | Optional configuration for the instance, such as a custom buffer allocator. |
{
// Called when the muxer wants to allocate a message that is written, defaults to Buffer.allocUnsafe.
alloc (size) {}
}mux = Protomux.from(stream | muxer, [options])
Helper to accept either an existing muxer instance or a stream (which creates a new one).
| Parameter | Type | Description |
|---|---|---|
stream | object | A framed stream or an existing Protomux instance. |
opts | ProtomuxOptions | Muxer options passed through when a new instance is created. |
- Returns:
Protomux— The existing or newly created Protomux instance.
const mux = Protomux.from(someStream)Protomux.isProtomux(mux)
Returns true when value looks like a Protomux instance.
| Parameter | Type | Description |
|---|---|---|
mux | object | Value to test. |
- Returns:
boolean—truewhenmuxis a Protomux instance.
Protomux.isProtomux(mux) // true
Protomux.isProtomux({}) // falsemux.cork()
Same as channel.cork but on the muxer instance.
- Returns:
void
mux.cork()
channelA.messages[0].send('hello')
channelB.messages[0].send('world')
mux.uncork() // sends both as one framemux.uncork()
Same as channel.uncork but on the muxer instance.
- Returns:
void
mux.cork()
msg.send('hello')
mux.uncork()mux.isIdle()
Convenience method that returns true if the number of channels is currently 0.
- Returns:
boolean—trueif the channel count is currently zero.
if (mux.isIdle()) console.log('no open channels')for (const channel of muxer) { ... }
The muxer instance is iterable, so you can iterate over all the channels.
Pairing and channel discovery
mux.pair({ protocol, id }, callback)
Register a callback to be called everytime a new channel is requested.
| Parameter | Type | Description |
|---|---|---|
options | ChannelKey | Protocol name and optional binary id to match. |
notify | Function | Async callback called with the channel's binary id when a matching remote channel opens. |
- Returns:
void
mux.pair({ protocol: 'my-protocol' }, async (id) => {
const channel = mux.createChannel({ protocol: 'my-protocol' })
channel.open()
})mux.unpair({ protocol, id })
Unregisters the pair callback.
| Parameter | Type | Description |
|---|---|---|
options | ChannelKey | Protocol name and optional binary id to deregister. |
- Returns:
void
mux.unpair({ protocol: 'my-protocol' })mux.opened({ protocol, id })
Boolean that indicates if the channel is opened.
| Parameter | Type | Description |
|---|---|---|
options | ChannelKey | Protocol name and optional binary id to check. |
- Returns:
boolean—truewhen one or more matching channels are open.
if (mux.opened({ protocol: 'my-protocol' })) {
console.log('already open')
}mux.getLastChannel(options)
Returns the most recently opened matching channel, or null if none is open.
| Parameter | Type | Description |
|---|---|---|
options | ChannelKey | Protocol name and optional binary id. |
- Returns:
Channel\|null— The most recently opened matching channel, ornull.
const ch = mux.getLastChannel({ protocol: 'my-protocol' })Creating channels
mux.createChannel(opts)
Add a new protocol channel.
| Parameter | Type | Description |
|---|---|---|
opts | CreateChannelOptions | Channel creation options. |
- Returns:
Channel\|null— The new channel, ornullif it cannot be opened.
Mux properties
mux.stream
The framed transport stream backing this mux.
- Returns:
object
mux.drained
The current writable backpressure state from the underlying stream.
- Returns:
boolean
Channel lifecycle
channel.open([handshake])
Open the channel.
| Parameter | Type | Description |
|---|---|---|
handshake | * | Optional handshake value encoded with the handshake encoding provided to createChannel. |
- Returns:
void
const channel = mux.createChannel({ protocol: 'my-protocol' })
channel.open()channel.fullyOpened()
Resolves to true when the channel fully opens or false if it closes first.
- Returns:
Promise<boolean>
const opened = await channel.fullyOpened()
if (opened) console.log('channel is open')channel.fullyClosed()
Resolves once the channel has been destroyed and all pending async handlers have finished.
- Returns:
Promise<void>
await channel.fullyClosed()
console.log('channel destroyed')channel.close()
Closes the protocol channel.
- Returns:
void
channel.close()channel.cork()
Corking the protocol channel, makes it buffer messages and send them all in a batch when it uncorks.
- Returns:
void
channel.cork()
one.send('hello')
two.send(true)
channel.uncork() // sends both as a single batchchannel.uncork()
Uncork and send the batch.
- Returns:
void
channel.cork()
one.send('hello')
channel.uncork()Registering and sending messages
channel.addMessage(opts)
Add/register a message type for a certain encoding. Options include:
| Parameter | Type | Description |
|---|---|---|
opts | AddMessageOptions | Message options including encoding and onmessage handler. |
- Returns:
object— Message object with asend(data)method for sending encoded messages.
m.send(data)
Send a message.
m.encoding
The encoding for this message.
m.onmessage
Function that is called when a message arrives.
Channel properties
channel.userData
- Returns: The arbitrary metadata value passed to
mux.createChannel(...).
channel.protocol
- Returns: The channel protocol name.
channel.aliases
- Returns: The list of alternate protocol names registered for this channel family.
channel.id
- Returns: The optional binary identifier distinguishing this channel family.
channel.handshake
- Returns: The decoded handshake payload after the channel fully opens, or
nullwhen no handshake encoder was configured.
channel.messages
- Returns: The array of registered message descriptors in type order.
channel.opened
channel.closed
- Returns:
trueafter either side closes the channel.
channel.destroyed
- Returns:
trueafter the close lifecycle and pending handlers have fully drained.
channel.drained
true when the underlying stream's write buffer is empty.
- Returns:
boolean
Lifecycle callbacks
channel.onopen
- Returns: Called when the channel opens.
handshakeis the decoded open payload ornull, andchannelis the channel instance.
channel.onclose
- Returns: Called when the channel closes.
isRemoteistruewhen the remote side initiated the close, andchannelis the channel instance.
channel.ondestroy
- Returns: Called when the channel is destroyed.
channelis the destroyed channel instance.
channel.ondrain
- Returns: Called when the channel's underlying mux becomes writable again.
channelis that channel instance.
Types
ProtomuxOptions
Options for allocating buffers in a Protomux instance.
| Property | Type | Default | Description |
|---|---|---|---|
alloc | Function | — | Custom allocator; called with (size) and must return a Buffer. Defaults to Buffer.allocUnsafe. |
CreateChannelOptions
Options for creating a protocol channel.
| Property | Type | Default | Description |
|---|---|---|---|
protocol | string | — | Protocol name used to match channels between peers. |
id | Buffer|null | null | Optional binary identifier to distinguish multiple channels with the same protocol name. |
handshake | * | null | Compact-encoding codec for encoding/decoding the handshake value exchanged on open. |
messages | Array<AddMessageOptions> | [] | Array of message descriptors registered on channel open. |
unique | boolean | true | When true, returns null if a channel with this protocol+id is already open. |
aliases | Array<string> | [] | Alternative protocol names that also match this channel. |
userData | * | null | Arbitrary value stored as channel.userData; not transmitted. |
onopen | Function | — | Called with (handshake, channel) when the remote side opens this protocol. |
onclose | Function | — | Called with (isRemote, channel) when either side closes the channel. |
ondestroy | Function | — | Called with (channel) after onclose resolves and all pending promises settle. |
ondrain | Function | — | Called with (channel) when the underlying stream drains. |
AddMessageOptions
Options for registering a message type on a channel.
| Property | Type | Default | Description |
|---|---|---|---|
encoding | object | — | A compact-encoding codec. Defaults to raw binary (c.raw). |
autoBatch | boolean | true | When true, batch replies are collected before the next tick. |
onmessage | Function | — | Called with (message, channel) when the remote sends a message of this type. |
ChannelKey
Protocol + id selector used by pair/unpair/opened/getLastChannel.
| Property | Type | Default | Description |
|---|---|---|---|
protocol | string | — | Protocol name to match. |
id | Buffer|null | null | Optional binary id to narrow the match. |
See also
- Secretstream—the encrypted framed stream most commonly used underneath Protomux.
- Compact encoding—the schema toolkit Protomux uses for handshakes and message payloads.
- Hyperswarm—common peer-transport entry point before you layer on Secretstream and Protomux.
- Upstream Protomux repository—source, releases, and implementation details.