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

Commit 422d0fd

Browse files
authored
feat: connectedMultiaddr (#49)
* feat: connectedMultiaddr * feat: all new shiny API that makes everyone happy
1 parent 21700b8 commit 422d0fd

File tree

6 files changed

+299
-207
lines changed

6 files changed

+299
-207
lines changed

README.md

+17-9
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,19 @@
2828
- [API](#api)
2929
- [`PeerInfo.create([id, ] callback)`](#peerinfocreateid-callback)
3030
- [`new PeerInfo(id)`](#new-peerinfoid)
31-
- [`multiaddrs`](#multiaddrs)
32-
- [`multiaddr.add(addr)`](#multiaddraddaddr)
33-
- [`multiaddr.addSafe(addr)`](#multiaddraddsafeaddr)
34-
- [`multiaddr.rm(addr)`](#multiaddrrmaddr)
35-
- [`multiaddr.replace(existing, fresh)`](#multiaddrreplaceexisting-fresh)
31+
- [`.connect(ma)`](#connectma)
32+
- [`.disconnect()`](#connectma)
33+
- [`.isConnected()`](#connectma)
34+
- [`.multiaddrs`](#multiaddrs)
35+
- [`.multiaddrs.add(addr)`](#multiaddraddaddr)
36+
- [`.multiaddrs.addSafe(addr)`](#multiaddraddsafeaddr)
37+
- [`.multiaddrs.forEach(fn)`](#multiaddrforeachfn)
38+
- [`.multaiddrs.size`]((#multiaddrsize)
39+
- [`.multiaddrs.has()`]((#multiaddrhas)
40+
- [`.multiaddrs.delete(addr)`](#multiaddrdeleteaddr)
41+
- [`.multiaddrs.toArray()`](#multiaddrtoarray)
42+
- [`.multiaddrs.replace(existing, fresh)`](#multiaddrreplaceexisting-fresh)
43+
- [`.multiaddrs.distinct()`](#distinct)
3644
- [Contribute](#contribute)
3745
- [License](#license)
3846

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

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

106-
### `multiaddr.add(addr)`
114+
### `.multiaddrs.add(addr)`
107115

108116
- `addr: Multiaddr`
109117

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

113-
### `multiaddr.addSafe(addr)`
121+
### `.multiaddr.addSafe(addr)`
114122

115123
- `addr: Multiaddr`
116124

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

126-
### `multiaddr.rm(addr)`
134+
### `.multiaddr.delete(addr)`
127135

128136
- `addr: Multiaddr`
129137

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

132-
### `multiaddr.replace(existing, fresh)`
140+
### `.multiaddr.replace(existing, fresh)`
133141

134142
- `existing: Multiaddr`
135143
- `fresh: Multiaddr`

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@
4343
"pre-commit": "^1.2.2"
4444
},
4545
"dependencies": {
46-
"multiaddr": "^2.2.3",
46+
"multiaddr": "^2.3.0",
4747
"lodash.uniqby": "^4.7.0",
48-
"peer-id": "^0.8.5"
48+
"peer-id": "^0.8.6"
4949
},
5050
"contributors": [
5151
"David Dias <daviddias.p@gmail.com>",

src/index.js

+22-83
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,36 @@
11
'use strict'
22

33
const Id = require('peer-id')
4-
const multiaddr = require('multiaddr')
5-
const uniqBy = require('lodash.uniqby')
6-
7-
exports = module.exports = PeerInfo
8-
9-
function ensureMultiaddr (addr) {
10-
if (multiaddr.isMultiaddr(addr)) {
11-
return addr
12-
}
13-
14-
return multiaddr(addr)
15-
}
4+
const ensureMultiaddr = require('./utils').ensureMultiaddr
5+
const MultiaddrSet = require('./multiaddr-set')
6+
const assert = require('assert')
167

178
// Peer represents a peer on the IPFS network
18-
function PeerInfo (peerId) {
19-
if (!(this instanceof PeerInfo)) {
20-
return new PeerInfo(peerId)
21-
}
9+
class PeerInfo {
10+
constructor (peerId) {
11+
assert(peerId, 'Missing peerId. Use Peer.create(cb) to create one')
2212

23-
if (!peerId) {
24-
throw new Error('Missing peerId. Use Peer.create(cb) to create one')
13+
this.id = peerId
14+
this.multiaddrs = new MultiaddrSet()
15+
this.protocols = new Set()
16+
this._connectedMultiaddr = undefined
2517
}
2618

27-
this.id = peerId
28-
29-
this.multiaddrs = []
30-
const observedMultiaddrs = []
31-
32-
this.multiaddr = {}
33-
34-
this.multiaddr.add = (addr) => {
35-
addr = ensureMultiaddr(addr)
36-
37-
var exists = false
38-
this.multiaddrs.some((m, i) => {
39-
if (m.equals(addr)) {
40-
exists = true
41-
return true
42-
}
43-
})
44-
if (!exists) {
45-
this.multiaddrs.push(addr)
19+
// only stores the current multiaddr being used
20+
connect (ma) {
21+
ma = ensureMultiaddr(ma)
22+
if (!this.multiaddrs.has(ma)) {
23+
throw new Error('can\'t be connected to missing multiaddr from set')
4624
}
25+
this._connectedMultiaddr = ma
4726
}
4827

49-
// to prevent multiaddr explosion
50-
this.multiaddr.addSafe = (addr) => {
51-
addr = ensureMultiaddr(addr)
52-
53-
var check = false
54-
observedMultiaddrs.some((m, i) => {
55-
if (m.equals(addr)) {
56-
this.multiaddr.add(addr)
57-
observedMultiaddrs.splice(i, 1)
58-
check = true
59-
}
60-
})
61-
if (!check) {
62-
observedMultiaddrs.push(addr)
63-
}
64-
}
65-
66-
this.multiaddr.rm = (addr) => {
67-
addr = ensureMultiaddr(addr)
68-
69-
this.multiaddrs.some((m, i) => {
70-
if (m.equals(addr)) {
71-
this.multiaddrs.splice(i, 1)
72-
return true
73-
}
74-
})
75-
}
76-
77-
this.multiaddr.replace = (existing, fresh) => {
78-
if (!Array.isArray(existing)) {
79-
existing = [existing]
80-
}
81-
if (!Array.isArray(fresh)) {
82-
fresh = [fresh]
83-
}
84-
existing.forEach((m) => {
85-
this.multiaddr.rm(m)
86-
})
87-
fresh.forEach((m) => {
88-
this.multiaddr.add(m)
89-
})
28+
disconnect () {
29+
this._connectedMultiaddr = undefined
9030
}
9131

92-
this.distinctMultiaddr = () => {
93-
var result = uniqBy(this.multiaddrs, function (item) {
94-
return [item.toOptions().port, item.toOptions().transport].join()
95-
})
96-
return result
32+
isConnected () {
33+
return Boolean(this._connectedMultiaddr)
9734
}
9835
}
9936

@@ -120,3 +57,5 @@ PeerInfo.isPeerInfo = (peerInfo) => {
12057
peerInfo.id &&
12158
peerInfo.multiaddrs)
12259
}
60+
61+
module.exports = PeerInfo

src/multiaddr-set.js

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
'use strict'
2+
3+
const ensureMultiaddr = require('./utils').ensureMultiaddr
4+
const uniqBy = require('lodash.uniqby')
5+
6+
// Because JavaScript doesn't let you overload the compare in Set()..
7+
class MultiaddrSet {
8+
constructor (multiaddrs) {
9+
this._multiaddrs = multiaddrs || []
10+
this._observedMultiaddrs = []
11+
}
12+
13+
add (ma) {
14+
ma = ensureMultiaddr(ma)
15+
16+
if (!this.has(ma)) {
17+
this._multiaddrs.push(ma)
18+
}
19+
}
20+
21+
// addSafe - prevent multiaddr explosion™
22+
// Multiaddr explosion is when you dial to a bunch of nodes and every node
23+
// gives you a different observed address and you start storing them all to
24+
// share with other peers. This seems like a good idea until you realize that
25+
// most of those addresses are unique to the subnet that peer is in and so,
26+
// they are completely worthless for all the other peers. This method is
27+
// exclusively used by identify.
28+
addSafe (ma) {
29+
ma = ensureMultiaddr(ma)
30+
31+
const check = this._observedMultiaddrs.some((m, i) => {
32+
if (m.equals(ma)) {
33+
this.add(ma)
34+
this._observedMultiaddrs.splice(i, 1)
35+
return true
36+
}
37+
})
38+
if (!check) {
39+
this._observedMultiaddrs.push(ma)
40+
}
41+
}
42+
43+
toArray () {
44+
return this._multiaddrs.slice()
45+
}
46+
47+
get size () {
48+
return this._multiaddrs.length
49+
}
50+
51+
forEach (fn) {
52+
return this._multiaddrs.forEach(fn)
53+
}
54+
55+
has (ma) {
56+
ma = ensureMultiaddr(ma)
57+
return this._multiaddrs.some((m) => m.equals(ma))
58+
}
59+
60+
delete (ma) {
61+
ma = ensureMultiaddr(ma)
62+
63+
this._multiaddrs.some((m, i) => {
64+
if (m.equals(ma)) {
65+
this._multiaddrs.splice(i, 1)
66+
return true
67+
}
68+
})
69+
}
70+
71+
// replaces selected existing multiaddrs with new ones
72+
replace (existing, fresh) {
73+
if (!Array.isArray(existing)) {
74+
existing = [existing]
75+
}
76+
if (!Array.isArray(fresh)) {
77+
fresh = [fresh]
78+
}
79+
existing.forEach((m) => this.delete(m))
80+
fresh.forEach((m) => this.add(m))
81+
}
82+
83+
clear () {
84+
this._multiaddrs = []
85+
}
86+
87+
// this only really helps make ip6 and ip4 multiaddrs distinct if they are
88+
// different
89+
// TODO this is not an ideal solution, probably this code should just be
90+
// in libp2p-tcp
91+
distinct () {
92+
return uniqBy(this._multiaddrs, (ma) => {
93+
return [ma.toOptions().port, ma.toOptions().transport].join()
94+
})
95+
}
96+
}
97+
98+
module.exports = MultiaddrSet

src/utils.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict'
2+
3+
const multiaddr = require('multiaddr')
4+
5+
function ensureMultiaddr (ma) {
6+
if (multiaddr.isMultiaddr(ma)) {
7+
return ma
8+
}
9+
10+
return multiaddr(ma)
11+
}
12+
13+
module.exports = {
14+
ensureMultiaddr: ensureMultiaddr
15+
}

0 commit comments

Comments
 (0)