mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-11 23:01:34 +00:00
Compare commits
17 Commits
v0.24.0-rc
...
v0.24.0
Author | SHA1 | Date | |
---|---|---|---|
2e4459b315 | |||
2a5232b541 | |||
44915b3723 | |||
64bba57255 | |||
88ebd1fc09 | |||
92cd591da4 | |||
320d84f541 | |||
970deec2a4 | |||
714b6ec2b9 | |||
f71fdfdf35 | |||
e92053da9a | |||
17b5f73b3d | |||
c18d2a4147 | |||
f1baa7e0b1 | |||
4abc868ab3 | |||
40e840d5fd | |||
9518eb44b3 |
@ -1,3 +1,8 @@
|
|||||||
|
<a name="0.24.0"></a>
|
||||||
|
# [0.24.0](https://github.com/libp2p/js-libp2p/compare/v0.24.0-rc.3...v0.24.0) (2018-11-16)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.23.1"></a>
|
<a name="0.23.1"></a>
|
||||||
## [0.23.1](https://github.com/libp2p/js-libp2p/compare/v0.23.0...v0.23.1) (2018-08-13)
|
## [0.23.1](https://github.com/libp2p/js-libp2p/compare/v0.23.0...v0.23.1) (2018-08-13)
|
||||||
|
|
||||||
|
@ -261,12 +261,12 @@ Required keys in the `options` object:
|
|||||||
- `key`: Buffer
|
- `key`: Buffer
|
||||||
- `options`: object of options
|
- `options`: object of options
|
||||||
- `options.maxTimeout`: Number milliseconds
|
- `options.maxTimeout`: Number milliseconds
|
||||||
|
- `options.maxNumProviders` maximum number of providers to find
|
||||||
|
|
||||||
#### `libp2p.contentRouting.provide(key, callback)`
|
#### `libp2p.contentRouting.provide(key, callback)`
|
||||||
|
|
||||||
- `key`: Buffer
|
- `key`: Buffer
|
||||||
|
|
||||||
|
|
||||||
#### `libp2p.handle(protocol, handlerFunc [, matchFunc])`
|
#### `libp2p.handle(protocol, handlerFunc [, matchFunc])`
|
||||||
|
|
||||||
> Handle new protocol
|
> Handle new protocol
|
||||||
|
29
appveyor.yml
29
appveyor.yml
@ -1,29 +0,0 @@
|
|||||||
# Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories.
|
|
||||||
version: "{build}"
|
|
||||||
|
|
||||||
environment:
|
|
||||||
matrix:
|
|
||||||
- nodejs_version: "6"
|
|
||||||
- nodejs_version: "8"
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
|
|
||||||
install:
|
|
||||||
# Install Node.js
|
|
||||||
- ps: Install-Product node $env:nodejs_version
|
|
||||||
|
|
||||||
# Upgrade npm
|
|
||||||
- npm install -g npm
|
|
||||||
|
|
||||||
# Output our current versions for debugging
|
|
||||||
- node --version
|
|
||||||
- npm --version
|
|
||||||
|
|
||||||
# Install our package dependencies
|
|
||||||
- npm install
|
|
||||||
|
|
||||||
test_script:
|
|
||||||
- npm run test:node
|
|
||||||
|
|
||||||
build: off
|
|
22
circle.yml
22
circle.yml
@ -1,22 +0,0 @@
|
|||||||
machine:
|
|
||||||
node:
|
|
||||||
version: 8.11.3
|
|
||||||
|
|
||||||
test:
|
|
||||||
post:
|
|
||||||
- npm run coverage -- --upload --providers coveralls
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
pre:
|
|
||||||
- google-chrome --version
|
|
||||||
- curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
|
||||||
- for v in $(curl http://archive.ubuntu.com/ubuntu/pool/main/n/nss/ | grep "href=" | grep "libnss3.*deb\"" -o | grep -o "libnss3.*deb" | grep "3.28" | grep "14.04"); do curl -L -o $v http://archive.ubuntu.com/ubuntu/pool/main/n/nss/$v; done && rm libnss3-tools*_i386.deb libnss3-dev*_i386.deb
|
|
||||||
- sudo dpkg -i google-chrome.deb || true
|
|
||||||
- sudo dpkg -i libnss3*.deb || true
|
|
||||||
- sudo apt-get update
|
|
||||||
- sudo apt-get install -f || true
|
|
||||||
- sudo dpkg -i libnss3*.deb
|
|
||||||
- sudo apt-get install -f
|
|
||||||
- sudo apt-get install --only-upgrade lsb-base
|
|
||||||
- sudo dpkg -i google-chrome.deb
|
|
||||||
- google-chrome --version
|
|
@ -10,4 +10,4 @@ This example creates a simple chat app in your terminal.
|
|||||||
1. Run the listener in window 1, `node listener.js`
|
1. Run the listener in window 1, `node listener.js`
|
||||||
2. Run the dialer in window 2, `node dialer.js`
|
2. Run the dialer in window 2, `node dialer.js`
|
||||||
3. Type a message in either window and hit _enter_
|
3. Type a message in either window and hit _enter_
|
||||||
4. Tell youself secrets to your hearts content!
|
4. Tell yourself secrets to your hearts content!
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const MulticastDNS = require('libp2p-mdns')
|
const MulticastDNS = require('libp2p-mdns')
|
||||||
const WS = require('libp2p-websockets')
|
const WS = require('libp2p-websockets')
|
||||||
const Bootstrap = require('libp2p-railing')
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
const spdy = require('libp2p-spdy')
|
const spdy = require('libp2p-spdy')
|
||||||
const KadDHT = require('libp2p-kad-dht')
|
const KadDHT = require('libp2p-kad-dht')
|
||||||
const mplex = require('libp2p-mplex')
|
const mplex = require('libp2p-mplex')
|
||||||
|
@ -18,8 +18,8 @@ various Peer Discovery modules and see the impact it has on your Peer count.
|
|||||||
1. Install IPFS locally if you dont already have it. [Install Guide](https://docs.ipfs.io/introduction/install/)
|
1. Install IPFS locally if you dont already have it. [Install Guide](https://docs.ipfs.io/introduction/install/)
|
||||||
2. Run the IPFS daemon: `ipfs daemon`
|
2. Run the IPFS daemon: `ipfs daemon`
|
||||||
3. The daemon will output a line about its API address, like `API server listening on /ip4/127.0.0.1/tcp/8080`
|
3. The daemon will output a line about its API address, like `API server listening on /ip4/127.0.0.1/tcp/8080`
|
||||||
4. In another window output the addresses of the node: `ipfs id`. Make note of the websocket address, is will contain `/ws/` in the address.
|
4. In another window output the addresses of the node: `ipfs id`. Make note of the websocket address, it will contain `/ws/` in the address.
|
||||||
5. In `./src/libp2p-bundle.js` replace the `delegatedApiOptions` host and port of your node if they are different.
|
5. In `./src/libp2p-bundle.js` check if the host and port of your node are correct, according to the previous step. If they are different, replace them.
|
||||||
6. In `./src/App.js` replace `BootstrapNode` with your nodes Websocket address from step 4.
|
6. In `./src/App.js` replace `BootstrapNode` with your nodes Websocket address from step 4.
|
||||||
7. Start this example:
|
7. Start this example:
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ const TCP = require('libp2p-tcp')
|
|||||||
const Mplex = require('libp2p-mplex')
|
const Mplex = require('libp2p-mplex')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
const PeerInfo = require('peer-info')
|
||||||
const Bootstrap = require('libp2p-railing')
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
const waterfall = require('async/waterfall')
|
const waterfall = require('async/waterfall')
|
||||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
const defaultsDeep = require('@nodeutils/defaults-deep')
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const MulticastDNS = require('libp2p-mdns')
|
const MulticastDNS = require('libp2p-mdns')
|
||||||
const WS = require('libp2p-websockets')
|
const WS = require('libp2p-websockets')
|
||||||
const Bootstrap = require('libp2p-railing')
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
const spdy = require('libp2p-spdy')
|
const spdy = require('libp2p-spdy')
|
||||||
const KadDHT = require('libp2p-kad-dht')
|
const KadDHT = require('libp2p-kad-dht')
|
||||||
const mplex = require('libp2p-mplex')
|
const mplex = require('libp2p-mplex')
|
||||||
|
@ -37,4 +37,4 @@ And that's it, from now on, all your libp2p communications are encrypted. Try ru
|
|||||||
|
|
||||||
If you want to want to learn more about how SECIO works, you can read the [great write up done by Dominic Tarr](https://github.com/auditdrivencrypto/secure-channel/blob/master/prior-art.md#ipfss-secure-channel).
|
If you want to want to learn more about how SECIO works, you can read the [great write up done by Dominic Tarr](https://github.com/auditdrivencrypto/secure-channel/blob/master/prior-art.md#ipfss-secure-channel).
|
||||||
|
|
||||||
Importante note: SECIO hasn't been audited and so, we do not recommend to trust its security. We intent to move to TLS 1.3 once the specification is finalized and an implementation exists that we can use.
|
Important note: SECIO hasn't been audited and so, we do not recommend to trust its security. We intent to move to TLS 1.3 once the specification is finalized and an implementation exists that we can use.
|
||||||
|
@ -17,11 +17,12 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"detect-dom-ready": "^1.0.2",
|
"detect-dom-ready": "^1.0.2",
|
||||||
|
"libp2p-bootstrap": "~0.9.3",
|
||||||
"libp2p-mplex": "~0.8.0",
|
"libp2p-mplex": "~0.8.0",
|
||||||
"libp2p-railing": "~0.9.1",
|
|
||||||
"libp2p-secio": "~0.10.0",
|
"libp2p-secio": "~0.10.0",
|
||||||
"libp2p-spdy": "~0.12.1",
|
"libp2p-spdy": "~0.12.1",
|
||||||
"libp2p-webrtc-star": "~0.15.3",
|
"libp2p-webrtc-star": "~0.15.3",
|
||||||
|
"libp2p-websocket-star": "~0.8.1",
|
||||||
"libp2p-websockets": "~0.12.0",
|
"libp2p-websockets": "~0.12.0",
|
||||||
"peer-info": "~0.14.1"
|
"peer-info": "~0.14.1"
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,16 @@
|
|||||||
|
|
||||||
const WebRTCStar = require('libp2p-webrtc-star')
|
const WebRTCStar = require('libp2p-webrtc-star')
|
||||||
const WebSockets = require('libp2p-websockets')
|
const WebSockets = require('libp2p-websockets')
|
||||||
|
const WebSocketStar = require('libp2p-websocket-star')
|
||||||
const Mplex = require('libp2p-mplex')
|
const Mplex = require('libp2p-mplex')
|
||||||
const SPDY = require('libp2p-spdy')
|
const SPDY = require('libp2p-spdy')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const Bootstrap = require('libp2p-railing')
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
const defaultsDeep = require('@nodeutils/defaults-deep')
|
||||||
const libp2p = require('../../../../')
|
const libp2p = require('../../../../')
|
||||||
|
|
||||||
// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-browser.json
|
// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-browser.json
|
||||||
const bootstrapers = [
|
const bootstrapList = [
|
||||||
'/dns4/ams-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
|
'/dns4/ams-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
|
||||||
'/dns4/sfo-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx',
|
'/dns4/sfo-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx',
|
||||||
'/dns4/lon-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
|
'/dns4/lon-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
|
||||||
@ -19,19 +20,21 @@ const bootstrapers = [
|
|||||||
'/dns4/sgp-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
|
'/dns4/sgp-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
|
||||||
'/dns4/nyc-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
|
'/dns4/nyc-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
|
||||||
'/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64',
|
'/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64',
|
||||||
'/dns4/wss0.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
|
'/dns4/node0.preload.ipfs.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
|
||||||
'/dns4/wss1.bootstrap.libp2p.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6'
|
'/dns4/node0.preload.ipfs.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6'
|
||||||
]
|
]
|
||||||
|
|
||||||
class Node extends libp2p {
|
class Node extends libp2p {
|
||||||
constructor (_options) {
|
constructor (_options) {
|
||||||
const wrtcStar = new WebRTCStar({ id: _options.peerInfo.id })
|
const wrtcStar = new WebRTCStar({ id: _options.peerInfo.id })
|
||||||
|
const wsstar = new WebSocketStar({ id: _options.peerInfo.id })
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
modules: {
|
modules: {
|
||||||
transport: [
|
transport: [
|
||||||
wrtcStar,
|
wrtcStar,
|
||||||
new WebSockets()
|
WebSockets,
|
||||||
|
wsstar
|
||||||
],
|
],
|
||||||
streamMuxer: [
|
streamMuxer: [
|
||||||
Mplex,
|
Mplex,
|
||||||
@ -42,6 +45,7 @@ class Node extends libp2p {
|
|||||||
],
|
],
|
||||||
peerDiscovery: [
|
peerDiscovery: [
|
||||||
wrtcStar.discovery,
|
wrtcStar.discovery,
|
||||||
|
wsstar.discovery,
|
||||||
Bootstrap
|
Bootstrap
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -55,14 +59,14 @@ class Node extends libp2p {
|
|||||||
},
|
},
|
||||||
bootstrap: {
|
bootstrap: {
|
||||||
interval: 10000,
|
interval: 10000,
|
||||||
enabled: false,
|
enabled: true,
|
||||||
list: bootstrapers
|
list: bootstrapList
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
relay: {
|
relay: {
|
||||||
enabled: false,
|
enabled: true,
|
||||||
hop: {
|
hop: {
|
||||||
enabled: false,
|
enabled: true,
|
||||||
active: false
|
active: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -70,6 +74,9 @@ class Node extends libp2p {
|
|||||||
dht: false,
|
dht: false,
|
||||||
pubsub: false
|
pubsub: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
connectionManager: {
|
||||||
|
maxPeers: 50
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint no-console: ["error", { allow: ["log"] }] */
|
||||||
|
/* eslint max-nested-callbacks: ["error", 5] */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const domReady = require('detect-dom-ready')
|
const domReady = require('detect-dom-ready')
|
||||||
@ -13,13 +14,25 @@ domReady(() => {
|
|||||||
return console.log('Could not create the Node, check if your browser has WebRTC Support', err)
|
return console.log('Could not create the Node, check if your browser has WebRTC Support', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
node.on('peer:discovery', (peerInfo) => {
|
let connections = {}
|
||||||
console.log('Discovered a peer')
|
|
||||||
const idStr = peerInfo.id.toB58String()
|
|
||||||
console.log('Discovered: ' + idStr)
|
|
||||||
|
|
||||||
|
node.on('peer:discovery', (peerInfo) => {
|
||||||
|
const idStr = peerInfo.id.toB58String()
|
||||||
|
if (connections[idStr]) {
|
||||||
|
// If we're already trying to connect to this peer, dont dial again
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log('Discovered a peer:', idStr)
|
||||||
|
|
||||||
|
connections[idStr] = true
|
||||||
node.dial(peerInfo, (err, conn) => {
|
node.dial(peerInfo, (err, conn) => {
|
||||||
if (err) { return console.log('Failed to dial:', idStr) }
|
if (err) {
|
||||||
|
// Prevent immediate connection retries from happening
|
||||||
|
// and include a 10s jitter
|
||||||
|
const timeToNextDial = 25 * 1000 + (Math.random(0) * 10000).toFixed(0)
|
||||||
|
console.log('Failed to dial:', idStr)
|
||||||
|
setTimeout(() => delete connections[idStr], timeToNextDial)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -34,8 +47,10 @@ domReady(() => {
|
|||||||
|
|
||||||
node.on('peer:disconnect', (peerInfo) => {
|
node.on('peer:disconnect', (peerInfo) => {
|
||||||
const idStr = peerInfo.id.toB58String()
|
const idStr = peerInfo.id.toB58String()
|
||||||
|
delete connections[idStr]
|
||||||
console.log('Lost connection to: ' + idStr)
|
console.log('Lost connection to: ' + idStr)
|
||||||
document.getElementById(idStr).remove()
|
const el = document.getElementById(idStr)
|
||||||
|
el && el.remove()
|
||||||
})
|
})
|
||||||
|
|
||||||
node.start((err) => {
|
node.start((err) => {
|
||||||
|
50
package.json
50
package.json
@ -1,9 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "libp2p",
|
"name": "libp2p",
|
||||||
"version": "0.23.1",
|
"version": "0.24.0",
|
||||||
"description": "JavaScript base class for libp2p bundles",
|
"description": "JavaScript base class for libp2p bundles",
|
||||||
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
|
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"src"
|
||||||
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "aegir lint",
|
"lint": "aegir lint",
|
||||||
"build": "aegir build",
|
"build": "aegir build",
|
||||||
@ -38,51 +42,52 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "^2.6.1",
|
"async": "^2.6.1",
|
||||||
"debug": "^4.0.1",
|
"debug": "^4.1.0",
|
||||||
"err-code": "^1.1.2",
|
"err-code": "^1.1.2",
|
||||||
"fsm-event": "^2.1.0",
|
"fsm-event": "^2.1.0",
|
||||||
"joi": "^13.6.0",
|
"joi": "^14.0.6",
|
||||||
"joi-browser": "^13.4.0",
|
"joi-browser": "^13.4.0",
|
||||||
"libp2p-connection-manager": "~0.0.2",
|
"libp2p-connection-manager": "~0.0.2",
|
||||||
"libp2p-floodsub": "~0.15.0",
|
"libp2p-floodsub": "~0.15.1",
|
||||||
"libp2p-ping": "~0.8.0",
|
"libp2p-ping": "~0.8.3",
|
||||||
"libp2p-switch": "~0.41.0",
|
"libp2p-switch": "~0.41.2",
|
||||||
"libp2p-websockets": "~0.12.0",
|
"libp2p-websockets": "~0.12.0",
|
||||||
"mafmt": "^6.0.2",
|
"mafmt": "^6.0.2",
|
||||||
"multiaddr": "^5.0.0",
|
"multiaddr": "^5.0.2",
|
||||||
"nock": "^9.4.3",
|
|
||||||
"peer-book": "~0.8.0",
|
"peer-book": "~0.8.0",
|
||||||
"peer-id": "~0.11.0",
|
"peer-id": "~0.12.0",
|
||||||
"peer-info": "~0.14.1"
|
"peer-info": "~0.14.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nodeutils/defaults-deep": "^1.1.0",
|
"@nodeutils/defaults-deep": "^1.1.0",
|
||||||
"aegir": "^15.2.0",
|
"aegir": "^17.0.1",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.2.0",
|
||||||
"chai-checkmark": "^1.0.1",
|
"chai-checkmark": "^1.0.1",
|
||||||
"cids": "~0.5.3",
|
"cids": "~0.5.5",
|
||||||
"dirty-chai": "^2.0.1",
|
"dirty-chai": "^2.0.1",
|
||||||
"electron-webrtc": "~0.3.0",
|
"electron-webrtc": "~0.3.0",
|
||||||
|
"interface-datastore": "~0.6.0",
|
||||||
"libp2p-bootstrap": "~0.9.3",
|
"libp2p-bootstrap": "~0.9.3",
|
||||||
"libp2p-circuit": "~0.2.1",
|
"libp2p-circuit": "~0.3.0",
|
||||||
"libp2p-delegated-content-routing": "~0.2.2",
|
"libp2p-delegated-content-routing": "~0.2.2",
|
||||||
"libp2p-delegated-peer-routing": "~0.2.2",
|
"libp2p-delegated-peer-routing": "~0.2.2",
|
||||||
"libp2p-kad-dht": "~0.10.5",
|
"libp2p-kad-dht": "~0.11.1",
|
||||||
"libp2p-mdns": "~0.12.0",
|
"libp2p-mdns": "~0.12.0",
|
||||||
"libp2p-mplex": "~0.8.2",
|
"libp2p-mplex": "~0.8.4",
|
||||||
"libp2p-secio": "~0.10.0",
|
"libp2p-secio": "~0.10.1",
|
||||||
"libp2p-spdy": "~0.12.1",
|
"libp2p-spdy": "~0.13.0",
|
||||||
"libp2p-tcp": "~0.13.0",
|
"libp2p-tcp": "~0.13.0",
|
||||||
"libp2p-webrtc-star": "~0.15.5",
|
"libp2p-webrtc-star": "~0.15.5",
|
||||||
"libp2p-websocket-star": "~0.8.1",
|
"libp2p-websocket-star": "~0.9.0",
|
||||||
"libp2p-websocket-star-rendezvous": "~0.2.3",
|
"libp2p-websocket-star-rendezvous": "~0.2.4",
|
||||||
"lodash.times": "^4.3.2",
|
"lodash.times": "^4.3.2",
|
||||||
|
"nock": "^10.0.2",
|
||||||
"pull-goodbye": "0.0.2",
|
"pull-goodbye": "0.0.2",
|
||||||
"pull-serializer": "~0.3.2",
|
"pull-serializer": "~0.3.2",
|
||||||
"pull-stream": "^3.6.9",
|
"pull-stream": "^3.6.9",
|
||||||
"sinon": "^6.3.4",
|
"sinon": "^7.1.1",
|
||||||
"webrtcsupport": "^2.2.0",
|
"webrtcsupport": "^2.2.0",
|
||||||
"wrtc": "~0.2.0"
|
"wrtc": "~0.3.2"
|
||||||
},
|
},
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Alan Shaw <alan@tableflip.io>",
|
"Alan Shaw <alan@tableflip.io>",
|
||||||
@ -96,6 +101,7 @@
|
|||||||
"Florian-Merle <florian.david.merle@gmail.com>",
|
"Florian-Merle <florian.david.merle@gmail.com>",
|
||||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||||
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
||||||
|
"Henrique Dias <hacdias@gmail.com>",
|
||||||
"Hugo Dias <hugomrdias@gmail.com>",
|
"Hugo Dias <hugomrdias@gmail.com>",
|
||||||
"Irakli Gozalishvili <rfobic@gmail.com>",
|
"Irakli Gozalishvili <rfobic@gmail.com>",
|
||||||
"Jacob Heun <jacobheun@gmail.com>",
|
"Jacob Heun <jacobheun@gmail.com>",
|
||||||
@ -113,6 +119,8 @@
|
|||||||
"Ryan Bell <ryan@piing.net>",
|
"Ryan Bell <ryan@piing.net>",
|
||||||
"Sönke Hahn <soenkehahn@gmail.com>",
|
"Sönke Hahn <soenkehahn@gmail.com>",
|
||||||
"Tiago Alves <alvesjtiago@gmail.com>",
|
"Tiago Alves <alvesjtiago@gmail.com>",
|
||||||
|
"Vasco Santos <vasco.santos@ua.pt>",
|
||||||
|
"Vasco Santos <vasco.santos@moxy.studio>",
|
||||||
"Volker Mische <volker.mische@gmail.com>",
|
"Volker Mische <volker.mische@gmail.com>",
|
||||||
"Zane Starr <zcstarr@gmail.com>",
|
"Zane Starr <zcstarr@gmail.com>",
|
||||||
"greenkeeperio-bot <support@greenkeeper.io>",
|
"greenkeeperio-bot <support@greenkeeper.io>",
|
||||||
|
@ -7,6 +7,7 @@ const ModuleSchema = Joi.alternatives().try(Joi.func(), Joi.object())
|
|||||||
const OptionsSchema = Joi.object({
|
const OptionsSchema = Joi.object({
|
||||||
// TODO: create proper validators for the generics
|
// TODO: create proper validators for the generics
|
||||||
connectionManager: Joi.object(),
|
connectionManager: Joi.object(),
|
||||||
|
datastore: Joi.object(),
|
||||||
peerInfo: Joi.object().required(),
|
peerInfo: Joi.object().required(),
|
||||||
peerBook: Joi.object(),
|
peerBook: Joi.object(),
|
||||||
modules: Joi.object().keys({
|
modules: Joi.object().keys({
|
||||||
|
@ -20,14 +20,11 @@ module.exports = (node) => {
|
|||||||
* @param {CID} key The CID key of the content to find
|
* @param {CID} key The CID key of the content to find
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {number} options.maxTimeout How long the query should run
|
* @param {number} options.maxTimeout How long the query should run
|
||||||
|
* @param {number} options.maxNumProviders - maximum number of providers to find
|
||||||
* @param {function(Error, Result<Array>)} callback
|
* @param {function(Error, Result<Array>)} callback
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
findProviders: (key, options, callback) => {
|
findProviders: (key, options, callback) => {
|
||||||
if (!routers.length) {
|
|
||||||
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof options === 'function') {
|
if (typeof options === 'function') {
|
||||||
callback = options
|
callback = options
|
||||||
options = {}
|
options = {}
|
||||||
@ -37,6 +34,10 @@ module.exports = (node) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!routers.length) {
|
||||||
|
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
|
||||||
|
}
|
||||||
|
|
||||||
const tasks = routers.map((router) => {
|
const tasks = routers.map((router) => {
|
||||||
return (cb) => router.findProviders(key, options, (err, results) => {
|
return (cb) => router.findProviders(key, options, (err, results) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const PeerInfo = require('peer-info')
|
const PeerInfo = require('peer-info')
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
const setImmediate = require('async/setImmediate')
|
const errCode = require('err-code')
|
||||||
|
|
||||||
module.exports = (node) => {
|
module.exports = (node) => {
|
||||||
/*
|
/*
|
||||||
@ -20,16 +20,21 @@ module.exports = (node) => {
|
|||||||
try {
|
try {
|
||||||
peer = multiaddr(peer)
|
peer = multiaddr(peer)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return setImmediate(() => callback(err))
|
return callback(
|
||||||
|
errCode(err, 'ERR_INVALID_MULTIADDR')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const peerIdB58Str = peer.getPeerId()
|
const peerIdB58Str = peer.getPeerId()
|
||||||
|
|
||||||
if (!peerIdB58Str) {
|
if (!peerIdB58Str) {
|
||||||
return setImmediate(() => {
|
return callback(
|
||||||
callback(new Error('peer multiaddr instance or string must include peerId'))
|
errCode(
|
||||||
})
|
new Error('peer multiaddr instance or string must include peerId'),
|
||||||
|
'ERR_INVALID_MULTIADDR'
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -48,9 +53,14 @@ module.exports = (node) => {
|
|||||||
return node.peerRouting.findPeer(peer, callback)
|
return node.peerRouting.findPeer(peer, callback)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return setImmediate(() => callback(new Error('peer type not recognized')))
|
return callback(
|
||||||
|
errCode(
|
||||||
|
new Error(`${p} is not a valid peer type`),
|
||||||
|
'ERR_INVALID_PEER_TYPE'
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
setImmediate(() => callback(null, p))
|
callback(null, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
src/index.js
23
src/index.js
@ -41,6 +41,7 @@ class Node extends EventEmitter {
|
|||||||
// and add default values where appropriate
|
// and add default values where appropriate
|
||||||
_options = validateConfig(_options)
|
_options = validateConfig(_options)
|
||||||
|
|
||||||
|
this.datastore = _options.datastore
|
||||||
this.peerInfo = _options.peerInfo
|
this.peerInfo = _options.peerInfo
|
||||||
this.peerBook = _options.peerBook || new PeerBook()
|
this.peerBook = _options.peerBook || new PeerBook()
|
||||||
|
|
||||||
@ -50,7 +51,10 @@ class Node extends EventEmitter {
|
|||||||
this._transport = [] // Transport instances/references
|
this._transport = [] // Transport instances/references
|
||||||
this._discovery = [] // Discovery service instances/references
|
this._discovery = [] // Discovery service instances/references
|
||||||
|
|
||||||
|
// create the switch, and listen for errors
|
||||||
this._switch = new Switch(this.peerInfo, this.peerBook, _options.switch)
|
this._switch = new Switch(this.peerInfo, this.peerBook, _options.switch)
|
||||||
|
this._switch.on('error', (...args) => this.emit('error', ...args))
|
||||||
|
|
||||||
this.stats = this._switch.stats
|
this.stats = this._switch.stats
|
||||||
this.connectionManager = new ConnectionManager(this, _options.connectionManager)
|
this.connectionManager = new ConnectionManager(this, _options.connectionManager)
|
||||||
|
|
||||||
@ -100,9 +104,7 @@ class Node extends EventEmitter {
|
|||||||
this._dht = new DHT(this._switch, {
|
this._dht = new DHT(this._switch, {
|
||||||
kBucketSize: this._config.dht.kBucketSize || 20,
|
kBucketSize: this._config.dht.kBucketSize || 20,
|
||||||
enabledDiscovery,
|
enabledDiscovery,
|
||||||
// TODO make datastore an option of libp2p itself so
|
datastore: this.datastore
|
||||||
// that other things can use it as well
|
|
||||||
datastore: dht.datastore
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,6 +165,21 @@ class Node extends EventEmitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides EventEmitter.emit to conditionally emit errors
|
||||||
|
* if there is a handler. If not, errors will be logged.
|
||||||
|
* @param {string} eventName
|
||||||
|
* @param {...any} args
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
emit (eventName, ...args) {
|
||||||
|
if (eventName === 'error' && !this._events.error) {
|
||||||
|
log.error(...args)
|
||||||
|
} else {
|
||||||
|
super.emit(eventName, ...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the libp2p node and all sub services
|
* Starts the libp2p node and all sub services
|
||||||
*
|
*
|
||||||
|
@ -22,15 +22,15 @@ module.exports = (node) => {
|
|||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
findPeer: (id, options, callback) => {
|
findPeer: (id, options, callback) => {
|
||||||
if (!routers.length) {
|
|
||||||
callback(errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE'))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof options === 'function') {
|
if (typeof options === 'function') {
|
||||||
callback = options
|
callback = options
|
||||||
options = {}
|
options = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!routers.length) {
|
||||||
|
callback(errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE'))
|
||||||
|
}
|
||||||
|
|
||||||
const tasks = routers.map((router) => {
|
const tasks = routers.map((router) => {
|
||||||
return (cb) => router.findPeer(id, options, (err, result) => {
|
return (cb) => router.findPeer(id, options, (err, result) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -107,6 +107,22 @@ describe('.contentRouting', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('nodeE.contentRouting.findProviders with limited number of providers', (done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => nodeA.contentRouting.provide(cid, cb),
|
||||||
|
(cb) => nodeB.contentRouting.provide(cid, cb),
|
||||||
|
(cb) => nodeC.contentRouting.provide(cid, cb)
|
||||||
|
], (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
nodeE.contentRouting.findProviders(cid, { maxNumProviders: 2 }, (err, providers) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(providers).to.have.length(2)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('nodeC.contentRouting.findProviders for non existing record (timeout)', (done) => {
|
it('nodeC.contentRouting.findProviders for non existing record (timeout)', (done) => {
|
||||||
const cid = new CID('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSnnnn')
|
const cid = new CID('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSnnnn')
|
||||||
|
|
||||||
@ -367,4 +383,29 @@ describe('.contentRouting', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('no routers', () => {
|
||||||
|
let nodeA
|
||||||
|
before((done) => {
|
||||||
|
createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeA = node
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('.findProviders should return an error with no options', (done) => {
|
||||||
|
nodeA.contentRouting.findProviders('a cid', (err) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('.findProviders should return an error with options', (done) => {
|
||||||
|
nodeA.contentRouting.findProviders('a cid', { maxTimeout: 5000 }, (err) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -80,4 +80,25 @@ describe('libp2p creation', () => {
|
|||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not throw errors from switch if node has no error listeners', (done) => {
|
||||||
|
createNode([], {}, (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
node._switch.emit('error', new Error('bad things'))
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should emit errors from switch if node has error listeners', (done) => {
|
||||||
|
const error = new Error('bad things')
|
||||||
|
createNode([], {}, (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
node.once('error', (err) => {
|
||||||
|
expect(err).to.eql(error)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
node._switch.emit('error', error)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -6,14 +6,18 @@ const chai = require('chai')
|
|||||||
chai.use(require('dirty-chai'))
|
chai.use(require('dirty-chai'))
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
const MemoryStore = require('interface-datastore').MemoryDatastore
|
||||||
|
|
||||||
const createNode = require('./utils/create-node')
|
const createNode = require('./utils/create-node')
|
||||||
|
|
||||||
describe('.dht', () => {
|
describe('.dht', () => {
|
||||||
describe('enabled', () => {
|
describe('enabled', () => {
|
||||||
let nodeA
|
let nodeA
|
||||||
|
const datastore = new MemoryStore()
|
||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
createNode('/ip4/0.0.0.0/tcp/0', {
|
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||||
|
datastore,
|
||||||
config: {
|
config: {
|
||||||
EXPERIMENTAL: {
|
EXPERIMENTAL: {
|
||||||
dht: true
|
dht: true
|
||||||
|
@ -11,7 +11,7 @@ describe('getPeerInfo', () => {
|
|||||||
it('should callback with error for invalid string multiaddr', (done) => {
|
it('should callback with error for invalid string multiaddr', (done) => {
|
||||||
getPeerInfo(null)('INVALID MULTIADDR', (err) => {
|
getPeerInfo(null)('INVALID MULTIADDR', (err) => {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
expect(err.message).to.contain('must start with a "/"')
|
expect(err.code).to.eql('ERR_INVALID_MULTIADDR')
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -19,7 +19,15 @@ describe('getPeerInfo', () => {
|
|||||||
it('should callback with error for invalid non-peer multiaddr', (done) => {
|
it('should callback with error for invalid non-peer multiaddr', (done) => {
|
||||||
getPeerInfo(null)('/ip4/8.8.8.8/tcp/1080', (err) => {
|
getPeerInfo(null)('/ip4/8.8.8.8/tcp/1080', (err) => {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
expect(err.message).to.equal('peer multiaddr instance or string must include peerId')
|
expect(err.code).to.equal('ERR_INVALID_MULTIADDR')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should callback with error for invalid non-peer multiaddr', (done) => {
|
||||||
|
getPeerInfo(null)(undefined, (err) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
expect(err.code).to.eql('ERR_INVALID_PEER_TYPE')
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -29,10 +29,12 @@ describe('multiaddr trim', () => {
|
|||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
const multiaddrs = node.peerInfo.multiaddrs.toArray()
|
const multiaddrs = node.peerInfo.multiaddrs.toArray()
|
||||||
|
expect(multiaddrs.length).to.be.at.least(2)
|
||||||
|
// ensure the p2p-webrtc-direct address has been trimmed
|
||||||
|
multiaddrs.forEach((addr) => {
|
||||||
|
expect(() => addr.decapsulate('/ip4/0.0.0.0/tcp/999/wss/p2p-webrtc-direct')).to.throw()
|
||||||
|
})
|
||||||
|
|
||||||
expect(multiaddrs.length).to.at.least(2)
|
|
||||||
expect(multiaddrs[0].toString())
|
|
||||||
.to.match(/^\/ip4\/127\.0\.0\.1\/tcp\/[0-9]+\/ws\/ipfs\/\w+$/)
|
|
||||||
node.stop(done)
|
node.stop(done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -266,4 +266,29 @@ describe('.peerRouting', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('no routers', () => {
|
||||||
|
let nodeA
|
||||||
|
before((done) => {
|
||||||
|
createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeA = node
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('.findPeer should return an error with no options', (done) => {
|
||||||
|
nodeA.peerRouting.findPeer('a cid', (err) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('.findPeer should return an error with options', (done) => {
|
||||||
|
nodeA.peerRouting.findPeer('a cid', { maxTimeout: 5000 }, (err) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -28,8 +28,6 @@ function teardown (nodeA, nodeB, callback) {
|
|||||||
|
|
||||||
describe('stream muxing', () => {
|
describe('stream muxing', () => {
|
||||||
it('spdy only', function (done) {
|
it('spdy only', function (done) {
|
||||||
this.timeout(5 * 1000)
|
|
||||||
|
|
||||||
let nodeA
|
let nodeA
|
||||||
let nodeB
|
let nodeB
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user