Skip to content

Commit

Permalink
add libp2p-ping to aleph nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
yusefnapora committed Jan 9, 2017
1 parent 08dc687 commit cf537ee
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 14 deletions.
21 changes: 13 additions & 8 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -37,6 +37,7 @@
"knex": "^0.12.6",
"levelup": "^1.3.3",
"libp2p-crypto": "git://github.com/libp2p/js-libp2p-crypto.git#c45bdf602e765411d9d5fc2fddd45b31830f08e8",
"libp2p-ping": "^0.3.0",
"libp2p-secio": "0.6.4",
"libp2p-spdy": "0.10.1",
"libp2p-swarm": "0.26.2",
Expand Down
19 changes: 19 additions & 0 deletions src/peer/libp2p_node.js
Expand Up @@ -10,6 +10,7 @@ const PeerId = require('peer-id')
const PeerInfo = require('peer-info')
const PeerBook = require('peer-book')
const multiaddr = require('multiaddr')
const Ping = require('libp2p-ping')
const mafmt = require('mafmt')
const Abortable = require('pull-abortable')
const { promiseTimeout } = require('./util')
Expand Down Expand Up @@ -62,6 +63,8 @@ class P2PNode {
this.peerBook.removeByB58String(peerInfo.id.toB58String())
})

Ping.mount(this.swarm)

this.abortables = new Set()
}

Expand Down Expand Up @@ -227,6 +230,22 @@ class P2PNode {
unhandle (protocol: string): any {
return this.swarm.unhandle(protocol)
}

ping (peer: PeerInfo): Promise<number> {
const pingPromise = new Promise((resolve, reject) => {
const p = new Ping(this.swarm, peer)
p.on('error', err => {
p.stop()
reject(err)
})

p.on('ping', latency => {
p.stop()
resolve(latency)
})
})
return promiseTimeout(this.dialTimeout, pingPromise)
}
}

module.exports = P2PNode
22 changes: 18 additions & 4 deletions src/peer/node.js
Expand Up @@ -192,23 +192,37 @@ class MediachainNode {
return this.lookup(peer)
}

openConnection (peer: PeerInfo | PeerId | string, protocol: string): Promise<Connection> {
_resolvePeer (peer: PeerInfo | PeerId | string): Promise<PeerInfo> {
return this._lookupIfNeeded(peer)
.then(maybePeer => {
if (!maybePeer) throw new Error(`Unable to locate peer ${peer}`)
return maybePeer
})
}

openConnection (peer: PeerInfo | PeerId | string, protocol: string): Promise<Connection> {
return this._resolvePeer(peer)
.then(peerInfo => this.p2p.dialByPeerInfo(peerInfo, protocol))
}

ping (peer: PeerInfo | PeerId | string): Promise<boolean> {
return this.openConnection(peer, PROTOCOLS.node.ping)
ping (peer: PeerInfo | PeerId | string): Promise<number> {
let timestamp: number
let latency: number

return this._resolvePeer(peer)
.then(peerInfo => this.p2p.ping(peerInfo))

// fall-back to deprecated mediachain ping protocol if remote node
// doesn't support libp2p ping
.catch(_err => this.openConnection(peer, PROTOCOLS.node.ping))
.then((conn: Connection) => pullToPromise(
pull.values([{}]),
protoStreamEncode(pb.node.Ping),
pull.through(() => { timestamp = Date.now() }),
conn,
pull.through(() => { latency = Date.now() - timestamp }),
protoStreamDecode(pb.node.Pong),
pull.map(_ => { return true })
pull.map(_ => { return latency })
))
}

Expand Down
20 changes: 18 additions & 2 deletions test/ping_test.js
Expand Up @@ -7,11 +7,12 @@ const PeerInfo = require('peer-info')
const Multiaddr = require('multiaddr')

describe('Ping', function () {
let p1, p2, invalidPeer
let p1, p2, p3, invalidPeer

before(() => Promise.all([
makeNode().then(_p1 => { p1 = _p1 }),
makeNode().then(_p2 => { p2 = _p2 }),
makeNode().then(_p3 => { p3 = _p3 }),
getTestNodeId().then(id => {
invalidPeer = PeerInfo(id)
invalidPeer.multiaddr.add(Multiaddr('/ip4/1.2.3.4/tcp/4321'))
Expand All @@ -21,7 +22,22 @@ describe('Ping', function () {
it('pings another node directly by PeerInfo', () => {
return Promise.all([p1.start(), p2.start()]) // start both peers
.then(() => p1.ping(p2.peerInfo))
.then(result => assert(result))
.then(result => assert(result != null))
})

it('uses the libp2p-ping protocol (if possible)', () => {
return Promise.all([p1.start(), p2.start()]) // start both peers
.then(() => p1.p2p.ping(p2.peerInfo))
.then(result => assert.equal(typeof result, 'number', 'libp2p-ping should return latency in ms'))
})

it('falls back to mediachain ping if libp2p-ping fails', () => {
p3.p2p.ping = () => Promise.reject(new Error('I only support artisanal, hand-crafted ping protocols!'))
return Promise.all([p1.start(), p3.start()])
.then(() => p2.ping(p3.peerInfo))
.then(result => {
assert(result != null)
})
})

it('fails to ping a non-existent node', () => {
Expand Down

0 comments on commit cf537ee

Please sign in to comment.