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

new peer-book #30

Merged
merged 2 commits into from
Mar 31, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/diasdavid/js-peer-book.git"
"url": "git+https://github.com/libp2p/js-peer-book.git"
},
"pre-commit": [
"lint",
Expand All @@ -33,19 +33,20 @@
"author": "David Dias <daviddias@ipfs.io>",
"license": "MIT",
"bugs": {
"url": "https://github.com/diasdavid/js-peer-book/issues"
"url": "https://github.com/libp2p/js-peer-book/issues"
},
"homepage": "https://github.com/diasdavid/js-peer-book#readme",
"homepage": "https://github.com/libp2p/js-peer-book#readme",
"dependencies": {
"bs58": "^4.0.0"
"bs58": "^4.0.0",
"peer-id": "^0.8.6",
"peer-info": "^0.9.1"
},
"devDependencies": {
"aegir": "^11.0.1",
"async": "^2.2.0",
"chai": "^3.5.0",
"dirty-chai": "^1.2.2",
"multiaddr": "^2.2.3",
"peer-info": "~0.8.5",
"multiaddr": "^2.3.0",
"pre-commit": "^1.2.2"
},
"contributors": [
Expand All @@ -54,4 +55,4 @@
"greenkeeperio-bot <support@greenkeeper.io>",
"npmcdn-to-unpkg-bot <npmcdn-to-unpkg-bot@users.noreply.github.com>"
]
}
}
119 changes: 84 additions & 35 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,121 @@
'use strict'

const bs58 = require('bs58')
const PeerId = require('peer-id')
const PeerInfo = require('peer-info')

module.exports = PeerBook
function getB58Str (peer) {
let b58Str

function PeerBook () {
if (!(this instanceof PeerBook)) {
return new PeerBook()
if (typeof peer === 'string') {
b58Str = peer
} else if (Buffer.isBuffer(peer)) {
b58Str = bs58.encode(peer).toString()
} else if (PeerId.isPeerId(peer)) {
b58Str = peer.toB58String()
} else if (PeerInfo.isPeerInfo(peer)) {
b58Str = peer.id.toB58String()
} else {
throw new Error('not valid PeerId or PeerInfo, or B58Str')
}

const peers = {}
return b58Str
}

this.put = (peerInfo, replace) => {
if (peers[peerInfo.id.toB58String()] && !replace) {
// peerInfo.replace merges by default
peers[peerInfo.id.toB58String()].multiaddr.replace([], peerInfo.multiaddrs)
}
peers[peerInfo.id.toB58String()] = peerInfo
class PeerBook {
constructor () {
this._peers = {}
}

this.getAll = () => {
return peers
// checks if peer exists
// peer can be PeerId, b58String or PeerInfo
has (peer) {
const b58Str = getB58Str(peer)
return Boolean(this._peers[b58Str])
}

/**
* Get the info to the given PeerId.
* Stores a peerInfo, if already exist, merges the new into the old.
*
* @param {PeerId} id
* @param {PeerInfo} peerInfo
* @param {replace} boolean
* @returns {PeerInfo}
*/
this.get = (id) => {
return this.getByB58String(id.toB58String())
put (peerInfo, replace) {
const localPeerInfo = this._peers[peerInfo.id.toB58String()]

// insert if doesn't exist or replace if replace flag is true
if (!localPeerInfo || replace) {
this._peers[peerInfo.id.toB58String()] = peerInfo
return peerInfo
}

// peerInfo.replace merges by default if none to replace are passed
peerInfo.multiaddrs.forEach((ma) => localPeerInfo.multiaddrs.add(ma))

// pass active connection state
const ma = peerInfo.isConnected()
if (ma) {
localPeerInfo.connect(ma)
}

// pass known protocols
peerInfo.protocols.forEach((p) => localPeerInfo.protocols.add(p))

if (!localPeerInfo.id.privKey && peerInfo.id.privKey) {
localPeerInfo.id.privKey = peerInfo.id.privKey
}

if (!localPeerInfo.id.pubKey && peerInfo.id.pubKey) {
localPeerInfo.id.pubKey = peerInfo.id.pubKey
}

return localPeerInfo
}

this.getByB58String = (b58String) => {
const peerInfo = peers[b58String]
/**
* Get the info to the given PeerId, PeerInfo or b58Str id
*
* @param {PeerId} id
* @returns {PeerInfo}
*/
get (peer) {
const b58Str = getB58Str(peer)

const peerInfo = this._peers[b58Str]

if (peerInfo) {
return peerInfo
}
throw new Error('PeerInfo not found')
}

this.getByMultihash = (multihash) => {
const b58multihash = bs58.encode(multihash).toString()
return this.getByB58String(b58multihash)
}

this.removeByB58String = (b58String) => {
if (peers[b58String]) {
delete peers[b58String]
}
getAll () {
return this._peers
}

this.removeByMultihash = (multihash) => {
const b58multihash = bs58.encode(multihash).toString()
this.removeByB58String(b58multihash)
getAllArray () {
return Object.keys(this._peers).map((b58Str) => this._peers[b58Str])
}

/**
* Return all multiaddrs for a given PeerId.
*
* @param {PeerId} id
* @param {PeerId, PeerInfo, Multihash, B58Str} id
* @returns {Array<Multiaddr>}
*/
this.getAddrs = (id) => {
const info = this.get(id)
getMultiaddrs (peer) {
const info = this.get(peer)
return info.multiaddrs
}

// TODO serialize PeerBook into MerkleDAG Objects
remove (peer) {
const b58Str = getB58Str(peer)

if (this._peers[b58Str]) {
delete this._peers[b58Str]
}
}
}

module.exports = PeerBook
127 changes: 70 additions & 57 deletions test/peer-book.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ chai.use(dirtyChai)
const Multiaddr = require('multiaddr')
const PeerInfo = require('peer-info')
const async = require('async')
const utils = require('./utils')
const createPeerInfo = utils.createPeerInfo

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

describe('peer-book', function () {
this.timeout(50000)
describe('peer-book', () => {
let pb
let p1
let p2
Expand All @@ -21,10 +22,22 @@ describe('peer-book', function () {

before((done) => {
async.parallel([
(cb) => PeerInfo.create(cb),
(cb) => PeerInfo.create(cb),
(cb) => PeerInfo.create(cb),
(cb) => PeerInfo.create(cb)
(cb) => createPeerInfo([
'/tcp/1000',
'/tcp/1001'
], cb),
(cb) => createPeerInfo([
'/tcp/2000',
'/tcp/2001'
], cb),
(cb) => createPeerInfo([
'/tcp/3000',
'/tcp/3001'
], cb),
(cb) => createPeerInfo([
'/tcp/4000',
'/tcp/4001'
], cb)
], (err, infos) => {
if (err) {
return done(err)
Expand All @@ -44,44 +57,48 @@ describe('peer-book', function () {
expect(pb).to.exist()
})

it('put peerInfo', () => {
pb.put(p1)
pb.put(p2)
pb.put(p3)
it('.put', () => {
expect(pb.put(p1)).to.eql(p1)
expect(pb.put(p2)).to.eql(p2)
expect(pb.put(p3)).to.eql(p3)
})

it('get all peerInfo', () => {
it('.getAll', () => {
const peers = pb.getAll()
expect(Object.keys(peers).length).to.equal(3)
})

it('get', () => {
it('.getAllArray', () => {
expect(pb.getAllArray()).to.have.length(3)
})

it('.get by PeerId', () => {
const peer = pb.get(p1.id)
expect(peer).to.deep.equal(p1)
expect(peer).to.eql(p1)
})

it('getByB58String', () => {
const p1Id = p1.id.toB58String()
const peer = pb.getByB58String(p1Id)
expect(peer).to.deep.equal(p1)
it('.get by B58String ', () => {
const b58Str = p1.id.toB58String()
const peer = pb.get(b58Str)
expect(peer).to.eql(p1)
})

it('getByB58String non existent', (done) => {
it('.get by B58String non existent', (done) => {
try {
pb.getByB58String(p4.id.toB58String())
pb.get(p4.id.toB58String())
} catch (err) {
expect(err).to.exist()
done()
}
})

it('getByMultihash', () => {
const p1Id = p1.id.toBytes()
const peer = pb.getByMultihash(p1Id)
expect(peer).to.deep.equal(p1)
it('.get by Multihash', () => {
const mh = p1.id.toBytes()
const peer = pb.get(mh)
expect(peer).to.eql(p1)
})

it('getByMultihash non existent', (done) => {
it('.get by Multihash non existent', (done) => {
try {
pb.getByMultihash(p4.id.toBytes())
} catch (err) {
Expand All @@ -90,49 +107,45 @@ describe('peer-book', function () {
}
})

it('removeByB58String', (done) => {
const p1Id = p1.id.toB58String()
pb.removeByB58String(p1Id)
try {
pb.getByB58String(p1Id)
} catch (err) {
expect(err).to.exist()
done()
}
it('.remove by B58String', () => {
const b58Str = p1.id.toB58String()

pb.remove(b58Str)
expect(pb.has(b58Str)).to.equal(false)
})

it('removeByMultihash', (done) => {
const p1Id = p1.id.toBytes()
pb.removeByMultihash(p1Id)
try {
pb.getByMultihash(p1Id)
} catch (err) {
expect(err).to.exist()
done()
}
it('.remove by Multihash', () => {
const mh = p1.id.toBytes()

pb.remove(mh)
expect(pb.has(mh)).to.equal(false)
})

it('add repeated Id, merge info', () => {
const peerA = new PeerInfo(p3.id)
peerA.multiaddr.add(new Multiaddr('/ip4/127.0.0.1/tcp/4001'))
pb.put(peerA)
const peerB = pb.getByB58String(p3.id.toB58String())
expect(peerA).to.deep.equal(peerB)
it('.put repeated Id, merge info', () => {
const peer3A = new PeerInfo(p3.id)
peer3A.multiaddrs.add(new Multiaddr('/ip4/127.0.0.1/tcp/4001'))

pb.put(peer3A)
const peer3B = pb.get(p3.id.toBytes())

expect(peer3B.multiaddrs.toArray()).to.have.length(3)
})

it('add repeated Id, replace info', () => {
const peerA = new PeerInfo(p3.id)
peerA.multiaddr.add(new Multiaddr('/ip4/188.0.0.1/tcp/5001'))
pb.put(peerA, true)
const peerB = pb.getByB58String(p3.id.toB58String())
expect(peerA).to.deep.equal(peerB)
it('.put repeated Id, replace info', () => {
const peer3A = new PeerInfo(p3.id)
peer3A.multiaddrs.add(new Multiaddr('/ip4/188.0.0.1/tcp/5001'))

pb.put(peer3A, true)
const peer3B = pb.get(p3.id.toB58String())
expect(peer3A.multiaddrs.toArray()).to.eql(peer3B.multiaddrs.toArray())
})

it('getAddrs', () => {
it('.getMultiaddrs', () => {
const pb = new PeerBook()
const peer = new PeerInfo(p3.id)
peer.multiaddr.add(new Multiaddr('/ip4/127.0.0.1/tcp/1234'))
peer.multiaddrs.add(new Multiaddr('/ip4/127.0.0.1/tcp/1234'))

pb.put(peer)
expect(pb.getAddrs(p3.id)).to.be.eql(peer.multiaddrs)
expect(pb.getMultiaddrs(p3.id)).to.be.eql(peer.multiaddrs)
})
})
Loading