JavaScript implementation of multistream-select
$ npm i @libp2p/multistream-select
TLDR; multistream-select is protocol multiplexing per connection/stream. Full spec here
The caller will send "interactive" messages, expecting for some acknowledgement from the callee, which will "select" the handler for the desired and supported protocol:
< /multistream-select/0.3.0 # i speak multistream-select/0.3.0
> /multistream-select/0.3.0 # ok, let's speak multistream-select/0.3.0
> /ipfs-dht/0.2.3 # i want to speak ipfs-dht/0.2.3
< na # ipfs-dht/0.2.3 is not available
> /ipfs-dht/0.1.9 # What about ipfs-dht/0.1.9 ?
< /ipfs-dht/0.1.9 # ok let's speak ipfs-dht/0.1.9 -- in a sense acts as an ACK
> <dht-message>
> <dht-message>
> <dht-message>
import { select, handle } from '@libp2p/multistream-select'
// You can now use
// select - actively select a protocol with a remote
// handle - handle a protocol with a remote
import { pipe } from 'it-pipe'
import * as mss from '@libp2p/multistream-select'
import { Mplex } from '@libp2p/mplex'
const muxer = new Mplex()
const muxedStream = muxer.newStream()
// mss.select(protocol(s))
// Select from one of the passed protocols (in priority order)
// Returns selected stream and protocol
const { stream: dhtStream, protocol } = await mss.select(muxedStream, [
// This might just be different versions of DHT, but could be different impls
'/ipfs-dht/2.0.0', // Most of the time this will probably just be one item.
'/ipfs-dht/1.0.0'
])
// Typically this stream will be passed back to the caller of libp2p.dialProtocol
//
// ...it might then do something like this:
// try {
// await pipe(
// [uint8ArrayFromString('Some DHT data')]
// dhtStream,
// async source => {
// for await (const chunk of source)
// // DHT response data
// }
// )
// } catch (err) {
// // Error in stream
// }
import { pipe } from 'it-pipe'
import * as mss from '@libp2p/multistream-select'
import { Mplex } from '@libp2p/mplex'
const muxer = new Mplex({
async onStream (muxedStream) {
// mss.handle(handledProtocols)
// Returns selected stream and protocol
const { stream, protocol } = await mss.handle(muxedStream, [
'/ipfs-dht/1.0.0',
'/ipfs-bitswap/1.0.0'
])
// Typically here we'd call the handler function that was registered in
// libp2p for the given protocol:
// e.g. handlers[protocol].handler(stream)
//
// If protocol was /ipfs-dht/1.0.0 it might do something like this:
// try {
// await pipe(
// dhtStream,
// source => (async function * () {
// for await (const chunk of source)
// // Incoming DHT data -> process and yield to respond
// })(),
// dhtStream
// )
// } catch (err) {
// // Error in stream
// }
}
})
Negotiate a protocol to use from a list of protocols.
duplex
(Duplex
) - A duplex iterable stream to dial on.protocols
(string[]
/string
) - A list of protocols (or single protocol) to negotiate with. Protocols are attempted in order until a match is made.options
({ signal: AbortSignal, writeBytes?: boolean }
) - an options object containing an AbortSignal and an optional booleanwriteBytes
- if this is true,Uint8Array
s will be written intoduplex
, otherwiseUint8ArrayList
s will
Promise<{ stream<Duplex>, protocol<string> }>
- A stream for the selected protocol and the protocol that was selected from the list of protocols provided to select
.
Note that after a protocol is selected dialer
can no longer be used.
const { stream, protocol } = await dialer.select([
// This might just be different versions of DHT, but could be different impls
'/ipfs-dht/2.0.0', // Most of the time this will probably just be one item.
'/ipfs-dht/1.0.0'
])
// Now talk `protocol` on `stream`
Handle multistream protocol selections for the given list of protocols.
duplex
(Duplex
) - A duplex iterable stream to listen on.protocols
(String[]
/String
) - A list of protocols (or single protocol) that this listener is able to speak.options
({ signal: AbortSignal, writeBytes?: boolean }
) - an options object containing an AbortSignal and an optional booleanwriteBytes
- if this is true,Uint8Array
s will be written intoduplex
, otherwiseUint8ArrayList
s will
Promise<{ stream<Duplex>, protocol<string> }>
- A stream for the selected protocol and the protocol that was selected from the list of protocols provided to select
.
Note that after a protocol is handled listener
can no longer be used.
const { stream, protocol } = await mss.handle(duplex, [
'/ipfs-dht/1.0.0',
'/ipfs-bitswap/1.0.0'
])
// Remote wants to speak `protocol`
Licensed under either of
- Apache 2.0, (LICENSE-APACHE / http://www.apache.org/licenses/LICENSE-2.0)
- MIT (LICENSE-MIT / http://opensource.org/licenses/MIT)
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.