Compare commits

...

39 Commits

Author SHA1 Message Date
Vasco Santos
e0597b35b9 chore: release version v0.30.13 2021-08-19 13:28:31 +02:00
Vasco Santos
4e494ad3d5 chore: update contributors 2021-08-19 13:28:30 +02:00
Vasco Santos
356f4f7d48 chore: add uint8array to deps in 0.30.x line 2021-08-19 13:26:47 +02:00
Vasco Santos
8e1743cac4 chore: release version v0.30.12 2021-03-27 13:43:36 +01:00
Vasco Santos
3ea95ce642 chore: update contributors 2021-03-27 13:43:35 +01:00
Alex Potsides
c4cae29ef3 chore: do not look up external IP during test (#906)
The NAT manager test will throw if the current computer is behind a
double NAT as at runtime it won't be possible to map external ports.

We don't care about that during the test so configure a fake external
IP so the test will still test the shut-down functionality on a computer
that is behind a double NAT.
2021-03-27 13:15:35 +01:00
Alex Potsides
a7128f07ec fix: the API of es6-promisify is not the same as promisify-es6 (#905) 2021-03-26 18:13:07 +01:00
Vasco Santos
c3e147df6b chore: delegates config md properties for client (#903) 2021-03-24 09:35:17 +01:00
Vasco Santos
b89445274d chore: release version v0.30.11 2021-03-23 09:51:32 +01:00
Vasco Santos
b9e3bcd91e chore: update contributors 2021-03-23 09:51:32 +01:00
Vasco Santos
f5c1cd1fb0 fix: interface-datastore update 2021-03-23 09:39:28 +01:00
Vasco Santos
975e4b0fe0 chore: increase bundle size 2021-03-23 09:39:28 +01:00
Vasco Santos
9504f1951a fix: connection direction should be only inbound or outbound 2021-03-23 09:39:28 +01:00
Vasco Santos
8e1fc78353 chore: release version v0.30.10 2021-03-09 18:52:37 +01:00
Vasco Santos
8895a092b6 chore: update contributors 2021-03-09 18:52:37 +01:00
TJKoury
f2f361998d chore: swap promisify to maintained package (#896)
Co-authored-by: Vasco Santos <vasco.santos@moxy.studio>
2021-03-09 16:55:38 +01:00
Vasco Santos
5f702f3481 fix: conn mgr access to moving averages record object (#897)
* fix: conn mgr access to moving averages record object

* chore: remove node 12

* chore: add parcel workaround
2021-03-09 16:51:41 +01:00
Philipp Muens
03b34cac7d docs: fix link to connection encryption example (#894) 2021-03-02 13:07:52 +01:00
Aleksei
9c67364caa Add an example of webrtc-direct (#868)
Co-authored-by: Vasco Santos <vasco.santos@moxy.studio>
2021-02-25 16:34:02 +01:00
Vasco Santos
a1424826e7 chore: release version v0.30.9 2021-02-25 15:31:26 +01:00
Vasco Santos
3d5bba070b chore: update contributors 2021-02-25 15:31:26 +01:00
Vasco Santos
3f314d5e90 fix: transport manager fault tolerance should include tolerance to transport listen fail (#893) 2021-02-25 15:23:07 +01:00
Miguel Mota
4ee3e1973b chore: minor grammar fixes on discovery example (#890) 2021-02-18 11:36:35 +01:00
Vasco Santos
fc6558b897 chore: release version v0.30.8 2021-02-11 14:57:43 +01:00
Vasco Santos
3e302570e5 chore: update contributors 2021-02-11 14:57:43 +01:00
Vasco Santos
a34d2bbcc3 fix: routers should only use dht if enabled (#885) 2021-02-11 14:37:34 +01:00
Vasco Santos
9941414a91 chore: update delegates config docs to use http client (#853) 2021-02-11 11:42:10 +01:00
Vasco Santos
46cb46188a chore: add discovery example with relay and pubsub discovery (#855) 2021-02-11 11:37:11 +01:00
Vasco Santos
1af8472dc6 chore: add transports example (#851) 2021-02-11 11:12:23 +01:00
Vasco Santos
f6a4cad827 chore: add pubsub example tests (#850) 2021-02-10 21:00:40 +01:00
Vasco Santos
b1079474de chore: add protocol and stream muxing example tests (#849) 2021-02-10 15:40:19 +01:00
Vasco Santos
a150ea60c5 chore: add peer and content routing example tests (#848) 2021-02-08 11:03:42 +01:00
Vasco Santos
aec8e3d3bb chore: release version v0.30.7 2021-02-01 18:40:05 +01:00
Vasco Santos
3abf4aeb35 chore: update contributors 2021-02-01 18:40:05 +01:00
Alex Potsides
a36b2112aa fix: do not add observed address received from peers (#882) 2021-02-01 18:32:57 +01:00
Vasco Santos
8d3b61710a chore: release version v0.30.6 2021-01-29 14:39:41 +01:00
Vasco Santos
5dbbeef311 chore: update contributors 2021-01-29 14:39:41 +01:00
Vasco Santos
3e7594f697 fix: peer discovery type in config (#878)
to any
2021-01-29 14:32:13 +01:00
Alex Potsides
ce2a624a09 fix: unref nat manager retries (#877)
The retry operation in the NAT Manager can prevent node from shutting
down, so unref the retries so they don't keep adding work to the
event loop.
2021-01-29 14:09:59 +01:00
46 changed files with 1210 additions and 85 deletions

View File

@@ -48,7 +48,7 @@ const after = async () => {
}
module.exports = {
bundlesize: { maxSize: '215kB' },
bundlesize: { maxSize: '223kB' },
hooks: {
pre: before,
post: after

View File

@@ -27,7 +27,7 @@ jobs:
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
node: [12, 14]
node: [14]
fail-fast: true
steps:
- uses: actions/checkout@v2
@@ -79,20 +79,6 @@ jobs:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- connection-encryption
test-echo-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- echo
test-libp2p-in-the-browser-example:
needs: check
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- libp2p-in-the-browser
test-discovery-mechanisms-example:
needs: check
runs-on: macos-latest
@@ -100,6 +86,27 @@ jobs:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- discovery-mechanisms
test-echo-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- echo
test-libp2p-in-the-browser-example:
needs: check
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- libp2p-in-the-browser
test-peer-and-content-routing-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- peer-and-content-routing
test-pnet-example:
needs: check
runs-on: ubuntu-latest
@@ -107,3 +114,31 @@ jobs:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- pnet
test-protocol-and-stream-muxing-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- protocol-and-stream-muxing
test-pubsub-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- pubsub
test-transports-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- transports
test-webrtc-direct-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- webrtc-direct

View File

@@ -1,3 +1,72 @@
## [0.30.13](https://github.com/libp2p/js-libp2p/compare/v0.30.12...v0.30.13) (2021-08-19)
## [0.30.12](https://github.com/libp2p/js-libp2p/compare/v0.30.11...v0.30.12) (2021-03-27)
### Bug Fixes
* the API of es6-promisify is not the same as promisify-es6 ([#905](https://github.com/libp2p/js-libp2p/issues/905)) ([a7128f0](https://github.com/libp2p/js-libp2p/commit/a7128f07ec8d4b729145ecfc6ad1d585ffddea46))
## [0.30.11](https://github.com/libp2p/js-libp2p/compare/v0.30.10...v0.30.11) (2021-03-23)
### Bug Fixes
* connection direction should be only inbound or outbound ([9504f19](https://github.com/libp2p/js-libp2p/commit/9504f1951a3cca55bb7b4e25e4934e4024034ee8))
* interface-datastore update ([f5c1cd1](https://github.com/libp2p/js-libp2p/commit/f5c1cd1fb07bc73cf9d9da3c2eb4327bed4279a4))
## [0.30.10](https://github.com/libp2p/js-libp2p/compare/v0.30.9...v0.30.10) (2021-03-09)
### Bug Fixes
* conn mgr access to moving averages record object ([#897](https://github.com/libp2p/js-libp2p/issues/897)) ([5f702f3](https://github.com/libp2p/js-libp2p/commit/5f702f3481afd4ad4fbc89f0e9b75a6d56b03520))
## [0.30.9](https://github.com/libp2p/js-libp2p/compare/v0.30.8...v0.30.9) (2021-02-25)
### Bug Fixes
* transport manager fault tolerance should include tolerance to transport listen fail ([#893](https://github.com/libp2p/js-libp2p/issues/893)) ([3f314d5](https://github.com/libp2p/js-libp2p/commit/3f314d5e90f74583b721386d0c9c5d8363cd4de7))
## [0.30.8](https://github.com/libp2p/js-libp2p/compare/v0.30.7...v0.30.8) (2021-02-11)
### Bug Fixes
* routers should only use dht if enabled ([#885](https://github.com/libp2p/js-libp2p/issues/885)) ([a34d2bb](https://github.com/libp2p/js-libp2p/commit/a34d2bbcc3d69ec3006137a909a7e8c53b9d378e))
## [0.30.7](https://github.com/libp2p/js-libp2p/compare/v0.30.6...v0.30.7) (2021-02-01)
### Bug Fixes
* do not add observed address received from peers ([#882](https://github.com/libp2p/js-libp2p/issues/882)) ([a36b211](https://github.com/libp2p/js-libp2p/commit/a36b2112aafcee309a02de0cff5440cf69cd53a7))
## [0.30.6](https://github.com/libp2p/js-libp2p/compare/v0.30.5...v0.30.6) (2021-01-29)
### Bug Fixes
* peer discovery type in config ([#878](https://github.com/libp2p/js-libp2p/issues/878)) ([3e7594f](https://github.com/libp2p/js-libp2p/commit/3e7594f69733bf374b374a6065458fa6cae81c5f))
* unref nat manager retries ([#877](https://github.com/libp2p/js-libp2p/issues/877)) ([ce2a624](https://github.com/libp2p/js-libp2p/commit/ce2a624a09b3107c0b2b4752e666804ecea54fb5))
## [0.30.5](https://github.com/libp2p/js-libp2p/compare/v0.30.4...v0.30.5) (2021-01-28)

View File

@@ -391,6 +391,7 @@ const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
const ipfsHttpClient = require('ipfs-http-client')
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
const DelegatedContentRouter = require('libp2p-delegated-content-routing')
const PeerId = require('peer-id')
@@ -398,17 +399,25 @@ const PeerId = require('peer-id')
// create a peerId
const peerId = await PeerId.create()
const delegatedPeerRouting = new DelegatedPeerRouter(ipfsHttpClient({
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
protocol: 'https',
port: 443
}))
const delegatedContentRouting = new DelegatedContentRouter(peerId, ipfsHttpClient({
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
protocol: 'https',
port: 443
}))
const node = await Libp2p.create({
modules: {
transport: [TCP],
streamMuxer: [MPLEX],
connEncryption: [NOISE],
contentRouting: [
new DelegatedContentRouter(peerId)
],
peerRouting: [
new DelegatedPeerRouter()
],
contentRouting: [delegatedContentRouting],
peerRouting: [delegatedPeerRouting],
},
peerId,
peerRouting: { // Peer routing configuration

View File

@@ -8,7 +8,7 @@ Let us know if you find any issues, or if you want to contribute and add a new t
- [Transports](./transports)
- [Protocol and Stream Muxing](./protocol-and-stream-muxing)
- [Encrypted Communications](./encrypted-communications)
- [Connection Encryption](./connection-encryption)
- [Discovery Mechanisms](./discovery-mechanisms)
- [Peer and Content Routing](./peer-and-content-routing)
- [PubSub](./pubsub)

View File

@@ -0,0 +1,68 @@
/* eslint-disable no-console */
'use strict'
const Libp2p = require('../../')
const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
const Gossipsub = require('libp2p-gossipsub')
const Bootstrap = require('libp2p-bootstrap')
const PubsubPeerDiscovery = require('libp2p-pubsub-peer-discovery')
const createRelayServer = require('libp2p-relay-server')
const createNode = async (bootstrapers) => {
const node = await Libp2p.create({
addresses: {
listen: ['/ip4/0.0.0.0/tcp/0']
},
modules: {
transport: [TCP],
streamMuxer: [Mplex],
connEncryption: [NOISE],
pubsub: Gossipsub,
peerDiscovery: [Bootstrap, PubsubPeerDiscovery]
},
config: {
peerDiscovery: {
[PubsubPeerDiscovery.tag]: {
interval: 1000,
enabled: true
},
[Bootstrap.tag]: {
enabled: true,
list: bootstrapers
}
}
}
})
return node
}
;(async () => {
const relay = await createRelayServer({
listenAddresses: ['/ip4/0.0.0.0/tcp/0']
})
console.log(`libp2p relay starting with id: ${relay.peerId.toB58String()}`)
await relay.start()
const relayMultiaddrs = relay.multiaddrs.map((m) => `${m.toString()}/p2p/${relay.peerId.toB58String()}`)
const [node1, node2] = await Promise.all([
createNode(relayMultiaddrs),
createNode(relayMultiaddrs)
])
node1.on('peer:discovery', (peerId) => {
console.log(`Peer ${node1.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
})
node2.on('peer:discovery', (peerId) => {
console.log(`Peer ${node2.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
})
;[node1, node2].forEach((node, index) => console.log(`Node ${index} starting with id: ${node.peerId.toB58String()}`))
await Promise.all([
node1.start(),
node2.start()
])
})();

View File

@@ -2,13 +2,13 @@
A Peer Discovery module enables libp2p to find peers to connect to. Think of these mechanisms as ways to join the rest of the network, as railing points.
With these system, a libp2p node can both have a set of nodes to always connect on boot (bootstraper nodes), discover nodes through locality (e.g connected in the same LAN) or through serendipity (random walks on a DHT).
With this system, a libp2p node can both have a set of nodes to always connect on boot (bootstraper nodes), discover nodes through locality (e.g connected in the same LAN) or through serendipity (random walks on a DHT).
These mechanisms save configuration and enable a node to operate without any explicit dials, it will just work. Once new peers are discovered, their known data is stored in the peer's PeerStore.
## 1. Bootstrap list of Peers when booting a node
For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex and NOISE. You can see the complete example at [1.js](./1.js).
For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex, and NOISE. You can see the complete example at [1.js](./1.js).
First, we create our libp2p node.
@@ -16,7 +16,7 @@ First, we create our libp2p node.
const Libp2p = require('libp2p')
const Bootstrap = require('libp2p-bootstrap')
const node = Libp2p.create({
const node = await Libp2p.create({
modules: {
transport: [ TCP ],
streamMuxer: [ Mplex ],
@@ -156,10 +156,103 @@ Discovered: QmSSbQpuKrxkoXHm1v4Pi35hPN5hUHMZoBoawEs2Nhvi8m
Discovered: QmRcXXhtG8vTqwVBRonKWtV4ovDoC1Fe56WYtcrw694eiJ
```
## 3. Where to find other Peer Discovery Mechanisms
## 3. Pubsub based Peer Discovery
For this example, we need [`libp2p-pubsub-peer-discovery`](https://github.com/libp2p/js-libp2p-pubsub-peer-discovery/), go ahead and `npm install` it. You also need to spin up a set of [`libp2p-relay-servers`](https://github.com/libp2p/js-libp2p-relay-server). These servers act as relay servers and a peer discovery source.
In the context of this example, we will create and run the `libp2p-relay-server` in the same code snippet. You can find the complete solution at [3.js](./3.js).
You can create your libp2p nodes as follows:
```js
const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
const Gossipsub = require('libp2p-gossipsub')
const Bootstrap = require('libp2p-bootstrap')
const PubsubPeerDiscovery = require('libp2p-pubsub-peer-discovery')
const createNode = async (bootstrapers) => {
const node = await Libp2p.create({
addresses: {
listen: ['/ip4/0.0.0.0/tcp/0']
},
modules: {
transport: [TCP],
streamMuxer: [Mplex],
connEncryption: [NOISE],
pubsub: Gossipsub,
peerDiscovery: [Bootstrap, PubsubPeerDiscovery]
},
config: {
peerDiscovery: {
[PubsubPeerDiscovery.tag]: {
interval: 1000,
enabled: true
},
[Bootstrap.tag]: {
enabled: true,
list: bootstrapers
}
}
}
})
return node
}
```
We will use the `libp2p-relay-server` as bootstrap nodes for the libp2p nodes, so that they establish a connection with the relay after starting. As a result, after they establish a connection with the relay, the pubsub discovery will kick in and the relay will advertise them.
```js
const relay = await createRelayServer({
listenAddresses: ['/ip4/0.0.0.0/tcp/0']
})
console.log(`libp2p relay starting with id: ${relay.peerId.toB58String()}`)
await relay.start()
const relayMultiaddrs = relay.multiaddrs.map((m) => `${m.toString()}/p2p/${relay.peerId.toB58String()}`)
const [node1, node2] = await Promise.all([
createNode(relayMultiaddrs),
createNode(relayMultiaddrs)
])
node1.on('peer:discovery', (peerId) => {
console.log(`Peer ${node1.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
})
node2.on('peer:discovery', (peerId) => {
console.log(`Peer ${node2.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
})
;[node1, node2].forEach((node, index) => console.log(`Node ${index} starting with id: ${node.peerId.toB58String()}`))
await Promise.all([
node1.start(),
node2.start()
])
```
If you run this example, you will see the other peers being discovered.
```bash
> node 3.js
libp2p relay starting with id: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo
Node 0 starting with id: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N
Node 1 starting with id: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv
Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo
Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo
Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N
Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv
```
Taking into account the output, after the relay and both libp2p nodes start, both libp2p nodes will discover the bootstrap node (relay) and connect with it. After establishing a connection with the relay, they will discover each other.
This is really useful when running libp2p in constrained environments like a browser. You can run a set of `libp2p-relay-server` nodes that will be responsible for both relaying websocket connections between browser nodes and for discovering other browser peers.
## 4. Where to find other Peer Discovery Mechanisms
There are plenty more Peer Discovery Mechanisms out there, you can:
- Find one in [libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star). Yes, a transport with discovery capabilities! This happens because WebRTC requires a rendezvous point for peers to exchange [SDP](https://tools.ietf.org/html/rfc4317) offer, which means we have one or more points that can introduce peers to each other. Think of it as MulticastDNS for the Web, as in MulticastDNS only works in LAN.
- Any DHT will offer you a discovery capability. You can simple _random-walk_ the routing tables to find other peers to connect to. For example [libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) can be used for peer discovery. An example how to configure it to enable random walks can be found [here](https://github.com/libp2p/js-libp2p/blob/v0.28.4/doc/CONFIGURATION.md#customizing-dht).
- Any DHT will offer you a discovery capability. You can simple _random-walk_ the routing tables to find other peers to connect to. For example [libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) can be used for peer discovery. An example of how to configure it to enable random walks can be found [here](https://github.com/libp2p/js-libp2p/blob/v0.28.4/doc/CONFIGURATION.md#customizing-dht).
- You can create your own Discovery service, a registry, a list, a radio beacon, you name it!

View File

@@ -0,0 +1,35 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pWaitFor = require('p-wait-for')
const uint8ArrayToString = require('uint8arrays/to-string')
const discoveredCopy = 'discovered:'
async function test() {
let discoverCount = 0
process.stdout.write('3.js\n')
const proc = execa('node', [path.join(__dirname, '3.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
// Discovered or Connected
if (line.includes(discoveredCopy)) {
discoverCount++
}
})
await pWaitFor(() => discoverCount === 4)
proc.kill()
}
module.exports = test

View File

@@ -2,10 +2,12 @@
const test1 = require('./test-1')
const test2 = require('./test-2')
const test3 = require('./test-3')
async function test () {
await test1()
await test2()
await test3()
}
module.exports = test

View File

@@ -15,7 +15,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"@babel/preset-env": "^7.8.3",
"@babel/preset-env": "^7.13.0",
"libp2p": "../../",
"libp2p-bootstrap": "^0.12.1",
"libp2p-mplex": "^0.10.0",
@@ -24,11 +24,11 @@
"libp2p-websockets": "^0.14.0"
},
"devDependencies": {
"@babel/cli": "^7.8.3",
"@babel/core": "^7.8.3",
"@babel/cli": "^7.13.10",
"@babel/core": "^7.13.0",
"babel-plugin-syntax-async-functions": "^6.13.0",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-polyfill": "^6.26.0",
"parcel-bundler": "^1.12.4"
"parcel-bundler": "1.12.3"
}
}

View File

@@ -10,6 +10,8 @@
"dependencies": {
"execa": "^2.1.0",
"fs-extra": "^8.1.0",
"libp2p-pubsub-peer-discovery": "^3.0.0",
"libp2p-relay-server": "^0.1.2",
"p-defer": "^3.0.0",
"which": "^2.0.1"
},

View File

@@ -0,0 +1,36 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pWaitFor = require('p-wait-for')
const uint8ArrayToString = require('uint8arrays/to-string')
async function test() {
process.stdout.write('1.js\n')
const addrs = []
let foundIt = false
const proc = execa('node', [path.join(__dirname, '1.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
// Discovered peer
if (!foundIt && line.includes('Found it, multiaddrs are:')) {
foundIt = true
}
addrs.push(line)
})
await pWaitFor(() => addrs.length === 2)
proc.kill()
}
module.exports = test

View File

@@ -0,0 +1,40 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pDefer = require('p-defer')
const uint8ArrayToString = require('uint8arrays/to-string')
const providedCopy = 'is providing'
const foundCopy = 'Found provider:'
async function test() {
process.stdout.write('2.js\n')
const providedDefer = pDefer()
const foundDefer = pDefer()
const proc = execa('node', [path.join(__dirname, '2.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
if (line.includes(providedCopy)) {
providedDefer.resolve()
} else if (line.includes(foundCopy)) {
foundDefer.resolve()
}
})
await Promise.all([
providedDefer.promise,
foundDefer.promise
])
proc.kill()
}
module.exports = test

View File

@@ -0,0 +1,11 @@
'use strict'
const test1 = require('./test-1')
const test2 = require('./test-2')
async function test() {
await test1()
await test2()
}
module.exports = test

View File

@@ -0,0 +1,31 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pDefer = require('p-defer')
const uint8ArrayToString = require('uint8arrays/to-string')
async function test() {
const messageDefer = pDefer()
process.stdout.write('1.js\n')
const proc = execa('node', [path.join(__dirname, '1.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
if (line.includes('my own protocol, wow!')) {
messageDefer.resolve()
}
})
await messageDefer.promise
proc.kill()
}
module.exports = test

View File

@@ -0,0 +1,38 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pWaitFor = require('p-wait-for')
const uint8ArrayToString = require('uint8arrays/to-string')
const messages = [
'protocol (a)',
'protocol (b)',
'another stream on protocol (b)'
]
async function test() {
process.stdout.write('2.js\n')
let count = 0
const proc = execa('node', [path.join(__dirname, '2.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
if (messages.find((m) => line.includes(m))) {
count += 1
}
})
await pWaitFor(() => count === messages.length)
proc.kill()
}
module.exports = test

View File

@@ -0,0 +1,37 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pWaitFor = require('p-wait-for')
const uint8ArrayToString = require('uint8arrays/to-string')
const messages = [
'from 1 to 2',
'from 2 to 1'
]
async function test() {
process.stdout.write('3.js\n')
let count = 0
const proc = execa('node', [path.join(__dirname, '3.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
if (messages.find((m) => line.includes(m))) {
count += 1
}
})
await pWaitFor(() => count === messages.length)
proc.kill()
}
module.exports = test

View File

@@ -0,0 +1,13 @@
'use strict'
const test1 = require('./test-1')
const test2 = require('./test-2')
const test3 = require('./test-3')
async function test() {
await test1()
await test2()
await test3()
}
module.exports = test

View File

@@ -0,0 +1,67 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pDefer = require('p-defer')
const uint8ArrayToString = require('uint8arrays/to-string')
const stdout = [
{
topic: 'banana',
messageCount: 2
},
{
topic: 'apple',
messageCount: 2
},
{
topic: 'car',
messageCount: 0
},
{
topic: 'orange',
messageCount: 2
},
]
async function test () {
const defer = pDefer()
let topicCount = 0
let topicMessageCount = 0
process.stdout.write('message-filtering/1.js\n')
const proc = execa('node', [path.join(__dirname, '1.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
// End
if (topicCount === stdout.length) {
defer.resolve()
proc.all.removeAllListeners('data')
}
process.stdout.write(data)
const line = uint8ArrayToString(data)
if (stdout[topicCount] && line.includes(stdout[topicCount].topic)) {
// Validate previous number of messages
if (topicCount > 0 && topicMessageCount > stdout[topicCount - 1].messageCount) {
defer.reject()
throw new Error(`topic ${stdout[topicCount - 1].topic} had ${topicMessageCount} messages instead of ${stdout[topicCount - 1].messageCount}`)
}
topicCount++
topicMessageCount = 0
} else {
topicMessageCount++
}
})
await defer.promise
proc.kill()
}
module.exports = test

30
examples/pubsub/test-1.js Normal file
View File

@@ -0,0 +1,30 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pDefer = require('p-defer')
const uint8ArrayToString = require('uint8arrays/to-string')
async function test () {
const defer = pDefer()
process.stdout.write('1.js\n')
const proc = execa('node', [path.join(__dirname, '1.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
if (line.includes('node1 received: Bird bird bird, bird is the word!')) {
defer.resolve()
}
})
await defer.promise
proc.kill()
}
module.exports = test

11
examples/pubsub/test.js Normal file
View File

@@ -0,0 +1,11 @@
'use strict'
const test1 = require('./test-1')
const testMessageFiltering = require('./message-filtering/test')
async function test() {
await test1()
await testMessageFiltering()
}
module.exports = test

View File

@@ -0,0 +1,38 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pDefer = require('p-defer')
const uint8ArrayToString = require('uint8arrays/to-string')
async function test () {
const deferStarted = pDefer()
const deferListen = pDefer()
process.stdout.write('1.js\n')
const proc = execa('node', [path.join(__dirname, '1.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
if (line.includes('node has started (true/false): true')) {
deferStarted.resolve()
} else if (line.includes('p2p')) {
deferListen.resolve()
}
})
await Promise.all([
deferStarted.promise,
deferListen.promise
])
proc.kill()
}
module.exports = test

View File

@@ -0,0 +1,30 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pDefer = require('p-defer')
const uint8ArrayToString = require('uint8arrays/to-string')
async function test () {
const defer = pDefer()
process.stdout.write('2.js\n')
const proc = execa('node', [path.join(__dirname, '2.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
if (line.includes('Hello p2p world!')) {
defer.resolve()
}
})
await defer.promise
proc.kill()
}
module.exports = test

View File

@@ -0,0 +1,41 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pDefer = require('p-defer')
const uint8ArrayToString = require('uint8arrays/to-string')
async function test () {
const deferNode1 = pDefer()
const deferNode2 = pDefer()
const deferNode3 = pDefer()
process.stdout.write('3.js\n')
const proc = execa('node', [path.join(__dirname, '3.js')], {
cwd: path.resolve(__dirname),
all: true
})
proc.all.on('data', async (data) => {
process.stdout.write(data)
const line = uint8ArrayToString(data)
if (line.includes('node 1 dialed to node 2 successfully')) {
deferNode1.resolve()
} else if (line.includes('node 2 dialed to node 3 successfully')) {
deferNode2.resolve()
} else if (line.includes('node 3 failed to dial to node 1 with:')) {
deferNode3.resolve()
}
})
await Promise.all([
deferNode1.promise,
deferNode2.promise,
deferNode3.promise
])
proc.kill()
}
module.exports = test

View File

@@ -0,0 +1,13 @@
'use strict'
const test1 = require('./test-1')
const test2 = require('./test-2')
const test3 = require('./test-3')
async function test() {
await test1()
await test2()
await test3()
}
module.exports = test

View File

@@ -0,0 +1,33 @@
### Webrtc-direct example
An example that uses [js-libp2p-webrtc-direct](https://github.com/libp2p/js-libp2p-webrtc-direct) for connecting
nodejs libp2p and browser libp2p clients. To run the example:
## 0. Run a nodejs libp2p listener
When in the root folder of this example, type `node listener.js` in terminal. You should see an address that listens for
incoming connections. Below is just an example of such address. In your case the suffix hash (`peerId`) will be different.
```bash
$ node listener.js
Listening on:
/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct/p2p/QmUKQCzEUhhhobcNSrXU5uzxTqbvF1BjMCGNGZzZU14Kgd
```
## 1. Prepare a browser libp2p dialer
Confirm that the above address is the same as the field `list` in `public/dialer.js`:
```js
peerDiscovery: {
[Bootstrap.tag]: {
enabled: true,
// paste the address into `list`
list: ['/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct/p2p/QmUKQCzEUhhhobcNSrXU5uzxTqbvF1BjMCGNGZzZU14Kgd']
}
}
```
## 2. Run a browser libp2p dialer
When in the root folder of this example, type `npm run dev` in terminal. You should see an address where you can browse
the running client. Open this address in your browser. In console
logs you should see logs about successful connection with the node client. In the output of node client you should see
a log message about successful connection as well.

View File

@@ -0,0 +1,57 @@
import 'babel-polyfill'
const Libp2p = require('libp2p')
const WebRTCDirect = require('libp2p-webrtc-direct')
const Mplex = require('libp2p-mplex')
const {NOISE} = require('libp2p-noise')
const Bootstrap = require('libp2p-bootstrap')
document.addEventListener('DOMContentLoaded', async () => {
// use the same peer id as in `listener.js` to avoid copy-pasting of listener's peer id into `peerDiscovery`
const hardcodedPeerId = '12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m'
const libp2p = await Libp2p.create({
modules: {
transport: [WebRTCDirect],
streamMuxer: [Mplex],
connEncryption: [NOISE],
peerDiscovery: [Bootstrap]
},
config: {
peerDiscovery: {
[Bootstrap.tag]: {
enabled: true,
list: [`/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct/p2p/${hardcodedPeerId}`]
}
}
}
})
const status = document.getElementById('status')
const output = document.getElementById('output')
output.textContent = ''
function log (txt) {
console.info(txt)
output.textContent += `${txt.trim()}\n`
}
// Listen for new peers
libp2p.on('peer:discovery', (peerId) => {
log(`Found peer ${peerId.toB58String()}`)
})
// Listen for new connections to peers
libp2p.connectionManager.on('peer:connect', (connection) => {
log(`Connected to ${connection.remotePeer.toB58String()}`)
})
// Listen for peers disconnecting
libp2p.connectionManager.on('peer:disconnect', (connection) => {
log(`Disconnected from ${connection.remotePeer.toB58String()}`)
})
await libp2p.start()
status.innerText = 'libp2p started!'
log(`libp2p id is ${libp2p.peerId.toB58String()}`)
})

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js-libp2p parcel.js browser example</title>
</head>
<body>
<header>
<h1 id="status">Starting libp2p...</h1>
</header>
<main>
<pre id="output"></pre>
</main>
<script src="./dialer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,44 @@
const Libp2p = require('libp2p')
const Bootstrap = require('libp2p-bootstrap')
const WebRTCDirect = require('libp2p-webrtc-direct')
const Mplex = require('libp2p-mplex')
const {NOISE} = require('libp2p-noise')
const PeerId = require('peer-id')
;(async () => {
// hardcoded peer id to avoid copy-pasting of listener's peer id into the dialer's bootstrap list
// generated with cmd `peer-id --type=ed25519`
const hardcodedPeerId = await PeerId.createFromJSON({
"id": "12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m",
"privKey": "CAESQAG6Ld7ev6nnD0FKPs033/j0eQpjWilhxnzJ2CCTqT0+LfcWoI2Vr+zdc1vwk7XAVdyoCa2nwUR3RJebPWsF1/I=",
"pubKey": "CAESIC33FqCNla/s3XNb8JO1wFXcqAmtp8FEd0SXmz1rBdfy"
})
const node = await Libp2p.create({
peerId: hardcodedPeerId,
addresses: {
listen: ['/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct']
},
modules: {
transport: [WebRTCDirect],
streamMuxer: [Mplex],
connEncryption: [NOISE]
},
config: {
peerDiscovery: {
[Bootstrap.tag]: {
enabled: false,
}
}
}
})
node.connectionManager.on('peer:connect', (connection) => {
console.info(`Connected to ${connection.remotePeer.toB58String()}!`)
})
await node.start()
console.log('Listening on:')
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
})()

View File

@@ -0,0 +1,31 @@
{
"name": "webrtc-direct",
"version": "0.0.1",
"private": true,
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "parcel build index.html",
"start": "parcel index.html"
},
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.13.10",
"@babel/core": "^7.13.10",
"babel-plugin-syntax-async-functions": "^6.13.0",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-polyfill": "^6.26.0",
"parcel-bundler": "1.12.3"
},
"dependencies": {
"libp2p": "../../",
"libp2p-bootstrap": "^0.12.1",
"libp2p-mplex": "^0.10.1",
"libp2p-noise": "^2.0.1",
"libp2p-webrtc-direct": "^0.5.0",
"peer-id": "^0.14.3"
},
"browser": {
"ipfs": "ipfs/dist/index.min.js"
}
}

View File

@@ -0,0 +1,93 @@
'use strict'
const path = require('path')
const execa = require('execa')
const pDefer = require('p-defer')
const uint8ArrayToString = require('uint8arrays/to-string')
const { chromium } = require('playwright');
function startNode (name, args = []) {
return execa('node', [path.join(__dirname, name), ...args], {
cwd: path.resolve(__dirname),
all: true
})
}
function startBrowser (name, args = []) {
return execa('parcel', [path.join(__dirname, name), ...args], {
preferLocal: true,
localDir: __dirname,
cwd: __dirname,
all: true
})
}
async function test () {
// Step 1, listener process
const listenerProcReady = pDefer()
let listenerOutput = ''
process.stdout.write('listener.js\n')
const listenerProc = startNode('listener.js')
listenerProc.all.on('data', async (data) => {
process.stdout.write(data)
listenerOutput += uint8ArrayToString(data)
if (listenerOutput.includes('Listening on:') && listenerOutput.includes('12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m')) {
listenerProcReady.resolve()
}
})
await listenerProcReady.promise
process.stdout.write('==================================================================\n')
// Step 2, dialer process
process.stdout.write('dialer.js\n')
let dialerUrl = ''
const dialerProc = startBrowser('index.html')
dialerProc.all.on('data', async (chunk) => {
/**@type {string} */
const out = chunk.toString()
if (out.includes('Server running at')) {
dialerUrl = out.replace('Server running at ', '')
}
if (out.includes('✨ Built in ')) {
try {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(dialerUrl);
await page.waitForFunction(selector => document.querySelector(selector).innerText === 'libp2p started!', '#status')
await page.waitForFunction(
selector => {
const text = document.querySelector(selector).innerText
return text.includes('libp2p id is') &&
text.includes('Found peer') &&
text.includes('Connected to')
},
'#output',
{ timeout: 10000 }
)
await browser.close();
} catch (err) {
console.error(err)
process.exit(1)
} finally {
dialerProc.cancel()
listenerProc.kill()
}
}
})
await Promise.all([
listenerProc,
dialerProc,
]).catch((err) => {
if (err.signal !== 'SIGTERM') {
throw err
}
})
}
module.exports = test

View File

@@ -1,6 +1,6 @@
{
"name": "libp2p",
"version": "0.30.5",
"version": "0.30.13",
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
"main": "src/index.js",
@@ -63,6 +63,7 @@
"class-is": "^1.1.0",
"debug": "^4.3.1",
"err-code": "^2.0.0",
"es6-promisify": "^6.1.1",
"events": "^3.2.0",
"hashlru": "^2.3.0",
"interface-datastore": "^3.0.3",
@@ -97,18 +98,19 @@
"p-settle": "^4.0.1",
"peer-id": "^0.14.2",
"private-ip": "^2.0.0",
"promisify-es6": "^1.0.3",
"protons": "^2.0.0",
"retimer": "^2.0.0",
"sanitize-filename": "^1.6.3",
"set-delayed-interval": "^1.0.0",
"streaming-iterables": "^5.0.2",
"timeout-abort-controller": "^1.1.1",
"uint8arrays": "^2.1.3",
"varint": "^6.0.0",
"xsalsa20": "^1.0.2"
},
"devDependencies": {
"@nodeutils/defaults-deep": "^1.1.0",
"@types/es6-promisify": "^6.0.0",
"abortable-iterator": "^3.0.0",
"aegir": "^29.2.0",
"chai-bytes": "^0.1.2",
@@ -156,43 +158,60 @@
"Hugo Dias <mail@hugodias.me>",
"Volker Mische <volker.mische@gmail.com>",
"dirkmc <dirkmdev@gmail.com>",
"Chris Dostert <chrisdostert@users.noreply.github.com>",
"Richard Littauer <richard.littauer@gmail.com>",
"a1300 <matthias-knopp@gmx.net>",
"Ryan Bell <ryan@piing.net>",
"Andrew Nesbitt <andrewnez@gmail.com>",
"Elven <mon.samuel@qq.com>",
"Giovanni T. Parra <fiatjaf@gmail.com>",
"Samlior <samlior@foxmail.com>",
"Thomas Eizinger <thomas@eizinger.io>",
"Andrew Nesbitt <andrewnez@gmail.com>",
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
"Giovanni T. Parra <fiatjaf@gmail.com>",
"Ryan Bell <ryan@piing.net>",
"Thomas Eizinger <thomas@eizinger.io>",
"Samlior <samlior@foxmail.com>",
"acolytec3 <17355484+acolytec3@users.noreply.github.com>",
"Didrik Nordström <didrik@betamos.se>",
"Irakli Gozalishvili <rfobic@gmail.com>",
"Joel Gustafson <joelg@mit.edu>",
"John Rees <johnrees@users.noreply.github.com>",
"João Santos <joaosantos15@users.noreply.github.com>",
"Julien Bouquillon <contact@revolunet.com>",
"Kevin Kwok <antimatter15@gmail.com>",
"Kevin Lacker <lacker@gmail.com>",
"Ethan Lam <elmemphis2000@gmail.com>",
"Lars Gierth <lgierth@users.noreply.github.com>",
"Marcin Tojek <mtojek@users.noreply.github.com>",
"Michael Burns <5170+mburns@users.noreply.github.com>",
"Miguel Mota <miguelmota2@gmail.com>",
"Nuno Nogueira <nunofmn@gmail.com>",
"Dmitriy Ryajov <dryajov@gmail.com>",
"Philipp Muens <raute1337@gmx.de>",
"RasmusErik Voel Jensen <github@solsort.com>",
"Diogo Silva <fsdiogo@gmail.com>",
"Aditya Bose <13054902+adbose@users.noreply.github.com>",
"Smite Chow <xiaopengyou@live.com>",
"Soeren <nikorpoulsen@gmail.com>",
"Sönke Hahn <soenkehahn@gmail.com>",
"TJKoury <TJKoury@gmail.com>",
"Tiago Alves <alvesjtiago@gmail.com>",
"Daijiro Wachi <daijiro.wachi@gmail.com>",
"Yusef Napora <yusef@napora.org>",
"Zane Starr <zcstarr@gmail.com>",
"robertkiel <robert.kiel@validitylabs.org>",
"Cindy Wu <ciindy.wu@gmail.com>",
"Chris Bratlien <chrisbratlien@gmail.com>",
"ebinks <elizabethjbinks@gmail.com>",
"Francis Gulotta <wizard@roborooter.com>",
"Florian-Merle <florian.david.merle@gmail.com>",
"Yusef Napora <yusef@napora.org>",
"Zane Starr <zcstarr@gmail.com>",
"Bernd Strehl <bernd.strehl@gmail.com>",
"Henrique Dias <hacdias@gmail.com>",
"ebinks <elizabethjbinks@gmail.com>",
"Ethan Lam <elmemphis2000@gmail.com>",
"isan_rivkin <isanrivkin@gmail.com>",
"mayerwin <mayerwin@users.noreply.github.com>",
"phillmac <phillmac@users.noreply.github.com>",
"robertkiel <robert.kiel@validitylabs.org>",
"shresthagrawal <34920931+shresthagrawal@users.noreply.github.com>",
"swedneck <40505480+swedneck@users.noreply.github.com>",
"Aleksei <vozhdb@gmail.com>",
"Fei Liu <liu.feiwood@gmail.com>",
"Felipe Martins <felipebrasil93@gmail.com>",
"Fei Liu <liu.feiwood@gmail.com>"
"Florian-Merle <florian.david.merle@gmail.com>",
"Francis Gulotta <wizard@roborooter.com>",
"Dmitriy Ryajov <dryajov@gmail.com>",
"Guy Sviry <32539816+guysv@users.noreply.github.com>",
"Henrique Dias <hacdias@gmail.com>",
"Irakli Gozalishvili <rfobic@gmail.com>",
"Diogo Silva <fsdiogo@gmail.com>",
"Joel Gustafson <joelg@mit.edu>"
]
}

View File

@@ -35,7 +35,7 @@ class ContentRouting {
this.dht = libp2p._dht
// If we have the dht, add it to the available content routers
if (this.dht) {
if (this.dht && libp2p._config.dht.enabled) {
this.routers.push(this.dht)
}
}

View File

@@ -202,9 +202,9 @@ class IdentifyService {
this.peerStore.protoBook.set(id, protocols)
this.peerStore.metadataBook.set(id, 'AgentVersion', uint8ArrayFromString(message.agentVersion))
// TODO: Score our observed addr
// TODO: Add and score our observed addr
log('received observed address of %s', observedAddr)
this.addressManager.addObservedAddr(observedAddr)
// this.addressManager.addObservedAddr(observedAddr)
}
/**

View File

@@ -51,9 +51,6 @@ const { updateSelfPeerRecord } = require('./record/utils')
* @typedef {Object} PeerStoreOptions
* @property {boolean} persistence
*
* @typedef {Object} PeerDiscoveryOptions
* @property {boolean} autoDial
*
* @typedef {Object} RelayOptions
* @property {boolean} enabled
* @property {import('./circuit').RelayAdvertiseOptions} advertise
@@ -62,7 +59,7 @@ const { updateSelfPeerRecord } = require('./record/utils')
*
* @typedef {Object} Libp2pConfig
* @property {Object} [dht] dht module options
* @property {PeerDiscoveryOptions} [peerDiscovery]
* @property {Object} [peerDiscovery]
* @property {Pubsub} [pubsub] pubsub module options
* @property {RelayOptions} [relay]
* @property {Record<string, Object>} [transport] transport options indexed by transport key

View File

@@ -14,7 +14,7 @@ require('node-forge/lib/sha512')
/**
* @typedef {import('peer-id')} PeerId
* @typedef {import('interface-datastore/src/types').Datastore} Datastore
* @typedef {import('interface-datastore').Datastore} Datastore
*/
const keyPrefix = '/pkcs8/'

View File

@@ -82,7 +82,7 @@ class Stats extends EventEmitter {
/**
* Returns a clone of the internal movingAverages
*
* @returns {MovingAverage}
* @returns {Object}
*/
get movingAverages () {
return Object.assign({}, this._movingAverages)

View File

@@ -2,7 +2,7 @@
const NatAPI = require('@motrix/nat-api')
const debug = require('debug')
const promisify = require('promisify-es6')
const { promisify } = require('es6-promisify')
const Multiaddr = require('multiaddr')
const log = Object.assign(debug('libp2p:nat'), {
error: debug('libp2p:nat:err')
@@ -132,15 +132,33 @@ class NatManager {
}
const client = new NatAPI(this._options)
const map = promisify(client.map, { context: client })
const destroy = promisify(client.destroy, { context: client })
const externalIp = promisify(client.externalIp, { context: client })
/** @type {(...any) => any} */
const map = promisify(client.map.bind(client))
/** @type {(...any) => any} */
const destroy = promisify(client.destroy.bind(client))
/** @type {(...any) => any} */
const externalIp = promisify(client.externalIp.bind(client))
// these are all network operations so add a retry
this._client = {
// these are all network operations so add a retry
map: (...args) => retry(() => map(...args), { onFailedAttempt: log.error }),
destroy: (...args) => retry(() => destroy(...args), { onFailedAttempt: log.error }),
externalIp: (...args) => retry(() => externalIp(...args), { onFailedAttempt: log.error })
/**
* @param {...any} args
* @returns {Promise<void>}
*/
map: (...args) => retry(() => map(...args), { onFailedAttempt: log.error, unref: true }),
/**
* @param {...any} args
* @returns {Promise<void>}
*/
destroy: (...args) => retry(() => destroy(...args), { onFailedAttempt: log.error, unref: true }),
/**
* @param {...any} args
* @returns {Promise<string>}
*/
externalIp: (...args) => retry(() => externalIp(...args), { onFailedAttempt: log.error, unref: true })
}
return this._client

View File

@@ -36,7 +36,7 @@ class PeerRouting {
this._routers = libp2p._modules.peerRouting || []
// If we have the dht, add it to the available peer routers
if (libp2p._dht) {
if (libp2p._dht && libp2p._config.dht.enabled) {
this._routers.push(libp2p._dht)
}

View File

@@ -196,7 +196,7 @@ class TransportManager {
// listening on remote addresses as they may be offline. We could then potentially
// just wait for any (`p-any`) listener to succeed on each transport before returning
const isListening = results.find(r => r.isFulfilled === true)
if (!isListening) {
if (!isListening && this.faultTolerance !== FAULT_TOLERANCE.NO_FATAL) {
throw errCode(new Error(`Transport (${key}) could not listen on any available address`), codes.ERR_NO_VALID_ADDRESSES)
}
}

View File

@@ -201,7 +201,7 @@ class Upgrader {
* @private
* @param {object} options
* @param {string} options.cryptoProtocol - The crypto protocol that was negotiated
* @param {string} options.direction - One of ['inbound', 'outbound']
* @param {'inbound' | 'outbound'} options.direction - One of ['inbound', 'outbound']
* @param {MultiaddrConnection} options.maConn - The transport layer connection
* @param {MuxedStream | MultiaddrConnection} options.upgradedConn - A duplex connection returned from multiplexer and/or crypto selection
* @param {MuxerFactory} [options.Muxer] - The muxer to be used for muxing

View File

@@ -107,9 +107,7 @@ describe('content-routing', () => {
host: '0.0.0.0',
protocol: 'http',
port: 60197
}), [
multiaddr('/ip4/0.0.0.0/tcp/60197')
])
}))
;[node] = await peerUtils.createPeer({
config: mergeOptions(baseOptions, {
@@ -131,6 +129,10 @@ describe('content-routing', () => {
afterEach(() => node.stop())
it('should only have one router', () => {
expect(node.contentRouting.routers).to.have.lengthOf(1)
})
it('should use the delegate router to provide', () => {
const deferred = pDefer()
@@ -253,9 +255,7 @@ describe('content-routing', () => {
host: '0.0.0.0',
protocol: 'http',
port: 60197
}), [
multiaddr('/ip4/0.0.0.0/tcp/60197')
])
}))
;[node] = await peerUtils.createPeer({
config: mergeOptions(routingOptions, {

View File

@@ -119,7 +119,6 @@ describe('Dialing (direct, WebSockets)', () => {
await expect(dialer.connectToPeer(unsupportedAddr))
.to.eventually.be.rejectedWith(AggregateError)
.and.to.have.nested.property('._errors[0].code', ErrorCodes.ERR_TRANSPORT_DIAL_FAILED)
})
it('should be able to connect to a given peer', async () => {
@@ -151,7 +150,6 @@ describe('Dialing (direct, WebSockets)', () => {
await expect(dialer.connectToPeer(peerId))
.to.eventually.be.rejectedWith(AggregateError)
.and.to.have.nested.property('._errors[0].code', ErrorCodes.ERR_TRANSPORT_DIAL_FAILED)
})
it('should abort dials on queue task timeout', async () => {

View File

@@ -3,6 +3,7 @@
const { expect } = require('aegir/utils/chai')
const sinon = require('sinon')
const { networkInterfaces } = require('os')
const AddressManager = require('../../src/address-manager')
const TransportManager = require('../../src/transport-manager')
const Transport = require('libp2p-tcp')
@@ -156,7 +157,7 @@ describe('Nat Manager (TCP)', () => {
natManager,
addressManager
} = await createNatManager([
'/ip6/::/tcp/5001'
'/ip6/::/tcp/0'
])
let observed = addressManager.getObservedAddrs().map(ma => ma.toString())
@@ -173,7 +174,7 @@ describe('Nat Manager (TCP)', () => {
natManager,
addressManager
} = await createNatManager([
'/ip6/::1/tcp/5001'
'/ip6/::1/tcp/0'
])
let observed = addressManager.getObservedAddrs().map(ma => ma.toString())
@@ -207,7 +208,7 @@ describe('Nat Manager (TCP)', () => {
natManager,
addressManager
} = await createNatManager([
'/ip4/127.0.0.1/tcp/5900'
'/ip4/127.0.0.1/tcp/0'
])
let observed = addressManager.getObservedAddrs().map(ma => ma.toString())
@@ -224,7 +225,7 @@ describe('Nat Manager (TCP)', () => {
natManager,
addressManager
} = await createNatManager([
'/ip4/0.0.0.0/tcp/5900/sctp/49832'
'/ip4/0.0.0.0/tcp/0/sctp/0'
])
let observed = addressManager.getObservedAddrs().map(ma => ma.toString())
@@ -241,4 +242,50 @@ describe('Nat Manager (TCP)', () => {
new NatManager({ ttl: 5 }) // eslint-disable-line no-new
}).to.throw().with.property('code', ERR_INVALID_PARAMETERS)
})
it('shuts the nat api down when stopping', async function () {
function findRoutableAddress () {
const interfaces = networkInterfaces()
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
if (iface.family === 'IPv4' && !iface.internal) {
return iface.address
}
}
}
}
const addr = findRoutableAddress()
if (!addr) {
// skip test if no non-loopback address is found
this.skip()
}
const {
natManager
} = await createNatManager([
`/ip4/${addr}/tcp/0`
], {
// so we don't try to look up the current computer's external address
externalIp: '184.12.31.4'
})
// use the actual nat manager client not the stub
delete natManager._client
await natManager._start()
const client = natManager._client
expect(client).to.be.ok()
// ensure the client was stopped
const spy = sinon.spy(client, 'destroy')
await natManager.stop()
expect(spy.called).to.be.true()
})
})

View File

@@ -132,6 +132,10 @@ describe('peer-routing', () => {
afterEach(() => node.stop())
it('should only have one router', () => {
expect(node.peerRouting._routers).to.have.lengthOf(1)
})
it('should use the delegate router to find peers', async () => {
const deferred = pDefer()
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })

View File

@@ -209,7 +209,7 @@ describe('libp2p.transportManager (dial only)', () => {
throw new Error('it should fail to start if multiaddr fails to listen')
})
it('does not fail to start if multiaddr fails to listen when supporting dial only mode', async () => {
it('does not fail to start if provided listen multiaddr are not compatible to configured transports (when supporting dial only mode)', async () => {
libp2p = new Libp2p({
peerId,
addresses: {
@@ -226,4 +226,22 @@ describe('libp2p.transportManager (dial only)', () => {
await libp2p.start()
})
it('does not fail to start if provided listen multiaddr fail to listen on configured transports (when supporting dial only mode)', async () => {
libp2p = new Libp2p({
peerId,
addresses: {
listen: [multiaddr('/ip4/127.0.0.1/tcp/12345/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3/p2p-circuit')]
},
transportManager: {
faultTolerance: FaultTolerance.NO_FATAL
},
modules: {
transport: [Transport],
connEncryption: [Crypto]
}
})
await libp2p.start()
})
})