Compare commits

..

22 Commits

Author SHA1 Message Date
0489972b4b chore: release version v0.26.0-rc.3 2019-08-06 12:27:28 +02:00
3f31b1f422 chore: update contributors 2019-08-06 12:27:27 +02:00
a2b3446ed7 docs: async migration (#397) 2019-08-06 12:01:16 +02:00
ff7a6c86a0 fix: promisified methods (#398)
* chore: update ws rendezvous dep

test(fix): fix tests with latest ws rendezvous server

* fix: promisification of libp2p methods

test: add tests to verify promisify support until async/await endeavor is complete

* chore: fix linting
2019-08-06 10:53:23 +02:00
9a8d609a59 chore: release version v0.26.0-rc.2 2019-08-01 17:17:54 +02:00
9fef58cb7d chore: update contributors 2019-08-01 17:17:54 +02:00
684f283aec chore: update switch (#395)
BREAKING CHANGE: switch configuration has changed.
'blacklistTTL' is now 'denyTTL' and 'blackListAttempts' is now 'denyAttempts'
2019-08-01 17:15:02 +02:00
3e95e6f9e4 fix: dont override methods of created instance (#394)
* fix: dont override methods of created instance

* chore: fix lint
2019-08-01 16:08:38 +02:00
f4f3f0f03a fix: pubsub default config (#393)
* docs: update browser example pubsub

* docs: fix pubsub example config

* fix: make pubsub default to enabled

This allows for only adding the module to have it enabled. Previously you would have to supply and enable the module which is unncessary for users
2019-07-31 18:47:30 +02:00
7c2c852fc0 chore: release version v0.26.0-rc.1 2019-07-31 14:35:43 +02:00
e8d8aab278 chore: update contributors 2019-07-31 14:35:42 +02:00
dd48d268ec chore: promisify pubsub start and stop (#392) 2019-07-31 14:33:00 +02:00
99a53592e2 chore: release version v0.26.0-rc.0 2019-07-31 09:47:06 +02:00
2a2e7a1012 chore: update contributors 2019-07-31 09:47:06 +02:00
791f39a09b feat: integrate gossipsub by default (#365)
BREAKING CHANGE: new configuration for deciding the implementation of pubsub to be used.
In this context, the experimental flags were also removed. See the README for the latest usage.
2019-07-31 09:38:14 +02:00
65d52857a5 test(fix): correct findProviders test for missing provider (#391)
* test(fix): correct findProviders test for missing provider

* chore: fix lint
2019-07-30 15:11:24 +02:00
48b1b442e9 docs: libp2p in browser example (#390)
* docs: improve browser example

* docs: remove bad ipfs link
2019-07-30 12:38:02 +02:00
9554b05c6f fix: make subscribe comply with ipfs interface (#389)
BREAKING CHANGE: The ipfs interface specified that options
should be provided after the handler, not before.
https://github.com/ipfs/interface-js-ipfs-core/blob/v0.109.0/SPEC/PUBSUB.md#pubsubsubscribe

This corrects the order of parameters. See the jsdocs examples
for subscribe to see how it should be used.
2019-07-30 12:36:23 +02:00
df6ef45a2d feat: promisify all api methods that accept callbacks (#381)
* feat: promisify all api methods that accept callbacks

This is a stop-gap until the full async/await migration can be
completed.  It means we can refactor tests of other modules that
depend on this module without having to mix async flow control
strategies.

N.b. some methods that were previously callable without callbacks
(e.g. `node.start()`, `node.stop()`, etc) now require callbacks
otherwise a promise is returned which, if rejected, can cause
`unhandledPromiseRejection` events and lead to memory leaks.

* docs: add a global note to the api about promisify

* fix: update the logic for unsubscribe

* test(fix): correct pubsub unsubscribe usage for api change

* test(fix): update content routing tests for latest delegate version
2019-07-29 15:40:40 +02:00
b4a70ea476 chore: release version v0.25.5 2019-07-12 13:10:55 +01:00
45716da465 chore: update contributors 2019-07-12 13:10:53 +01:00
905c911946 fix: peer routing for delegate router (#377)
* fix: peer routing tests

* test: fix mock payload type

Provider results are type 4, not type 1: 6e566d10f4/routing/query.go (L15-L24)
2019-07-12 13:02:03 +01:00
39 changed files with 678 additions and 403 deletions

View File

@ -1,7 +1,6 @@
'use strict' 'use strict'
const pull = require('pull-stream') const pull = require('pull-stream')
const parallel = require('async/parallel')
const WebSocketStarRendezvous = require('libp2p-websocket-star-rendezvous') const WebSocketStarRendezvous = require('libp2p-websocket-star-rendezvous')
const sigServer = require('libp2p-webrtc-star/src/sig-server') const sigServer = require('libp2p-webrtc-star/src/sig-server')
@ -15,68 +14,46 @@ const {
let wrtcRendezvous let wrtcRendezvous
let wsRendezvous let wsRendezvous
let node let node
let peerInfo
const before = (done) => { const before = async () => {
parallel([ [wrtcRendezvous, wsRendezvous, peerInfo] = await Promise.all([
(cb) => { sigServer.start({
sigServer.start({ port: WRTC_RENDEZVOUS_MULTIADDR.nodeAddress().port
port: WRTC_RENDEZVOUS_MULTIADDR.nodeAddress().port // cryptoChallenge: true TODO: needs https://github.com/libp2p/js-libp2p-webrtc-star/issues/128
// cryptoChallenge: true TODO: needs https://github.com/libp2p/js-libp2p-webrtc-star/issues/128 }),
}) WebSocketStarRendezvous.start({
.then(server => { port: WS_RENDEZVOUS_MULTIADDR.nodeAddress().port,
wrtcRendezvous = server refreshPeerListIntervalMS: 1000,
cb() strictMultiaddr: false,
}) cryptoChallenge: true
.catch(cb) }),
}, getPeerRelay()
(cb) => { ])
WebSocketStarRendezvous.start({
port: WS_RENDEZVOUS_MULTIADDR.nodeAddress().port, node = new Node({
refreshPeerListIntervalMS: 1000, peerInfo,
strictMultiaddr: false, config: {
cryptoChallenge: true relay: {
}, (err, _server) => { enabled: true,
if (err) { hop: {
return cb(err) enabled: true,
active: true
} }
wsRendezvous = _server }
cb()
})
},
(cb) => {
getPeerRelay((err, peerInfo) => {
if (err) {
return done(err)
}
node = new Node({
peerInfo,
config: {
relay: {
enabled: true,
hop: {
enabled: true,
active: true
}
}
}
})
node.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
node.start(cb)
})
} }
], done) })
node.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
await node.start()
} }
const after = (done) => { const after = () => {
setTimeout(() => return Promise.all([
parallel([ wrtcRendezvous.stop(),
(cb) => wrtcRendezvous.stop().then(cb).catch(cb), wsRendezvous.stop(),
...[node, wsRendezvous].map((s) => (cb) => s.stop(cb)), node.stop()
], done), ])
2000
)
} }
module.exports = { module.exports = {

View File

@ -1,3 +1,78 @@
<a name="0.26.0-rc.3"></a>
# [0.26.0-rc.3](https://github.com/libp2p/js-libp2p/compare/v0.26.0-rc.2...v0.26.0-rc.3) (2019-08-06)
### Bug Fixes
* promisified methods ([#398](https://github.com/libp2p/js-libp2p/issues/398)) ([ff7a6c8](https://github.com/libp2p/js-libp2p/commit/ff7a6c8))
<a name="0.26.0-rc.2"></a>
# [0.26.0-rc.2](https://github.com/libp2p/js-libp2p/compare/v0.26.0-rc.1...v0.26.0-rc.2) (2019-08-01)
### Bug Fixes
* dont override methods of created instance ([#394](https://github.com/libp2p/js-libp2p/issues/394)) ([3e95e6f](https://github.com/libp2p/js-libp2p/commit/3e95e6f))
* pubsub default config ([#393](https://github.com/libp2p/js-libp2p/issues/393)) ([f4f3f0f](https://github.com/libp2p/js-libp2p/commit/f4f3f0f))
### Chores
* update switch ([#395](https://github.com/libp2p/js-libp2p/issues/395)) ([684f283](https://github.com/libp2p/js-libp2p/commit/684f283))
### BREAKING CHANGES
* switch configuration has changed.
'blacklistTTL' is now 'denyTTL' and 'blackListAttempts' is now 'denyAttempts'
<a name="0.26.0-rc.1"></a>
# [0.26.0-rc.1](https://github.com/libp2p/js-libp2p/compare/v0.26.0-rc.0...v0.26.0-rc.1) (2019-07-31)
<a name="0.26.0-rc.0"></a>
# [0.26.0-rc.0](https://github.com/libp2p/js-libp2p/compare/v0.25.5...v0.26.0-rc.0) (2019-07-31)
### Bug Fixes
* make subscribe comply with ipfs interface ([#389](https://github.com/libp2p/js-libp2p/issues/389)) ([9554b05](https://github.com/libp2p/js-libp2p/commit/9554b05))
### Features
* integrate gossipsub by default ([#365](https://github.com/libp2p/js-libp2p/issues/365)) ([791f39a](https://github.com/libp2p/js-libp2p/commit/791f39a))
* promisify all api methods that accept callbacks ([#381](https://github.com/libp2p/js-libp2p/issues/381)) ([df6ef45](https://github.com/libp2p/js-libp2p/commit/df6ef45))
### BREAKING CHANGES
* new configuration for deciding the implementation of pubsub to be used.
In this context, the experimental flags were also removed. See the README for the latest usage.
* The ipfs interface specified that options
should be provided after the handler, not before.
https://github.com/ipfs/interface-js-ipfs-core/blob/v0.109.0/SPEC/PUBSUB.md#pubsubsubscribe
This corrects the order of parameters. See the jsdocs examples
for subscribe to see how it should be used.
<a name="0.25.5"></a>
## [0.25.5](https://github.com/libp2p/js-libp2p/compare/v0.25.4...v0.25.5) (2019-07-12)
### Bug Fixes
* peer routing for delegate router ([#377](https://github.com/libp2p/js-libp2p/issues/377)) ([905c911](https://github.com/libp2p/js-libp2p/commit/905c911)), closes [/github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L15-L24](https://github.com//github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go/issues/L15-L24)
<a name="0.25.4"></a> <a name="0.25.4"></a>
## [0.25.4](https://github.com/libp2p/js-libp2p/compare/v0.25.3...v0.25.4) (2019-06-07) ## [0.25.4](https://github.com/libp2p/js-libp2p/compare/v0.25.3...v0.25.4) (2019-06-07)

View File

@ -94,6 +94,8 @@ npm install --save libp2p
## Usage ## Usage
**IMPORTANT NOTE**: We are currently on the way of migrating all our `libp2p` modules to use `async await` and `async iterators`, instead of callbacks and `pull-streams`. As a consequence, when you start a new libp2p project, we must check which versions of the modules you should use. For now, it is required to use the modules using callbacks with `libp2p`, while we are working on getting the remaining modules ready for a full migration. For more details, you can have a look at [libp2p/js-libp2p#266](https://github.com/libp2p/js-libp2p/issues/266).
### [Tutorials and Examples](/examples) ### [Tutorials and Examples](/examples)
You can find multiple examples on the [examples folder](/examples) that will guide you through using libp2p for several scenarios. You can find multiple examples on the [examples folder](/examples) that will guide you through using libp2p for several scenarios.
@ -119,6 +121,7 @@ const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const SECIO = require('libp2p-secio')
const MulticastDNS = require('libp2p-mdns') const MulticastDNS = require('libp2p-mdns')
const DHT = require('libp2p-kad-dht') const DHT = require('libp2p-kad-dht')
const GossipSub = require('libp2p-gossipsub')
const defaultsDeep = require('@nodeutils/defaults-deep') const defaultsDeep = require('@nodeutils/defaults-deep')
const Protector = require('libp2p-pnet') const Protector = require('libp2p-pnet')
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing') const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
@ -154,7 +157,8 @@ class Node extends Libp2p {
peerDiscovery: [ peerDiscovery: [
MulticastDNS MulticastDNS
], ],
dht: DHT // DHT enables PeerRouting, ContentRouting and DHT itself components dht: DHT, // DHT enables PeerRouting, ContentRouting and DHT itself components
pubsub: GossipSub
}, },
// libp2p config options (typically found on a config.json) // libp2p config options (typically found on a config.json)
@ -187,9 +191,8 @@ class Node extends Libp2p {
timeout: 10e3 timeout: 10e3
} }
}, },
// Enable/Disable Experimental features pubsub: {
EXPERIMENTAL: { // Experimental features ("behind a flag") enabled: true
pubsub: false
} }
} }
} }
@ -204,6 +207,8 @@ class Node extends Libp2p {
### API ### API
**IMPORTANT NOTE**: All the methods listed in the API section that take a callback are also now Promisified. Libp2p is migrating away from callbacks to async/await, and in a future release (that will be announced in advance), callback support will be removed entirely. You can follow progress of the async/await endeavor at https://github.com/ipfs/js-ipfs/issues/1670.
#### Create a Node - `Libp2p.createLibp2p(options, callback)` #### Create a Node - `Libp2p.createLibp2p(options, callback)`
> Behaves exactly like `new Libp2p(options)`, but doesn't require a PeerInfo. One will be generated instead > Behaves exactly like `new Libp2p(options)`, but doesn't require a PeerInfo. One will be generated instead

View File

@ -10,17 +10,18 @@ The starting [Libp2p Bundle](./src/libp2p-bundle.js) in this example starts by d
Once you've completed the example, you should try enabled the DHT and see what kind of results you get! You can also enable the Once you've completed the example, you should try enabled the DHT and see what kind of results you get! You can also enable the
various Peer Discovery modules and see the impact it has on your Peer count. various Peer Discovery modules and see the impact it has on your Peer count.
## Prerequisite
**NOTE**: This example is currently dependent on a clone of the [delegated routing support branch of go-ipfs](https://github.com/ipfs/go-ipfs/pull/4595).
## Running this example ## Running this example
1. Install go-ipfs locally if you dont already have it. [Install Guide](https://docs.ipfs.io/introduction/install/). 1. Install IPFS locally if you dont already have it. [Install Guide](https://docs.ipfs.io/introduction/install/)
1. Run the IPFS daemon: `ipfs daemon`. 2. Run the IPFS daemon: `ipfs daemon`
1. The daemon will output a line about its API address, like `API server listening on /ip4/127.0.0.1/tcp/8080`. 3. The daemon will output a line about its API address, like `API server listening on /ip4/127.0.0.1/tcp/8080`
1. In another window, while the daemon is running, Configure the IPFS Gateway to support delegate routing `ipfs config Gateway.APICommands --json '["dht/findprovs", "dht/findpeer", "refs", "swarm/connect"]'`. 4. In another window output the addresses of the node: `ipfs id`. Make note of the websocket address, it will contain `/ws/` in the address.
1. In the same window, output the addresses of the node: `ipfs id`. Make note of the websocket address, it will contain `/ws` in the address, like `/ip4/127.0.0.1/tcp/8081/ws`. 5. In `./src/libp2p-bundle.js` check if the host and port of your node are correct, according to the previous step. If they are different, replace them.
1. In `./src/libp2p-bundle.js` check if the host and port of your node are correct, according to the previous step. If they are different, replace them. 6. In `./src/App.js` replace `BootstrapNode` with your nodes Websocket address from step 4.
1. In `./src/App.js` replace `BootstrapNode` with your nodes Websocket address from step 3. **Also**, in `./src/App.js` set BootstrapNodeID to your nodes id, which is displayed when running `ipfs id` in the `ID` property. 7. Start this example:
1. Start this example:
```sh ```sh
npm install npm install
@ -46,12 +47,3 @@ This will do a few things:
2. Copy one of the CIDs from the list of peer addresses, this will be the last portion of the address and will look something like `QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8`. 2. Copy one of the CIDs from the list of peer addresses, this will be the last portion of the address and will look something like `QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8`.
3. In your browser, paste the CID into the *Peer* field and hit `Find`. 3. In your browser, paste the CID into the *Peer* field and hit `Find`.
4. You should see information about the peer including its addresses. 4. You should see information about the peer including its addresses.
### Adding Content via the Delegate
1. In one browser, such as Firefox, enter some text in the `Add Data` field and click `Add`.
2. Once added, JSON will be printed in the browser. Copy the value of `"hash"`.
3. Close your Firefox tab. Open a new browser window in a **different** browser, such as Chrome.
4. In the new window, copy the hash from step 2 into the `Hash` field and click `Find`.
5. The text you entered in step 1 should display.
**Note**: By closing the first window before fetching the content, you are ensuring that data cannot be retrieved from it, and instead the delegate must be relied on.

View File

@ -3,16 +3,16 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"ipfs": "~0.36.1", "ipfs": "~0.34.4",
"libp2p": "github:libp2p/js-libp2p#master", "libp2p": "github:libp2p/js-libp2p#master",
"libp2p-delegated-content-routing": "~0.2.2", "libp2p-delegated-content-routing": "~0.2.2",
"libp2p-delegated-peer-routing": "~0.2.2", "libp2p-delegated-peer-routing": "~0.2.2",
"libp2p-kad-dht": "~0.15.0", "libp2p-kad-dht": "~0.14.12",
"libp2p-mplex": "~0.8.5",
"libp2p-secio": "~0.11.1", "libp2p-secio": "~0.11.1",
"libp2p-webrtc-star": "~0.16.1", "libp2p-webrtc-star": "~0.15.8",
"libp2p-websocket-star": "~0.10.2", "libp2p-websocket-star": "~0.10.2",
"libp2p-websockets": "~0.12.2", "libp2p-websockets": "~0.12.2",
"pull-mplex": "~0.1.2",
"react": "^16.8.6", "react": "^16.8.6",
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"react-scripts": "2.1.8" "react-scripts": "2.1.8"

View File

@ -6,10 +6,7 @@ import Ipfs from 'ipfs'
import libp2pBundle from './libp2p-bundle' import libp2pBundle from './libp2p-bundle'
const Component = React.Component const Component = React.Component
/* TODO: Add your go IPFS nodes ID here by running `ipfs id` */ const BootstrapNode = '/ip4/127.0.0.1/tcp/8081/ws/p2p/QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8'
const BootstrapNodeID = 'Qm...'
/* TODO: Ensure the IP and port match your nodes Websocket address shown when running the daemon `ipfs daemon` */
const BootstrapNode = `/ip4/127.0.0.1/tcp/8081/ws/p2p/${BootstrapNodeID}`
class App extends Component { class App extends Component {
constructor (props) { constructor (props) {
@ -20,7 +17,6 @@ class App extends Component {
hash: 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB', hash: 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB',
// This peer is one of the Bootstrap nodes for IPFS // This peer is one of the Bootstrap nodes for IPFS
peer: 'QmV6kA2fB8kTr6jc3pL5zbNsjKbmPUHAPKKHRBYe1kDEyc', peer: 'QmV6kA2fB8kTr6jc3pL5zbNsjKbmPUHAPKKHRBYe1kDEyc',
data: '',
isLoading: 0 isLoading: 0
} }
this.peerInterval = null this.peerInterval = null
@ -29,8 +25,6 @@ class App extends Component {
this.handleHashSubmit = this.handleHashSubmit.bind(this) this.handleHashSubmit = this.handleHashSubmit.bind(this)
this.handlePeerChange = this.handlePeerChange.bind(this) this.handlePeerChange = this.handlePeerChange.bind(this)
this.handlePeerSubmit = this.handlePeerSubmit.bind(this) this.handlePeerSubmit = this.handlePeerSubmit.bind(this)
this.handleDataChange = this.handleDataChange.bind(this)
this.handleDataSubmit = this.handleDataSubmit.bind(this)
} }
handleHashChange (event) { handleHashChange (event) {
@ -43,11 +37,6 @@ class App extends Component {
peer: event.target.value peer: event.target.value
}) })
} }
handleDataChange (event) {
this.setState({
data: event.target.value
})
}
handleHashSubmit (event) { handleHashSubmit (event) {
event.preventDefault() event.preventDefault()
@ -55,7 +44,7 @@ class App extends Component {
isLoading: this.state.isLoading + 1 isLoading: this.state.isLoading + 1
}) })
this.ipfs.cat(this.state.hash, (err, data) => { this.ipfs.files.cat(this.state.hash, (err, data) => {
if (err) console.log('Error', err) if (err) console.log('Error', err)
this.setState({ this.setState({
@ -70,22 +59,7 @@ class App extends Component {
isLoading: this.state.isLoading + 1 isLoading: this.state.isLoading + 1
}) })
this.ipfs.dht.findPeer(this.state.peer, (err, results) => { this.ipfs.dht.findpeer(this.state.peer, (err, results) => {
if (err) console.log('Error', err)
this.setState({
response: JSON.stringify(results, null, 2),
isLoading: this.state.isLoading - 1
})
})
}
handleDataSubmit (event) {
event.preventDefault()
this.setState({
isLoading: this.state.isLoading + 1
})
this.ipfs.add(Buffer.from(this.state.data), (err, results) => {
if (err) console.log('Error', err) if (err) console.log('Error', err)
this.setState({ this.setState({
@ -161,13 +135,6 @@ class App extends Component {
<input type="submit" value="Find" /> <input type="submit" value="Find" />
</label> </label>
</form> </form>
<form onSubmit={this.handleDataSubmit}>
<label>
Add Data:
<input type="text" value={this.state.data} onChange={this.handleDataChange} />
<input type="submit" value="Add" />
</label>
</form>
</section> </section>
<section className={[this.state.isLoading > 0 ? 'loading' : '', 'loader'].join(' ')}> <section className={[this.state.isLoading > 0 ? 'loading' : '', 'loader'].join(' ')}>
<div className="lds-ripple"><div></div><div></div></div> <div className="lds-ripple"><div></div><div></div></div>

View File

@ -5,7 +5,7 @@ const Libp2p = require('libp2p')
const Websockets = require('libp2p-websockets') const Websockets = require('libp2p-websockets')
const WebSocketStar = require('libp2p-websocket-star') const WebSocketStar = require('libp2p-websocket-star')
const WebRTCStar = require('libp2p-webrtc-star') const WebRTCStar = require('libp2p-webrtc-star')
const MPLEX = require('pull-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const SECIO = require('libp2p-secio')
const KadDHT = require('libp2p-kad-dht') const KadDHT = require('libp2p-kad-dht')
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing') const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
@ -14,9 +14,8 @@ const DelegatedContentRouter = require('libp2p-delegated-content-routing')
export default function Libp2pBundle ({peerInfo, peerBook}) { export default function Libp2pBundle ({peerInfo, peerBook}) {
const wrtcstar = new WebRTCStar({id: peerInfo.id}) const wrtcstar = new WebRTCStar({id: peerInfo.id})
const wsstar = new WebSocketStar({id: peerInfo.id}) const wsstar = new WebSocketStar({id: peerInfo.id})
/* TODO: Ensure the delegatedApiOptions match your IPFS nodes API server */
const delegatedApiOptions = { const delegatedApiOptions = {
host: '127.0.0.1', host: '0.0.0.0',
protocol: 'http', protocol: 'http',
port: '8080' port: '8080'
} }
@ -26,8 +25,7 @@ export default function Libp2pBundle ({peerInfo, peerBook}) {
peerBook, peerBook,
// Lets limit the connection managers peers and have it check peer health less frequently // Lets limit the connection managers peers and have it check peer health less frequently
connectionManager: { connectionManager: {
minPeers: 20, maxPeers: 10,
maxPeers: 50,
pollInterval: 5000 pollInterval: 5000
}, },
modules: { modules: {

View File

@ -17,7 +17,10 @@
}, },
"dependencies": { "dependencies": {
"detect-dom-ready": "^1.0.2", "detect-dom-ready": "^1.0.2",
"libp2p": "../../../",
"libp2p-bootstrap": "~0.9.7", "libp2p-bootstrap": "~0.9.7",
"libp2p-gossipsub": "~0.0.4",
"libp2p-kad-dht": "^0.15.3",
"libp2p-mplex": "~0.8.5", "libp2p-mplex": "~0.8.5",
"libp2p-secio": "~0.11.1", "libp2p-secio": "~0.11.1",
"libp2p-spdy": "~0.13.3", "libp2p-spdy": "~0.13.3",

View File

@ -8,8 +8,8 @@ const SPDY = require('libp2p-spdy')
const SECIO = require('libp2p-secio') const SECIO = require('libp2p-secio')
const Bootstrap = require('libp2p-bootstrap') const Bootstrap = require('libp2p-bootstrap')
const DHT = require('libp2p-kad-dht') const DHT = require('libp2p-kad-dht')
const defaultsDeep = require('@nodeutils/defaults-deep') const Gossipsub = require('libp2p-gossipsub')
const libp2p = require('../../../../') const libp2p = require('libp2p')
// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-browser.json // Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-browser.json
const bootstrapList = [ const bootstrapList = [
@ -26,9 +26,9 @@ const bootstrapList = [
] ]
class Node extends libp2p { class Node extends libp2p {
constructor (_options) { constructor ({ peerInfo }) {
const wrtcStar = new WebRTCStar({ id: _options.peerInfo.id }) const wrtcStar = new WebRTCStar({ id: peerInfo.id })
const wsstar = new WebSocketStar({ id: _options.peerInfo.id }) const wsstar = new WebSocketStar({ id: peerInfo.id })
const defaults = { const defaults = {
modules: { modules: {
@ -49,7 +49,8 @@ class Node extends libp2p {
wsstar.discovery, wsstar.discovery,
Bootstrap Bootstrap
], ],
dht: DHT dht: DHT,
pubsub: Gossipsub
}, },
config: { config: {
peerDiscovery: { peerDiscovery: {
@ -76,8 +77,8 @@ class Node extends libp2p {
dht: { dht: {
enabled: false enabled: false
}, },
EXPERIMENTAL: { pubsub: {
pubsub: false enabled: false
} }
}, },
connectionManager: { connectionManager: {
@ -86,7 +87,7 @@ class Node extends libp2p {
} }
} }
super(defaultsDeep(_options, defaults)) super({ ...defaults, peerInfo })
} }
} }

View File

@ -10,9 +10,11 @@ function createNode (callback) {
} }
const peerIdStr = peerInfo.id.toB58String() const peerIdStr = peerInfo.id.toB58String()
const ma = `/dns4/star-signal.cloud.ipfs.team/tcp/443/wss/p2p-webrtc-star/p2p/${peerIdStr}` const webrtcAddr = `/dns4/star-signal.cloud.ipfs.team/tcp/443/wss/p2p-webrtc-star/p2p/${peerIdStr}`
const wsAddr = `/dns4/ws-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star`
peerInfo.multiaddrs.add(ma) peerInfo.multiaddrs.add(webrtcAddr)
peerInfo.multiaddrs.add(wsAddr)
const node = new Node({ const node = new Node({
peerInfo peerInfo

View File

@ -46,6 +46,9 @@ domReady(() => {
myPeerDiv.append(idDiv) myPeerDiv.append(idDiv)
console.log('Node is listening o/') console.log('Node is listening o/')
node.peerInfo.multiaddrs.toArray().forEach(ma => {
console.log(ma.toString())
})
// NOTE: to stop the node // NOTE: to stop the node
// node.stop((err) => {}) // node.stop((err) => {})

View File

@ -20,5 +20,3 @@ Then simply go into the folder [1](./1) and execute the following
> npm start > npm start
# open your browser in port :9090 # open your browser in port :9090
``` ```
[Version Published on IPFS](http://ipfs.io/ipfs/Qmbc1J7ehw1dNYachbkCWPto4RsnVvqCKNVzmYEod2gXcy)

View File

@ -7,10 +7,10 @@ const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const SECIO = require('libp2p-secio')
const PeerInfo = require('peer-info') const PeerInfo = require('peer-info')
const MulticastDNS = require('libp2p-mdns') const MulticastDNS = require('libp2p-mdns')
const Gossipsub = require('libp2p-gossipsub')
const defaultsDeep = require('@nodeutils/defaults-deep') const defaultsDeep = require('@nodeutils/defaults-deep')
const waterfall = require('async/waterfall') const waterfall = require('async/waterfall')
const parallel = require('async/parallel') const parallel = require('async/parallel')
const series = require('async/series')
class MyBundle extends libp2p { class MyBundle extends libp2p {
constructor (_options) { constructor (_options) {
@ -19,7 +19,8 @@ class MyBundle extends libp2p {
transport: [ TCP ], transport: [ TCP ],
streamMuxer: [ Mplex ], streamMuxer: [ Mplex ],
connEncryption: [ SECIO ], connEncryption: [ SECIO ],
peerDiscovery: [ MulticastDNS ] peerDiscovery: [ MulticastDNS ],
pubsub: Gossipsub
}, },
config: { config: {
peerDiscovery: { peerDiscovery: {
@ -27,9 +28,6 @@ class MyBundle extends libp2p {
interval: 2000, interval: 2000,
enabled: true enabled: true
} }
},
EXPERIMENTAL: {
pubsub: true
} }
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "libp2p", "name": "libp2p",
"version": "0.25.4", "version": "0.26.0-rc.3",
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack", "description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>", "leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
"main": "src/index.js", "main": "src/index.js",
@ -48,9 +48,8 @@
"err-code": "^1.1.2", "err-code": "^1.1.2",
"fsm-event": "^2.1.0", "fsm-event": "^2.1.0",
"libp2p-connection-manager": "^0.1.0", "libp2p-connection-manager": "^0.1.0",
"libp2p-floodsub": "^0.16.1",
"libp2p-ping": "^0.8.5", "libp2p-ping": "^0.8.5",
"libp2p-switch": "^0.42.12", "libp2p-switch": "^0.43.0",
"libp2p-websockets": "^0.12.2", "libp2p-websockets": "^0.12.2",
"mafmt": "^6.0.7", "mafmt": "^6.0.7",
"multiaddr": "^6.1.0", "multiaddr": "^6.1.0",
@ -58,11 +57,12 @@
"peer-book": "^0.9.1", "peer-book": "^0.9.1",
"peer-id": "^0.12.2", "peer-id": "^0.12.2",
"peer-info": "^0.15.1", "peer-info": "^0.15.1",
"promisify-es6": "^1.0.3",
"superstruct": "^0.6.0" "superstruct": "^0.6.0"
}, },
"devDependencies": { "devDependencies": {
"@nodeutils/defaults-deep": "^1.1.0", "@nodeutils/defaults-deep": "^1.1.0",
"aegir": "^19.0.3", "aegir": "^20.0.0",
"chai": "^4.2.0", "chai": "^4.2.0",
"chai-checkmark": "^1.0.1", "chai-checkmark": "^1.0.1",
"cids": "^0.7.1", "cids": "^0.7.1",
@ -73,7 +73,9 @@
"libp2p-circuit": "^0.3.7", "libp2p-circuit": "^0.3.7",
"libp2p-delegated-content-routing": "^0.2.2", "libp2p-delegated-content-routing": "^0.2.2",
"libp2p-delegated-peer-routing": "^0.2.2", "libp2p-delegated-peer-routing": "^0.2.2",
"libp2p-kad-dht": "^0.15.2", "libp2p-floodsub": "~0.17.0",
"libp2p-gossipsub": "~0.0.4",
"libp2p-kad-dht": "^0.15.3",
"libp2p-mdns": "^0.12.3", "libp2p-mdns": "^0.12.3",
"libp2p-mplex": "^0.8.4", "libp2p-mplex": "^0.8.4",
"libp2p-secio": "^0.11.1", "libp2p-secio": "^0.11.1",
@ -81,8 +83,9 @@
"libp2p-tcp": "^0.13.0", "libp2p-tcp": "^0.13.0",
"libp2p-webrtc-star": "^0.16.1", "libp2p-webrtc-star": "^0.16.1",
"libp2p-websocket-star": "~0.10.2", "libp2p-websocket-star": "~0.10.2",
"libp2p-websocket-star-rendezvous": "~0.3.0", "libp2p-websocket-star-rendezvous": "~0.4.1",
"lodash.times": "^4.3.2", "lodash.times": "^4.3.2",
"merge-options": "^1.0.1",
"nock": "^10.0.6", "nock": "^10.0.6",
"pull-goodbye": "0.0.2", "pull-goodbye": "0.0.2",
"pull-mplex": "^0.1.2", "pull-mplex": "^0.1.2",
@ -95,6 +98,7 @@
"Aditya Bose <13054902+adbose@users.noreply.github.com>", "Aditya Bose <13054902+adbose@users.noreply.github.com>",
"Alan Shaw <alan.shaw@protocol.ai>", "Alan Shaw <alan.shaw@protocol.ai>",
"Alan Shaw <alan@tableflip.io>", "Alan Shaw <alan@tableflip.io>",
"Alex Potsides <alex@achingbrain.net>",
"Andrew Nesbitt <andrewnez@gmail.com>", "Andrew Nesbitt <andrewnez@gmail.com>",
"Chris Bratlien <chrisbratlien@gmail.com>", "Chris Bratlien <chrisbratlien@gmail.com>",
"Chris Dostert <chrisdostert@users.noreply.github.com>", "Chris Dostert <chrisdostert@users.noreply.github.com>",
@ -129,8 +133,8 @@
"Sönke Hahn <soenkehahn@gmail.com>", "Sönke Hahn <soenkehahn@gmail.com>",
"Thomas Eizinger <thomas@eizinger.io>", "Thomas Eizinger <thomas@eizinger.io>",
"Tiago Alves <alvesjtiago@gmail.com>", "Tiago Alves <alvesjtiago@gmail.com>",
"Vasco Santos <vasco.santos@ua.pt>",
"Vasco Santos <vasco.santos@moxy.studio>", "Vasco Santos <vasco.santos@moxy.studio>",
"Vasco Santos <vasco.santos@ua.pt>",
"Volker Mische <volker.mische@gmail.com>", "Volker Mische <volker.mische@gmail.com>",
"Yusef Napora <yusef@napora.org>", "Yusef Napora <yusef@napora.org>",
"Zane Starr <zcstarr@gmail.com>", "Zane Starr <zcstarr@gmail.com>",

View File

@ -19,6 +19,7 @@ const modulesSchema = s({
connProtector: s.union(['undefined', s.interface({ protect: 'function' })]), connProtector: s.union(['undefined', s.interface({ protect: 'function' })]),
contentRouting: optional(list(['object'])), contentRouting: optional(list(['object'])),
dht: optional(s('null|function|object')), dht: optional(s('null|function|object')),
pubsub: optional(s('null|function|object')),
peerDiscovery: optional(list([s('object|function')])), peerDiscovery: optional(list([s('object|function')])),
peerRouting: optional(list(['object'])), peerRouting: optional(list(['object'])),
streamMuxer: optional(list([s('object|function')])), streamMuxer: optional(list([s('object|function')])),
@ -59,12 +60,10 @@ const configSchema = s({
timeout: 10e3 timeout: 10e3
} }
}), }),
// Experimental config // Pubsub config
EXPERIMENTAL: s({ pubsub: s('object?', {
pubsub: 'boolean' // Pubsub defaults
}, { enabled: true
// Experimental defaults
pubsub: false
}) })
}, {}) }, {})

View File

@ -3,6 +3,7 @@
const tryEach = require('async/tryEach') const tryEach = require('async/tryEach')
const parallel = require('async/parallel') const parallel = require('async/parallel')
const errCode = require('err-code') const errCode = require('err-code')
const promisify = require('promisify-es6')
module.exports = (node) => { module.exports = (node) => {
const routers = node._modules.contentRouting || [] const routers = node._modules.contentRouting || []
@ -24,7 +25,7 @@ module.exports = (node) => {
* @param {function(Error, Result<Array>)} callback * @param {function(Error, Result<Array>)} callback
* @returns {void} * @returns {void}
*/ */
findProviders: (key, options, callback) => { findProviders: promisify((key, options, callback) => {
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options callback = options
options = {} options = {}
@ -60,7 +61,7 @@ module.exports = (node) => {
results = results || [] results = results || []
callback(null, results) callback(null, results)
}) })
}, }),
/** /**
* Iterates over all content routers in parallel to notify it is * Iterates over all content routers in parallel to notify it is
@ -70,7 +71,7 @@ module.exports = (node) => {
* @param {function(Error)} callback * @param {function(Error)} callback
* @returns {void} * @returns {void}
*/ */
provide: (key, callback) => { provide: promisify((key, callback) => {
if (!routers.length) { if (!routers.length) {
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')) return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
} }
@ -78,6 +79,6 @@ module.exports = (node) => {
parallel(routers.map((router) => { parallel(routers.map((router) => {
return (cb) => router.provide(key, cb) return (cb) => router.provide(key, cb)
}), callback) }), callback)
} })
} }
} }

View File

@ -2,19 +2,20 @@
const nextTick = require('async/nextTick') const nextTick = require('async/nextTick')
const errCode = require('err-code') const errCode = require('err-code')
const promisify = require('promisify-es6')
const { messages, codes } = require('./errors') const { messages, codes } = require('./errors')
module.exports = (node) => { module.exports = (node) => {
return { return {
put: (key, value, callback) => { put: promisify((key, value, callback) => {
if (!node._dht) { if (!node._dht) {
return nextTick(callback, errCode(new Error(messages.DHT_DISABLED), codes.DHT_DISABLED)) return nextTick(callback, errCode(new Error(messages.DHT_DISABLED), codes.DHT_DISABLED))
} }
node._dht.put(key, value, callback) node._dht.put(key, value, callback)
}, }),
get: (key, options, callback) => { get: promisify((key, options, callback) => {
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options callback = options
options = {} options = {}
@ -25,8 +26,8 @@ module.exports = (node) => {
} }
node._dht.get(key, options, callback) node._dht.get(key, options, callback)
}, }),
getMany: (key, nVals, options, callback) => { getMany: promisify((key, nVals, options, callback) => {
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options callback = options
options = {} options = {}
@ -37,6 +38,6 @@ module.exports = (node) => {
} }
node._dht.getMany(key, nVals, options, callback) node._dht.getMany(key, nVals, options, callback)
} })
} }
} }

View File

@ -4,12 +4,13 @@ const PeerId = require('peer-id')
const PeerInfo = require('peer-info') const PeerInfo = require('peer-info')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const errCode = require('err-code') const errCode = require('err-code')
const promisify = require('promisify-es6')
module.exports = (node) => { module.exports = (node) => {
/* /*
* Helper method to check the data type of peer and convert it to PeerInfo * Helper method to check the data type of peer and convert it to PeerInfo
*/ */
return function (peer, callback) { return promisify(function (peer, callback) {
let p let p
// PeerInfo // PeerInfo
if (PeerInfo.isPeerInfo(peer)) { if (PeerInfo.isPeerInfo(peer)) {
@ -62,5 +63,5 @@ module.exports = (node) => {
} }
callback(null, p) callback(null, p)
} })
} }

View File

@ -6,6 +6,7 @@ const debug = require('debug')
const log = debug('libp2p') const log = debug('libp2p')
log.error = debug('libp2p:error') log.error = debug('libp2p:error')
const errCode = require('err-code') const errCode = require('err-code')
const promisify = require('promisify-es6')
const each = require('async/each') const each = require('async/each')
const series = require('async/series') const series = require('async/series')
@ -68,7 +69,7 @@ class Libp2p extends EventEmitter {
// Attach stream multiplexers // Attach stream multiplexers
if (this._modules.streamMuxer) { if (this._modules.streamMuxer) {
let muxers = this._modules.streamMuxer const muxers = this._modules.streamMuxer
muxers.forEach((muxer) => this._switch.connection.addStreamMuxer(muxer)) muxers.forEach((muxer) => this._switch.connection.addStreamMuxer(muxer))
// If muxer exists // If muxer exists
@ -98,7 +99,7 @@ class Libp2p extends EventEmitter {
// Attach crypto channels // Attach crypto channels
if (this._modules.connEncryption) { if (this._modules.connEncryption) {
let cryptos = this._modules.connEncryption const cryptos = this._modules.connEncryption
cryptos.forEach((crypto) => { cryptos.forEach((crypto) => {
this._switch.connection.crypto(crypto.tag, crypto.encrypt) this._switch.connection.crypto(crypto.tag, crypto.encrypt)
}) })
@ -121,9 +122,9 @@ class Libp2p extends EventEmitter {
}) })
} }
// enable/disable pubsub // start pubsub
if (this._config.EXPERIMENTAL.pubsub) { if (this._modules.pubsub && this._config.pubsub.enabled !== false) {
this.pubsub = pubsub(this) this.pubsub = pubsub(this, this._modules.pubsub)
} }
// Attach remaining APIs // Attach remaining APIs
@ -186,6 +187,11 @@ class Libp2p extends EventEmitter {
}) })
this._peerDiscovered = this._peerDiscovered.bind(this) this._peerDiscovered = this._peerDiscovered.bind(this)
// promisify all instance methods
;['start', 'stop', 'dial', 'dialProtocol', 'dialFSM', 'hangUp', 'ping'].forEach(method => {
this[method] = promisify(this[method], { context: this })
})
} }
/** /**
@ -294,6 +300,13 @@ class Libp2p extends EventEmitter {
}) })
} }
/**
* Disconnects from the given peer
*
* @param {PeerInfo|PeerId|Multiaddr|string} peer The peer to ping
* @param {function(Error)} callback
* @returns {void}
*/
hangUp (peer, callback) { hangUp (peer, callback) {
this._getPeerInfo(peer, (err, peerInfo) => { this._getPeerInfo(peer, (err, peerInfo) => {
if (err) { return callback(err) } if (err) { return callback(err) }
@ -302,6 +315,13 @@ class Libp2p extends EventEmitter {
}) })
} }
/**
* Pings the provided peer
*
* @param {PeerInfo|PeerId|Multiaddr|string} peer The peer to ping
* @param {function(Error, Ping)} callback
* @returns {void}
*/
ping (peer, callback) { ping (peer, callback) {
if (!this.isStarted()) { if (!this.isStarted()) {
return callback(notStarted('ping', this.state._state)) return callback(notStarted('ping', this.state._state))
@ -395,8 +415,8 @@ class Libp2p extends EventEmitter {
} }
}, },
(cb) => { (cb) => {
if (this._floodSub) { if (this.pubsub) {
return this._floodSub.start(cb) return this.pubsub.start(cb)
} }
cb() cb()
}, },
@ -434,8 +454,8 @@ class Libp2p extends EventEmitter {
) )
}, },
(cb) => { (cb) => {
if (this._floodSub) { if (this.pubsub) {
return this._floodSub.stop(cb) return this.pubsub.stop(cb)
} }
cb() cb()
}, },
@ -557,7 +577,7 @@ module.exports = Libp2p
* @param {function(Error, Libp2p)} callback * @param {function(Error, Libp2p)} callback
* @returns {void} * @returns {void}
*/ */
module.exports.createLibp2p = (options, callback) => { module.exports.createLibp2p = promisify((options, callback) => {
if (options.peerInfo) { if (options.peerInfo) {
return nextTick(callback, null, new Libp2p(options)) return nextTick(callback, null, new Libp2p(options))
} }
@ -566,4 +586,4 @@ module.exports.createLibp2p = (options, callback) => {
options.peerInfo = peerInfo options.peerInfo = peerInfo
callback(null, new Libp2p(options)) callback(null, new Libp2p(options))
}) })
} })

View File

@ -2,6 +2,7 @@
const tryEach = require('async/tryEach') const tryEach = require('async/tryEach')
const errCode = require('err-code') const errCode = require('err-code')
const promisify = require('promisify-es6')
module.exports = (node) => { module.exports = (node) => {
const routers = node._modules.peerRouting || [] const routers = node._modules.peerRouting || []
@ -21,7 +22,7 @@ module.exports = (node) => {
* @param {function(Error, Result<Array>)} callback * @param {function(Error, Result<Array>)} callback
* @returns {void} * @returns {void}
*/ */
findPeer: (id, options, callback) => { findPeer: promisify((id, options, callback) => {
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options callback = options
options = {} options = {}
@ -47,12 +48,12 @@ module.exports = (node) => {
}) })
tryEach(tasks, (err, results) => { tryEach(tasks, (err, results) => {
if (err && err.code !== 'NOT_FOUND') { if (err) {
return callback(err) return callback(err)
} }
results = results || [] results = results || []
callback(null, results) callback(null, results)
}) })
} })
} }
} }

View File

@ -2,82 +2,128 @@
const nextTick = require('async/nextTick') const nextTick = require('async/nextTick')
const { messages, codes } = require('./errors') const { messages, codes } = require('./errors')
const FloodSub = require('libp2p-floodsub') const promisify = require('promisify-es6')
const errCode = require('err-code') const errCode = require('err-code')
module.exports = (node) => { module.exports = (node, Pubsub) => {
const floodSub = new FloodSub(node) const pubsub = new Pubsub(node, { emitSelf: true })
node._floodSub = floodSub
return { return {
subscribe: (topic, options, handler, callback) => { /**
* Subscribe the given handler to a pubsub topic
*
* @param {string} topic
* @param {function} handler The handler to subscribe
* @param {object|null} [options]
* @param {function} [callback] An optional callback
*
* @returns {Promise|void} A promise is returned if no callback is provided
*
* @example <caption>Subscribe a handler to a topic</caption>
*
* // `null` must be passed for options until subscribe is no longer using promisify
* const handler = (message) => { }
* await libp2p.subscribe(topic, handler, null)
*
* @example <caption>Use a callback instead of the Promise api</caption>
*
* // `options` may be passed or omitted when supplying a callback
* const handler = (message) => { }
* libp2p.subscribe(topic, handler, callback)
*/
subscribe: promisify((topic, handler, options, callback) => {
if (typeof options === 'function') { if (typeof options === 'function') {
callback = handler callback = options
handler = options
options = {} options = {}
} }
if (!node.isStarted() && !floodSub.started) { if (!node.isStarted() && !pubsub.started) {
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)) return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
} }
function subscribe (cb) { function subscribe (cb) {
if (floodSub.listenerCount(topic) === 0) { if (pubsub.listenerCount(topic) === 0) {
floodSub.subscribe(topic) pubsub.subscribe(topic)
} }
floodSub.on(topic, handler) pubsub.on(topic, handler)
nextTick(cb) nextTick(cb)
} }
subscribe(callback) subscribe(callback)
}, }),
unsubscribe: (topic, handler, callback) => { /**
if (!node.isStarted() && !floodSub.started) { * Unsubscribes from a pubsub topic
*
* @param {string} topic
* @param {function|null} handler The handler to unsubscribe from
* @param {function} [callback] An optional callback
*
* @returns {Promise|void} A promise is returned if no callback is provided
*
* @example <caption>Unsubscribe a topic for all handlers</caption>
*
* // `null` must be passed until unsubscribe is no longer using promisify
* await libp2p.unsubscribe(topic, null)
*
* @example <caption>Unsubscribe a topic for 1 handler</caption>
*
* await libp2p.unsubscribe(topic, handler)
*
* @example <caption>Use a callback instead of the Promise api</caption>
*
* libp2p.unsubscribe(topic, handler, callback)
*/
unsubscribe: promisify((topic, handler, callback) => {
if (!node.isStarted() && !pubsub.started) {
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)) return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
} }
if (!handler && !callback) {
floodSub.removeAllListeners(topic) if (!handler) {
pubsub.removeAllListeners(topic)
} else { } else {
floodSub.removeListener(topic, handler) pubsub.removeListener(topic, handler)
} }
if (floodSub.listenerCount(topic) === 0) { if (pubsub.listenerCount(topic) === 0) {
floodSub.unsubscribe(topic) pubsub.unsubscribe(topic)
} }
if (typeof callback === 'function') { if (typeof callback === 'function') {
nextTick(() => callback()) return nextTick(() => callback())
} }
},
publish: (topic, data, callback) => { return Promise.resolve()
if (!node.isStarted() && !floodSub.started) { }),
publish: promisify((topic, data, callback) => {
if (!node.isStarted() && !pubsub.started) {
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)) return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
} }
if (!Buffer.isBuffer(data)) { try {
return nextTick(callback, errCode(new Error('data must be a Buffer'), 'ERR_DATA_IS_NOT_A_BUFFER')) data = Buffer.from(data)
} catch (err) {
return nextTick(callback, errCode(new Error('data must be convertible to a Buffer'), 'ERR_DATA_IS_NOT_VALID'))
} }
floodSub.publish(topic, data, callback) pubsub.publish(topic, data, callback)
}, }),
ls: (callback) => { ls: promisify((callback) => {
if (!node.isStarted() && !floodSub.started) { if (!node.isStarted() && !pubsub.started) {
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)) return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
} }
const subscriptions = Array.from(floodSub.subscriptions) const subscriptions = Array.from(pubsub.subscriptions)
nextTick(() => callback(null, subscriptions)) nextTick(() => callback(null, subscriptions))
}, }),
peers: (topic, callback) => { peers: promisify((topic, callback) => {
if (!node.isStarted() && !floodSub.started) { if (!node.isStarted() && !pubsub.started) {
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)) return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
} }
@ -86,15 +132,19 @@ module.exports = (node) => {
topic = null topic = null
} }
const peers = Array.from(floodSub.peers.values()) const peers = Array.from(pubsub.peers.values())
.filter((peer) => topic ? peer.topics.has(topic) : true) .filter((peer) => topic ? peer.topics.has(topic) : true)
.map((peer) => peer.info.id.toB58String()) .map((peer) => peer.info.id.toB58String())
nextTick(() => callback(null, peers)) nextTick(() => callback(null, peers))
}, }),
setMaxListeners (n) { setMaxListeners (n) {
return floodSub.setMaxListeners(n) return pubsub.setMaxListeners(n)
} },
start: promisify((cb) => pubsub.start(cb)),
stop: promisify((cb) => pubsub.stop(cb))
} }
} }

View File

@ -43,12 +43,7 @@ describe('circuit relay', () => {
let peerRelay let peerRelay
before('get peer relay', async () => { before('get peer relay', async () => {
peerRelay = await new Promise(resolve => { peerRelay = await getPeerRelay()
getPeerRelay((err, peer) => {
expect(err).to.not.exist()
resolve(peer)
})
})
}) })
before('create the browser nodes', async () => { before('create the browser nodes', async () => {

View File

@ -16,7 +16,7 @@ const tryEcho = require('./utils/try-echo')
const echo = require('./utils/echo') const echo = require('./utils/echo')
describe('circuit relay', () => { describe('circuit relay', () => {
let handlerSpies = [] const handlerSpies = []
let relayNode1 let relayNode1
let relayNode2 let relayNode2
let nodeWS1 let nodeWS1

View File

@ -33,7 +33,7 @@ describe('configuration', () => {
expect(() => { expect(() => {
validateConfig({ validateConfig({
modules: { modules: {
transport: [ WS ] transport: [WS]
} }
}) })
}).to.throw() }).to.throw()
@ -52,7 +52,7 @@ describe('configuration', () => {
validateConfig({ validateConfig({
peerInfo, peerInfo,
modules: { modules: {
transport: [ ] transport: []
} }
}) })
}).to.throw('ERROR_EMPTY') }).to.throw('ERROR_EMPTY')
@ -62,8 +62,8 @@ describe('configuration', () => {
const options = { const options = {
peerInfo, peerInfo,
modules: { modules: {
transport: [ WS ], transport: [WS],
peerDiscovery: [ Bootstrap ], peerDiscovery: [Bootstrap],
dht: DHT dht: DHT
} }
} }
@ -74,16 +74,16 @@ describe('configuration', () => {
minPeers: 25 minPeers: 25
}, },
modules: { modules: {
transport: [ WS ], transport: [WS],
peerDiscovery: [ Bootstrap ], peerDiscovery: [Bootstrap],
dht: DHT dht: DHT
}, },
config: { config: {
peerDiscovery: { peerDiscovery: {
autoDial: true autoDial: true
}, },
EXPERIMENTAL: { pubsub: {
pubsub: false enabled: true
}, },
dht: { dht: {
kBucketSize: 20, kBucketSize: 20,
@ -112,8 +112,8 @@ describe('configuration', () => {
const options = { const options = {
peerInfo, peerInfo,
modules: { modules: {
transport: [ WS ], transport: [WS],
peerDiscovery: [ Bootstrap ], peerDiscovery: [Bootstrap],
dht: DHT dht: DHT
}, },
config: { config: {
@ -132,8 +132,8 @@ describe('configuration', () => {
minPeers: 25 minPeers: 25
}, },
modules: { modules: {
transport: [ WS ], transport: [WS],
peerDiscovery: [ Bootstrap ], peerDiscovery: [Bootstrap],
dht: DHT dht: DHT
}, },
config: { config: {
@ -144,8 +144,8 @@ describe('configuration', () => {
enabled: true enabled: true
} }
}, },
EXPERIMENTAL: { pubsub: {
pubsub: false enabled: true
}, },
dht: { dht: {
kBucketSize: 20, kBucketSize: 20,
@ -174,22 +174,22 @@ describe('configuration', () => {
const options = { const options = {
peerInfo, peerInfo,
switch: { switch: {
blacklistTTL: 60e3, denyTTL: 60e3,
blackListAttempts: 5, denyAttempts: 5,
maxParallelDials: 100, maxParallelDials: 100,
maxColdCalls: 50, maxColdCalls: 50,
dialTimeout: 30e3 dialTimeout: 30e3
}, },
modules: { modules: {
transport: [ WS ], transport: [WS],
peerDiscovery: [ ] peerDiscovery: []
} }
} }
expect(validateConfig(options)).to.deep.include({ expect(validateConfig(options)).to.deep.include({
switch: { switch: {
blacklistTTL: 60e3, denyTTL: 60e3,
blackListAttempts: 5, denyAttempts: 5,
maxParallelDials: 100, maxParallelDials: 100,
maxColdCalls: 50, maxColdCalls: 50,
dialTimeout: 30e3 dialTimeout: 30e3
@ -204,10 +204,10 @@ describe('configuration', () => {
const options = { const options = {
peerInfo, peerInfo,
modules: { modules: {
transport: [ WS ], transport: [WS],
peerDiscovery: [ Bootstrap ], peerDiscovery: [Bootstrap],
peerRouting: [ peerRouter ], peerRouting: [peerRouter],
contentRouting: [ contentRouter ], contentRouting: [contentRouter],
dht: DHT dht: DHT
}, },
config: { config: {
@ -221,8 +221,8 @@ describe('configuration', () => {
} }
expect(validateConfig(options).modules).to.deep.include({ expect(validateConfig(options).modules).to.deep.include({
peerRouting: [ peerRouter ], peerRouting: [peerRouter],
contentRouting: [ contentRouter ] contentRouting: [contentRouter]
}) })
}) })
@ -230,7 +230,7 @@ describe('configuration', () => {
const options = { const options = {
peerInfo, peerInfo,
modules: { modules: {
transport: [ WS ] transport: [WS]
}, },
config: { config: {
dht: { dht: {
@ -269,8 +269,8 @@ describe('configuration', () => {
dht: DHT dht: DHT
}, },
config: { config: {
EXPERIMENTAL: { pubsub: {
pubsub: false enabled: true
}, },
peerDiscovery: { peerDiscovery: {
autoDial: true autoDial: true

View File

@ -121,8 +121,9 @@ describe('.contentRouting', () => {
const cid = new CID('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSnnnn') const cid = new CID('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSnnnn')
nodeE.contentRouting.findProviders(cid, { maxTimeout: 5000 }, (err, providers) => { nodeE.contentRouting.findProviders(cid, { maxTimeout: 5000 }, (err, providers) => {
expect(err).to.not.exist() expect(err).to.exist()
expect(providers).to.have.length(0) expect(err.code).to.eql('ERR_NOT_FOUND')
expect(providers).to.not.exist()
done() done()
}) })
}) })
@ -150,7 +151,7 @@ describe('.contentRouting', () => {
nodeA = new Node({ nodeA = new Node({
peerInfo, peerInfo,
modules: { modules: {
contentRouting: [ delegate ] contentRouting: [delegate]
}, },
config: { config: {
dht: { dht: {
@ -185,19 +186,10 @@ describe('.contentRouting', () => {
it('should be able to register as a provider', (done) => { it('should be able to register as a provider', (done) => {
const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB') const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB')
const mockApi = nock('http://0.0.0.0:60197') const mockApi = nock('http://0.0.0.0:60197')
// mock the swarm connect
.post('/api/v0/swarm/connect')
.query({
arg: `/ip4/0.0.0.0/tcp/60194/p2p-circuit/ipfs/${nodeA.peerInfo.id.toB58String()}`,
'stream-channels': true
})
.reply(200, {
Strings: [`connect ${nodeA.peerInfo.id.toB58String()} success`]
}, ['Content-Type', 'application/json'])
// mock the refs call // mock the refs call
.post('/api/v0/refs') .post('/api/v0/refs')
.query({ .query({
recursive: true, recursive: false,
arg: cid.toBaseEncodedString(), arg: cid.toBaseEncodedString(),
'stream-channels': true 'stream-channels': true
}) })
@ -216,10 +208,11 @@ describe('.contentRouting', () => {
it('should handle errors when registering as a provider', (done) => { it('should handle errors when registering as a provider', (done) => {
const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB') const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB')
const mockApi = nock('http://0.0.0.0:60197') const mockApi = nock('http://0.0.0.0:60197')
// mock the swarm connect // mock the refs call
.post('/api/v0/swarm/connect') .post('/api/v0/refs')
.query({ .query({
arg: `/ip4/0.0.0.0/tcp/60194/p2p-circuit/ipfs/${nodeA.peerInfo.id.toB58String()}`, recursive: false,
arg: cid.toBaseEncodedString(),
'stream-channels': true 'stream-channels': true
}) })
.reply(502, 'Bad Gateway', ['Content-Type', 'application/json']) .reply(502, 'Bad Gateway', ['Content-Type', 'application/json'])
@ -251,7 +244,7 @@ describe('.contentRouting', () => {
timeout: '1000ms', timeout: '1000ms',
'stream-channels': true 'stream-channels': true
}) })
.reply(200, `{"Extra":"","ID":"QmWKqWXCtRXEeCQTo3FoZ7g4AfnGiauYYiczvNxFCHicbB","Responses":[{"Addrs":["/ip4/0.0.0.0/tcp/0"],"ID":"${provider}"}],"Type":1}\n`, [ .reply(200, `{"Extra":"","ID":"QmWKqWXCtRXEeCQTo3FoZ7g4AfnGiauYYiczvNxFCHicbB","Responses":[{"Addrs":["/ip4/0.0.0.0/tcp/0"],"ID":"${provider}"}],"Type":4}\n`, [
'Content-Type', 'application/json', 'Content-Type', 'application/json',
'X-Chunked-Output', '1' 'X-Chunked-Output', '1'
]) ])
@ -308,7 +301,7 @@ describe('.contentRouting', () => {
nodeA = new Node({ nodeA = new Node({
peerInfo, peerInfo,
modules: { modules: {
contentRouting: [ delegate ] contentRouting: [delegate]
}, },
config: { config: {
relay: { relay: {

View File

@ -19,8 +19,8 @@ describe('libp2p creation', () => {
it('should be able to start and stop successfully', (done) => { it('should be able to start and stop successfully', (done) => {
createNode([], { createNode([], {
config: { config: {
EXPERIMENTAL: { pubsub: {
pubsub: true enabled: true
}, },
dht: { dht: {
enabled: true enabled: true
@ -29,10 +29,10 @@ describe('libp2p creation', () => {
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
let sw = node._switch const sw = node._switch
let cm = node.connectionManager const cm = node.connectionManager
let dht = node._dht const dht = node._dht
let pub = node._floodSub const pub = node.pubsub
sinon.spy(sw, 'start') sinon.spy(sw, 'start')
sinon.spy(cm, 'start') sinon.spy(cm, 'start')
@ -77,13 +77,13 @@ describe('libp2p creation', () => {
it('should not create disabled modules', (done) => { it('should not create disabled modules', (done) => {
createNode([], { createNode([], {
config: { config: {
EXPERIMENTAL: { pubsub: {
pubsub: false enabled: false
} }
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
expect(node._floodSub).to.not.exist() expect(node._pubsub).to.not.exist()
done() done()
}) })
}) })
@ -113,7 +113,7 @@ describe('libp2p creation', () => {
this.timeout(10e3) this.timeout(10e3)
createLibp2p({ createLibp2p({
modules: { modules: {
transport: [ WS ] transport: [WS]
} }
}, (err, libp2p) => { }, (err, libp2p) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -130,7 +130,7 @@ describe('libp2p creation', () => {
createLibp2p({ createLibp2p({
peerInfo, peerInfo,
modules: { modules: {
transport: [ WS ] transport: [WS]
} }
}, (err, libp2p) => { }, (err, libp2p) => {
expect(err).to.not.exist() expect(err).to.not.exist()

View File

@ -60,9 +60,9 @@ describe('libp2p state machine (fsm)', () => {
node.once('stop', done) node.once('stop', done)
// stop the stopped node // stop the stopped node
node.stop() node.stop(() => {})
}) })
node.start() node.start(() => {})
}) })
it('should callback with an error when it occurs on stop', (done) => { it('should callback with an error when it occurs on stop', (done) => {
@ -79,7 +79,7 @@ describe('libp2p state machine (fsm)', () => {
expect(2).checks(done) expect(2).checks(done)
sinon.stub(node._switch, 'stop').callsArgWith(0, error) sinon.stub(node._switch, 'stop').callsArgWith(0, error)
node.start() node.start(() => {})
}) })
it('should noop when starting a started node', (done) => { it('should noop when starting a started node', (done) => {
@ -89,17 +89,17 @@ describe('libp2p state machine (fsm)', () => {
}) })
node.once('start', () => { node.once('start', () => {
node.once('stop', done) node.once('stop', done)
node.stop() node.stop(() => {})
}) })
// start the started node // start the started node
node.start() node.start(() => {})
}) })
node.start() node.start(() => {})
}) })
it('should error on start with no transports', (done) => { it('should error on start with no transports', (done) => {
let transports = node._modules.transport const transports = node._modules.transport
node._modules.transport = null node._modules.transport = null
node.on('stop', () => { node.on('stop', () => {
@ -115,7 +115,7 @@ describe('libp2p state machine (fsm)', () => {
expect(2).checks(done) expect(2).checks(done)
node.start() node.start(() => {})
}) })
it('should not start if the switch fails to start', (done) => { it('should not start if the switch fails to start', (done) => {
@ -150,7 +150,7 @@ describe('libp2p state machine (fsm)', () => {
}) })
}) })
node.stop() node.stop(() => {})
}) })
it('should not dial (fsm) when the node is stopped', (done) => { it('should not dial (fsm) when the node is stopped', (done) => {
@ -162,7 +162,7 @@ describe('libp2p state machine (fsm)', () => {
}) })
}) })
node.stop() node.stop(() => {})
}) })
}) })
}) })

View File

@ -6,6 +6,7 @@ require('./stream-muxing.node')
require('./peer-discovery.node') require('./peer-discovery.node')
require('./peer-routing.node') require('./peer-routing.node')
require('./ping.node') require('./ping.node')
require('./promisify.node')
require('./pubsub.node') require('./pubsub.node')
require('./content-routing.node') require('./content-routing.node')
require('./circuit-relay.node') require('./circuit-relay.node')

View File

@ -72,7 +72,7 @@ describe('peer discovery', () => {
stop: sinon.stub().callsArg(0) stop: sinon.stub().callsArg(0)
} }
const options = { modules: { peerDiscovery: [ mockDiscovery ] } } const options = { modules: { peerDiscovery: [mockDiscovery] } }
createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => { createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -95,7 +95,7 @@ describe('peer discovery', () => {
const MockDiscovery = sinon.stub().returns(mockDiscovery) const MockDiscovery = sinon.stub().returns(mockDiscovery)
const options = { modules: { peerDiscovery: [ MockDiscovery ] } } const options = { modules: { peerDiscovery: [MockDiscovery] } }
createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => { createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -120,7 +120,7 @@ describe('peer discovery', () => {
const enabled = sinon.stub().returns(true) const enabled = sinon.stub().returns(true)
const options = { const options = {
modules: { peerDiscovery: [ mockDiscovery ] }, modules: { peerDiscovery: [mockDiscovery] },
config: { config: {
peerDiscovery: { peerDiscovery: {
mockDiscovery: { mockDiscovery: {
@ -156,7 +156,7 @@ describe('peer discovery', () => {
const disabled = sinon.stub().returns(false) const disabled = sinon.stub().returns(false)
const options = { const options = {
modules: { peerDiscovery: [ mockDiscovery ] }, modules: { peerDiscovery: [mockDiscovery] },
config: { config: {
peerDiscovery: { peerDiscovery: {
mockDiscovery: { mockDiscovery: {
@ -192,7 +192,7 @@ describe('peer discovery', () => {
MockDiscovery.tag = 'mockDiscovery' MockDiscovery.tag = 'mockDiscovery'
const options = { const options = {
modules: { peerDiscovery: [ MockDiscovery ] }, modules: { peerDiscovery: [MockDiscovery] },
config: { config: {
peerDiscovery: { peerDiscovery: {
mockDiscovery: { mockDiscovery: {
@ -228,7 +228,7 @@ describe('peer discovery', () => {
} }
const options = { const options = {
modules: { peerDiscovery: [ mockDiscovery ] }, modules: { peerDiscovery: [mockDiscovery] },
config: { config: {
peerDiscovery: { peerDiscovery: {
mockDiscovery: { enabled: true } mockDiscovery: { enabled: true }
@ -294,7 +294,7 @@ describe('peer discovery', () => {
}) })
it('find peers', function (done) { it('find peers', function (done) {
let expectedPeers = new Set([ const expectedPeers = new Set([
nodeB.peerInfo.id.toB58String(), nodeB.peerInfo.id.toB58String(),
nodeC.peerInfo.id.toB58String() nodeC.peerInfo.id.toB58String()
]) ])
@ -332,7 +332,7 @@ describe('peer discovery', () => {
it('find peers', function (done) { it('find peers', function (done) {
this.timeout(20e3) this.timeout(20e3)
let expectedPeers = new Set([ const expectedPeers = new Set([
nodeB.peerInfo.id.toB58String(), nodeB.peerInfo.id.toB58String(),
nodeC.peerInfo.id.toB58String() nodeC.peerInfo.id.toB58String()
]) ])
@ -374,7 +374,7 @@ describe('peer discovery', () => {
}) })
it('find peers', function (done) { it('find peers', function (done) {
let expectedPeers = new Set([ const expectedPeers = new Set([
nodeB.peerInfo.id.toB58String(), nodeB.peerInfo.id.toB58String(),
nodeC.peerInfo.id.toB58String() nodeC.peerInfo.id.toB58String()
]) ])
@ -421,7 +421,7 @@ describe('peer discovery', () => {
}) })
it('find peers through the dht', function (done) { it('find peers through the dht', function (done) {
let expectedPeers = new Set([ const expectedPeers = new Set([
nodeB.peerInfo.id.toB58String(), nodeB.peerInfo.id.toB58String(),
nodeC.peerInfo.id.toB58String() nodeC.peerInfo.id.toB58String()
]) ])

View File

@ -105,7 +105,7 @@ describe('.peerRouting', () => {
}) })
createNode('/ip4/0.0.0.0/tcp/0', { createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
peerRouting: [ delegate ] peerRouting: [delegate]
}, },
config: { config: {
dht: { dht: {
@ -211,7 +211,7 @@ describe('.peerRouting', () => {
}) })
createNode('/ip4/0.0.0.0/tcp/0', { createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
peerRouting: [ delegate ] peerRouting: [delegate]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()

View File

@ -24,7 +24,7 @@ describe('private network', () => {
config = { config = {
peerInfo, peerInfo,
modules: { modules: {
transport: [ WS ], transport: [WS],
dht: DHT dht: DHT
} }
} }
@ -50,14 +50,14 @@ describe('private network', () => {
it('should create a libp2p node with a provided protector', () => { it('should create a libp2p node with a provided protector', () => {
let node let node
let protector = { const protector = {
psk: '123', psk: '123',
tag: '/psk/1.0.0', tag: '/psk/1.0.0',
protect: () => { } protect: () => { }
} }
expect(() => { expect(() => {
let options = defaultsDeep(config, { const options = defaultsDeep(config, {
modules: { modules: {
connProtector: protector connProtector: protector
} }
@ -71,7 +71,7 @@ describe('private network', () => {
it('should throw an error if the protector does not have a protect method', () => { it('should throw an error if the protector does not have a protect method', () => {
expect(() => { expect(() => {
let options = defaultsDeep(config, { const options = defaultsDeep(config, {
modules: { modules: {
connProtector: { } connProtector: { }
} }

87
test/promisify.node.js Normal file
View File

@ -0,0 +1,87 @@
/* eslint-env mocha */
'use strict'
/**
* This test suite is intended to validate compatability of
* the promisified api, until libp2p has been fully migrated to
* async/await. Once the migration is complete and all tests
* are using async/await, this file can be removed.
*/
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const promisify = require('promisify-es6')
const createNode = promisify(require('./utils/create-node'))
const { createPeerInfo } = require('./utils/create-node')
const Node = require('./utils/bundle-nodejs')
const pull = require('pull-stream')
const Ping = require('libp2p-ping')
/**
* As libp2p is currently promisified, when extending libp2p,
* method arguments must be passed to `super` to ensure the
* promisify callbacks are properly resolved
*/
class AsyncLibp2p extends Node {
async start (...args) {
await super.start(...args)
}
async stop (...args) {
await super.start(...args)
}
}
async function createAsyncNode () {
const peerInfo = await promisify(createPeerInfo)()
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
return new AsyncLibp2p({ peerInfo })
}
describe('promisified libp2p', () => {
let libp2p
let otherNode
const ECHO_PROTO = '/echo/1.0.0'
before('Create and Start', async () => {
[libp2p, otherNode] = await Promise.all([
createNode('/ip4/0.0.0.0/tcp/0'),
createAsyncNode()
])
return [libp2p, otherNode].map(node => {
node.handle(ECHO_PROTO, (_, conn) => pull(conn, conn))
return node.start()
})
})
after('Stop', () => {
return [libp2p, otherNode].map(node => node.stop())
})
afterEach('Hang up', () => {
return libp2p.hangUp(otherNode.peerInfo)
})
it('dial', async () => {
const stream = await libp2p.dial(otherNode.peerInfo)
expect(stream).to.not.exist()
expect(libp2p._switch.connection.getAll()).to.have.length(1)
})
it('dialFSM', async () => {
const connectionFSM = await libp2p.dialFSM(otherNode.peerInfo, ECHO_PROTO)
expect(connectionFSM).to.exist()
})
it('dialProtocol', async () => {
const stream = await libp2p.dialProtocol(otherNode.peerInfo, ECHO_PROTO)
expect(stream).to.exist()
})
it('ping', async () => {
const ping = await libp2p.ping(otherNode.peerInfo)
expect(ping).to.be.an.instanceOf(Ping)
})
})

View File

@ -11,23 +11,31 @@ const parallel = require('async/parallel')
const series = require('async/series') const series = require('async/series')
const _times = require('lodash.times') const _times = require('lodash.times')
const Floodsub = require('libp2p-floodsub')
const mergeOptions = require('merge-options')
const { codes } = require('../src/errors') const { codes } = require('../src/errors')
const createNode = require('./utils/create-node') const createNode = require('./utils/create-node')
function startTwo (callback) { function startTwo (options, callback) {
if (typeof options === 'function') {
callback = options
options = {}
}
const tasks = _times(2, () => (cb) => { const tasks = _times(2, () => (cb) => {
createNode('/ip4/0.0.0.0/tcp/0', { createNode('/ip4/0.0.0.0/tcp/0', mergeOptions({
config: { config: {
peerDiscovery: { peerDiscovery: {
mdns: { mdns: {
enabled: false enabled: false
} }
}, },
EXPERIMENTAL: { pubsub: {
pubsub: true enabled: true
} }
} }
}, (err, node) => { }, options), (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
node.start((err) => cb(err, node)) node.start((err) => cb(err, node))
}) })
@ -47,22 +55,17 @@ function stopTwo (nodes, callback) {
], callback) ], callback)
} }
// There is a vast test suite on PubSub through js-ipfs
// https://github.com/ipfs/interface-ipfs-core/blob/master/js/src/pubsub.js
// and libp2p-floodsub itself
// https://github.com/libp2p/js-libp2p-floodsub/tree/master/test
// TODO: consider if all or some of those should come here
describe('.pubsub', () => { describe('.pubsub', () => {
describe('.pubsub on (default)', (done) => { describe('.pubsub on (default)', () => {
it('start two nodes and send one message, then unsubscribe', (done) => { it('start two nodes and send one message, then unsubscribe', (done) => {
// Check the final series error, and the publish handler // Check the final series error, and the publish handler
expect(2).checks(done) expect(2).checks(done)
let nodes let nodes
const data = Buffer.from('test') const data = 'test'
const handler = (msg) => { const handler = (msg) => {
// verify the data is correct and mark the expect // verify the data is correct and mark the expect
expect(msg.data).to.eql(data).mark() expect(msg.data.toString()).to.eql(data).mark()
} }
series([ series([
@ -72,15 +75,11 @@ describe('.pubsub', () => {
cb(err) cb(err)
}), }),
// subscribe on the first // subscribe on the first
(cb) => nodes[0].pubsub.subscribe('pubsub', handler, cb), (cb) => nodes[0].pubsub.subscribe('pubsub', handler, null, cb),
// Wait a moment before publishing // Wait a moment before publishing
(cb) => setTimeout(cb, 500), (cb) => setTimeout(cb, 500),
// publish on the second // publish on the second
(cb) => nodes[1].pubsub.publish('pubsub', data, cb), (cb) => nodes[1].pubsub.publish('pubsub', data, cb),
// ls subscripts
(cb) => nodes[1].pubsub.ls(cb),
// get subscribed peers
(cb) => nodes[1].pubsub.peers('pubsub', cb),
// Wait a moment before unsubscribing // Wait a moment before unsubscribing
(cb) => setTimeout(cb, 500), (cb) => setTimeout(cb, 500),
// unsubscribe on the first // unsubscribe on the first
@ -110,6 +109,85 @@ describe('.pubsub', () => {
cb(err) cb(err)
}), }),
// subscribe on the first // subscribe on the first
(cb) => nodes[0].pubsub.subscribe('pubsub', handler, {}, cb),
// Wait a moment before publishing
(cb) => setTimeout(cb, 500),
// publish on the second
(cb) => nodes[1].pubsub.publish('pubsub', data, cb),
// ls subscripts
(cb) => nodes[1].pubsub.ls(cb),
// get subscribed peers
(cb) => nodes[1].pubsub.peers('pubsub', cb),
// Wait a moment before unsubscribing
(cb) => setTimeout(cb, 500),
// unsubscribe from all
(cb) => nodes[0].pubsub.unsubscribe('pubsub', null, cb),
// Verify unsubscribed
(cb) => {
nodes[0].pubsub.ls((err, topics) => {
expect(topics.length).to.eql(0).mark()
cb(err)
})
},
// Stop both nodes
(cb) => stopTwo(nodes, cb)
], (err) => {
// Verify there was no error, and mark the expect
expect(err).to.not.exist().mark()
})
})
it('publish should fail if data is not a buffer nor a string', (done) => {
createNode('/ip4/0.0.0.0/tcp/0', {
config: {
peerDiscovery: {
mdns: {
enabled: false
}
},
pubsub: {
enabled: true
}
}
}, (err, node) => {
expect(err).to.not.exist()
node.start((err) => {
expect(err).to.not.exist()
node.pubsub.publish('pubsub', 10, (err) => {
expect(err).to.exist()
expect(err.code).to.equal('ERR_DATA_IS_NOT_VALID')
done()
})
})
})
})
})
describe('.pubsub on using floodsub', () => {
it('start two nodes and send one message, then unsubscribe', (done) => {
// Check the final series error, and the publish handler
expect(2).checks(done)
let nodes
const data = Buffer.from('test')
const handler = (msg) => {
// verify the data is correct and mark the expect
expect(msg.data).to.eql(data).mark()
}
series([
// Start the nodes
(cb) => startTwo({
modules: {
pubsub: Floodsub
}
}, (err, _nodes) => {
nodes = _nodes
cb(err)
}),
// subscribe on the first
(cb) => nodes[0].pubsub.subscribe('pubsub', handler, cb), (cb) => nodes[0].pubsub.subscribe('pubsub', handler, cb),
// Wait a moment before publishing // Wait a moment before publishing
(cb) => setTimeout(cb, 500), (cb) => setTimeout(cb, 500),
@ -118,11 +196,45 @@ describe('.pubsub', () => {
// Wait a moment before unsubscribing // Wait a moment before unsubscribing
(cb) => setTimeout(cb, 500), (cb) => setTimeout(cb, 500),
// unsubscribe on the first // unsubscribe on the first
(cb) => { (cb) => nodes[0].pubsub.unsubscribe('pubsub', handler, cb),
nodes[0].pubsub.unsubscribe('pubsub') // Stop both nodes
// Wait a moment to make sure the ubsubscribe-from-all worked (cb) => stopTwo(nodes, cb)
setTimeout(cb, 500) ], (err) => {
}, // Verify there was no error, and mark the expect
expect(err).to.not.exist().mark()
})
})
it('start two nodes and send one message, then unsubscribe without handler', (done) => {
// Check the final series error, and the publish handler
expect(3).checks(done)
let nodes
const data = Buffer.from('test')
const handler = (msg) => {
// verify the data is correct and mark the expect
expect(msg.data).to.eql(data).mark()
}
series([
// Start the nodes
(cb) => startTwo({
modules: {
pubsub: Floodsub
}
}, (err, _nodes) => {
nodes = _nodes
cb(err)
}),
// subscribe on the first
(cb) => nodes[0].pubsub.subscribe('pubsub', handler, cb),
// Wait a moment before publishing
(cb) => setTimeout(cb, 500),
// publish on the second
(cb) => nodes[1].pubsub.publish('pubsub', data, cb),
// Wait a moment before unsubscribing
(cb) => setTimeout(cb, 500),
// unsubscribe from all
(cb) => nodes[0].pubsub.unsubscribe('pubsub', null, cb),
// Verify unsubscribed // Verify unsubscribed
(cb) => { (cb) => {
nodes[0].pubsub.ls((err, topics) => { nodes[0].pubsub.ls((err, topics) => {
@ -145,9 +257,12 @@ describe('.pubsub', () => {
enabled: false enabled: false
} }
}, },
EXPERIMENTAL: { pubsub: {
pubsub: true enabled: true
} }
},
modules: {
pubsub: Floodsub
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -155,9 +270,9 @@ describe('.pubsub', () => {
node.start((err) => { node.start((err) => {
expect(err).to.not.exist() expect(err).to.not.exist()
node.pubsub.publish('pubsub', 'datastr', (err) => { node.pubsub.publish('pubsub', 10, (err) => {
expect(err).to.exist() expect(err).to.exist()
expect(err.code).to.equal('ERR_DATA_IS_NOT_A_BUFFER') expect(err.code).to.equal('ERR_DATA_IS_NOT_VALID')
done() done()
}) })
@ -174,9 +289,6 @@ describe('.pubsub', () => {
mdns: { mdns: {
enabled: false enabled: false
} }
},
EXPERIMENTAL: {
pubsub: false
} }
} }
}, (err, node) => { }, (err, node) => {
@ -198,8 +310,8 @@ describe('.pubsub', () => {
enabled: false enabled: false
} }
}, },
EXPERIMENTAL: { pubsub: {
pubsub: true enabled: true
} }
} }
}, (err, node) => { }, (err, node) => {

View File

@ -36,7 +36,7 @@ describe('stream muxing', () => {
parallel([ parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ SPDY ] streamMuxer: [SPDY]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -46,7 +46,7 @@ describe('stream muxing', () => {
}), }),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ SPDY ] streamMuxer: [SPDY]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -72,7 +72,7 @@ describe('stream muxing', () => {
parallel([ parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ Mplex ] streamMuxer: [Mplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -82,7 +82,7 @@ describe('stream muxing', () => {
}), }),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ Mplex ] streamMuxer: [Mplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -108,7 +108,7 @@ describe('stream muxing', () => {
parallel([ parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ pMplex ] streamMuxer: [pMplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -118,7 +118,7 @@ describe('stream muxing', () => {
}), }),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ pMplex ] streamMuxer: [pMplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -146,7 +146,7 @@ describe('stream muxing', () => {
parallel([ parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ Mplex ] streamMuxer: [Mplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -156,7 +156,7 @@ describe('stream muxing', () => {
}), }),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ SPDY, Mplex ] streamMuxer: [SPDY, Mplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -184,7 +184,7 @@ describe('stream muxing', () => {
parallel([ parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ Mplex ] streamMuxer: [Mplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -194,7 +194,7 @@ describe('stream muxing', () => {
}), }),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ pMplex ] streamMuxer: [pMplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -222,7 +222,7 @@ describe('stream muxing', () => {
parallel([ parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ SPDY, Mplex ] streamMuxer: [SPDY, Mplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -232,7 +232,7 @@ describe('stream muxing', () => {
}), }),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ Mplex, SPDY ] streamMuxer: [Mplex, SPDY]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -260,7 +260,7 @@ describe('stream muxing', () => {
parallel([ parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ SPDY, pMplex ] streamMuxer: [SPDY, pMplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -270,7 +270,7 @@ describe('stream muxing', () => {
}), }),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ pMplex, SPDY ] streamMuxer: [pMplex, SPDY]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -298,7 +298,7 @@ describe('stream muxing', () => {
parallel([ parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ SPDY ] streamMuxer: [SPDY]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -308,7 +308,7 @@ describe('stream muxing', () => {
}), }),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', { (cb) => createNode('/ip4/0.0.0.0/tcp/0', {
modules: { modules: {
streamMuxer: [ Mplex ] streamMuxer: [Mplex]
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()

View File

@ -25,14 +25,11 @@ describe('transports', () => {
let peerBMultiaddr let peerBMultiaddr
let nodeA let nodeA
before((done) => { before(async () => {
getPeerRelay((err, peerInfo) => { const peerInfo = await getPeerRelay()
expect(err).to.not.exist() peerB = new PeerInfo(peerInfo.id)
peerB = new PeerInfo(peerInfo.id) peerBMultiaddr = `/ip4/127.0.0.1/tcp/9200/ws/p2p/${peerInfo.id.toB58String()}`
peerBMultiaddr = `/ip4/127.0.0.1/tcp/9200/ws/p2p/${peerInfo.id.toB58String()}` peerB.multiaddrs.add(peerBMultiaddr)
peerB.multiaddrs.add(peerBMultiaddr)
done()
})
}) })
after((done) => nodeA.stop(done)) after((done) => nodeA.stop(done))
@ -55,7 +52,7 @@ describe('transports', () => {
const b = new Node({ const b = new Node({
peerInfo: peerInfo, peerInfo: peerInfo,
modules: { modules: {
streamMuxer: [ Mplex ] streamMuxer: [Mplex]
} }
}) })
expect(b._modules.streamMuxer).to.eql([require('pull-mplex')]) expect(b._modules.streamMuxer).to.eql([require('pull-mplex')])

View File

@ -17,7 +17,9 @@ const createNode = require('./utils/create-node.js')
const tryEcho = require('./utils/try-echo') const tryEcho = require('./utils/try-echo')
const echo = require('./utils/echo') const echo = require('./utils/echo')
const { WRTC_RENDEZVOUS_MULTIADDR } = require('./utils/constants') const {
WRTC_RENDEZVOUS_MULTIADDR
} = require('./utils/constants')
describe('transports', () => { describe('transports', () => {
describe('TCP only', () => { describe('TCP only', () => {
@ -576,25 +578,24 @@ describe('transports', () => {
let nodeTCP let nodeTCP
let nodeWS let nodeWS
let nodeWebSocketStar let nodeWebSocketStar
let ss let ss
const PORT = 24642
before(async () => {
ss = await rendezvous.start({
port: PORT
})
})
before((done) => { before((done) => {
parallel([ parallel([
(cb) => {
rendezvous.start({ port: 24642 }, (err, server) => {
expect(err).to.not.exist()
ss = server
cb()
})
},
(cb) => { (cb) => {
const wstar = new WSStar() const wstar = new WSStar()
createNode([ createNode([
'/ip4/0.0.0.0/tcp/0', '/ip4/0.0.0.0/tcp/0',
'/ip4/127.0.0.1/tcp/25011/ws', '/ip4/127.0.0.1/tcp/25011/ws',
'/ip4/127.0.0.1/tcp/24642/ws/p2p-websocket-star' `/ip4/127.0.0.1/tcp/${PORT}/ws/p2p-websocket-star`
], { ], {
modules: { modules: {
transport: [ transport: [
@ -603,13 +604,6 @@ describe('transports', () => {
wstar wstar
], ],
peerDiscovery: [wstar.discovery] peerDiscovery: [wstar.discovery]
},
config: {
peerDiscovery: {
[wstar.discovery.tag]: {
enabled: true
}
}
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -640,18 +634,11 @@ describe('transports', () => {
const wstar = new WSStar({}) const wstar = new WSStar({})
createNode([ createNode([
'/ip4/127.0.0.1/tcp/24642/ws/p2p-websocket-star' `/ip4/127.0.0.1/tcp/${PORT}/ws/p2p-websocket-star`
], { ], {
modules: { modules: {
transport: [wstar], transport: [wstar],
peerDiscovery: [wstar.discovery] peerDiscovery: [wstar.discovery]
},
config: {
peerDiscovery: {
[wstar.discovery.tag]: {
enabled: true
}
}
} }
}, (err, node) => { }, (err, node) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -670,7 +657,9 @@ describe('transports', () => {
(cb) => nodeTCP.stop(cb), (cb) => nodeTCP.stop(cb),
(cb) => nodeWS.stop(cb), (cb) => nodeWS.stop(cb),
(cb) => nodeWebSocketStar.stop(cb), (cb) => nodeWebSocketStar.stop(cb),
(cb) => ss.stop(cb) async () => {
await ss.stop()
}
], done) ], done)
}) })

View File

@ -8,6 +8,7 @@ const SPDY = require('libp2p-spdy')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const PULLMPLEX = require('pull-mplex') const PULLMPLEX = require('pull-mplex')
const KadDHT = require('libp2p-kad-dht') const KadDHT = require('libp2p-kad-dht')
const GossipSub = require('libp2p-gossipsub')
const SECIO = require('libp2p-secio') const SECIO = require('libp2p-secio')
const defaultsDeep = require('@nodeutils/defaults-deep') const defaultsDeep = require('@nodeutils/defaults-deep')
const libp2p = require('../..') const libp2p = require('../..')
@ -57,7 +58,8 @@ class Node extends libp2p {
wsStar.discovery, wsStar.discovery,
Bootstrap Bootstrap
], ],
dht: KadDHT dht: KadDHT,
pubsub: GossipSub
}, },
config: { config: {
peerDiscovery: { peerDiscovery: {
@ -88,8 +90,8 @@ class Node extends libp2p {
}, },
enabled: false enabled: false
}, },
EXPERIMENTAL: { pubsub: {
pubsub: false enabled: false
} }
} }
} }

View File

@ -6,6 +6,7 @@ const WS = require('libp2p-websockets')
const Bootstrap = require('libp2p-bootstrap') const Bootstrap = require('libp2p-bootstrap')
const SPDY = require('libp2p-spdy') const SPDY = require('libp2p-spdy')
const KadDHT = require('libp2p-kad-dht') const KadDHT = require('libp2p-kad-dht')
const GossipSub = require('libp2p-gossipsub')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const PULLMPLEX = require('pull-mplex') const PULLMPLEX = require('pull-mplex')
const SECIO = require('libp2p-secio') const SECIO = require('libp2p-secio')
@ -52,7 +53,8 @@ class Node extends libp2p {
MulticastDNS, MulticastDNS,
Bootstrap Bootstrap
], ],
dht: KadDHT dht: KadDHT,
pubsub: GossipSub
}, },
config: { config: {
peerDiscovery: { peerDiscovery: {
@ -81,8 +83,8 @@ class Node extends libp2p {
}, },
enabled: true enabled: true
}, },
EXPERIMENTAL: { pubsub: {
pubsub: false enabled: false
} }
} }
} }

View File

@ -5,6 +5,7 @@ const PeerInfo = require('peer-info')
const nextTick = require('async/nextTick') const nextTick = require('async/nextTick')
const peerJSON = require('../fixtures/test-peer') const peerJSON = require('../fixtures/test-peer')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const promisify = require('promisify-es6')
let peerRelay = null let peerRelay = null
@ -20,7 +21,7 @@ let peerRelay = null
* @param {function(error, PeerInfo)} callback * @param {function(error, PeerInfo)} callback
* @returns {void} * @returns {void}
*/ */
module.exports.getPeerRelay = (callback) => { module.exports.getPeerRelay = promisify((callback) => {
if (peerRelay) return nextTick(callback, null, peerRelay) if (peerRelay) return nextTick(callback, null, peerRelay)
PeerId.createFromJSON(peerJSON, (err, peerId) => { PeerId.createFromJSON(peerJSON, (err, peerId) => {
@ -34,7 +35,7 @@ module.exports.getPeerRelay = (callback) => {
callback(null, peerRelay) callback(null, peerRelay)
}) })
} })
module.exports.WS_RENDEZVOUS_MULTIADDR = multiaddr('/ip4/127.0.0.1/tcp/14444/wss') module.exports.WS_RENDEZVOUS_MULTIADDR = multiaddr('/ip4/127.0.0.1/tcp/14444/ws')
module.exports.WRTC_RENDEZVOUS_MULTIADDR = multiaddr('/ip4/127.0.0.1/tcp/15555/wss') module.exports.WRTC_RENDEZVOUS_MULTIADDR = multiaddr('/ip4/127.0.0.1/tcp/15555/ws')