mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-23 04:21:55 +00:00
Compare commits
46 Commits
v0.31.0-rc
...
v0.31.8
Author | SHA1 | Date | |
---|---|---|---|
|
4b27c95fe8 | ||
|
c8cc1adcc6 | ||
|
172c2c7f42 | ||
|
f7183e8afd | ||
|
b9988adce9 | ||
|
b291bc06ec | ||
|
755eb909f2 | ||
|
afe0f854e8 | ||
|
50f7f32e53 | ||
|
052aad4e06 | ||
|
2c4b567b00 | ||
|
2a6a635f13 | ||
|
cd152f122f | ||
|
2959794796 | ||
|
2068c845cb | ||
|
d8ba284883 | ||
|
869d35d852 | ||
|
d6540bf01d | ||
|
478963ad2d | ||
|
d22ad83890 | ||
|
538f296b0a | ||
|
7bac2045cc | ||
|
818d2b2a98 | ||
|
d163ffd224 | ||
|
b29d6c9304 | ||
|
890dd05941 | ||
|
a79c6b50d7 | ||
|
d372a68692 | ||
|
4e3fc19623 | ||
|
2fa82b387c | ||
|
8fc6f8af81 | ||
|
924585b143 | ||
|
556f0203db | ||
|
b5a9eb2087 | ||
|
e5187d02ba | ||
|
150e4f97c1 | ||
|
302bb90058 | ||
|
f860ffb3e7 | ||
|
2572f3e034 | ||
|
d76356e56a | ||
|
e9543eb2e1 | ||
|
5282708263 | ||
|
ed494f03ae | ||
|
ac370fc967 | ||
|
ef4393649f | ||
|
f23fd4b7c7 |
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: libp2p Official Forum
|
||||
url: https://discuss.libp2p.io
|
||||
about: For general questions, support requests and discussions
|
55
.github/ISSUE_TEMPLATE/open_an_issue.md
vendored
Normal file
55
.github/ISSUE_TEMPLATE/open_an_issue.md
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
name: Open an issue
|
||||
about: For reporting bugs or errors in the JavaScript libp2p implementation
|
||||
title: ''
|
||||
labels: need/triage
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!--
|
||||
Thank you for reporting an issue.
|
||||
|
||||
This issue tracker is for bugs found within the JavaScript implementation of libp2p.
|
||||
|
||||
If you are asking a question about how to use libp2p, please ask on https://discuss.libp2p.io
|
||||
|
||||
Otherwise please fill in as much of the template below as possible.
|
||||
-->
|
||||
|
||||
- **Version**:
|
||||
<!--
|
||||
Check package.json version
|
||||
-->
|
||||
|
||||
- **Platform**:
|
||||
<!--
|
||||
Output of `uname -a` (UNIX), or version and 32 or 64-bit (Windows). If using in a Browser, please share the browser version as well
|
||||
-->
|
||||
|
||||
- **Subsystem**:
|
||||
<!--
|
||||
If known, please specify affected core module name (e.g Dialer, Pubsub, Relay etc)
|
||||
-->
|
||||
|
||||
#### Severity:
|
||||
<!--
|
||||
One of following:
|
||||
Critical - System crash, application panic.
|
||||
High - The main functionality of the application does not work, API breakage, repo format breakage, etc.
|
||||
Medium - A non-essential functionality does not work, performance issues, etc.
|
||||
Low - An optional functionality does not work.
|
||||
Very Low - Translation or documentation mistake. Something that won't give anyone a bad day.
|
||||
-->
|
||||
|
||||
#### Description:
|
||||
<!--
|
||||
- What you did
|
||||
- What happened
|
||||
- What you expected to happen
|
||||
-->
|
||||
|
||||
#### Steps to reproduce the error:
|
||||
<!--
|
||||
If possible, please provide code that demonstrates the problem, keeping it as simple and free of external dependencies as you are able
|
||||
-->
|
||||
|
@@ -25,7 +25,6 @@
|
||||
- [ ] [js-ipfs](https://github.com/ipfs/js-ipfs)
|
||||
- Documentation
|
||||
- [ ] Ensure that README.md is up to date
|
||||
- [ ] Ensure [libp2p/js-libp2p-examples](https://github.com/libp2p/js-libp2p-examples) is updated
|
||||
- [ ] Ensure that [libp2p/docs](https://github.com/libp2p/docs) is updated
|
||||
- Communication
|
||||
- [ ] Create the release issue
|
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
node: [14]
|
||||
node: [14, 16]
|
||||
fail-fast: true
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
81
CHANGELOG.md
81
CHANGELOG.md
@@ -1,3 +1,84 @@
|
||||
## [0.31.8](https://github.com/libp2p/js-libp2p/compare/v0.31.7...v0.31.8) (2021-09-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* hot fix uint8arrays 0.31.x ([172c2c7](https://github.com/libp2p/js-libp2p/commit/172c2c7f428afb54667d2789ea68b6e7e86d6b4f))
|
||||
|
||||
|
||||
|
||||
## [0.31.7](https://github.com/libp2p/js-libp2p/compare/v0.31.6...v0.31.7) (2021-06-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* chat example with new multiaddr ([#946](https://github.com/libp2p/js-libp2p/issues/946)) ([d8ba284](https://github.com/libp2p/js-libp2p/commit/d8ba2848833d9fb8a963d1b7c8d27062c6f829da))
|
||||
* dialer leaking resources after stopping ([#947](https://github.com/libp2p/js-libp2p/issues/947)) ([b291bc0](https://github.com/libp2p/js-libp2p/commit/b291bc06ec13feeb6e010730edfad754a3b2dc1b))
|
||||
|
||||
|
||||
|
||||
## [0.31.6](https://github.com/libp2p/js-libp2p/compare/v0.31.5...v0.31.6) (2021-05-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* keychain rotate passphrase ([#944](https://github.com/libp2p/js-libp2p/issues/944)) ([478963a](https://github.com/libp2p/js-libp2p/commit/478963ad2d195444494c0acc54cb3847a29e117c))
|
||||
|
||||
|
||||
|
||||
## [0.31.5](https://github.com/libp2p/js-libp2p/compare/v0.31.4...v0.31.5) (2021-05-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* store remote agent and protocol version during identify ([#943](https://github.com/libp2p/js-libp2p/issues/943)) ([818d2b2](https://github.com/libp2p/js-libp2p/commit/818d2b2a98736f4242694479089396f6070cdad5))
|
||||
|
||||
|
||||
|
||||
## [0.31.4](https://github.com/libp2p/js-libp2p/compare/v0.31.3...v0.31.4) (2021-05-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* peerRouting.findPeer() trying to find self ([#941](https://github.com/libp2p/js-libp2p/issues/941)) ([a79c6b5](https://github.com/libp2p/js-libp2p/commit/a79c6b50d7fddbcdb1af53efae922cecad4c9a83))
|
||||
|
||||
|
||||
|
||||
## [0.31.3](https://github.com/libp2p/js-libp2p/compare/v0.31.2...v0.31.3) (2021-05-04)
|
||||
|
||||
|
||||
|
||||
## [0.31.2](https://github.com/libp2p/js-libp2p/compare/v0.31.1...v0.31.2) (2021-04-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* moving averages record types ([#935](https://github.com/libp2p/js-libp2p/issues/935)) ([b5a9eb2](https://github.com/libp2p/js-libp2p/commit/b5a9eb208763efa027d0b4caae87c515b6f5869b))
|
||||
|
||||
|
||||
|
||||
## [0.31.1](https://github.com/libp2p/js-libp2p/compare/v0.31.0...v0.31.1) (2021-04-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* event emitter and interfaces types for discovery and routing ([#934](https://github.com/libp2p/js-libp2p/issues/934)) ([302bb90](https://github.com/libp2p/js-libp2p/commit/302bb9005891aa06b70a5f354bfac6b2d5a3c3b8))
|
||||
|
||||
|
||||
|
||||
# [0.31.0](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.7...v0.31.0) (2021-04-28)
|
||||
|
||||
|
||||
|
||||
# [0.31.0-rc.7](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.6...v0.31.0-rc.7) (2021-04-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* address book guarantees no replicated entries are added ([#927](https://github.com/libp2p/js-libp2p/issues/927)) ([ac370fc](https://github.com/libp2p/js-libp2p/commit/ac370fc9679b51da8cee3791b6dd268d0695d136))
|
||||
|
||||
|
||||
|
||||
# [0.31.0-rc.6](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.5...v0.31.0-rc.6) (2021-04-22)
|
||||
|
||||
|
||||
|
@@ -282,7 +282,7 @@ const node = await Libp2p.create({
|
||||
interval: 1000,
|
||||
enabled: true
|
||||
},
|
||||
[Bootstrap.tag:] {
|
||||
[Bootstrap.tag]: {
|
||||
list: [ // A list of bootstrap peers to connect to starting up the node
|
||||
"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
|
||||
"/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
|
||||
@@ -373,7 +373,7 @@ const node = await Libp2p.create({
|
||||
config: {
|
||||
dht: { // The DHT options (and defaults) can be found in its documentation
|
||||
kBucketSize: 20,
|
||||
enabled: true,
|
||||
enabled: true, // This flag is required for DHT to run (disabled by default)
|
||||
randomWalk: {
|
||||
enabled: true, // Allows to disable discovery (enabled by default)
|
||||
interval: 300e3,
|
||||
@@ -399,13 +399,13 @@ const PeerId = require('peer-id')
|
||||
// create a peerId
|
||||
const peerId = await PeerId.create()
|
||||
|
||||
const delegatedPeerRouting = new DelegatedPeerRouter(ipfsHttpClient({
|
||||
const delegatedPeerRouting = new DelegatedPeerRouter(ipfsHttpClient.create({
|
||||
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
|
||||
protocol: 'https',
|
||||
port: 443
|
||||
}))
|
||||
|
||||
const delegatedContentRouting = new DelegatedContentRouter(peerId, ipfsHttpClient({
|
||||
const delegatedContentRouting = new DelegatedContentRouter(peerId, ipfsHttpClient.create({
|
||||
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
|
||||
protocol: 'https',
|
||||
port: 443
|
||||
@@ -515,7 +515,7 @@ const node = await Libp2p.create({
|
||||
}
|
||||
})
|
||||
|
||||
await libp2p.loadKeychain()
|
||||
await node.loadKeychain()
|
||||
```
|
||||
|
||||
#### Configuring Dialing
|
||||
|
123
doc/migrations/v0.30-v0.31.md
Normal file
123
doc/migrations/v0.30-v0.31.md
Normal file
@@ -0,0 +1,123 @@
|
||||
<!--Specify versions for migration below-->
|
||||
# Migrating to libp2p@31
|
||||
|
||||
A migration guide for refactoring your application code from libp2p v0.30.x to v0.31.0.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Types](#types)
|
||||
- [API](#api)
|
||||
- [Module Updates](#module-updates)
|
||||
|
||||
## Types
|
||||
|
||||
Most of the type definitions in the libp2p configuration were `any` or were not included before this release. This might cause breaking changes on upstream projects relying on the previous provided types, as well as to libp2p modules implemented by the libp2p community.
|
||||
|
||||
## API
|
||||
|
||||
### Core API
|
||||
|
||||
`libp2p.dialProtocol` does not accept empty or null protocols returning a connection anymore and `dial` must be used instead.
|
||||
|
||||
```js
|
||||
const connection = await libp2p.dialProtocol(peerId)
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const connection = await libp2p.dial(peerId)
|
||||
```
|
||||
|
||||
### Connection Manager Options
|
||||
|
||||
We updated the connection manager options naming in `libp2p@0.29` but kept it backward compatible until now.
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const node = await Libp2p.create({
|
||||
connectionManager: {
|
||||
minPeers: 0
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const node = await Libp2p.create({
|
||||
connectionManager: {
|
||||
minConnections: 0
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You can see full details on how to configure the connection manager [here](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#configuring-connection-manager).
|
||||
|
||||
### Dialer and Keychain components
|
||||
|
||||
Internal property names to create a libp2p `Dialer` and `Keychain` were updated to reflect the properties naming in the libp2p configuration. These are internal modules of libp2p core and should not impact most of the users, but as it is possible to use them separately here follow the changes:
|
||||
|
||||
***Before**
|
||||
|
||||
```js
|
||||
const dialer = new Dialer({
|
||||
transportManager,
|
||||
peerStore,
|
||||
concurrency,
|
||||
perPeerLimit,
|
||||
timeout,
|
||||
resolvers,
|
||||
addressSorter
|
||||
})
|
||||
|
||||
const keychain = new Keychain(datastore, {
|
||||
passPhrase
|
||||
})
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
this.dialer = new Dialer({
|
||||
transportManager,
|
||||
peerStore,
|
||||
maxParallelDials,
|
||||
maxDialsPerPeer,
|
||||
dialTimeout,
|
||||
resolvers,
|
||||
addressSorter
|
||||
})
|
||||
|
||||
const keychain = new Keychain(datastore, {
|
||||
pass
|
||||
})
|
||||
```
|
||||
|
||||
## Module Updates
|
||||
|
||||
With this release you should update the following libp2p modules if you are relying on them:
|
||||
|
||||
<!--Specify module versions in JSON for migration below.
|
||||
It's recommended to check package.json changes for this:
|
||||
`git diff <release> <prev> -- package.json`
|
||||
-->
|
||||
|
||||
```json
|
||||
"libp2p-bootstrap": "^0.12.3",
|
||||
"libp2p-crypto": "^0.19.4",
|
||||
"libp2p-interfaces": "^0.10.0",
|
||||
"libp2p-delegated-content-routing": "^0.10.0",
|
||||
"libp2p-delegated-peer-routing": "^0.9.0",
|
||||
"libp2p-floodsub": "^0.25.1",
|
||||
"libp2p-gossipsub": "^0.9.0",
|
||||
"libp2p-kad-dht": "^0.22.0",
|
||||
"libp2p-mdns": "^0.16.0",
|
||||
"libp2p-noise": "^3.0.0",
|
||||
"libp2p-tcp": "^0.15.4",
|
||||
"libp2p-webrtc-star": "^0.22.2",
|
||||
"libp2p-websockets": "^0.15.6"
|
||||
```
|
||||
|
||||
One of the main changes in this new release is the update to `multiaddr@9.0.0`. This should also be updated in upstream projects to avoid several multiaddr versions in the bundle and to avoid potential problems when libp2p interacts with provided outdated multiaddr instances.
|
@@ -2,11 +2,11 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const PeerId = require('peer-id')
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const createLibp2p = require('./libp2p')
|
||||
const { stdinToStream, streamToConsole } = require('./stream')
|
||||
|
||||
async function run() {
|
||||
async function run () {
|
||||
const [idDialer, idListener] = await Promise.all([
|
||||
PeerId.createFromJSON(require('./peer-id-dialer')),
|
||||
PeerId.createFromJSON(require('./peer-id-listener'))
|
||||
@@ -30,7 +30,7 @@ async function run() {
|
||||
})
|
||||
|
||||
// Dial to the remote peer (the "listener")
|
||||
const listenerMa = multiaddr(`/ip4/127.0.0.1/tcp/10333/p2p/${idListener.toB58String()}`)
|
||||
const listenerMa = new Multiaddr(`/ip4/127.0.0.1/tcp/10333/p2p/${idListener.toB58String()}`)
|
||||
const { stream } = await nodeDialer.dialProtocol(listenerMa, '/chat/1.0.0')
|
||||
|
||||
console.log('Dialer dialed to listener on protocol: /chat/1.0.0')
|
||||
|
@@ -5,7 +5,7 @@ const PeerId = require('peer-id')
|
||||
const createLibp2p = require('./libp2p.js')
|
||||
const { stdinToStream, streamToConsole } = require('./stream')
|
||||
|
||||
async function run() {
|
||||
async function run () {
|
||||
// Create a new libp2p node with the given multi-address
|
||||
const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
|
||||
const nodeListener = await createLibp2p({
|
||||
|
@@ -10,12 +10,14 @@
|
||||
"dependencies": {
|
||||
"execa": "^2.1.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"libp2p-pubsub-peer-discovery": "^3.0.0",
|
||||
"libp2p-relay-server": "^0.1.2",
|
||||
"libp2p-pubsub-peer-discovery": "^4.0.0",
|
||||
"libp2p-relay-server": "^0.2.0",
|
||||
"libp2p-gossipsub": "^0.9.1",
|
||||
"p-defer": "^3.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"https": "^1.0.0",
|
||||
"playwright": "^1.7.1"
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,10 @@ We've seen many interesting use cases appear with this, here are some highlights
|
||||
- [IPFS PubSub (using libp2p-floodsub) for IoT](https://www.youtube.com/watch?v=qLpM5pBDGiE).
|
||||
- [Real Time distributed Applications](https://www.youtube.com/watch?v=vQrbxyDPSXg)
|
||||
|
||||
## 0. Set up the example
|
||||
|
||||
Before moving into the examples, you should run `npm install` on the top level `js-libp2p` folder, in order to install all the dependencies needed for this example. In addition, you will need to install the example related dependencies by doing `cd examples && npm install`. Once the install finishes, you should move into the example folder with `cd pubsub`.
|
||||
|
||||
## 1. Setting up a simple PubSub network on top of libp2p
|
||||
|
||||
For this example, we will use MulticastDNS for automatic Peer Discovery. This example is based the previous examples found in [Discovery Mechanisms](../discovery-mechanisms). You can find the complete version at [1.js](./1.js).
|
||||
|
89
examples/transports/4.js
Normal file
89
examples/transports/4.js
Normal file
@@ -0,0 +1,89 @@
|
||||
/* eslint-disable no-console */
|
||||
'use strict'
|
||||
|
||||
const Libp2p = require('../..')
|
||||
const TCP = require('libp2p-tcp')
|
||||
const WebSockets = require('libp2p-websockets')
|
||||
const { NOISE } = require('libp2p-noise')
|
||||
const MPLEX = require('libp2p-mplex')
|
||||
|
||||
const fs = require('fs');
|
||||
const https = require('https');
|
||||
const pipe = require('it-pipe')
|
||||
|
||||
const transportKey = WebSockets.prototype[Symbol.toStringTag];
|
||||
|
||||
const httpServer = https.createServer({
|
||||
cert: fs.readFileSync('./test_certs/cert.pem'),
|
||||
key: fs.readFileSync('./test_certs/key.pem'),
|
||||
});
|
||||
|
||||
const createNode = async (addresses = []) => {
|
||||
if (!Array.isArray(addresses)) {
|
||||
addresses = [addresses]
|
||||
}
|
||||
|
||||
const node = await Libp2p.create({
|
||||
addresses: {
|
||||
listen: addresses
|
||||
},
|
||||
modules: {
|
||||
transport: [WebSockets],
|
||||
connEncryption: [NOISE],
|
||||
streamMuxer: [MPLEX]
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
// Disable autoDial as it would fail because we are using a self-signed cert.
|
||||
// `dialProtocol` does not fail because we pass `rejectUnauthorized: false`.
|
||||
autoDial: false
|
||||
},
|
||||
transport: {
|
||||
[transportKey]: {
|
||||
listenerOptions: { server: httpServer },
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
await node.start()
|
||||
return node
|
||||
}
|
||||
|
||||
function printAddrs(node, number) {
|
||||
console.log('node %s is listening on:', number)
|
||||
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
|
||||
}
|
||||
|
||||
function print ({ stream }) {
|
||||
pipe(
|
||||
stream,
|
||||
async function (source) {
|
||||
for await (const msg of source) {
|
||||
console.log(msg.toString())
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
;(async () => {
|
||||
const [node1, node2] = await Promise.all([
|
||||
createNode('/ip4/127.0.0.1/tcp/10000/wss'),
|
||||
createNode([])
|
||||
])
|
||||
|
||||
printAddrs(node1, '1')
|
||||
printAddrs(node2, '2')
|
||||
|
||||
node1.handle('/print', print)
|
||||
node2.handle('/print', print)
|
||||
|
||||
const targetAddr = `${node1.multiaddrs[0]}/p2p/${node1.peerId.toB58String()}`;
|
||||
|
||||
// node 2 (Secure WebSockets) dials to node 1 (Secure Websockets)
|
||||
const { stream } = await node2.dialProtocol(targetAddr, '/print', { websocket: { rejectUnauthorized: false } })
|
||||
await pipe(
|
||||
['node 2 dialed to node 1 successfully'],
|
||||
stream
|
||||
)
|
||||
})();
|
33
examples/transports/test-4.js
Normal file
33
examples/transports/test-4.js
Normal file
@@ -0,0 +1,33 @@
|
||||
'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()
|
||||
|
||||
process.stdout.write('4.js\n')
|
||||
|
||||
const proc = execa('node', [path.join(__dirname, '4.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 2 dialed to node 1 successfully')) {
|
||||
deferNode1.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
deferNode1.promise,
|
||||
])
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
@@ -3,11 +3,13 @@
|
||||
const test1 = require('./test-1')
|
||||
const test2 = require('./test-2')
|
||||
const test3 = require('./test-3')
|
||||
const test4 = require('./test-4')
|
||||
|
||||
async function test() {
|
||||
await test1()
|
||||
await test2()
|
||||
await test3()
|
||||
await test4()
|
||||
}
|
||||
|
||||
module.exports = test
|
||||
|
32
examples/transports/test_certs/cert.pem
Normal file
32
examples/transports/test_certs/cert.pem
Normal file
@@ -0,0 +1,32 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
52
examples/transports/test_certs/key.pem
Normal file
52
examples/transports/test_certs/key.pem
Normal file
@@ -0,0 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDTYVwbtBh9Ss5f
|
||||
YmkMQsRJ8sgEoUuRWEnHSsaqWLICU+KaC1i0AWUBBSxKm3YpZSJU2ajLLI1qpBS9
|
||||
sZo6nXJzihRGVGq57VRNocRWGEHsdhYvDGMBY/j77e+HdNsT8n8xTRYMl2tRGpKB
|
||||
gcApWn9yO41u62j7nY3H+B58EO6/zcIjvBahxWYC3E58CPG5PnMQ6AwKrpoajAeZ
|
||||
53q6ryhMkfRW9j6C/vD8DjyTjikw1cCzHjCbtli0fAFNhczo+UlSNqrLvT7OWs8r
|
||||
A/CkADHMOMvbOnaN+kmjEEvOX271wVe1wajA9+BzwVGxYgqBaGgsyvWX26Ql8lST
|
||||
FDZsOYcqvZ241LeCr6/+fG1NoI1CknT3+ioQcRZw2cJftqqj3VSG/6rcMxxMbSVq
|
||||
t7qZJVzToNx6Eer3K9TvUXiR68y0TBG+dVj9Wjf6idv5UbJHGeAPNOqsK1uuwb5z
|
||||
oOrN2bcRzfb927Mn7LwuusPDxHwpwlcboAu3FFtILVueAFO+U97pIO1/prxAq//q
|
||||
iMzRASMcQj4HnwhvyQHSYUOUgr6AEQFT0rVCFg5ooA3jre4KOZym3VSCeO22wRVI
|
||||
R09pkx7t9Hx4Uakg3B88BO2c+mCSCZiqtvVJs1GsxZypS1OuzIyycIgz5nwtxsjn
|
||||
QFpJGROYY7ZIsvt8lqBB4WiWESNbtwIDAQABAoICAQCpGV3iG7Trpohp7gQzdsYo
|
||||
kjxI1+/oGkULVVqQs9vT2N+SdDlF50eyBT1lgfCJNQq97lIGF2IaSaD+D7Jd6c7B
|
||||
d1i42pd2ndGvORYj+cvjKqSchsA9QIjSoYnZRzZrQrdV7WESOZ/0hdlmGTJs4qTJ
|
||||
8bI3ZcPaZjQiIO/iOHmGn0gL5lAEojH1X+C5gT4+/yJ2B+x6LyvAyPzbtj6MUctf
|
||||
VfOuDdf8W47VVV5IfJWfJ6C8qg4gw0M7P2ibZ8qBJcvuJSWFT6OK2UKaGtDLogw0
|
||||
X8tVWfO1qOB3vnWmZtoRZ9aO5JnnpWS9tY1w5gmZdLjB/Kt0DJXIdZALCURwV6U0
|
||||
q5XR0SETEgdRrNX92PA2lmxO9fAgXRSjP/OoeDjAVhnRfYyShDbEIb8GHk7nE+is
|
||||
6ak5ufxKE53S8wB9L7MTPqTvxusBHi8saLevdnPBMQPvtEVkg2Iw/iPBsegUuUjD
|
||||
uzXlq4WUMCUBJEMVPuYEsaQizxpp2oM6AZj/ecuTKFX5CirFFWKOQ4cp+O8lrfI5
|
||||
ruwHrMkfjowDYcQaOLHq13anvt8+8LBlngVw+jiAGB/bGwrAwEZWUc8i1HbH/G8e
|
||||
sm0kMuCqV1GbRyMCUO3pWjzrsz8LEy74Jr0z7KZn52vLWrTkiD4NRXahxTBhHpXb
|
||||
AVclJ+a4BKk2rRJVRFRRQQKCAQEA7+uTl2ZHp1v7A8/I2zPIxoVz0fiwxwAjuv34
|
||||
cV+uxG0n5Tko4PKMxavddRFKNeGvrz0aO/GNX8NIW7pDqZ2CwHyskgUX/bFAqGKF
|
||||
Z/z2DmiZ2rdSUH89O3ysq+OF3RjX/FBNJ0SVdwtrpz3kCSWpa4PnmN7+IevL6zxY
|
||||
8gLrs07Ge+ci94FZaDHBNrkGQ00krbOmwIvnc90hyRPCKfMS+u2/ejKZ5QDyRG+H
|
||||
jbQ008ZV2OqUdS6h1twfoJ1Q4QhHijB6PegRLGdZGuUXIQfFP8dIUsQluKSUFyOy
|
||||
bL9W2yBwtbn3EwYDHLJQnLICxfcTBWg/2vOIucsSjxG7KNY0yQKCAQEA4YwcVpi3
|
||||
D+8OcnbpRBRlHo84DRZorp0RO8vhxevvB1CcBnkLRIYXlS2JIfrnhZAI/5jBk1ei
|
||||
FmgRFyAjZ8gDdkDCiDMQMDUwUhLGSVurI9sk16B4TQKCM+iE0LDrXIy9ezJRJkj0
|
||||
rOt8sqo2/TOttm2KEXY8Cco59tU4bMZg5Tr9l7SMTTj4skTO6Jn6/6hX3XuFkJw7
|
||||
B0DsSzIqXyRHAzOidagIEoIr7k4cEGXsrSWoSiHg/eky1ihCyUw3vDDOmoViBR7s
|
||||
h5nLjQNNAzOtyoKLqST7B7uXkdUo5nV2IUHSGD5LNxlTaNp0XL9Ph3EBtcuwNuB6
|
||||
zyKXc+O5iNfMfwKCAQEA5/RJKCnRgsORxpif5xWEujIRzOHz/yFqagHarbnFHNEv
|
||||
rhT6Kak2YnIL1H/X0IoWsYSQlX2uofQKQ+ysOBM5c2HV8gKMtFAnY+SEeAn/1eRZ
|
||||
QzTTl1G84INj6Xc6V40KXD1CqoFLQ+G9vd4/Vnyb9H99bLXC2wa+ivo4QBqEyEGT
|
||||
8fyAOOxMhUj9NSvjGzQ9DtbOk/9u0PztChtZL/d61TEAW2MKmHW2xGVTl7OvE0QA
|
||||
gYwh5b0k6La+uSj/JeE8USUXOjzgRZ7RbggouV1q3YOMr8BFe+NZ7Zksiqjej1Io
|
||||
xfk6H6FDZv4ao7QSrFR4hlTIz6V9/aqQkdOhsBSQyQKCAQEAzHwz4Qr5xVduGLbY
|
||||
S6HV/7vHDI6Jf+3lBvqUidWa013w5yls3sZXsSckkgshRoVMszayIbystnXJMNcx
|
||||
YlEDWn3iIItzHNHMKkzdOvsCETMIlvnkt6UTmK4xY+dSq4jp7Ty0N+qi8fdaCb2q
|
||||
tyrYTnHHYId6bUHMBY5QZsYAaTNvYNAO96A0UaNyl42q84iTiLkJYg9SsQPad15W
|
||||
7gU84Jk6rEMYdndQDvEAHpnZ1y0yA2vtySZYsbK0wj34tgTl+0/8izn7JgF4ezNH
|
||||
6iQ7Z0OuDT763IrmIxBH0ZEi9YnwSYyIsr6iUYjlQIUuPFRnQYQXEdm5Xfw1pZsL
|
||||
xhYoTwKCAQB9edDe4LX+0z9i4qr0iHV8H/WoyI5UD/Pc217PKkYM3+ewR9SL9D9z
|
||||
TS78Sl7HgRgEmIu+MR/u5B2ePf7jkvB/oxyPwqAzJeJ72mV3Mevm27G/Ndd8lt5W
|
||||
FBCGOx7ZeP4/Cv4mvPD979ix2IalDoWMSWJnpQPN+B1jGeCrUYAXQc1k/vU99gLa
|
||||
8Tuu3WfBpVAsO7hAC9mu6tuLyfKVqiMOVs2aky9xLqiqW/6uIcGu+owrr+gkDDY/
|
||||
JfBSUfxYKcjtJiHOEbFGrrRe93XsngmaTz/Hv9A/QLVCuJgWEHlt4WHSc+BtAtaV
|
||||
9avp6VlyVNfe4KEKW7IekrI0cmfMdXkl
|
||||
-----END PRIVATE KEY-----
|
71
package.json
71
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "libp2p",
|
||||
"version": "0.31.0-rc.6",
|
||||
"version": "0.31.8",
|
||||
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
|
||||
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
|
||||
"main": "src/index.js",
|
||||
@@ -79,6 +79,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@motrix/nat-api": "^0.3.1",
|
||||
"@vascosantos/moving-average": "^1.1.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"aggregate-error": "^3.1.0",
|
||||
"any-signal": "^2.1.1",
|
||||
@@ -91,7 +92,6 @@
|
||||
"events": "^3.3.0",
|
||||
"hashlru": "^2.3.0",
|
||||
"interface-datastore": "^4.0.0",
|
||||
"ipfs-utils": "^6.0.0",
|
||||
"it-all": "^1.0.4",
|
||||
"it-buffer": "^0.1.2",
|
||||
"it-drain": "^1.0.3",
|
||||
@@ -103,12 +103,11 @@
|
||||
"it-merge": "1.0.0",
|
||||
"it-pipe": "^1.1.0",
|
||||
"it-take": "1.0.0",
|
||||
"libp2p-crypto": "^0.19.0",
|
||||
"libp2p-interfaces": "^0.10.3",
|
||||
"libp2p-crypto": "^0.19.4",
|
||||
"libp2p-interfaces": "^0.10.4",
|
||||
"libp2p-utils": "^0.3.1",
|
||||
"mafmt": "^9.0.0",
|
||||
"merge-options": "^3.0.4",
|
||||
"moving-average": "^1.0.0",
|
||||
"multiaddr": "^9.0.1",
|
||||
"multicodec": "^3.0.1",
|
||||
"multihashing-async": "^2.1.2",
|
||||
@@ -127,7 +126,9 @@
|
||||
"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",
|
||||
"wherearewe": "^1.0.0",
|
||||
"xsalsa20": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -136,14 +137,12 @@
|
||||
"@types/node-forge": "^0.9.7",
|
||||
"@types/varint": "^6.0.0",
|
||||
"abortable-iterator": "^3.0.0",
|
||||
"aegir": "^33.0.0",
|
||||
"aegir": "^33.1.1",
|
||||
"buffer": "^6.0.3",
|
||||
"chai-bytes": "^0.1.2",
|
||||
"chai-string": "^1.5.0",
|
||||
"delay": "^5.0.0",
|
||||
"interop-libp2p": "^0.3.0",
|
||||
"interop-libp2p": "^0.4.0",
|
||||
"into-stream": "^6.0.0",
|
||||
"ipfs-http-client": "^49.0.4",
|
||||
"ipfs-http-client": "^50.1.1",
|
||||
"it-concat": "^1.0.0",
|
||||
"it-pair": "^1.0.0",
|
||||
"it-pushable": "^1.4.0",
|
||||
@@ -152,14 +151,14 @@
|
||||
"libp2p-delegated-content-routing": "^0.10.0",
|
||||
"libp2p-delegated-peer-routing": "^0.9.0",
|
||||
"libp2p-floodsub": "^0.25.0",
|
||||
"libp2p-gossipsub": "^0.8.0",
|
||||
"libp2p-kad-dht": "^0.21.0",
|
||||
"libp2p-gossipsub": "^0.9.0",
|
||||
"libp2p-kad-dht": "^0.22.0",
|
||||
"libp2p-mdns": "^0.16.0",
|
||||
"libp2p-mplex": "^0.10.1",
|
||||
"libp2p-noise": "^2.0.0",
|
||||
"libp2p-tcp": "^0.15.1",
|
||||
"libp2p-webrtc-star": "^0.22.0",
|
||||
"libp2p-websockets": "^0.15.0",
|
||||
"libp2p-noise": "^3.0.0",
|
||||
"libp2p-tcp": "^0.15.4",
|
||||
"libp2p-webrtc-star": "^0.22.2",
|
||||
"libp2p-websockets": "^0.15.8",
|
||||
"multihashes": "^4.0.2",
|
||||
"nock": "^13.0.3",
|
||||
"p-defer": "^3.0.0",
|
||||
@@ -167,12 +166,11 @@
|
||||
"p-wait-for": "^3.2.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"sinon": "^10.0.0",
|
||||
"uint8arrays": "^2.1.3",
|
||||
"util": "^0.12.3"
|
||||
},
|
||||
"contributors": [
|
||||
"David Dias <daviddias.p@gmail.com>",
|
||||
"Vasco Santos <vasco.santos@moxy.studio>",
|
||||
"David Dias <daviddias.p@gmail.com>",
|
||||
"Jacob Heun <jacobheun@gmail.com>",
|
||||
"Alex Potsides <alex@achingbrain.net>",
|
||||
"Alan Shaw <alan@tableflip.io>",
|
||||
@@ -182,19 +180,22 @@
|
||||
"Maciej Krüger <mkg20001@gmail.com>",
|
||||
"Hugo Dias <mail@hugodias.me>",
|
||||
"dirkmc <dirkmdev@gmail.com>",
|
||||
"Chris Dostert <chrisdostert@users.noreply.github.com>",
|
||||
"Volker Mische <volker.mische@gmail.com>",
|
||||
"zeim839 <50573884+zeim839@users.noreply.github.com>",
|
||||
"Richard Littauer <richard.littauer@gmail.com>",
|
||||
"a1300 <matthias-knopp@gmx.net>",
|
||||
"Elven <mon.samuel@qq.com>",
|
||||
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
||||
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
|
||||
"Thomas Eizinger <thomas@eizinger.io>",
|
||||
"Samlior <samlior@foxmail.com>",
|
||||
"Ryan Bell <ryan@piing.net>",
|
||||
"a1300 <matthias-knopp@gmx.net>",
|
||||
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
|
||||
"Samlior <samlior@foxmail.com>",
|
||||
"Andrew Nesbitt <andrewnez@gmail.com>",
|
||||
"Thomas Eizinger <thomas@eizinger.io>",
|
||||
"Franck Royer <franck@royer.one>",
|
||||
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
||||
"acolytec3 <17355484+acolytec3@users.noreply.github.com>",
|
||||
"Elven <mon.samuel@qq.com>",
|
||||
"Didrik Nordström <didrik.nordstrom@gmail.com>",
|
||||
"Nuno Nogueira <nunofmn@gmail.com>",
|
||||
"Philipp Muens <raute1337@gmx.de>",
|
||||
"RasmusErik Voel Jensen <github@solsort.com>",
|
||||
"Smite Chow <xiaopengyou@live.com>",
|
||||
"Soeren <nikorpoulsen@gmail.com>",
|
||||
"Sönke Hahn <soenkehahn@gmail.com>",
|
||||
@@ -204,8 +205,13 @@
|
||||
"Zane Starr <zcstarr@gmail.com>",
|
||||
"ebinks <elizabethjbinks@gmail.com>",
|
||||
"isan_rivkin <isanrivkin@gmail.com>",
|
||||
"mayerwin <mayerwin@users.noreply.github.com>",
|
||||
"mcclure <andi.m.mcclure@gmail.com>",
|
||||
"phillmac <phillmac@users.noreply.github.com>",
|
||||
"robertkiel <robert.kiel@validitylabs.org>",
|
||||
"RasmusErik Voel Jensen <github@solsort.com>",
|
||||
"shresthagrawal <34920931+shresthagrawal@users.noreply.github.com>",
|
||||
"swedneck <40505480+swedneck@users.noreply.github.com>",
|
||||
"Marcin Tojek <mtojek@users.noreply.github.com>",
|
||||
"Aleksei <vozhdb@gmail.com>",
|
||||
"Bernd Strehl <bernd.strehl@gmail.com>",
|
||||
"Chris Bratlien <chrisbratlien@gmail.com>",
|
||||
@@ -218,13 +224,20 @@
|
||||
"Felipe Martins <felipebrasil93@gmail.com>",
|
||||
"Florian-Merle <florian.david.merle@gmail.com>",
|
||||
"Francis Gulotta <wizard@roborooter.com>",
|
||||
"Franck Royer <franck@royer.one>",
|
||||
"Guy Sviry <32539816+guysv@users.noreply.github.com>",
|
||||
"Henrique Dias <hacdias@gmail.com>",
|
||||
"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>",
|
||||
"Miguel Mota <miguelmota2@gmail.com>"
|
||||
"Lars Gierth <lgierth@users.noreply.github.com>",
|
||||
"Aditya Bose <13054902+adbose@users.noreply.github.com>",
|
||||
"Michael Burns <5170+mburns@users.noreply.github.com>",
|
||||
"Miguel Mota <miguelmota2@gmail.com>",
|
||||
"Nuno Nogueira <nunofmn@gmail.com>",
|
||||
"Philipp Muens <raute1337@gmx.de>"
|
||||
]
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const EventEmitter = require('events')
|
||||
const { EventEmitter } = require('events')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
|
@@ -3,8 +3,6 @@
|
||||
const CID = require('cids')
|
||||
const multihashing = require('multihashing-async')
|
||||
|
||||
const TextEncoder = require('ipfs-utils/src/text-encoder')
|
||||
|
||||
/**
|
||||
* Convert a namespace string into a cid.
|
||||
*
|
||||
|
@@ -11,7 +11,7 @@ const LatencyMonitor = require('./latency-monitor')
|
||||
// @ts-ignore retimer does not have types
|
||||
const retimer = require('retimer')
|
||||
|
||||
const EventEmitter = require('events')
|
||||
const { EventEmitter } = require('events')
|
||||
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
@@ -97,6 +97,11 @@ class ConnectionManager extends EventEmitter {
|
||||
this._autoDialTimeout = null
|
||||
this._checkMetrics = this._checkMetrics.bind(this)
|
||||
this._autoDial = this._autoDial.bind(this)
|
||||
|
||||
this._latencyMonitor = new LatencyMonitor({
|
||||
latencyCheckIntervalMs: this._options.pollInterval,
|
||||
dataEmitIntervalMs: this._options.pollInterval
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,10 +122,7 @@ class ConnectionManager extends EventEmitter {
|
||||
}
|
||||
|
||||
// latency monitor
|
||||
this._latencyMonitor = new LatencyMonitor({
|
||||
latencyCheckIntervalMs: this._options.pollInterval,
|
||||
dataEmitIntervalMs: this._options.pollInterval
|
||||
})
|
||||
this._latencyMonitor.start()
|
||||
this._onLatencyMeasure = this._onLatencyMeasure.bind(this)
|
||||
this._latencyMonitor.on('data', this._onLatencyMeasure)
|
||||
|
||||
@@ -138,7 +140,9 @@ class ConnectionManager extends EventEmitter {
|
||||
async stop () {
|
||||
this._autoDialTimeout && this._autoDialTimeout.clear()
|
||||
this._timer && this._timer.clear()
|
||||
this._latencyMonitor && this._latencyMonitor.removeListener('data', this._onLatencyMeasure)
|
||||
|
||||
this._latencyMonitor.removeListener('data', this._onLatencyMeasure)
|
||||
this._latencyMonitor.stop()
|
||||
|
||||
this._started = false
|
||||
await this._close()
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* This code is based on `latency-monitor` (https://github.com/mlucool/latency-monitor) by `mlucool` (https://github.com/mlucool), available under Apache License 2.0 (https://github.com/mlucool/latency-monitor/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
const EventEmitter = require('events')
|
||||
const { EventEmitter } = require('events')
|
||||
const VisibilityChangeEmitter = require('./visibility-change-emitter')
|
||||
const debug = require('debug')('latency-monitor:LatencyMonitor')
|
||||
|
||||
@@ -69,49 +69,55 @@ class LatencyMonitor extends EventEmitter {
|
||||
}
|
||||
|
||||
that.asyncTestFn = asyncTestFn // If there is no asyncFn, we measure latency
|
||||
}
|
||||
|
||||
start () {
|
||||
// If process: use high resolution timer
|
||||
if (globalThis.process && globalThis.process.hrtime) { // eslint-disable-line no-undef
|
||||
debug('Using process.hrtime for timing')
|
||||
that.now = globalThis.process.hrtime // eslint-disable-line no-undef
|
||||
that.getDeltaMS = (startTime) => {
|
||||
const hrtime = that.now(startTime)
|
||||
this.now = globalThis.process.hrtime // eslint-disable-line no-undef
|
||||
this.getDeltaMS = (startTime) => {
|
||||
const hrtime = this.now(startTime)
|
||||
return (hrtime[0] * 1000) + (hrtime[1] / 1000000)
|
||||
}
|
||||
// Let's try for a timer that only monotonically increases
|
||||
} else if (typeof window !== 'undefined' && window.performance && window.performance.now) {
|
||||
debug('Using performance.now for timing')
|
||||
that.now = window.performance.now.bind(window.performance)
|
||||
that.getDeltaMS = (startTime) => Math.round(that.now() - startTime)
|
||||
this.now = window.performance.now.bind(window.performance)
|
||||
this.getDeltaMS = (startTime) => Math.round(this.now() - startTime)
|
||||
} else {
|
||||
debug('Using Date.now for timing')
|
||||
that.now = Date.now
|
||||
that.getDeltaMS = (startTime) => that.now() - startTime
|
||||
this.now = Date.now
|
||||
this.getDeltaMS = (startTime) => this.now() - startTime
|
||||
}
|
||||
|
||||
that._latencyData = that._initLatencyData()
|
||||
this._latencyData = this._initLatencyData()
|
||||
|
||||
// We check for isBrowser because of browsers set max rates of timeouts when a page is hidden,
|
||||
// so we fall back to another library
|
||||
// See: http://stackoverflow.com/questions/6032429/chrome-timeouts-interval-suspended-in-background-tabs
|
||||
if (isBrowser()) {
|
||||
that._visibilityChangeEmitter = new VisibilityChangeEmitter()
|
||||
this._visibilityChangeEmitter = new VisibilityChangeEmitter()
|
||||
|
||||
that._visibilityChangeEmitter.on('visibilityChange', (pageInFocus) => {
|
||||
this._visibilityChangeEmitter.on('visibilityChange', (pageInFocus) => {
|
||||
if (pageInFocus) {
|
||||
that._startTimers()
|
||||
this._startTimers()
|
||||
} else {
|
||||
that._emitSummary()
|
||||
that._stopTimers()
|
||||
this._emitSummary()
|
||||
this._stopTimers()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (!that._visibilityChangeEmitter || that._visibilityChangeEmitter.isVisible()) {
|
||||
that._startTimers()
|
||||
if (!this._visibilityChangeEmitter || this._visibilityChangeEmitter.isVisible()) {
|
||||
this._startTimers()
|
||||
}
|
||||
}
|
||||
|
||||
stop () {
|
||||
this._stopTimers()
|
||||
}
|
||||
|
||||
/**
|
||||
* Start internal timers
|
||||
*
|
||||
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
'use strict'
|
||||
|
||||
const EventEmitter = require('events')
|
||||
const { EventEmitter } = require('events')
|
||||
|
||||
const debug = require('debug')('latency-monitor:VisibilityChangeEmitter')
|
||||
|
||||
|
@@ -16,7 +16,7 @@ const { pipe } = require('it-pipe')
|
||||
* @typedef {import('peer-id')} PeerId
|
||||
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||
* @typedef {import('cids')} CID
|
||||
* @typedef {import('libp2p-interfaces/src/content-routing/types')} ContentRoutingModule
|
||||
* @typedef {import('libp2p-interfaces/src/content-routing/types').ContentRouting} ContentRoutingModule
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -8,6 +8,7 @@ const errCode = require('err-code')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
// @ts-ignore timeout-abourt-controles does not export types
|
||||
const TimeoutController = require('timeout-abort-controller')
|
||||
const { AbortError } = require('abortable-iterator')
|
||||
const { anySignal } = require('any-signal')
|
||||
|
||||
const DialRequest = require('./dial-request')
|
||||
@@ -76,6 +77,7 @@ class Dialer {
|
||||
this.maxDialsPerPeer = maxDialsPerPeer
|
||||
this.tokens = [...new Array(maxParallelDials)].map((_, index) => index)
|
||||
this._pendingDials = new Map()
|
||||
this._pendingDialTargets = new Map()
|
||||
|
||||
for (const [key, value] of Object.entries(resolvers)) {
|
||||
Multiaddr.resolvers.set(key, value)
|
||||
@@ -94,6 +96,11 @@ class Dialer {
|
||||
}
|
||||
}
|
||||
this._pendingDials.clear()
|
||||
|
||||
for (const pendingTarget of this._pendingDialTargets.values()) {
|
||||
pendingTarget.reject(new AbortError('Dialer was destroyed'))
|
||||
}
|
||||
this._pendingDialTargets.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +114,7 @@ class Dialer {
|
||||
* @returns {Promise<Connection>}
|
||||
*/
|
||||
async connectToPeer (peer, options = {}) {
|
||||
const dialTarget = await this._createDialTarget(peer)
|
||||
const dialTarget = await this._createCancellableDialTarget(peer)
|
||||
|
||||
if (!dialTarget.addrs.length) {
|
||||
throw errCode(new Error('The dial request has no valid addresses'), codes.ERR_NO_VALID_ADDRESSES)
|
||||
@@ -130,6 +137,31 @@ class Dialer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to a given `peer` by dialing all of its known addresses.
|
||||
* The dial to the first address that is successfully able to upgrade a connection
|
||||
* will be used.
|
||||
*
|
||||
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
||||
* @returns {Promise<DialTarget>}
|
||||
*/
|
||||
async _createCancellableDialTarget (peer) {
|
||||
// Make dial target promise cancellable
|
||||
const id = `${(parseInt(String(Math.random() * 1e9), 10)).toString() + Date.now()}`
|
||||
const cancellablePromise = new Promise((resolve, reject) => {
|
||||
this._pendingDialTargets.set(id, { resolve, reject })
|
||||
})
|
||||
|
||||
const dialTarget = await Promise.race([
|
||||
this._createDialTarget(peer),
|
||||
cancellablePromise
|
||||
])
|
||||
|
||||
this._pendingDialTargets.delete(id)
|
||||
|
||||
return dialTarget
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DialTarget. The DialTarget is used to create and track
|
||||
* the DialRequest to a given peer.
|
||||
|
@@ -189,6 +189,8 @@ class IdentifyService {
|
||||
const envelope = await Envelope.openAndCertify(signedPeerRecord, PeerRecord.DOMAIN)
|
||||
if (this.peerStore.addressBook.consumePeerRecord(envelope)) {
|
||||
this.peerStore.protoBook.set(id, protocols)
|
||||
this.peerStore.metadataBook.set(id, 'AgentVersion', uint8ArrayFromString(message.agentVersion))
|
||||
this.peerStore.metadataBook.set(id, 'ProtocolVersion', uint8ArrayFromString(message.protocolVersion))
|
||||
return
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -204,6 +206,7 @@ class IdentifyService {
|
||||
|
||||
this.peerStore.protoBook.set(id, protocols)
|
||||
this.peerStore.metadataBook.set(id, 'AgentVersion', uint8ArrayFromString(message.agentVersion))
|
||||
this.peerStore.metadataBook.set(id, 'ProtocolVersion', uint8ArrayFromString(message.protocolVersion))
|
||||
|
||||
// TODO: Add and score our observed addr
|
||||
log('received observed address of %s', cleanObservedAddr)
|
||||
|
12
src/index.js
12
src/index.js
@@ -4,7 +4,7 @@ const debug = require('debug')
|
||||
const log = Object.assign(debug('libp2p'), {
|
||||
error: debug('libp2p:err')
|
||||
})
|
||||
const EventEmitter = require('events')
|
||||
const { EventEmitter } = require('events')
|
||||
|
||||
const errCode = require('err-code')
|
||||
const PeerId = require('peer-id')
|
||||
@@ -40,9 +40,9 @@ const { updateSelfPeerRecord } = require('./record/utils')
|
||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||
* @typedef {import('libp2p-interfaces/src/transport/types').TransportFactory<any, any>} TransportFactory
|
||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxerFactory} MuxerFactory
|
||||
* @typedef {import('libp2p-interfaces/src/content-routing/types')} ContentRoutingModule
|
||||
* @typedef {import('libp2p-interfaces/src/peer-discovery/types')} PeerDiscoveryModule
|
||||
* @typedef {import('libp2p-interfaces/src/peer-routing/types')} PeerRoutingModule
|
||||
* @typedef {import('libp2p-interfaces/src/content-routing/types').ContentRouting} ContentRoutingModule
|
||||
* @typedef {import('libp2p-interfaces/src/peer-discovery/types').PeerDiscoveryFactory} PeerDiscoveryFactory
|
||||
* @typedef {import('libp2p-interfaces/src/peer-routing/types').PeerRouting} PeerRoutingModule
|
||||
* @typedef {import('libp2p-interfaces/src/crypto/types').Crypto} Crypto
|
||||
* @typedef {import('libp2p-interfaces/src/pubsub')} Pubsub
|
||||
* @typedef {import('libp2p-interfaces/src/pubsub').PubsubOptions} PubsubOptions
|
||||
@@ -100,7 +100,7 @@ const { updateSelfPeerRecord } = require('./record/utils')
|
||||
* @property {TransportFactory[]} transport
|
||||
* @property {MuxerFactory[]} streamMuxer
|
||||
* @property {Crypto[]} connEncryption
|
||||
* @property {PeerDiscoveryModule[]} [peerDiscovery]
|
||||
* @property {PeerDiscoveryFactory[]} [peerDiscovery]
|
||||
* @property {PeerRoutingModule[]} [peerRouting]
|
||||
* @property {ContentRoutingModule[]} [contentRouting]
|
||||
* @property {Object} [dht]
|
||||
@@ -714,7 +714,7 @@ class Libp2p extends EventEmitter {
|
||||
*/
|
||||
async _setupPeerDiscovery () {
|
||||
/**
|
||||
* @param {PeerDiscoveryModule} DiscoveryService
|
||||
* @param {PeerDiscoveryFactory} DiscoveryService
|
||||
*/
|
||||
const setupService = (DiscoveryService) => {
|
||||
let config = {
|
||||
|
@@ -1,6 +1,9 @@
|
||||
/* eslint max-nested-callbacks: ["error", 5] */
|
||||
'use strict'
|
||||
|
||||
const debug = require('debug')
|
||||
const log = Object.assign(debug('libp2p:keychain'), {
|
||||
error: debug('libp2p:keychain:err')
|
||||
})
|
||||
const sanitize = require('sanitize-filename')
|
||||
const mergeOptions = require('merge-options')
|
||||
const crypto = require('libp2p-crypto')
|
||||
@@ -503,6 +506,55 @@ class Keychain {
|
||||
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND'))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate keychain password and re-encrypt all assosciated keys
|
||||
*
|
||||
* @param {string} oldPass - The old local keychain password
|
||||
* @param {string} newPass - The new local keychain password
|
||||
*/
|
||||
async rotateKeychainPass (oldPass, newPass) {
|
||||
if (typeof oldPass !== 'string') {
|
||||
return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), 'ERR_INVALID_OLD_PASS_TYPE'))
|
||||
}
|
||||
if (typeof newPass !== 'string') {
|
||||
return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), 'ERR_INVALID_NEW_PASS_TYPE'))
|
||||
}
|
||||
if (newPass.length < 20) {
|
||||
return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), 'ERR_INVALID_PASS_LENGTH'))
|
||||
}
|
||||
log('recreating keychain')
|
||||
const oldDek = privates.get(this).dek
|
||||
this.opts.pass = newPass
|
||||
const newDek = newPass
|
||||
? crypto.pbkdf2(
|
||||
newPass,
|
||||
this.opts.dek.salt,
|
||||
this.opts.dek.iterationCount,
|
||||
this.opts.dek.keyLength,
|
||||
this.opts.dek.hash)
|
||||
: ''
|
||||
privates.set(this, { dek: newDek })
|
||||
const keys = await this.listKeys()
|
||||
for (const key of keys) {
|
||||
const res = await this.store.get(DsName(key.name))
|
||||
const pem = uint8ArrayToString(res)
|
||||
const privateKey = await crypto.keys.import(pem, oldDek)
|
||||
const password = newDek.toString()
|
||||
const keyAsPEM = await privateKey.export(password)
|
||||
|
||||
// Update stored key
|
||||
const batch = this.store.batch()
|
||||
const keyInfo = {
|
||||
name: key.name,
|
||||
id: key.id
|
||||
}
|
||||
batch.put(DsName(key.name), uint8ArrayFromString(keyAsPEM))
|
||||
batch.put(DsInfoName(key.name), uint8ArrayFromString(JSON.stringify(keyInfo)))
|
||||
await batch.commit()
|
||||
}
|
||||
log('keychain reconstructed')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Keychain
|
||||
|
@@ -1,11 +1,15 @@
|
||||
// @ts-nocheck
|
||||
'use strict'
|
||||
|
||||
const EventEmitter = require('events')
|
||||
const { EventEmitter } = require('events')
|
||||
const { BigNumber: Big } = require('bignumber.js')
|
||||
const MovingAverage = require('moving-average')
|
||||
const MovingAverage = require('@vascosantos/moving-average')
|
||||
const retimer = require('retimer')
|
||||
|
||||
/**
|
||||
* @typedef {import('@vascosantos/moving-average').IMovingAverage} IMovingAverage
|
||||
*/
|
||||
|
||||
class Stats extends EventEmitter {
|
||||
/**
|
||||
* A queue based manager for stat processing
|
||||
@@ -29,7 +33,7 @@ class Stats extends EventEmitter {
|
||||
this._frequencyLastTime = Date.now()
|
||||
this._frequencyAccumulators = {}
|
||||
|
||||
/** @type {{ dataReceived: MovingAverage[], dataSent: MovingAverage[] }} */
|
||||
/** @type {{ dataReceived: IMovingAverage[], dataSent: IMovingAverage[] }} */
|
||||
this._movingAverages = {}
|
||||
|
||||
this._update = this._update.bind(this)
|
||||
|
@@ -8,7 +8,7 @@ const { Multiaddr } = require('multiaddr')
|
||||
const log = Object.assign(debug('libp2p:nat'), {
|
||||
error: debug('libp2p:nat:err')
|
||||
})
|
||||
const { isBrowser } = require('ipfs-utils/src/env')
|
||||
const { isBrowser } = require('wherearewe')
|
||||
const retry = require('p-retry')
|
||||
// @ts-ignore private-api does not export types
|
||||
const isPrivateIp = require('private-ip')
|
||||
|
@@ -25,7 +25,7 @@ const {
|
||||
/**
|
||||
* @typedef {import('peer-id')} PeerId
|
||||
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||
* @typedef {import('libp2p-interfaces/src/peer-routing/types')} PeerRoutingModule
|
||||
* @typedef {import('libp2p-interfaces/src/peer-routing/types').PeerRouting} PeerRoutingModule
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -104,6 +104,10 @@ class PeerRouting {
|
||||
throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||
}
|
||||
|
||||
if (id.toB58String() === this._peerId.toB58String()) {
|
||||
throw errCode(new Error('Should not try to find self'), 'ERR_FIND_SELF')
|
||||
}
|
||||
|
||||
const output = await pipe(
|
||||
merge(
|
||||
...this._routers.map(router => [router.findPeer(id, options)])
|
||||
|
@@ -307,10 +307,13 @@ class AddressBook extends Book {
|
||||
throw errcode(new Error(`multiaddr ${addr} must be an instance of multiaddr`), ERR_INVALID_PARAMETERS)
|
||||
}
|
||||
|
||||
addresses.push({
|
||||
multiaddr: addr,
|
||||
isCertified
|
||||
})
|
||||
// Guarantee no replicates
|
||||
if (!addresses.find((a) => a.multiaddr.equals(addr))) {
|
||||
addresses.push({
|
||||
multiaddr: addr,
|
||||
isCertified
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return addresses
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
const errcode = require('err-code')
|
||||
|
||||
const EventEmitter = require('events')
|
||||
const { EventEmitter } = require('events')
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
const AddressBook = require('./address-book')
|
||||
|
@@ -137,7 +137,12 @@ class Upgrader {
|
||||
* @returns {Promise<Connection>}
|
||||
*/
|
||||
async upgradeOutbound (maConn) {
|
||||
const remotePeerId = PeerId.createFromB58String(maConn.remoteAddr.getPeerId())
|
||||
const idStr = maConn.remoteAddr.getPeerId()
|
||||
if (!idStr) {
|
||||
throw errCode(new Error('outbound connection must have a peer id'), codes.ERR_INVALID_MULTIADDR)
|
||||
}
|
||||
|
||||
const remotePeerId = PeerId.createFromB58String(idStr)
|
||||
|
||||
let encryptedConn
|
||||
let remotePeer
|
||||
|
@@ -3,14 +3,13 @@
|
||||
|
||||
const { expect } = require('aegir/utils/chai')
|
||||
const mergeOptions = require('merge-options')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const pDefer = require('p-defer')
|
||||
const delay = require('delay')
|
||||
|
||||
const { create } = require('../../src')
|
||||
const { baseOptions, subsystemOptions } = require('./utils')
|
||||
const { baseOptions, pubsubSubsystemOptions } = require('./utils')
|
||||
const peerUtils = require('../utils/creators/peer')
|
||||
|
||||
const listenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/0')
|
||||
|
||||
describe('Pubsub subsystem is configurable', () => {
|
||||
let libp2p
|
||||
|
||||
@@ -24,18 +23,15 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
})
|
||||
|
||||
it('should exist if the module is provided', async () => {
|
||||
libp2p = await create(subsystemOptions)
|
||||
libp2p = await create(pubsubSubsystemOptions)
|
||||
expect(libp2p.pubsub).to.exist()
|
||||
})
|
||||
|
||||
it('should start and stop by default once libp2p starts', async () => {
|
||||
const [peerId] = await peerUtils.createPeerId()
|
||||
|
||||
const customOptions = mergeOptions(subsystemOptions, {
|
||||
peerId,
|
||||
addresses: {
|
||||
listen: [listenAddr]
|
||||
}
|
||||
const customOptions = mergeOptions(pubsubSubsystemOptions, {
|
||||
peerId
|
||||
})
|
||||
|
||||
libp2p = await create(customOptions)
|
||||
@@ -51,11 +47,8 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
it('should not start if disabled once libp2p starts', async () => {
|
||||
const [peerId] = await peerUtils.createPeerId()
|
||||
|
||||
const customOptions = mergeOptions(subsystemOptions, {
|
||||
const customOptions = mergeOptions(pubsubSubsystemOptions, {
|
||||
peerId,
|
||||
addresses: {
|
||||
listen: [listenAddr]
|
||||
},
|
||||
config: {
|
||||
pubsub: {
|
||||
enabled: false
|
||||
@@ -73,11 +66,8 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
it('should allow a manual start', async () => {
|
||||
const [peerId] = await peerUtils.createPeerId()
|
||||
|
||||
const customOptions = mergeOptions(subsystemOptions, {
|
||||
const customOptions = mergeOptions(pubsubSubsystemOptions, {
|
||||
peerId,
|
||||
addresses: {
|
||||
listen: [listenAddr]
|
||||
},
|
||||
config: {
|
||||
pubsub: {
|
||||
enabled: false
|
||||
@@ -93,3 +83,47 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
expect(libp2p.pubsub.started).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Pubsub subscription handlers adapter', () => {
|
||||
let libp2p
|
||||
|
||||
beforeEach(async () => {
|
||||
const [peerId] = await peerUtils.createPeerId()
|
||||
|
||||
libp2p = await create(mergeOptions(pubsubSubsystemOptions, {
|
||||
peerId
|
||||
}))
|
||||
|
||||
await libp2p.start()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
libp2p && await libp2p.stop()
|
||||
})
|
||||
|
||||
it('extends pubsub with subscribe handler', async () => {
|
||||
let countMessages = 0
|
||||
const topic = 'topic'
|
||||
const defer = pDefer()
|
||||
|
||||
const handler = () => {
|
||||
countMessages++
|
||||
if (countMessages > 1) {
|
||||
throw new Error('only one message should be received')
|
||||
}
|
||||
|
||||
defer.resolve()
|
||||
}
|
||||
|
||||
await libp2p.pubsub.subscribe(topic, handler)
|
||||
|
||||
libp2p.pubsub.emit(topic, 'useless-data')
|
||||
await defer.promise
|
||||
|
||||
await libp2p.pubsub.unsubscribe(topic, handler)
|
||||
libp2p.pubsub.emit(topic, 'useless-data')
|
||||
|
||||
// wait to guarantee that the handler is not called twice
|
||||
await delay(100)
|
||||
})
|
||||
})
|
52
test/configuration/utils.js
Normal file
52
test/configuration/utils.js
Normal file
@@ -0,0 +1,52 @@
|
||||
'use strict'
|
||||
|
||||
const Pubsub = require('libp2p-interfaces/src/pubsub')
|
||||
const { NOISE: Crypto } = require('libp2p-noise')
|
||||
const Muxer = require('libp2p-mplex')
|
||||
const Transport = require('libp2p-websockets')
|
||||
const filters = require('libp2p-websockets/src/filters')
|
||||
const transportKey = Transport.prototype[Symbol.toStringTag]
|
||||
|
||||
const { MULTIADDRS_WEBSOCKETS } = require('../fixtures/browser')
|
||||
const relayAddr = MULTIADDRS_WEBSOCKETS[0]
|
||||
|
||||
const mergeOptions = require('merge-options')
|
||||
|
||||
const baseOptions = {
|
||||
modules: {
|
||||
transport: [Transport],
|
||||
streamMuxer: [Muxer],
|
||||
connEncryption: [Crypto]
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.baseOptions = baseOptions
|
||||
|
||||
class MockPubsub extends Pubsub {
|
||||
constructor (libp2p, options = {}) {
|
||||
super({
|
||||
debugName: 'mock-pubsub',
|
||||
multicodecs: '/mock-pubsub',
|
||||
libp2p,
|
||||
...options
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const pubsubSubsystemOptions = mergeOptions(baseOptions, {
|
||||
modules: {
|
||||
pubsub: MockPubsub
|
||||
},
|
||||
addresses: {
|
||||
listen: [`${relayAddr}/p2p-circuit`]
|
||||
},
|
||||
config: {
|
||||
transport: {
|
||||
[transportKey]: {
|
||||
filter: filters.all
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
module.exports.pubsubSubsystemOptions = pubsubSubsystemOptions
|
@@ -105,7 +105,7 @@ describe('content-routing', () => {
|
||||
beforeEach(async () => {
|
||||
const [peerId] = await peerUtils.createPeerId({ fixture: true })
|
||||
|
||||
delegate = new DelegatedContentRouter(peerId, ipfsHttpClient({
|
||||
delegate = new DelegatedContentRouter(peerId, ipfsHttpClient.create({
|
||||
host: '0.0.0.0',
|
||||
protocol: 'http',
|
||||
port: 60197
|
||||
@@ -253,7 +253,7 @@ describe('content-routing', () => {
|
||||
beforeEach(async () => {
|
||||
const [peerId] = await peerUtils.createPeerId({ fixture: true })
|
||||
|
||||
delegate = new DelegatedContentRouter(peerId, ipfsHttpClient({
|
||||
delegate = new DelegatedContentRouter(peerId, ipfsHttpClient.create({
|
||||
host: '0.0.0.0',
|
||||
protocol: 'http',
|
||||
port: 60197
|
||||
|
@@ -290,6 +290,34 @@ describe('Dialing (direct, WebSockets)', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('should cancel pending dial targets before proceeding', async () => {
|
||||
const dialer = new Dialer({
|
||||
transportManager: localTM,
|
||||
peerStore: {
|
||||
addressBook: {
|
||||
set: () => { }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
sinon.stub(dialer, '_createDialTarget').callsFake(() => {
|
||||
const deferredDial = pDefer()
|
||||
return deferredDial.promise
|
||||
})
|
||||
|
||||
// Perform dial
|
||||
const dialPromise = dialer.connectToPeer(peerId)
|
||||
|
||||
// Let the call stack run
|
||||
await delay(0)
|
||||
|
||||
dialer.destroy()
|
||||
|
||||
await expect(dialPromise)
|
||||
.to.eventually.be.rejected()
|
||||
.and.to.have.property('code', 'ABORT_ERR')
|
||||
})
|
||||
|
||||
describe('libp2p.dialer', () => {
|
||||
const transportKey = Transport.prototype[Symbol.toStringTag]
|
||||
let libp2p
|
||||
@@ -462,6 +490,42 @@ describe('Dialing (direct, WebSockets)', () => {
|
||||
await libp2p.hangUp(remoteAddr)
|
||||
})
|
||||
|
||||
it('should cancel pending dial targets and stop', async () => {
|
||||
const [, remotePeerId] = await createPeerId({ number: 2 })
|
||||
|
||||
libp2p = new Libp2p({
|
||||
peerId,
|
||||
modules: {
|
||||
transport: [Transport],
|
||||
streamMuxer: [Muxer],
|
||||
connEncryption: [Crypto]
|
||||
},
|
||||
config: {
|
||||
transport: {
|
||||
[transportKey]: {
|
||||
filter: filters.all
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
sinon.stub(libp2p.dialer, '_createDialTarget').callsFake(() => {
|
||||
const deferredDial = pDefer()
|
||||
return deferredDial.promise
|
||||
})
|
||||
|
||||
// Perform dial
|
||||
const dialPromise = libp2p.dial(remotePeerId)
|
||||
|
||||
// Let the call stack run
|
||||
await delay(0)
|
||||
|
||||
await libp2p.stop()
|
||||
await expect(dialPromise)
|
||||
.to.eventually.be.rejected()
|
||||
.and.to.have.property('code', 'ABORT_ERR')
|
||||
})
|
||||
|
||||
it('should abort pending dials on stop', async () => {
|
||||
libp2p = new Libp2p({
|
||||
peerId,
|
||||
|
@@ -430,6 +430,39 @@ describe('Identify', () => {
|
||||
await connection.close()
|
||||
})
|
||||
|
||||
it('should store remote agent and protocol versions in metadataBook after connecting', async () => {
|
||||
libp2p = new Libp2p({
|
||||
...baseOptions,
|
||||
peerId
|
||||
})
|
||||
|
||||
await libp2p.start()
|
||||
|
||||
sinon.spy(libp2p.identifyService, 'identify')
|
||||
const peerStoreSpyConsumeRecord = sinon.spy(libp2p.peerStore.addressBook, 'consumePeerRecord')
|
||||
const peerStoreSpyAdd = sinon.spy(libp2p.peerStore.addressBook, 'add')
|
||||
|
||||
const connection = await libp2p.dialer.connectToPeer(remoteAddr)
|
||||
expect(connection).to.exist()
|
||||
|
||||
// Wait for peer store to be updated
|
||||
// Dialer._createDialTarget (add), Identify (consume)
|
||||
await pWaitFor(() => peerStoreSpyConsumeRecord.callCount === 1 && peerStoreSpyAdd.callCount === 1)
|
||||
expect(libp2p.identifyService.identify.callCount).to.equal(1)
|
||||
|
||||
// The connection should have no open streams
|
||||
await pWaitFor(() => connection.streams.length === 0)
|
||||
await connection.close()
|
||||
|
||||
const remotePeer = PeerId.createFromB58String(remoteAddr.getPeerId())
|
||||
|
||||
const storedAgentVersion = libp2p.peerStore.metadataBook.getValue(remotePeer, 'AgentVersion')
|
||||
const storedProtocolVersion = libp2p.peerStore.metadataBook.getValue(remotePeer, 'ProtocolVersion')
|
||||
|
||||
expect(storedAgentVersion).to.exist()
|
||||
expect(storedProtocolVersion).to.exist()
|
||||
})
|
||||
|
||||
it('should push protocol updates to an already connected peer', async () => {
|
||||
libp2p = new Libp2p({
|
||||
...baseOptions,
|
||||
|
@@ -2,8 +2,7 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const { chai, expect } = require('aegir/utils/chai')
|
||||
chai.use(require('chai-string'))
|
||||
const { expect } = require('aegir/utils/chai')
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
const { MemoryDatastore } = require('interface-datastore')
|
||||
|
@@ -2,17 +2,17 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const { chai, expect } = require('aegir/utils/chai')
|
||||
const { expect } = require('aegir/utils/chai')
|
||||
const fail = expect.fail
|
||||
chai.use(require('chai-string'))
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const peerUtils = require('../utils/creators/peer')
|
||||
|
||||
const { MemoryDatastore } = require('interface-datastore')
|
||||
const { MemoryDatastore, Key } = require('interface-datastore')
|
||||
const Keychain = require('../../src/keychain')
|
||||
const PeerId = require('peer-id')
|
||||
const crypto = require('libp2p-crypto')
|
||||
|
||||
describe('keychain', () => {
|
||||
const passPhrase = 'this is not a secure phrase'
|
||||
@@ -493,6 +493,88 @@ describe('keychain', () => {
|
||||
expect(key).to.have.property('id', rsaKeyInfo.id)
|
||||
})
|
||||
})
|
||||
|
||||
describe('rotate keychain passphrase', () => {
|
||||
let oldPass
|
||||
let kc
|
||||
let options
|
||||
let ds
|
||||
before(async () => {
|
||||
ds = new MemoryDatastore()
|
||||
oldPass = `hello-${Date.now()}-${Date.now()}`
|
||||
options = {
|
||||
pass: oldPass,
|
||||
dek: {
|
||||
salt: '3Nd/Ya4ENB3bcByNKptb4IR',
|
||||
iterationCount: 10000,
|
||||
keyLength: 64,
|
||||
hash: 'sha2-512'
|
||||
}
|
||||
}
|
||||
kc = new Keychain(ds, options)
|
||||
await ds.open()
|
||||
})
|
||||
|
||||
it('should validate newPass is a string', async () => {
|
||||
try {
|
||||
await kc.rotateKeychainPass(oldPass, 1234567890)
|
||||
} catch (err) {
|
||||
expect(err).to.exist()
|
||||
}
|
||||
})
|
||||
|
||||
it('should validate oldPass is a string', async () => {
|
||||
try {
|
||||
await kc.rotateKeychainPass(1234, 'newInsecurePassword1')
|
||||
} catch (err) {
|
||||
expect(err).to.exist()
|
||||
}
|
||||
})
|
||||
|
||||
it('should validate newPass is at least 20 characters', async () => {
|
||||
try {
|
||||
await kc.rotateKeychainPass(oldPass, 'not20Chars')
|
||||
} catch (err) {
|
||||
expect(err).to.exist()
|
||||
}
|
||||
})
|
||||
|
||||
it('can rotate keychain passphrase', async () => {
|
||||
await kc.createKey('keyCreatedWithOldPassword', 'rsa', 2048)
|
||||
await kc.rotateKeychainPass(oldPass, 'newInsecurePassphrase')
|
||||
|
||||
// Get Key PEM from datastore
|
||||
const dsname = new Key('/pkcs8/' + 'keyCreatedWithOldPassword')
|
||||
const res = await ds.get(dsname)
|
||||
const pem = uint8ArrayToString(res)
|
||||
|
||||
const oldDek = options.pass
|
||||
? crypto.pbkdf2(
|
||||
options.pass,
|
||||
options.dek.salt,
|
||||
options.dek.iterationCount,
|
||||
options.dek.keyLength,
|
||||
options.dek.hash)
|
||||
: ''
|
||||
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
const newDek = 'newInsecurePassphrase'
|
||||
? crypto.pbkdf2(
|
||||
'newInsecurePassphrase',
|
||||
options.dek.salt,
|
||||
options.dek.iterationCount,
|
||||
options.dek.keyLength,
|
||||
options.dek.hash)
|
||||
: ''
|
||||
|
||||
// Dek with old password should not work:
|
||||
await expect(kc.importKey('keyWhosePassChanged', pem, oldDek))
|
||||
.to.eventually.be.rejected()
|
||||
// Dek with new password should work:
|
||||
await expect(kc.importKey('keyWhosePasswordChanged', pem, newDek))
|
||||
.to.eventually.have.property('name', 'keyWhosePasswordChanged')
|
||||
}).timeout(10000)
|
||||
})
|
||||
})
|
||||
|
||||
describe('libp2p.keychain', () => {
|
||||
|
@@ -100,6 +100,12 @@ describe('peer-routing', () => {
|
||||
|
||||
return deferred.promise
|
||||
})
|
||||
|
||||
it('should error when peer tries to find itself', async () => {
|
||||
await expect(nodes[0].peerRouting.findPeer(nodes[0].peerId))
|
||||
.to.eventually.be.rejected()
|
||||
.and.to.have.property('code', 'ERR_FIND_SELF')
|
||||
})
|
||||
})
|
||||
|
||||
describe('via delegate router', () => {
|
||||
@@ -107,7 +113,7 @@ describe('peer-routing', () => {
|
||||
let delegate
|
||||
|
||||
beforeEach(async () => {
|
||||
delegate = new DelegatedPeerRouter(ipfsHttpClient({
|
||||
delegate = new DelegatedPeerRouter(ipfsHttpClient.create({
|
||||
host: '0.0.0.0',
|
||||
protocol: 'http',
|
||||
port: 60197
|
||||
@@ -187,6 +193,12 @@ describe('peer-routing', () => {
|
||||
expect(mockApi.isDone()).to.equal(true)
|
||||
})
|
||||
|
||||
it('should error when peer tries to find itself', async () => {
|
||||
await expect(node.peerRouting.findPeer(node.peerId))
|
||||
.to.eventually.be.rejected()
|
||||
.and.to.have.property('code', 'ERR_FIND_SELF')
|
||||
})
|
||||
|
||||
it('should error when a peer cannot be found', async () => {
|
||||
const peerKey = 'key of a peer not on the network'
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
@@ -276,7 +288,7 @@ describe('peer-routing', () => {
|
||||
let delegate
|
||||
|
||||
beforeEach(async () => {
|
||||
delegate = new DelegatedPeerRouter(ipfsHttpClient({
|
||||
delegate = new DelegatedPeerRouter(ipfsHttpClient.create({
|
||||
host: '0.0.0.0',
|
||||
protocol: 'http',
|
||||
port: 60197
|
||||
|
@@ -287,6 +287,14 @@ describe('addressBook', () => {
|
||||
|
||||
await defer.promise
|
||||
})
|
||||
|
||||
it('does not add replicated content', () => {
|
||||
// set 1
|
||||
ab.set(peerId, [addr1, addr1])
|
||||
|
||||
const addresses = ab.get(peerId)
|
||||
expect(addresses).to.have.lengthOf(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('addressBook.get', () => {
|
||||
|
@@ -1,8 +1,7 @@
|
||||
'use strict'
|
||||
/* eslint-env mocha */
|
||||
|
||||
const { chai, expect } = require('aegir/utils/chai')
|
||||
chai.use(require('chai-bytes'))
|
||||
const { expect } = require('aegir/utils/chai')
|
||||
const sinon = require('sinon')
|
||||
|
||||
const PeerStore = require('../../src/peer-store')
|
||||
|
@@ -1,8 +1,7 @@
|
||||
'use strict'
|
||||
/* eslint-env mocha */
|
||||
|
||||
const { chai, expect } = require('aegir/utils/chai')
|
||||
chai.use(require('chai-bytes'))
|
||||
const { expect } = require('aegir/utils/chai')
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
|
||||
const pDefer = require('p-defer')
|
||||
|
@@ -1,8 +1,7 @@
|
||||
'use strict'
|
||||
/* eslint-env mocha */
|
||||
|
||||
const { chai, expect } = require('aegir/utils/chai')
|
||||
chai.use(require('chai-bytes'))
|
||||
const { expect } = require('aegir/utils/chai')
|
||||
const sinon = require('sinon')
|
||||
|
||||
const baseOptions = require('../utils/base-options')
|
||||
|
@@ -1,95 +0,0 @@
|
||||
'use strict'
|
||||
/* eslint-env mocha */
|
||||
|
||||
const { expect } = require('aegir/utils/chai')
|
||||
const pWaitFor = require('p-wait-for')
|
||||
const pDefer = require('p-defer')
|
||||
const mergeOptions = require('merge-options')
|
||||
|
||||
const Floodsub = require('libp2p-floodsub')
|
||||
const Gossipsub = require('libp2p-gossipsub')
|
||||
const { multicodec: floodsubMulticodec } = require('libp2p-floodsub')
|
||||
const { multicodec: gossipsubMulticodec } = require('libp2p-gossipsub')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
|
||||
const { create } = require('../../src')
|
||||
const { baseOptions } = require('./utils')
|
||||
const peerUtils = require('../utils/creators/peer')
|
||||
|
||||
const listenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/0')
|
||||
const remoteListenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/0')
|
||||
|
||||
describe('Pubsub subsystem is able to use different implementations', () => {
|
||||
let peerId, remotePeerId
|
||||
let libp2p, remoteLibp2p
|
||||
|
||||
beforeEach(async () => {
|
||||
[peerId, remotePeerId] = await peerUtils.createPeerId({ number: 2 })
|
||||
})
|
||||
|
||||
afterEach(() => Promise.all([
|
||||
libp2p && libp2p.stop(),
|
||||
remoteLibp2p && remoteLibp2p.stop()
|
||||
]))
|
||||
|
||||
it('Floodsub nodes', () => {
|
||||
return pubsubTest(floodsubMulticodec, Floodsub)
|
||||
})
|
||||
|
||||
it('Gossipsub nodes', () => {
|
||||
return pubsubTest(gossipsubMulticodec, Gossipsub)
|
||||
})
|
||||
|
||||
const pubsubTest = async (multicodec, pubsub) => {
|
||||
const defer = pDefer()
|
||||
const topic = 'test-topic'
|
||||
const data = 'hey!'
|
||||
|
||||
libp2p = await create(mergeOptions(baseOptions, {
|
||||
peerId,
|
||||
addresses: {
|
||||
listen: [listenAddr]
|
||||
},
|
||||
modules: {
|
||||
pubsub: pubsub
|
||||
}
|
||||
}))
|
||||
|
||||
remoteLibp2p = await create(mergeOptions(baseOptions, {
|
||||
peerId: remotePeerId,
|
||||
addresses: {
|
||||
listen: [remoteListenAddr]
|
||||
},
|
||||
modules: {
|
||||
pubsub: pubsub
|
||||
}
|
||||
}))
|
||||
|
||||
await Promise.all([
|
||||
libp2p.start(),
|
||||
remoteLibp2p.start()
|
||||
])
|
||||
|
||||
const libp2pId = libp2p.peerId.toB58String()
|
||||
libp2p.peerStore.addressBook.set(remotePeerId, remoteLibp2p.multiaddrs)
|
||||
|
||||
const connection = await libp2p.dialProtocol(remotePeerId, multicodec)
|
||||
expect(connection).to.exist()
|
||||
|
||||
libp2p.pubsub.subscribe(topic, (msg) => {
|
||||
expect(uint8ArrayToString(msg.data)).to.equal(data)
|
||||
defer.resolve()
|
||||
})
|
||||
|
||||
// wait for remoteLibp2p to know about libp2p subscription
|
||||
await pWaitFor(() => {
|
||||
const subscribedPeers = remoteLibp2p.pubsub.getSubscribers(topic)
|
||||
return subscribedPeers.includes(libp2pId)
|
||||
})
|
||||
|
||||
remoteLibp2p.pubsub.publish(topic, data)
|
||||
await defer.promise
|
||||
}
|
||||
})
|
@@ -1,326 +0,0 @@
|
||||
'use strict'
|
||||
/* eslint-env mocha */
|
||||
|
||||
const { expect } = require('aegir/utils/chai')
|
||||
const sinon = require('sinon')
|
||||
|
||||
const pWaitFor = require('p-wait-for')
|
||||
const pDefer = require('p-defer')
|
||||
const mergeOptions = require('merge-options')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const { create } = require('../../src')
|
||||
const { subsystemOptions, subsystemMulticodecs } = require('./utils')
|
||||
const peerUtils = require('../utils/creators/peer')
|
||||
|
||||
const listenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/0')
|
||||
const remoteListenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/0')
|
||||
|
||||
describe('Pubsub subsystem operates correctly', () => {
|
||||
let peerId, remotePeerId
|
||||
let libp2p, remoteLibp2p
|
||||
|
||||
beforeEach(async () => {
|
||||
[peerId, remotePeerId] = await peerUtils.createPeerId({ number: 2 })
|
||||
})
|
||||
|
||||
describe('pubsub started before connect', () => {
|
||||
beforeEach(async () => {
|
||||
libp2p = await create(mergeOptions(subsystemOptions, {
|
||||
peerId,
|
||||
addresses: {
|
||||
listen: [listenAddr]
|
||||
}
|
||||
}))
|
||||
|
||||
remoteLibp2p = await create(mergeOptions(subsystemOptions, {
|
||||
peerId: remotePeerId,
|
||||
addresses: {
|
||||
listen: [remoteListenAddr]
|
||||
}
|
||||
}))
|
||||
|
||||
await Promise.all([
|
||||
libp2p.start(),
|
||||
remoteLibp2p.start()
|
||||
])
|
||||
|
||||
libp2p.peerStore.addressBook.set(remotePeerId, remoteLibp2p.multiaddrs)
|
||||
})
|
||||
|
||||
afterEach(() => Promise.all([
|
||||
libp2p && libp2p.stop(),
|
||||
remoteLibp2p && remoteLibp2p.stop()
|
||||
]))
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
it('should get notified of connected peers on dial', async () => {
|
||||
const connection = await libp2p.dialProtocol(remotePeerId, subsystemMulticodecs)
|
||||
|
||||
expect(connection).to.exist()
|
||||
|
||||
return Promise.all([
|
||||
pWaitFor(() => libp2p.pubsub.peers.size === 1),
|
||||
pWaitFor(() => remoteLibp2p.pubsub.peers.size === 1)
|
||||
])
|
||||
})
|
||||
|
||||
it('should receive pubsub messages', async () => {
|
||||
const defer = pDefer()
|
||||
const topic = 'test-topic'
|
||||
const data = 'hey!'
|
||||
const libp2pId = libp2p.peerId.toB58String()
|
||||
|
||||
await libp2p.dialProtocol(remotePeerId, subsystemMulticodecs)
|
||||
|
||||
let subscribedTopics = libp2p.pubsub.getTopics()
|
||||
expect(subscribedTopics).to.not.include(topic)
|
||||
|
||||
libp2p.pubsub.subscribe(topic, (msg) => {
|
||||
expect(uint8ArrayToString(msg.data)).to.equal(data)
|
||||
defer.resolve()
|
||||
})
|
||||
|
||||
subscribedTopics = libp2p.pubsub.getTopics()
|
||||
expect(subscribedTopics).to.include(topic)
|
||||
|
||||
// wait for remoteLibp2p to know about libp2p subscription
|
||||
await pWaitFor(() => {
|
||||
const subscribedPeers = remoteLibp2p.pubsub.getSubscribers(topic)
|
||||
return subscribedPeers.includes(libp2pId)
|
||||
})
|
||||
remoteLibp2p.pubsub.publish(topic, data)
|
||||
|
||||
await defer.promise
|
||||
})
|
||||
})
|
||||
|
||||
describe('pubsub started after connect', () => {
|
||||
beforeEach(async () => {
|
||||
libp2p = await create(mergeOptions(subsystemOptions, {
|
||||
peerId,
|
||||
addresses: {
|
||||
listen: [listenAddr]
|
||||
}
|
||||
}))
|
||||
|
||||
remoteLibp2p = await create(mergeOptions(subsystemOptions, {
|
||||
peerId: remotePeerId,
|
||||
addresses: {
|
||||
listen: [remoteListenAddr]
|
||||
},
|
||||
config: {
|
||||
pubsub: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
await libp2p.start()
|
||||
await remoteLibp2p.start()
|
||||
|
||||
libp2p.peerStore.addressBook.set(remotePeerId, remoteLibp2p.multiaddrs)
|
||||
})
|
||||
|
||||
afterEach(() => Promise.all([
|
||||
libp2p && libp2p.stop(),
|
||||
remoteLibp2p && remoteLibp2p.stop()
|
||||
]))
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
it('should get notified of connected peers after starting', async () => {
|
||||
const connection = await libp2p.dial(remotePeerId)
|
||||
|
||||
expect(connection).to.exist()
|
||||
expect(libp2p.pubsub.peers.size).to.be.eql(0)
|
||||
expect(remoteLibp2p.pubsub.peers.size).to.be.eql(0)
|
||||
|
||||
remoteLibp2p.pubsub.start()
|
||||
|
||||
return Promise.all([
|
||||
pWaitFor(() => libp2p.pubsub.peers.size === 1),
|
||||
pWaitFor(() => remoteLibp2p.pubsub.peers.size === 1)
|
||||
])
|
||||
})
|
||||
|
||||
it('should receive pubsub messages', async function () {
|
||||
this.timeout(10e3)
|
||||
const defer = pDefer()
|
||||
const libp2pId = libp2p.peerId.toB58String()
|
||||
const topic = 'test-topic'
|
||||
const data = 'hey!'
|
||||
|
||||
await libp2p.dial(remotePeerId)
|
||||
|
||||
remoteLibp2p.pubsub.start()
|
||||
|
||||
await Promise.all([
|
||||
pWaitFor(() => libp2p.pubsub.peers.size === 1),
|
||||
pWaitFor(() => remoteLibp2p.pubsub.peers.size === 1)
|
||||
])
|
||||
|
||||
let subscribedTopics = libp2p.pubsub.getTopics()
|
||||
expect(subscribedTopics).to.not.include(topic)
|
||||
|
||||
libp2p.pubsub.subscribe(topic, (msg) => {
|
||||
expect(uint8ArrayToString(msg.data)).to.equal(data)
|
||||
defer.resolve()
|
||||
})
|
||||
|
||||
subscribedTopics = libp2p.pubsub.getTopics()
|
||||
expect(subscribedTopics).to.include(topic)
|
||||
|
||||
// wait for remoteLibp2p to know about libp2p subscription
|
||||
await pWaitFor(() => {
|
||||
const subscribedPeers = remoteLibp2p.pubsub.getSubscribers(topic)
|
||||
return subscribedPeers.includes(libp2pId)
|
||||
})
|
||||
|
||||
remoteLibp2p.pubsub.publish(topic, data)
|
||||
|
||||
await defer.promise
|
||||
})
|
||||
})
|
||||
|
||||
describe('pubsub with intermittent connections', () => {
|
||||
beforeEach(async () => {
|
||||
libp2p = await create(mergeOptions(subsystemOptions, {
|
||||
peerId,
|
||||
addresses: {
|
||||
listen: [listenAddr]
|
||||
},
|
||||
config: {
|
||||
pubsub: {
|
||||
enabled: true,
|
||||
emitSelf: false
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
remoteLibp2p = await create(mergeOptions(subsystemOptions, {
|
||||
peerId: remotePeerId,
|
||||
addresses: {
|
||||
listen: [remoteListenAddr]
|
||||
},
|
||||
config: {
|
||||
pubsub: {
|
||||
enabled: true,
|
||||
emitSelf: false
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
await libp2p.start()
|
||||
await remoteLibp2p.start()
|
||||
|
||||
libp2p.peerStore.addressBook.set(remotePeerId, remoteLibp2p.multiaddrs)
|
||||
})
|
||||
|
||||
afterEach(() => Promise.all([
|
||||
libp2p && libp2p.stop(),
|
||||
remoteLibp2p && remoteLibp2p.stop()
|
||||
]))
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
it('should receive pubsub messages after a node restart', async () => {
|
||||
const topic = 'test-topic'
|
||||
const data = 'hey!'
|
||||
const libp2pId = libp2p.peerId.toB58String()
|
||||
|
||||
let counter = 0
|
||||
const defer1 = pDefer()
|
||||
const defer2 = pDefer()
|
||||
const handler = (msg) => {
|
||||
expect(uint8ArrayToString(msg.data)).to.equal(data)
|
||||
counter++
|
||||
counter === 1 ? defer1.resolve() : defer2.resolve()
|
||||
}
|
||||
|
||||
await libp2p.dial(remotePeerId)
|
||||
|
||||
let subscribedTopics = libp2p.pubsub.getTopics()
|
||||
expect(subscribedTopics).to.not.include(topic)
|
||||
|
||||
libp2p.pubsub.subscribe(topic, handler)
|
||||
|
||||
subscribedTopics = libp2p.pubsub.getTopics()
|
||||
expect(subscribedTopics).to.include(topic)
|
||||
|
||||
// wait for remoteLibp2p to know about libp2p subscription
|
||||
await pWaitFor(() => {
|
||||
const subscribedPeers = remoteLibp2p.pubsub.getSubscribers(topic)
|
||||
return subscribedPeers.includes(libp2pId)
|
||||
})
|
||||
remoteLibp2p.pubsub.publish(topic, data)
|
||||
|
||||
await defer1.promise
|
||||
|
||||
await remoteLibp2p.stop()
|
||||
await remoteLibp2p.start()
|
||||
|
||||
libp2p.peerStore.addressBook.set(remotePeerId, remoteLibp2p.multiaddrs)
|
||||
await libp2p.dial(remotePeerId)
|
||||
|
||||
// wait for remoteLibp2p to know about libp2p subscription
|
||||
await pWaitFor(() => {
|
||||
const subscribedPeers = remoteLibp2p.pubsub.getSubscribers(topic)
|
||||
return subscribedPeers.includes(libp2pId)
|
||||
})
|
||||
|
||||
remoteLibp2p.pubsub.publish(topic, data)
|
||||
|
||||
await defer2.promise
|
||||
})
|
||||
|
||||
it('should handle quick reconnects with a delayed disconnect', async () => {
|
||||
// Subscribe on both
|
||||
const handlerSpy = sinon.spy()
|
||||
const topic = 'reconnect-channel'
|
||||
await Promise.all([
|
||||
libp2p.pubsub.subscribe(topic, handlerSpy),
|
||||
remoteLibp2p.pubsub.subscribe(topic, handlerSpy)
|
||||
])
|
||||
// Create two connections to the remote peer
|
||||
const originalConnection = await libp2p.dialer.connectToPeer(remoteLibp2p.peerId)
|
||||
// second connection
|
||||
await libp2p.dialer.connectToPeer(remoteLibp2p.peerId)
|
||||
expect(libp2p.connections.get(remoteLibp2p.peerId.toB58String())).to.have.length(2)
|
||||
|
||||
// Wait for subscriptions to occur
|
||||
await pWaitFor(() => {
|
||||
return libp2p.pubsub.getSubscribers(topic).includes(remoteLibp2p.peerId.toB58String()) &&
|
||||
remoteLibp2p.pubsub.getSubscribers(topic).includes(libp2p.peerId.toB58String())
|
||||
})
|
||||
|
||||
// Verify messages go both ways
|
||||
libp2p.pubsub.publish(topic, 'message1')
|
||||
remoteLibp2p.pubsub.publish(topic, 'message2')
|
||||
await pWaitFor(() => handlerSpy.callCount === 2)
|
||||
expect(handlerSpy.args.map(([message]) => uint8ArrayToString(message.data))).to.include.members(['message1', 'message2'])
|
||||
|
||||
// Disconnect the first connection (this acts as a delayed reconnect)
|
||||
const libp2pConnUpdateSpy = sinon.spy(libp2p.connectionManager.connections, 'set')
|
||||
const remoteLibp2pConnUpdateSpy = sinon.spy(remoteLibp2p.connectionManager.connections, 'set')
|
||||
|
||||
await originalConnection.close()
|
||||
await pWaitFor(() => libp2pConnUpdateSpy.callCount === 1 && remoteLibp2pConnUpdateSpy.callCount === 1)
|
||||
|
||||
// Verify messages go both ways after the disconnect
|
||||
handlerSpy.resetHistory()
|
||||
libp2p.pubsub.publish(topic, 'message3')
|
||||
remoteLibp2p.pubsub.publish(topic, 'message4')
|
||||
await pWaitFor(() => handlerSpy.callCount === 2)
|
||||
expect(handlerSpy.args.map(([message]) => uint8ArrayToString(message.data))).to.include.members(['message3', 'message4'])
|
||||
})
|
||||
})
|
||||
})
|
@@ -1,29 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const Gossipsub = require('libp2p-gossipsub')
|
||||
const { multicodec } = require('libp2p-gossipsub')
|
||||
const Crypto = require('../../src/insecure/plaintext')
|
||||
const Muxer = require('libp2p-mplex')
|
||||
const Transport = require('libp2p-tcp')
|
||||
|
||||
const mergeOptions = require('merge-options')
|
||||
|
||||
const baseOptions = {
|
||||
modules: {
|
||||
transport: [Transport],
|
||||
streamMuxer: [Muxer],
|
||||
connEncryption: [Crypto]
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.baseOptions = baseOptions
|
||||
|
||||
const subsystemOptions = mergeOptions(baseOptions, {
|
||||
modules: {
|
||||
pubsub: Gossipsub
|
||||
}
|
||||
})
|
||||
|
||||
module.exports.subsystemOptions = subsystemOptions
|
||||
|
||||
module.exports.subsystemMulticodecs = [multicodec]
|
@@ -1,8 +1,7 @@
|
||||
'use strict'
|
||||
/* eslint-env mocha */
|
||||
|
||||
const { chai, expect } = require('aegir/utils/chai')
|
||||
chai.use(require('chai-bytes'))
|
||||
const { expect } = require('aegir/utils/chai')
|
||||
const uint8arrayFromString = require('uint8arrays/from-string')
|
||||
const uint8arrayEquals = require('uint8arrays/equals')
|
||||
const Envelope = require('../../src/record/envelope')
|
||||
|
@@ -515,7 +515,7 @@ describe('auto-relay', () => {
|
||||
|
||||
// Create 2 nodes, and turn HOP on for the relay
|
||||
;[local, remote, relayLibp2p] = peerIds.map((peerId, index) => {
|
||||
const delegate = new DelegatedContentRouter(peerId, ipfsHttpClient({
|
||||
const delegate = new DelegatedContentRouter(peerId, ipfsHttpClient.create({
|
||||
host: '0.0.0.0',
|
||||
protocol: 'http',
|
||||
port: 60197
|
||||
|
@@ -35,13 +35,13 @@ async function main() {
|
||||
// create a peerId
|
||||
const peerId = await PeerId.create()
|
||||
|
||||
const delegatedPeerRouting = new DelegatedPeerRouter(ipfsHttpClient({
|
||||
const delegatedPeerRouting = new DelegatedPeerRouter(ipfsHttpClient.create({
|
||||
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
|
||||
protocol: 'https',
|
||||
port: 443
|
||||
}))
|
||||
|
||||
const delegatedContentRouting = new DelegatedContentRouter(peerId, ipfsHttpClient({
|
||||
const delegatedContentRouting = new DelegatedContentRouter(peerId, ipfsHttpClient.create({
|
||||
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
|
||||
protocol: 'https',
|
||||
port: 443
|
||||
|
Reference in New Issue
Block a user