Compare commits

...

9 Commits

Author SHA1 Message Date
48656712ea chore: release version v0.29.4 2020-12-09 16:42:21 +01:00
1a5ae74741 chore: update contributors 2020-12-09 16:42:20 +01:00
8691465a52 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>
2020-12-09 16:31:17 +01:00
6350a187c7 fix: dial self (#826) 2020-12-09 16:13:25 +01:00
8e3bb09279 chore: remove references to Solarnet (#820)
Co-authored-by: Vasco Santos <vasco.santos@ua.pt>
2020-12-01 19:10:47 +01:00
73204958ee docs: use Libp2p.create() in examples (#811) (#814) 2020-11-30 11:15:09 +01:00
e9e4b731a5 docs: fix JSDOc for stop and create (#812) (#813) 2020-11-27 10:50:35 +01:00
d0a9fada32 feat: custom and store self agent version + store self protocol version (#800)
* feat: custom and store self protocol and agent version

* fix: do not enable custom protocolVersion
2020-11-20 15:14:01 +01:00
824a444f56 docs(fix): fix contentRouting.getMany (#803) 2020-11-18 10:28:43 +01:00
22 changed files with 281 additions and 108 deletions

View File

@ -1,3 +1,19 @@
<a name="0.29.4"></a>
## [0.29.4](https://github.com/libp2p/js-libp2p/compare/v0.29.3...v0.29.4) (2020-12-09)
### Bug Fixes
* dial self ([#826](https://github.com/libp2p/js-libp2p/issues/826)) ([6350a18](https://github.com/libp2p/js-libp2p/commit/6350a18))
### Features
* custom and store self agent version + store self protocol version ([#800](https://github.com/libp2p/js-libp2p/issues/800)) ([d0a9fad](https://github.com/libp2p/js-libp2p/commit/d0a9fad))
* support custom listener options ([#822](https://github.com/libp2p/js-libp2p/issues/822)) ([8691465](https://github.com/libp2p/js-libp2p/commit/8691465))
<a name="0.29.3"></a> <a name="0.29.3"></a>
## [0.29.3](https://github.com/libp2p/js-libp2p/compare/v0.29.2...v0.29.3) (2020-11-04) ## [0.29.3](https://github.com/libp2p/js-libp2p/compare/v0.29.2...v0.29.3) (2020-11-04)

View File

@ -92,6 +92,7 @@ Creates an instance of Libp2p.
| options.modules | [`Array<object>`](./CONFIGURATION.md#modules) | libp2p [modules](./CONFIGURATION.md#modules) to use | | options.modules | [`Array<object>`](./CONFIGURATION.md#modules) | libp2p [modules](./CONFIGURATION.md#modules) to use |
| [options.addresses] | `{ listen: Array<string>, announce: Array<string>, noAnnounce: Array<string> }` | Addresses for transport listening and to advertise to the network | | [options.addresses] | `{ listen: Array<string>, announce: Array<string>, noAnnounce: Array<string> }` | Addresses for transport listening and to advertise to the network |
| [options.config] | `object` | libp2p modules configuration and core configuration | | [options.config] | `object` | libp2p modules configuration and core configuration |
| [options.host] | `{ agentVersion: string }` | libp2p host options |
| [options.connectionManager] | [`object`](./CONFIGURATION.md#configuring-connection-manager) | libp2p Connection Manager [configuration](./CONFIGURATION.md#configuring-connection-manager) | | [options.connectionManager] | [`object`](./CONFIGURATION.md#configuring-connection-manager) | libp2p Connection Manager [configuration](./CONFIGURATION.md#configuring-connection-manager) |
| [options.transportManager] | [`object`](./CONFIGURATION.md#configuring-transport-manager) | libp2p transport manager [configuration](./CONFIGURATION.md#configuring-transport-manager) | | [options.transportManager] | [`object`](./CONFIGURATION.md#configuring-transport-manager) | libp2p transport manager [configuration](./CONFIGURATION.md#configuring-transport-manager) |
| [options.datastore] | `object` | must implement [ipfs/interface-datastore](https://github.com/ipfs/interface-datastore) (in memory datastore will be used if not provided) | | [options.datastore] | `object` | must implement [ipfs/interface-datastore](https://github.com/ipfs/interface-datastore) (in memory datastore will be used if not provided) |
@ -113,12 +114,25 @@ For Libp2p configurations and modules details read the [Configuration Document](
```js ```js
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
// specify options async function main () {
const options = {} // specify options
const options = {
modules: {
transport: [TCP],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
}
}
// create libp2p // create libp2p
const libp2p = await Libp2p.create(options) const libp2p = await Libp2p.create(options)
}
main()
``` ```
Note: The [`PeerId`][peer-id] option is not required and will be generated if it is not provided. Note: The [`PeerId`][peer-id] option is not required and will be generated if it is not provided.
@ -130,12 +144,30 @@ As an alternative, it is possible to create a Libp2p instance with the construct
```js ```js
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
const PeerId = require('peer-id')
// specify options async function main () {
const options = {} const peerId = await PeerId.create();
// create libp2p // specify options
const libp2p = new Libp2p(options) // peerId is required when Libp2p is instantiated via the constructor
const options = {
peerId,
modules: {
transport: [TCP],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
}
}
// create libp2p
const libp2p = new Libp2p(options)
}
main()
``` ```
Required keys in the `options` object: Required keys in the `options` object:
@ -665,7 +697,7 @@ Queries the DHT for the n values stored for the given key (without sorting).
// ... // ...
const key = '/key' const key = '/key'
const { from, val } = await libp2p.contentRouting.get(key) const records = await libp2p.contentRouting.getMany(key, 2)
``` ```
### peerRouting.findPeer ### peerRouting.findPeer

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

@ -3,7 +3,7 @@
const PeerId = require('peer-id') const PeerId = require('peer-id')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const Node = require('./libp2p-bundle') const createLibp2p = require('./libp2p-bundle')
const { stdinToStream, streamToConsole } = require('./stream') const { stdinToStream, streamToConsole } = require('./stream')
async function run() { async function run() {
@ -13,7 +13,7 @@ async function run() {
]) ])
// Create a new libp2p node on localhost with a randomly chosen port // Create a new libp2p node on localhost with a randomly chosen port
const nodeDialer = new Node({ const nodeDialer = await createLibp2p({
peerId: idDialer, peerId: idDialer,
addresses: { addresses: {
listen: ['/ip4/0.0.0.0/tcp/0'] listen: ['/ip4/0.0.0.0/tcp/0']

View File

@ -7,21 +7,16 @@ const { NOISE } = require('libp2p-noise')
const defaultsDeep = require('@nodeutils/defaults-deep') const defaultsDeep = require('@nodeutils/defaults-deep')
const libp2p = require('../../..') const libp2p = require('../../..')
class Node extends libp2p { async function createLibp2p(_options) {
constructor (_options) { const defaults = {
const defaults = { modules: {
modules: { transport: [TCP, WS],
transport: [ streamMuxer: [mplex],
TCP, connEncryption: [NOISE],
WS },
],
streamMuxer: [ mplex ],
connEncryption: [ NOISE ]
}
}
super(defaultsDeep(_options, defaults))
} }
return libp2p.create(defaultsDeep(_options, defaults))
} }
module.exports = Node module.exports = createLibp2p

View File

@ -2,13 +2,13 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
const PeerId = require('peer-id') const PeerId = require('peer-id')
const Node = require('./libp2p-bundle.js') const createLibp2p = require('./libp2p-bundle.js')
const { stdinToStream, streamToConsole } = require('./stream') const { stdinToStream, streamToConsole } = require('./stream')
async function run() { async function run() {
// Create a new libp2p node with the given multi-address // Create a new libp2p node with the given multi-address
const idListener = await PeerId.createFromJSON(require('./peer-id-listener')) const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
const nodeListener = new Node({ const nodeListener = await createLibp2p({
peerId: idListener, peerId: idListener,
addresses: { addresses: {
listen: ['/ip4/0.0.0.0/tcp/10333'] listen: ['/ip4/0.0.0.0/tcp/10333']

View File

@ -10,14 +10,11 @@ const Bootstrap = require('libp2p-bootstrap')
// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-nodejs.json // Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-nodejs.json
const bootstrapers = [ const bootstrapers = [
'/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
'/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
'/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
'/ip4/162.243.248.213/tcp/4001/p2p/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
'/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
'/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
'/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
'/ip4/178.62.61.185/tcp/4001/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
'/ip4/104.236.151.122/tcp/4001/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx'
] ]
;(async () => { ;(async () => {

View File

@ -40,14 +40,11 @@ In this configuration, we use a `bootstrappers` array listing peers to connect _
```JavaScript ```JavaScript
const bootstrapers = [ const bootstrapers = [
'/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
'/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
'/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
'/ip4/162.243.248.213/tcp/4001/p2p/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
'/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
'/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
'/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
'/ip4/178.62.61.185/tcp/4001/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
'/ip4/104.236.151.122/tcp/4001/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx'
] ]
``` ```
@ -93,23 +90,17 @@ From running [1.js](./1.js), you should see the following:
```bash ```bash
> node 1.js > node 1.js
Discovered: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ Discovered: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
Discovered: QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z Discovered: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN
Discovered: QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM Discovered: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb
Discovered: QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm Discovered: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp
Discovered: QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu Discovered: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa
Discovered: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64 Discovered: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt
Discovered: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
Discovered: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
Discovered: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
Connection established to: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ Connection established to: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
Connection established to: QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z Connection established to: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN
Connection established to: QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM Connection established to: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp
Connection established to: QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm Connection established to: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa
Connection established to: QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu Connection established to: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt
Connection established to: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64 Connection established to: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb
Connection established to: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
Connection established to: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
Connection established to: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
``` ```
## 2. MulticastDNS to find other peers in the network ## 2. MulticastDNS to find other peers in the network

View File

@ -5,9 +5,8 @@
* Dialer Node * Dialer Node
*/ */
const multiaddr = require('multiaddr')
const PeerId = require('peer-id') const PeerId = require('peer-id')
const Node = require('./libp2p-bundle') const createLibp2p = require('./libp2p-bundle')
const pipe = require('it-pipe') const pipe = require('it-pipe')
async function run() { async function run() {
@ -17,7 +16,7 @@ async function run() {
]) ])
// Dialer // Dialer
const dialerNode = new Node({ const dialerNode = await createLibp2p({
addresses: { addresses: {
listen: ['/ip4/0.0.0.0/tcp/0'] listen: ['/ip4/0.0.0.0/tcp/0']
}, },

View File

@ -8,21 +8,16 @@ const { NOISE } = require('libp2p-noise')
const defaultsDeep = require('@nodeutils/defaults-deep') const defaultsDeep = require('@nodeutils/defaults-deep')
const libp2p = require('../../..') const libp2p = require('../../..')
class Node extends libp2p { async function createLibp2p(_options) {
constructor (_options) { const defaults = {
const defaults = { modules: {
modules: { transport: [TCP, WS],
transport: [ streamMuxer: [mplex],
TCP, connEncryption: [NOISE],
WS },
],
streamMuxer: [ mplex ],
connEncryption: [ NOISE ]
}
}
super(defaultsDeep(_options, defaults))
} }
return libp2p.create(defaultsDeep(_options, defaults))
} }
module.exports = Node module.exports = createLibp2p

View File

@ -6,14 +6,14 @@
*/ */
const PeerId = require('peer-id') const PeerId = require('peer-id')
const Node = require('./libp2p-bundle') const createLibp2p = require('./libp2p-bundle')
const pipe = require('it-pipe') const pipe = require('it-pipe')
async function run() { async function run() {
const listenerId = await PeerId.createFromJSON(require('./id-l')) const listenerId = await PeerId.createFromJSON(require('./id-l'))
// Listener libp2p node // Listener libp2p node
const listenerNode = new Node({ const listenerNode = await createLibp2p({
addresses: { addresses: {
listen: ['/ip4/0.0.0.0/tcp/10333'] listen: ['/ip4/0.0.0.0/tcp/10333']
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "libp2p", "name": "libp2p",
"version": "0.29.3", "version": "0.29.4",
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack", "description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>", "leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
"main": "src/index.js", "main": "src/index.js",
@ -135,6 +135,7 @@
"dirkmc <dirkmdev@gmail.com>", "dirkmc <dirkmdev@gmail.com>",
"Volker Mische <volker.mische@gmail.com>", "Volker Mische <volker.mische@gmail.com>",
"Richard Littauer <richard.littauer@gmail.com>", "Richard Littauer <richard.littauer@gmail.com>",
"a1300 <matthias-knopp@gmx.net>",
"Elven <mon.samuel@qq.com>", "Elven <mon.samuel@qq.com>",
"Andrew Nesbitt <andrewnez@gmail.com>", "Andrew Nesbitt <andrewnez@gmail.com>",
"Giovanni T. Parra <fiatjaf@gmail.com>", "Giovanni T. Parra <fiatjaf@gmail.com>",
@ -142,8 +143,6 @@
"Thomas Eizinger <thomas@eizinger.io>", "Thomas Eizinger <thomas@eizinger.io>",
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>", "ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
"Didrik Nordström <didrik@betamos.se>", "Didrik Nordström <didrik@betamos.se>",
"Henrique Dias <hacdias@gmail.com>",
"Fei Liu <liu.feiwood@gmail.com>",
"Irakli Gozalishvili <rfobic@gmail.com>", "Irakli Gozalishvili <rfobic@gmail.com>",
"Ethan Lam <elmemphis2000@gmail.com>", "Ethan Lam <elmemphis2000@gmail.com>",
"Joel Gustafson <joelg@mit.edu>", "Joel Gustafson <joelg@mit.edu>",
@ -153,9 +152,11 @@
"Dmitriy Ryajov <dryajov@gmail.com>", "Dmitriy Ryajov <dryajov@gmail.com>",
"RasmusErik Voel Jensen <github@solsort.com>", "RasmusErik Voel Jensen <github@solsort.com>",
"Diogo Silva <fsdiogo@gmail.com>", "Diogo Silva <fsdiogo@gmail.com>",
"robertkiel <robert.kiel@validitylabs.org>", "Samlior <samlior@foxmail.com>",
"Smite Chow <xiaopengyou@live.com>",
"Soeren <nikorpoulsen@gmail.com>", "Soeren <nikorpoulsen@gmail.com>",
"Sönke Hahn <soenkehahn@gmail.com>", "Sönke Hahn <soenkehahn@gmail.com>",
"robertkiel <robert.kiel@validitylabs.org>",
"Tiago Alves <alvesjtiago@gmail.com>", "Tiago Alves <alvesjtiago@gmail.com>",
"Daijiro Wachi <daijiro.wachi@gmail.com>", "Daijiro Wachi <daijiro.wachi@gmail.com>",
"Yusef Napora <yusef@napora.org>", "Yusef Napora <yusef@napora.org>",
@ -164,9 +165,11 @@
"Chris Bratlien <chrisbratlien@gmail.com>", "Chris Bratlien <chrisbratlien@gmail.com>",
"ebinks <elizabethjbinks@gmail.com>", "ebinks <elizabethjbinks@gmail.com>",
"Bernd Strehl <bernd.strehl@gmail.com>", "Bernd Strehl <bernd.strehl@gmail.com>",
"isan_rivkin <isanrivkin@gmail.com>",
"Florian-Merle <florian.david.merle@gmail.com>", "Florian-Merle <florian.david.merle@gmail.com>",
"Francis Gulotta <wizard@roborooter.com>", "Francis Gulotta <wizard@roborooter.com>",
"Felipe Martins <felipebrasil93@gmail.com>" "Felipe Martins <felipebrasil93@gmail.com>",
"isan_rivkin <isanrivkin@gmail.com>",
"Henrique Dias <hacdias@gmail.com>",
"Fei Liu <liu.feiwood@gmail.com>"
] ]
} }

View File

@ -4,6 +4,7 @@ const mergeOptions = require('merge-options')
const { dnsaddrResolver } = require('multiaddr/src/resolvers') const { dnsaddrResolver } = require('multiaddr/src/resolvers')
const Constants = require('./constants') const Constants = require('./constants')
const { AGENT_VERSION } = require('./identify/consts')
const { FaultTolerance } = require('./transport-manager') const { FaultTolerance } = require('./transport-manager')
@ -27,6 +28,9 @@ const DefaultConfig = {
dnsaddr: dnsaddrResolver dnsaddr: dnsaddrResolver
} }
}, },
host: {
agentVersion: AGENT_VERSION
},
metrics: { metrics: {
enabled: false enabled: false
}, },

View File

@ -16,6 +16,7 @@ exports.codes = {
ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED', ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED',
ERR_ALREADY_ABORTED: 'ERR_ALREADY_ABORTED', ERR_ALREADY_ABORTED: 'ERR_ALREADY_ABORTED',
ERR_NO_VALID_ADDRESSES: 'ERR_NO_VALID_ADDRESSES', ERR_NO_VALID_ADDRESSES: 'ERR_NO_VALID_ADDRESSES',
ERR_DIALED_SELF: 'ERR_DIALED_SELF',
ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF', ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF',
ERR_DUPLICATE_TRANSPORT: 'ERR_DUPLICATE_TRANSPORT', ERR_DUPLICATE_TRANSPORT: 'ERR_DUPLICATE_TRANSPORT',
ERR_ENCRYPTION_FAILED: 'ERR_ENCRYPTION_FAILED', ERR_ENCRYPTION_FAILED: 'ERR_ENCRYPTION_FAILED',

View File

@ -83,6 +83,16 @@ class IdentifyService {
this._protocols = protocols this._protocols = protocols
this.handleMessage = this.handleMessage.bind(this) this.handleMessage = this.handleMessage.bind(this)
// Store self host metadata
this._host = {
agentVersion: AGENT_VERSION,
protocolVersion: PROTOCOL_VERSION,
...libp2p._options.host
}
this.peerStore.metadataBook.set(this.peerId, 'AgentVersion', uint8ArrayFromString(this._host.agentVersion))
this.peerStore.metadataBook.set(this.peerId, 'ProtocolVersion', uint8ArrayFromString(this._host.protocolVersion))
} }
/** /**
@ -246,8 +256,8 @@ class IdentifyService {
const signedPeerRecord = await this._getSelfPeerRecord() const signedPeerRecord = await this._getSelfPeerRecord()
const message = Message.encode({ const message = Message.encode({
protocolVersion: PROTOCOL_VERSION, protocolVersion: this._host.protocolVersion,
agentVersion: AGENT_VERSION, agentVersion: this._host.agentVersion,
publicKey, publicKey,
listenAddrs: this._libp2p.multiaddrs.map((ma) => ma.bytes), listenAddrs: this._libp2p.multiaddrs.map((ma) => ma.bytes),
signedPeerRecord, signedPeerRecord,

View File

@ -242,7 +242,7 @@ class Libp2p extends EventEmitter {
* Stop the libp2p node by closing its listeners and open connections * Stop the libp2p node by closing its listeners and open connections
* *
* @async * @async
* @returns {void} * @returns {Promise<void>}
*/ */
async stop () { async stop () {
log('libp2p is stopping') log('libp2p is stopping')
@ -335,6 +335,11 @@ class Libp2p extends EventEmitter {
*/ */
async dialProtocol (peer, protocols, options) { async dialProtocol (peer, protocols, options) {
const { id, multiaddrs } = getPeer(peer) const { id, multiaddrs } = getPeer(peer)
if (id.equals(this.peerId)) {
throw errCode(new Error('Cannot dial self'), codes.ERR_DIALED_SELF)
}
let connection = this.connectionManager.get(id) let connection = this.connectionManager.get(id)
if (!connection) { if (!connection) {
@ -601,7 +606,7 @@ class Libp2p extends EventEmitter {
* instance if one is not provided in options. * instance if one is not provided in options.
* *
* @param {object} options - Libp2p configuration options * @param {object} options - Libp2p configuration options
* @returns {Libp2p} * @returns {Promise<Libp2p>}
*/ */
Libp2p.create = async function create (options = {}) { Libp2p.create = async function create (options = {}) {
if (options.peerId) { if (options.peerId) {

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

@ -18,10 +18,16 @@ const listenMultiaddr = '/ip4/127.0.0.1/tcp/15002/ws'
describe('Connection Manager', () => { describe('Connection Manager', () => {
let libp2p let libp2p
let peerIds
before(async () => {
peerIds = await peerUtils.createPeerId({ number: 2 })
})
beforeEach(async () => { beforeEach(async () => {
[libp2p] = await peerUtils.createPeer({ [libp2p] = await peerUtils.createPeer({
config: { config: {
peerId: peerIds[0],
addresses: { addresses: {
listen: [listenMultiaddr] listen: [listenMultiaddr]
}, },
@ -33,12 +39,10 @@ describe('Connection Manager', () => {
afterEach(() => libp2p.stop()) afterEach(() => libp2p.stop())
it('should filter connections on disconnect, removing the closed one', async () => { it('should filter connections on disconnect, removing the closed one', async () => {
const [localPeer, remotePeer] = await peerUtils.createPeerId({ number: 2 }) const conn1 = await mockConnection({ localPeer: peerIds[0], remotePeer: peerIds[1] })
const conn2 = await mockConnection({ localPeer: peerIds[0], remotePeer: peerIds[1] })
const conn1 = await mockConnection({ localPeer, remotePeer }) const id = peerIds[1].toB58String()
const conn2 = await mockConnection({ localPeer, remotePeer })
const id = remotePeer.toB58String()
// Add connection to the connectionManager // Add connection to the connectionManager
libp2p.connectionManager.onConnect(conn1) libp2p.connectionManager.onConnect(conn1)
@ -57,6 +61,7 @@ describe('Connection Manager', () => {
it('should add connection on dial and remove on node stop', async () => { it('should add connection on dial and remove on node stop', async () => {
const [remoteLibp2p] = await peerUtils.createPeer({ const [remoteLibp2p] = await peerUtils.createPeer({
config: { config: {
peerId: peerIds[1],
addresses: { addresses: {
listen: ['/ip4/127.0.0.1/tcp/15003/ws'] listen: ['/ip4/127.0.0.1/tcp/15003/ws']
}, },
@ -89,9 +94,16 @@ describe('Connection Manager', () => {
}) })
describe('libp2p.connections', () => { describe('libp2p.connections', () => {
let peerIds
before(async () => {
peerIds = await peerUtils.createPeerId({ number: 2 })
})
it('libp2p.connections gets the connectionManager conns', async () => { it('libp2p.connections gets the connectionManager conns', async () => {
const [libp2p] = await peerUtils.createPeer({ const [libp2p] = await peerUtils.createPeer({
config: { config: {
peerId: peerIds[0],
addresses: { addresses: {
listen: ['/ip4/127.0.0.1/tcp/15003/ws'] listen: ['/ip4/127.0.0.1/tcp/15003/ws']
}, },
@ -100,6 +112,7 @@ describe('libp2p.connections', () => {
}) })
const [remoteLibp2p] = await peerUtils.createPeer({ const [remoteLibp2p] = await peerUtils.createPeer({
config: { config: {
peerId: peerIds[1],
addresses: { addresses: {
listen: ['/ip4/127.0.0.1/tcp/15004/ws'] listen: ['/ip4/127.0.0.1/tcp/15004/ws']
}, },

View File

@ -409,5 +409,20 @@ describe('Dialing (direct, WebSockets)', () => {
expect(libp2p.dialer.destroy).to.have.property('callCount', 1) expect(libp2p.dialer.destroy).to.have.property('callCount', 1)
}) })
it('should fail to dial self', async () => {
libp2p = new Libp2p({
peerId,
modules: {
transport: [Transport],
streamMuxer: [Muxer],
connEncryption: [Crypto]
}
})
await expect(libp2p.dial(peerId))
.to.eventually.be.rejected()
.and.to.have.property('code', ErrorCodes.ERR_DIALED_SELF)
})
}) })
}) })

View File

@ -53,7 +53,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols protocols
}) })
@ -63,7 +64,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols protocols
}) })
@ -106,7 +108,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols protocols
}) })
@ -116,7 +119,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols protocols
}) })
@ -165,7 +169,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: [] multiaddrs: [],
_options: { host: {} }
}, },
protocols protocols
}) })
@ -174,7 +179,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: [] multiaddrs: [],
_options: { host: {} }
}, },
protocols protocols
}) })
@ -201,6 +207,36 @@ describe('Identify', () => {
.and.to.have.property('code', Errors.ERR_INVALID_PEER) .and.to.have.property('code', Errors.ERR_INVALID_PEER)
}) })
it('should store host data and protocol version into metadataBook', () => {
const agentVersion = 'js-project/1.0.0'
const peerStore = new PeerStore({ peerId: localPeer })
sinon.spy(peerStore.metadataBook, 'set')
new IdentifyService({ // eslint-disable-line no-new
libp2p: {
peerId: localPeer,
connectionManager: new EventEmitter(),
peerStore,
multiaddrs: listenMaddrs,
_options: {
host: {
agentVersion
}
}
},
protocols
})
expect(peerStore.metadataBook.set.callCount).to.eql(2)
const storedAgentVersion = peerStore.metadataBook.getValue(localPeer, 'AgentVersion')
const storedProtocolVersion = peerStore.metadataBook.getValue(localPeer, 'ProtocolVersion')
expect(agentVersion).to.eql(unit8ArrayToString(storedAgentVersion))
expect(storedProtocolVersion).to.exist()
})
describe('push', () => { describe('push', () => {
it('should be able to push identify updates to another peer', async () => { it('should be able to push identify updates to another peer', async () => {
const connectionManager = new EventEmitter() const connectionManager = new EventEmitter()
@ -211,7 +247,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols: new Map([ protocols: new Map([
[multicodecs.IDENTIFY], [multicodecs.IDENTIFY],
@ -224,7 +261,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager, connectionManager,
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: [] multiaddrs: [],
_options: { host: {} }
} }
}) })
@ -272,7 +310,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols: new Map([ protocols: new Map([
[multicodecs.IDENTIFY], [multicodecs.IDENTIFY],
@ -285,7 +324,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager, connectionManager,
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: [] multiaddrs: [],
_options: { host: {} }
} }
}) })
@ -404,5 +444,23 @@ describe('Identify', () => {
// Verify the streams close // Verify the streams close
await pWaitFor(() => connection.streams.length === 0) await pWaitFor(() => connection.streams.length === 0)
}) })
it('should store host data and protocol version into metadataBook', () => {
const agentVersion = 'js-project/1.0.0'
libp2p = new Libp2p({
...baseOptions,
peerId,
host: {
agentVersion
}
})
const storedAgentVersion = libp2p.peerStore.metadataBook.getValue(localPeer, 'AgentVersion')
const storedProtocolVersion = libp2p.peerStore.metadataBook.getValue(localPeer, 'ProtocolVersion')
expect(agentVersion).to.eql(unit8ArrayToString(storedAgentVersion))
expect(storedProtocolVersion).to.exist()
})
}) })
}) })

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,