From 8691465a525b45c2737e2e44dd5651b0211f1348 Mon Sep 17 00:00:00 2001 From: Smite Chow Date: Wed, 9 Dec 2020 23:31:17 +0800 Subject: [PATCH] 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 * add missing comma Co-authored-by: Vasco Santos --- doc/CONFIGURATION.md | 29 +++++++++++++++++++++++ src/transport-manager.js | 4 +++- test/transports/transport-manager.node.js | 6 ++++- test/transports/transport-manager.spec.js | 6 ++++- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/doc/CONFIGURATION.md b/doc/CONFIGURATION.md index 527ee357..41055517 100644 --- a/doc/CONFIGURATION.md +++ b/doc/CONFIGURATION.md @@ -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 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: diff --git a/src/transport-manager.js b/src/transport-manager.js index e18841bf..f9cf8629 100644 --- a/src/transport-manager.js +++ b/src/transport-manager.js @@ -20,6 +20,7 @@ class TransportManager { this.upgrader = upgrader this._transports = new Map() this._listeners = new Map() + this._listenerOptions = new Map() this.faultTolerance = faultTolerance } @@ -47,6 +48,7 @@ class TransportManager { }) this._transports.set(key, transport) + this._listenerOptions.set(key, transportOptions.listenerOptions || {}) if (!this._listeners.has(key)) { this._listeners.set(key, []) } @@ -154,7 +156,7 @@ class TransportManager { // For each supported multiaddr, create a listener for (const addr of supportedAddrs) { 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) // We need to attempt to listen on everything diff --git a/test/transports/transport-manager.node.js b/test/transports/transport-manager.node.js index 1036230a..cd1e6fb8 100644 --- a/test/transports/transport-manager.node.js +++ b/test/transports/transport-manager.node.js @@ -10,6 +10,7 @@ const TransportManager = require('../../src/transport-manager') const Transport = require('libp2p-tcp') const multiaddr = require('multiaddr') const mockUpgrader = require('../utils/mockUpgrader') +const sinon = require('sinon') const addrs = [ 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 () => { - 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() expect(tm._listeners).to.have.key(Transport.prototype[Symbol.toStringTag]) 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) await tm.close() 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 () => { diff --git a/test/transports/transport-manager.spec.js b/test/transports/transport-manager.spec.js index b32b2807..f91de4af 100644 --- a/test/transports/transport-manager.spec.js +++ b/test/transports/transport-manager.spec.js @@ -125,7 +125,10 @@ describe('libp2p.transportManager', () => { const spy = sinon.spy() const key = spy.prototype[Symbol.toStringTag] = 'TransportSpy' const customOptions = { - another: 'value' + another: 'value', + listenerOptions: { + listen: 'carefully' + } } libp2p = new Libp2p({ peerId, @@ -143,6 +146,7 @@ describe('libp2p.transportManager', () => { expect(libp2p.transportManager).to.exist() // Our transport and circuit relay 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.getCall(0)).to.have.deep.property('args', [{ ...customOptions,