Skip to content
This repository has been archived by the owner on Mar 10, 2020. It is now read-only.

fix: handle peer-info validation errors #887

Merged
merged 4 commits into from
Nov 26, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"libp2p-crypto": "~0.14.0",
"lodash": "^4.17.11",
"lru-cache": "^4.1.3",
"multiaddr": "^5.0.0",
"multiaddr": "^5.0.2",
"multibase": "~0.5.0",
"multihashes": "~0.4.14",
"ndjson": "^1.5.0",
Expand Down Expand Up @@ -87,6 +87,7 @@
"gulp": "^3.9.1",
"interface-ipfs-core": "~0.84.3",
"ipfsd-ctl": "~0.40.0",
"nock": "^10.0.2",
"pull-stream": "^3.6.9",
"stream-equal": "^1.1.1"
},
Expand Down
93 changes: 51 additions & 42 deletions src/swarm/peers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,56 +10,65 @@ module.exports = (send) => {
callback = opts
opts = {}
}

const verbose = opts.v || opts.verbose

send({
path: 'swarm/peers',
qs: opts
}, (err, result) => {
}, (err, response) => {
if (err) {
return callback(err)
}
const peerInfo = parsePeersResponse(verbose, response)
callback(null, peerInfo)
})
})
}

// go-ipfs <= 0.4.4
if (result.Strings) {
return callback(null, result.Strings.map((p) => {
const res = {}

if (verbose) {
const parts = p.split(' ')
res.addr = multiaddr(parts[0])
res.latency = parts[1]
} else {
res.addr = multiaddr(p)
}

res.peer = PeerId.createFromB58String(
res.addr.decapsulate('ipfs')
)

return res
}))
}

// go-ipfs >= 0.4.5
callback(null, (result.Peers || []).map((p) => {
const res = {
addr: multiaddr(p.Addr),
peer: PeerId.createFromB58String(p.Peer),
muxer: p.Muxer
}

if (p.Latency) {
res.latency = p.Latency
}
function parsePeersResponse (verbose, response) {
// go-ipfs <= 0.4.4
if (Array.isArray(response.Strings)) {
return response.Strings.map(parseLegacyPeer.bind(null, verbose))
}
// go-ipfs >= 0.4.5
if (Array.isArray(response.Peers)) {
return response.Peers.map(parsePeer.bind(null, verbose))
}
return []
}

if (p.Streams) {
res.streams = p.Streams
}
function parseLegacyPeer (verbose, peer) {
const res = {}
try {
if (verbose) {
const parts = peer.split(' ')
res.addr = multiaddr(parts[0])
res.latency = parts[1]
} else {
res.addr = multiaddr(peer)
}
res.peer = PeerId.createFromB58String(res.addr.getPeerId())
} catch (error) {
res.error = error
res.rawPeerInfo = peer
}
return res
}

return res
}))
})
})
function parsePeer (verbose, peer) {
const res = {}
try {
res.addr = multiaddr(peer.Addr)
res.peer = PeerId.createFromB58String(peer.Peer)
res.muxer = peer.Muxer
} catch (error) {
res.error = error
res.rawPeerInfo = peer
}
if (peer.Latency) {
res.latency = peer.Latency
}
if (peer.Streams) {
res.streams = peer.Streams
}
return res
}
1 change: 1 addition & 0 deletions test/node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('./node/swarm')
110 changes: 110 additions & 0 deletions test/node/swarm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/* eslint-env mocha */
'use strict'

const nock = require('nock')
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)

const IPFSApi = require('../../src')

describe('.swarm.peers', function () {
this.timeout(50 * 1000) // slow CI

const ipfs = IPFSApi('/ip4/127.0.0.1/tcp/5001')
const apiUrl = 'http://127.0.0.1:5001'

it('handles a peer response', (done) => {
const response = { Peers: [{ Addr: '/ip4/104.131.131.82/tcp/4001', Peer: 'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', Latency: '', Muxer: '', Streams: null }] }

const scope = nock(apiUrl)
.post('/api/v0/swarm/peers')
.query(true)
.reply(200, response)

ipfs.swarm.peers((err, res) => {
expect(err).to.not.exist()
expect(res).to.be.a('array')
expect(res.length).to.equal(1)
expect(res[0].error).to.not.exist()
expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr)
expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer)
expect(scope.isDone()).to.equal(true)
done()
})
})

it('handles a go-ipfs <= 0.4.4 peer response', (done) => {
const response = { Strings: ['/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm'] }

const scope = nock(apiUrl)
.post('/api/v0/swarm/peers')
.query(true)
.reply(200, response)

ipfs.swarm.peers((err, res) => {
expect(err).to.not.exist()
expect(res).to.be.a('array')
expect(res.length).to.equal(1)
expect(res[0].error).to.not.exist()
expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm')
expect(res[0].peer.toB58String()).to.equal('QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm')
expect(scope.isDone()).to.equal(true)
done()
})
})

it('handles an ip6 quic peer', (done) => {
const response = { Peers: [{ Addr: '/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/4001/quic', Peer: 'QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC', Latency: '', Muxer: '', Streams: null }] }

const scope = nock(apiUrl)
.post('/api/v0/swarm/peers')
.query(true)
.reply(200, response)

ipfs.swarm.peers((err, res) => {
expect(err).to.not.exist()
expect(res).to.be.a('array')
expect(res.length).to.equal(1)
expect(res[0].error).to.not.exist()
expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr)
expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer)
expect(scope.isDone()).to.equal(true)
done()
})
})

it('handles unvalidatable peer addr', (done) => {
const response = { Peers: [{ Addr: '/ip4/104.131.131.82/future-tech', Peer: 'QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC', Latency: '', Muxer: '', Streams: null }] }

const scope = nock(apiUrl)
.post('/api/v0/swarm/peers')
.query(true)
.reply(200, response)

ipfs.swarm.peers((err, res) => {
expect(err).to.not.exist()
expect(res).to.be.a('array')
expect(res.length).to.equal(1)
expect(res[0].error).to.exist()
expect(res[0].rawPeerInfo).to.deep.equal(response.Peers[0])
expect(scope.isDone()).to.equal(true)
done()
})
})

it('handles an error response', (done) => {
const scope = nock(apiUrl)
.post('/api/v0/swarm/peers')
.query(true)
.replyWithError('something awful happened')

ipfs.swarm.peers((err, res) => {
expect(err.message).to.equal('something awful happened')
expect(res).to.not.exist()
expect(scope.isDone()).to.equal(true)
done()
})
})
})