Skip to content
This repository was archived by the owner on Aug 23, 2019. It is now read-only.

Commit 206dde8

Browse files
authored
advanced peer-book (#206)
* fix: improve availableTransports filtering (was actually broken before) * feat: new peer-info * feat: now logs the used multiaddr
1 parent effa2ca commit 206dde8

28 files changed

+488
-527
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ And use it in your Node.js code as:
5858
```JavaScript
5959
const Swarm = require('libp2p-swarm')
6060

61-
const sw = new Swarm(peerInfo)
61+
const sw = new Swarm(peerInfo [, peerBook])
6262
```
6363

6464
## API

gulpfile.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ const PeerInfo = require('peer-info')
55
const PeerId = require('peer-id')
66
const WebSockets = require('libp2p-websockets')
77
const pull = require('pull-stream')
8+
const PeerBook = require('peer-book')
89

910
const Swarm = require('./src')
1011
const spdy = require('libp2p-spdy')
11-
const multiaddr = require('multiaddr')
1212
const fs = require('fs')
1313
const path = require('path')
1414

@@ -27,19 +27,19 @@ gulp.task('test:browser:before', (done) => {
2727
function createListenerA (cb) {
2828
PeerId.createFromJSON(
2929
JSON.parse(
30-
fs.readFileSync(
31-
path.join(__dirname, './test/test-data/id-1.json'))
30+
fs.readFileSync(path.join(__dirname, './test/test-data/id-1.json'))
3231
),
3332
(err, id) => {
3433
if (err) {
3534
return cb(err)
3635
}
3736

3837
const peerA = new PeerInfo(id)
39-
const maA = multiaddr('/ip4/127.0.0.1/tcp/9100/ws')
38+
const maA = '/ip4/127.0.0.1/tcp/9100/ws'
39+
40+
peerA.multiaddrs.add(maA)
41+
swarmA = new Swarm(peerA, new PeerBook())
4042

41-
peerA.multiaddr.add(maA)
42-
swarmA = new Swarm(peerA)
4343
swarmA.transport.add('ws', new WebSockets())
4444
swarmA.transport.listen('ws', {}, echo, cb)
4545
})
@@ -48,19 +48,18 @@ gulp.task('test:browser:before', (done) => {
4848
function createListenerB (cb) {
4949
PeerId.createFromJSON(
5050
JSON.parse(
51-
fs.readFileSync(
52-
path.join(__dirname, './test/test-data/id-2.json'))
51+
fs.readFileSync(path.join(__dirname, './test/test-data/id-2.json'))
5352
),
5453
(err, id) => {
5554
if (err) {
5655
return cb(err)
5756
}
5857

5958
const peerB = new PeerInfo(id)
60-
const maB = multiaddr('/ip4/127.0.0.1/tcp/9200/ws')
59+
const maB = '/ip4/127.0.0.1/tcp/9200/ws'
6160

62-
peerB.multiaddr.add(maB)
63-
swarmB = new Swarm(peerB)
61+
peerB.multiaddrs.add(maB)
62+
swarmB = new Swarm(peerB, new PeerBook())
6463

6564
swarmB.transport.add('ws', new WebSockets())
6665
swarmB.connection.addStreamMuxer(spdy)

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@
4949
"libp2p-secio": "~0.6.8",
5050
"libp2p-spdy": "~0.10.6",
5151
"libp2p-tcp": "~0.10.0",
52-
"libp2p-webrtc-star": "~0.8.10",
52+
"libp2p-webrtc-star": "~0.9.0",
5353
"libp2p-websockets": "~0.10.0",
5454
"pre-commit": "^1.2.2",
5555
"pull-goodbye": "0.0.1",
56+
"peer-book": "~0.4.0",
5657
"pull-stream": "^3.5.0",
5758
"webrtcsupport": "^2.2.0"
5859
},
@@ -62,13 +63,13 @@
6263
"debug": "^2.6.3",
6364
"interface-connection": "~0.3.2",
6465
"ip-address": "^5.8.6",
65-
"libp2p-identify": "~0.3.3",
66+
"libp2p-identify": "~0.4.0",
6667
"lodash.includes": "^4.3.0",
6768
"multiaddr": "^2.3.0",
6869
"multistream-select": "~0.13.5",
6970
"once": "^1.4.0",
70-
"peer-id": "~0.8.5",
71-
"peer-info": "~0.8.5",
71+
"peer-id": "~0.8.6",
72+
"peer-info": "~0.9.2",
7273
"protocol-buffers": "^3.2.1"
7374
},
7475
"contributors": [
@@ -86,4 +87,4 @@
8687
"greenkeeper[bot] <greenkeeper[bot]@users.noreply.github.com>",
8788
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <[email protected]>"
8889
]
89-
}
90+
}

src/connection.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ module.exports = function connection (swarm) {
4141
(conn, cb) => identify.dialer(conn, cb),
4242
(peerInfo, observedAddrs, cb) => {
4343
observedAddrs.forEach((oa) => {
44-
swarm._peerInfo.multiaddr.addSafe(oa)
44+
swarm._peerInfo.multiaddrs.addSafe(oa)
4545
})
4646
cb(null, peerInfo)
4747
}
@@ -52,13 +52,28 @@ module.exports = function connection (swarm) {
5252
if (err) {
5353
return log('Identify not successful')
5454
}
55-
swarm.muxedConns[peerInfo.id.toB58String()] = {
56-
muxer: muxedConn
55+
const b58Str = peerInfo.id.toB58String()
56+
57+
swarm.muxedConns[b58Str] = { muxer: muxedConn }
58+
59+
if (peerInfo.multiaddrs.size > 0) {
60+
// with incomming conn and through identify, going to pick one
61+
// of the available multiaddrs from the other peer as the one
62+
// I'm connected to as we really can't be sure at the moment
63+
// TODO add this consideration to the connection abstraction!
64+
peerInfo.connect(peerInfo.multiaddrs.toArray()[0])
65+
} else {
66+
// for the case of websockets in the browser, where peers have
67+
// no addr, use just their IPFS id
68+
peerInfo.connect(`/ipfs/${b58Str}`)
5769
}
70+
peerInfo = swarm._peerBook.put(peerInfo)
5871

5972
swarm.emit('peer-mux-established', peerInfo)
6073
muxedConn.on('close', () => {
61-
delete swarm.muxedConns[peerInfo.id.toB58String()]
74+
delete swarm.muxedConns[b58Str]
75+
peerInfo.disconnect()
76+
peerInfo = swarm._peerBook.put(peerInfo)
6277
swarm.emit('peer-mux-closed', peerInfo)
6378
})
6479
})

src/dial.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ module.exports = function dial (swarm) {
1414
protocol = null
1515
}
1616

17-
if (!callback) {
18-
callback = function noop () {}
19-
}
17+
callback = callback || function noop () {}
2018

2119
const proxyConn = new Connection()
2220

@@ -160,7 +158,10 @@ module.exports = function dial (swarm) {
160158
swarm.emit('peer-mux-established', pi)
161159

162160
muxedConn.once('close', () => {
163-
delete swarm.muxedConns[pi.id.toB58String()]
161+
const b58Str = pi.id.toB58String()
162+
delete swarm.muxedConns[b58Str]
163+
pi.disconnect()
164+
swarm._peerBook.get(b58Str).disconnect()
164165
swarm.emit('peer-mux-closed', pi)
165166
})
166167

src/index.js

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,27 @@ const util = require('util')
44
const EE = require('events').EventEmitter
55
const each = require('async/each')
66
const series = require('async/series')
7-
const includes = require('lodash.includes')
8-
97
const transport = require('./transport')
108
const connection = require('./connection')
119
const dial = require('./dial')
1210
const protocolMuxer = require('./protocol-muxer')
1311
const plaintext = require('./plaintext')
12+
const assert = require('assert')
1413

1514
exports = module.exports = Swarm
1615

1716
util.inherits(Swarm, EE)
1817

19-
function Swarm (peerInfo) {
18+
function Swarm (peerInfo, peerBook) {
2019
if (!(this instanceof Swarm)) {
2120
return new Swarm(peerInfo)
2221
}
2322

24-
if (!peerInfo) {
25-
throw new Error('You must provide a value for `peerInfo`')
26-
}
23+
assert(peerInfo, 'You must provide a `peerInfo`')
24+
assert(peerBook, 'You must provide a `peerBook`')
2725

2826
this._peerInfo = peerInfo
27+
this._peerBook = peerBook
2928

3029
// transports --
3130
// { key: transport }; e.g { tcp: <tcp> }
@@ -59,25 +58,11 @@ function Swarm (peerInfo) {
5958
this.connection = connection(this)
6059

6160
this.availableTransports = (pi) => {
62-
const addrs = pi.multiaddrs
61+
const myAddrs = pi.multiaddrs.toArray()
62+
const myTransports = Object.keys(this.transports)
6363

6464
// Only listen on transports we actually have addresses for
65-
return Object.keys(this.transports).filter((ts) => {
66-
// ipfs multiaddrs are not dialable so we drop them here
67-
let dialable = addrs.map((addr) => {
68-
// webrtc-star needs the /ipfs/QmHash
69-
if (addr.toString().indexOf('webrtc-star') > 0) {
70-
return addr
71-
}
72-
73-
if (includes(addr.protoNames(), 'ipfs')) {
74-
return addr.decapsulate('ipfs')
75-
}
76-
return addr
77-
})
78-
79-
return this.transports[ts].filter(dialable).length > 0
80-
})
65+
return myTransports.filter((ts) => this.transports[ts].filter(myAddrs).length > 0)
8166
}
8267

8368
// higher level (public) API

src/limit-dialer/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ class LimitDialer {
3636
dialMany (peer, transport, addrs, callback) {
3737
log('dialMany:start')
3838
// we use a token to track if we want to cancel following dials
39-
const token = {cancel: false}
39+
const token = { cancel: false }
40+
4041
map(addrs, (m, cb) => {
4142
this.dialSingle(peer, transport, m, token, cb)
4243
}, (err, results) => {
@@ -47,7 +48,7 @@ class LimitDialer {
4748
const success = results.filter((res) => res.conn)
4849
if (success.length > 0) {
4950
log('dialMany:success')
50-
return callback(null, success[0].conn)
51+
return callback(null, success[0])
5152
}
5253

5354
log('dialMany:error')

src/limit-dialer/queue.js

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,34 +38,30 @@ class DialQueue {
3838
*/
3939
_doWork (transport, addr, token, callback) {
4040
log('work')
41-
this._dialWithTimeout(
42-
transport,
43-
addr,
44-
(err, conn) => {
45-
if (err) {
46-
log('work:error')
47-
return callback(null, {error: err})
48-
}
41+
this._dialWithTimeout(transport, addr, (err, conn) => {
42+
if (err) {
43+
log('work:error')
44+
return callback(null, {error: err})
45+
}
4946

50-
if (token.cancel) {
51-
log('work:cancel')
52-
// clean up already done dials
53-
pull(pull.empty(), conn)
54-
// TODO: proper cleanup once the connection interface supports it
55-
// return conn.close(() => callback(new Error('Manual cancel'))
56-
return callback(null, {cancel: true})
57-
}
47+
if (token.cancel) {
48+
log('work:cancel')
49+
// clean up already done dials
50+
pull(pull.empty(), conn)
51+
// TODO: proper cleanup once the connection interface supports it
52+
// return conn.close(() => callback(new Error('Manual cancel'))
53+
return callback(null, {cancel: true})
54+
}
5855

59-
// one is enough
60-
token.cancel = true
56+
// one is enough
57+
token.cancel = true
6158

62-
log('work:success')
59+
log('work:success')
6360

64-
const proxyConn = new Connection()
65-
proxyConn.setInnerConn(conn)
66-
callback(null, {conn})
67-
}
68-
)
61+
const proxyConn = new Connection()
62+
proxyConn.setInnerConn(conn)
63+
callback(null, { multiaddr: addr, conn: conn })
64+
})
6965
}
7066

7167
/**

src/transport.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ module.exports = function (swarm) {
2424
options = {}
2525
}
2626

27-
if (!callback) { callback = noop }
27+
callback = callback || noop
28+
2829
log('adding %s', key)
2930
if (swarm.transports[key]) {
3031
throw new Error('There is already a transport with this key')
@@ -39,7 +40,7 @@ module.exports = function (swarm) {
3940

4041
dial (key, pi, callback) {
4142
const t = swarm.transports[key]
42-
let multiaddrs = pi.multiaddrs.slice()
43+
let multiaddrs = pi.multiaddrs.toArray()
4344

4445
if (!Array.isArray(multiaddrs)) {
4546
multiaddrs = [multiaddrs]
@@ -48,7 +49,15 @@ module.exports = function (swarm) {
4849
// filter the multiaddrs that are actually valid for this transport (use a func from the transport itself) (maybe even make the transport do that)
4950
multiaddrs = dialables(t, multiaddrs)
5051

51-
dialer.dialMany(pi.id, t, multiaddrs, callback)
52+
dialer.dialMany(pi.id, t, multiaddrs, (err, success) => {
53+
if (err) {
54+
return callback(err)
55+
}
56+
57+
pi.connect(success.multiaddr)
58+
swarm._peerBook.put(pi)
59+
callback(null, success.conn)
60+
})
5261
},
5362

5463
listen (key, options, handler, callback) {
@@ -57,7 +66,7 @@ module.exports = function (swarm) {
5766
handler = protocolMuxer.bind(null, swarm.protocols)
5867
}
5968

60-
const multiaddrs = dialables(swarm.transports[key], swarm._peerInfo.distinctMultiaddr())
69+
const multiaddrs = dialables(swarm.transports[key], swarm._peerInfo.multiaddrs.distinct())
6170

6271
const transport = swarm.transports[key]
6372

@@ -96,7 +105,7 @@ module.exports = function (swarm) {
96105
}
97106

98107
// cause we can listen on port 0 or 0.0.0.0
99-
swarm._peerInfo.multiaddr.replace(multiaddrs, freshMultiaddrs)
108+
swarm._peerInfo.multiaddrs.replace(multiaddrs, freshMultiaddrs)
100109
callback()
101110
})
102111
},

0 commit comments

Comments
 (0)