feat: support custom listener options (#822)

* support custom listener options

* fix get listener options

* add doc to explain custom listener options

* add ut

* fix code style

* Apply suggestions from code review

Co-authored-by: Vasco Santos <vasco.santos@ua.pt>

* add missing comma

Co-authored-by: Vasco Santos <vasco.santos@ua.pt>
This commit is contained in:
Smite Chow 2020-12-09 23:31:17 +08:00 committed by GitHub
parent 6350a187c7
commit 8691465a52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 3 deletions

View File

@ -651,6 +651,35 @@ const node = await Libp2p.create({
}) })
``` ```
During Libp2p startup, transport listeners will be created for the configured listen multiaddrs. Some transports support custom listener options and you can set them using the `listenerOptions` in the transport configuration. For example, [libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star) transport listener supports the configuration of its underlying [simple-peer](https://github.com/feross/simple-peer) ice server(STUN/TURN) config as follows:
```js
const transportKey = WebRTCStar.prototype[Symbol.toStringTag]
const node = await Libp2p.create({
modules: {
transport: [WebRTCStar],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
},
addresses: {
listen: ['/dns4/your-wrtc-star.pub/tcp/443/wss/p2p-webrtc-star'] // your webrtc dns multiaddr
},
config: {
transport: {
[transportKey]: {
listenerOptions: {
config: {
iceServers: [
{"urls": ["turn:YOUR.TURN.SERVER:3478"], "username": "YOUR.USER", "credential": "YOUR.PASSWORD"},
{"urls": ["stun:YOUR.STUN.SERVER:3478"], "username": "", "credential": ""}]
}
}
}
}
}
})
```
## Configuration examples ## Configuration examples
As libp2p is designed to be a modular networking library, its usage will vary based on individual project needs. We've included links to some existing project configurations for your reference, in case you wish to replicate their configuration: As libp2p is designed to be a modular networking library, its usage will vary based on individual project needs. We've included links to some existing project configurations for your reference, in case you wish to replicate their configuration:

View File

@ -20,6 +20,7 @@ class TransportManager {
this.upgrader = upgrader this.upgrader = upgrader
this._transports = new Map() this._transports = new Map()
this._listeners = new Map() this._listeners = new Map()
this._listenerOptions = new Map()
this.faultTolerance = faultTolerance this.faultTolerance = faultTolerance
} }
@ -47,6 +48,7 @@ class TransportManager {
}) })
this._transports.set(key, transport) this._transports.set(key, transport)
this._listenerOptions.set(key, transportOptions.listenerOptions || {})
if (!this._listeners.has(key)) { if (!this._listeners.has(key)) {
this._listeners.set(key, []) this._listeners.set(key, [])
} }
@ -154,7 +156,7 @@ class TransportManager {
// For each supported multiaddr, create a listener // For each supported multiaddr, create a listener
for (const addr of supportedAddrs) { for (const addr of supportedAddrs) {
log('creating listener for %s on %s', key, addr) log('creating listener for %s on %s', key, addr)
const listener = transport.createListener({}, this.onConnection) const listener = transport.createListener(this._listenerOptions.get(key), this.onConnection)
this._listeners.get(key).push(listener) this._listeners.get(key).push(listener)
// We need to attempt to listen on everything // We need to attempt to listen on everything

View File

@ -10,6 +10,7 @@ const TransportManager = require('../../src/transport-manager')
const Transport = require('libp2p-tcp') const Transport = require('libp2p-tcp')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const mockUpgrader = require('../utils/mockUpgrader') const mockUpgrader = require('../utils/mockUpgrader')
const sinon = require('sinon')
const addrs = [ const addrs = [
multiaddr('/ip4/127.0.0.1/tcp/0'), multiaddr('/ip4/127.0.0.1/tcp/0'),
multiaddr('/ip4/127.0.0.1/tcp/0') multiaddr('/ip4/127.0.0.1/tcp/0')
@ -40,7 +41,9 @@ describe('Transport Manager (TCP)', () => {
}) })
it('should be able to listen', async () => { it('should be able to listen', async () => {
tm.add(Transport.prototype[Symbol.toStringTag], Transport) tm.add(Transport.prototype[Symbol.toStringTag], Transport, { listenerOptions: { listen: 'carefully' } })
const transport = tm._transports.get(Transport.prototype[Symbol.toStringTag])
const spyListener = sinon.spy(transport, 'createListener')
await tm.listen() await tm.listen()
expect(tm._listeners).to.have.key(Transport.prototype[Symbol.toStringTag]) expect(tm._listeners).to.have.key(Transport.prototype[Symbol.toStringTag])
expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(addrs.length) expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(addrs.length)
@ -48,6 +51,7 @@ describe('Transport Manager (TCP)', () => {
expect(tm.getAddrs().length).to.equal(addrs.length) expect(tm.getAddrs().length).to.equal(addrs.length)
await tm.close() await tm.close()
expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(0) expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(0)
expect(spyListener.firstCall.firstArg).to.deep.equal({ listen: 'carefully' })
}) })
it('should be able to dial', async () => { it('should be able to dial', async () => {

View File

@ -125,7 +125,10 @@ describe('libp2p.transportManager', () => {
const spy = sinon.spy() const spy = sinon.spy()
const key = spy.prototype[Symbol.toStringTag] = 'TransportSpy' const key = spy.prototype[Symbol.toStringTag] = 'TransportSpy'
const customOptions = { const customOptions = {
another: 'value' another: 'value',
listenerOptions: {
listen: 'carefully'
}
} }
libp2p = new Libp2p({ libp2p = new Libp2p({
peerId, peerId,
@ -143,6 +146,7 @@ describe('libp2p.transportManager', () => {
expect(libp2p.transportManager).to.exist() expect(libp2p.transportManager).to.exist()
// Our transport and circuit relay // Our transport and circuit relay
expect(libp2p.transportManager._transports.size).to.equal(2) expect(libp2p.transportManager._transports.size).to.equal(2)
expect(libp2p.transportManager._listenerOptions.size).to.equal(2)
expect(spy).to.have.property('callCount', 1) expect(spy).to.have.property('callCount', 1)
expect(spy.getCall(0)).to.have.deep.property('args', [{ expect(spy.getCall(0)).to.have.deep.property('args', [{
...customOptions, ...customOptions,