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

feat: connectedMultiaddr #49

Merged
merged 6 commits into from
Mar 30, 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
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,19 @@
- [API](#api)
- [`PeerInfo.create([id, ] callback)`](#peerinfocreateid-callback)
- [`new PeerInfo(id)`](#new-peerinfoid)
- [`multiaddrs`](#multiaddrs)
- [`multiaddr.add(addr)`](#multiaddraddaddr)
- [`multiaddr.addSafe(addr)`](#multiaddraddsafeaddr)
- [`multiaddr.rm(addr)`](#multiaddrrmaddr)
- [`multiaddr.replace(existing, fresh)`](#multiaddrreplaceexisting-fresh)
- [`.connect(ma)`](#connectma)
- [`.disconnect()`](#connectma)
- [`.isConnected()`](#connectma)
- [`.multiaddrs`](#multiaddrs)
- [`.multiaddrs.add(addr)`](#multiaddraddaddr)
- [`.multiaddrs.addSafe(addr)`](#multiaddraddsafeaddr)
- [`.multiaddrs.forEach(fn)`](#multiaddrforeachfn)
- [`.multaiddrs.size`]((#multiaddrsize)
- [`.multiaddrs.has()`]((#multiaddrhas)
- [`.multiaddrs.delete(addr)`](#multiaddrdeleteaddr)
- [`.multiaddrs.toArray()`](#multiaddrtoarray)
- [`.multiaddrs.replace(existing, fresh)`](#multiaddrreplaceexisting-fresh)
- [`.multiaddrs.distinct()`](#distinct)
- [Contribute](#contribute)
- [License](#license)

Expand Down Expand Up @@ -103,14 +111,14 @@ Creates a new PeerInfo instance from an existing PeerID.

A list of multiaddresses instances that `peer` can be reached at.

### `multiaddr.add(addr)`
### `.multiaddrs.add(addr)`

- `addr: Multiaddr`

Adds a new multiaddress that `peer` can be reached at. `addr` is an instance of
a [multiaddr](https://github.com/libp2p/js-multiaddr).

### `multiaddr.addSafe(addr)`
### `.multiaddr.addSafe(addr)`

- `addr: Multiaddr`

Expand All @@ -123,13 +131,13 @@ peers which will not provide a useful multiaddr to be shared to the rest of the
network (e.g. a multiaddr referring to a peer inside a LAN being shared to the
outside world).

### `multiaddr.rm(addr)`
### `.multiaddr.delete(addr)`

- `addr: Multiaddr`

Removes a multiaddress instance `addr` from `peer`.

### `multiaddr.replace(existing, fresh)`
### `.multiaddr.replace(existing, fresh)`

- `existing: Multiaddr`
- `fresh: Multiaddr`
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
"pre-commit": "^1.2.2"
},
"dependencies": {
"multiaddr": "^2.2.3",
"multiaddr": "^2.3.0",
"lodash.uniqby": "^4.7.0",
"peer-id": "^0.8.5"
"peer-id": "^0.8.6"
},
"contributors": [
"David Dias <daviddias.p@gmail.com>",
Expand Down
105 changes: 22 additions & 83 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,99 +1,36 @@
'use strict'

const Id = require('peer-id')
const multiaddr = require('multiaddr')
const uniqBy = require('lodash.uniqby')

exports = module.exports = PeerInfo

function ensureMultiaddr (addr) {
if (multiaddr.isMultiaddr(addr)) {
return addr
}

return multiaddr(addr)
}
const ensureMultiaddr = require('./utils').ensureMultiaddr
const MultiaddrSet = require('./multiaddr-set')
const assert = require('assert')

// Peer represents a peer on the IPFS network
function PeerInfo (peerId) {
if (!(this instanceof PeerInfo)) {
return new PeerInfo(peerId)
}
class PeerInfo {
constructor (peerId) {
assert(peerId, 'Missing peerId. Use Peer.create(cb) to create one')

if (!peerId) {
throw new Error('Missing peerId. Use Peer.create(cb) to create one')
this.id = peerId
this.multiaddrs = new MultiaddrSet()
this.protocols = new Set()
this._connectedMultiaddr = undefined
}

this.id = peerId

this.multiaddrs = []
const observedMultiaddrs = []

this.multiaddr = {}

this.multiaddr.add = (addr) => {
addr = ensureMultiaddr(addr)

var exists = false
this.multiaddrs.some((m, i) => {
if (m.equals(addr)) {
exists = true
return true
}
})
if (!exists) {
this.multiaddrs.push(addr)
// only stores the current multiaddr being used
connect (ma) {
ma = ensureMultiaddr(ma)
if (!this.multiaddrs.has(ma)) {
throw new Error('can\'t be connected to missing multiaddr from set')
}
this._connectedMultiaddr = ma
}

// to prevent multiaddr explosion
this.multiaddr.addSafe = (addr) => {
addr = ensureMultiaddr(addr)

var check = false
observedMultiaddrs.some((m, i) => {
if (m.equals(addr)) {
this.multiaddr.add(addr)
observedMultiaddrs.splice(i, 1)
check = true
}
})
if (!check) {
observedMultiaddrs.push(addr)
}
}

this.multiaddr.rm = (addr) => {
addr = ensureMultiaddr(addr)

this.multiaddrs.some((m, i) => {
if (m.equals(addr)) {
this.multiaddrs.splice(i, 1)
return true
}
})
}

this.multiaddr.replace = (existing, fresh) => {
if (!Array.isArray(existing)) {
existing = [existing]
}
if (!Array.isArray(fresh)) {
fresh = [fresh]
}
existing.forEach((m) => {
this.multiaddr.rm(m)
})
fresh.forEach((m) => {
this.multiaddr.add(m)
})
disconnect () {
this._connectedMultiaddr = undefined
}

this.distinctMultiaddr = () => {
var result = uniqBy(this.multiaddrs, function (item) {
return [item.toOptions().port, item.toOptions().transport].join()
})
return result
isConnected () {
return Boolean(this._connectedMultiaddr)
}
}

Expand All @@ -120,3 +57,5 @@ PeerInfo.isPeerInfo = (peerInfo) => {
peerInfo.id &&
peerInfo.multiaddrs)
}

module.exports = PeerInfo
98 changes: 98 additions & 0 deletions src/multiaddr-set.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
'use strict'

const ensureMultiaddr = require('./utils').ensureMultiaddr
const uniqBy = require('lodash.uniqby')

// Because JavaScript doesn't let you overload the compare in Set()..
class MultiaddrSet {
constructor (multiaddrs) {
this._multiaddrs = multiaddrs || []
this._observedMultiaddrs = []
}

add (ma) {
ma = ensureMultiaddr(ma)

if (!this.has(ma)) {
this._multiaddrs.push(ma)
}
}

// addSafe - prevent multiaddr explosion™
// Multiaddr explosion is when you dial to a bunch of nodes and every node
// gives you a different observed address and you start storing them all to
// share with other peers. This seems like a good idea until you realize that
// most of those addresses are unique to the subnet that peer is in and so,
// they are completely worthless for all the other peers. This method is
// exclusively used by identify.
addSafe (ma) {
ma = ensureMultiaddr(ma)

const check = this._observedMultiaddrs.some((m, i) => {
if (m.equals(ma)) {
this.add(ma)
this._observedMultiaddrs.splice(i, 1)
return true
}
})
if (!check) {
this._observedMultiaddrs.push(ma)
}
}

toArray () {
return this._multiaddrs.slice()
}

get size () {
return this._multiaddrs.length
}

forEach (fn) {
return this._multiaddrs.forEach(fn)
}

has (ma) {
ma = ensureMultiaddr(ma)
return this._multiaddrs.some((m) => m.equals(ma))
}

delete (ma) {
ma = ensureMultiaddr(ma)

this._multiaddrs.some((m, i) => {
if (m.equals(ma)) {
this._multiaddrs.splice(i, 1)
return true
}
})
}

// replaces selected existing multiaddrs with new ones
replace (existing, fresh) {
if (!Array.isArray(existing)) {
existing = [existing]
}
if (!Array.isArray(fresh)) {
fresh = [fresh]
}
existing.forEach((m) => this.delete(m))
fresh.forEach((m) => this.add(m))
}

clear () {
this._multiaddrs = []
}

// this only really helps make ip6 and ip4 multiaddrs distinct if they are
// different
// TODO this is not an ideal solution, probably this code should just be
// in libp2p-tcp
distinct () {
return uniqBy(this._multiaddrs, (ma) => {
return [ma.toOptions().port, ma.toOptions().transport].join()
})
}
}

module.exports = MultiaddrSet
15 changes: 15 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict'

const multiaddr = require('multiaddr')

function ensureMultiaddr (ma) {
if (multiaddr.isMultiaddr(ma)) {
return ma
}

return multiaddr(ma)
}

module.exports = {
ensureMultiaddr: ensureMultiaddr
}
Loading