Compare commits

...

25 Commits

Author SHA1 Message Date
a5b7de1b6b chore: release version v0.9.0 2017-04-06 15:50:57 -04:00
9a7a381f85 chore: update contributors 2017-04-06 15:50:56 -04:00
1f00855e6e chore: update deps 2017-04-06 15:46:13 -04:00
8aa932a491 [WIP] Awesome DHT (#86)
* feat: integrate dht

* better interfaces

* docs: add documentation for peerRouting, contentRouting, dht

* fix: take in passed datastore

* fix: update usage of _getPeerInfo

* fix: getPeerInfo

* docs: update docs

* moar
2017-04-06 15:45:23 -04:00
babb90fe17 chore: release version v0.8.0 2017-03-31 16:19:24 +01:00
2f9070a725 chore: update contributors 2017-03-31 16:19:24 +01:00
a48ec65961 Merge pull request #85 from libp2p/feat/advanced-peer-book
fix: correct method on peer-book
2017-03-31 16:18:37 +01:00
031ecb3fe7 fix: correct method on peer-book 2017-03-31 16:17:59 +01:00
c6bdd869be Merge pull request #76 from libp2p/feat/advanced-peer-book
fix: avoid deleting nodes from peerBook
2017-03-31 16:17:18 +01:00
dee0340806 chore: update to latest peer-info, peer-book and libp2p-swarm 2017-03-31 15:52:20 +01:00
a4b41b0f9a feat: not remove peer from peerBook on disconnect 2017-03-30 07:20:45 +01:00
291e79fc99 fix: addition of ipfs id appendix must come before transport filtering 2017-03-29 21:02:37 +01:00
59ea9c388f feat: append peer id to multiaddr if not there 2017-03-29 20:02:54 +01:00
300936f2f3 fix: avoid deleting nodes from peerBook 2017-03-29 18:03:00 +01:00
9f4ec2a915 chore: release version v0.7.0 2017-03-29 08:03:58 +01:00
c7f4368007 chore: update contributors 2017-03-29 08:03:58 +01:00
9ff04779f5 Merge pull request #75 from libp2p/feat/update-peer-events
feat: Feat/update peer events
2017-03-29 08:03:13 +01:00
f73c045767 feat: update events to conform with #74 2017-03-29 07:32:46 +01:00
8840c9b250 docs: document new events 2017-03-29 07:32:29 +01:00
df4c99df4a chore: release version v0.6.2 2017-03-28 12:44:52 +01:00
6e05a0b239 chore: update contributors 2017-03-28 12:44:52 +01:00
c781abc30c chore: deps 2017-03-28 12:43:00 +01:00
6a66931ba4 chore: release version v0.6.1 2017-03-27 16:48:53 +01:00
426fc27b26 chore: update contributors 2017-03-27 16:48:52 +01:00
d6325dee90 chore: update deps 2017-03-27 16:48:41 +01:00
4 changed files with 233 additions and 57 deletions

View File

@ -1,3 +1,46 @@
<a name="0.9.0"></a>
# [0.9.0](https://github.com/libp2p/js-libp2p/compare/v0.8.0...v0.9.0) (2017-04-06)
<a name="0.8.0"></a>
# [0.8.0](https://github.com/libp2p/js-libp2p/compare/v0.7.0...v0.8.0) (2017-03-31)
### Bug Fixes
* addition of ipfs id appendix must come before transport filtering ([291e79f](https://github.com/libp2p/js-libp2p/commit/291e79f))
* avoid deleting nodes from peerBook ([300936f](https://github.com/libp2p/js-libp2p/commit/300936f))
* correct method on peer-book ([031ecb3](https://github.com/libp2p/js-libp2p/commit/031ecb3))
### Features
* append peer id to multiaddr if not there ([59ea9c3](https://github.com/libp2p/js-libp2p/commit/59ea9c3))
* not remove peer from peerBook on disconnect ([a4b41b0](https://github.com/libp2p/js-libp2p/commit/a4b41b0))
<a name="0.7.0"></a>
# [0.7.0](https://github.com/libp2p/js-libp2p/compare/v0.6.2...v0.7.0) (2017-03-29)
### Features
* update events to conform with [#74](https://github.com/libp2p/js-libp2p/issues/74) ([f73c045](https://github.com/libp2p/js-libp2p/commit/f73c045))
<a name="0.6.2"></a>
## [0.6.2](https://github.com/libp2p/js-libp2p/compare/v0.6.1...v0.6.2) (2017-03-28)
<a name="0.6.1"></a>
## [0.6.1](https://github.com/libp2p/js-libp2p/compare/v0.6.0...v0.6.1) (2017-03-27)
<a name="0.6.0"></a> <a name="0.6.0"></a>
# [0.6.0](https://github.com/libp2p/js-libp2p/compare/v0.5.5...v0.6.0) (2017-03-27) # [0.6.0](https://github.com/libp2p/js-libp2p/compare/v0.5.5...v0.6.0) (2017-03-27)

View File

@ -75,6 +75,7 @@ const WS = require('libp2p-websockets')
const spdy = require('libp2p-spdy') const spdy = require('libp2p-spdy')
const secio = require('libp2p-secio') const secio = require('libp2p-secio')
const MulticastDNS = require('libp2p-mdns') const MulticastDNS = require('libp2p-mdns')
const DHT = require('libp2p-kad-dht')
class Node extends libp2p { class Node extends libp2p {
constructor (peerInfo, peerBook, options) { constructor (peerInfo, peerBook, options) {
@ -95,7 +96,9 @@ class Node extends libp2p {
}, },
discovery: [ discovery: [
new MulticastDNS(peerInfo, 'your-identifier') new MulticastDNS(peerInfo, 'your-identifier')
] ],
// DHT is passed as its own enabling PeerRouting, ContentRouting and DHT itself components
dht: DHT
} }
super(modules, peerInfo, peerBook, options) super(modules, peerInfo, peerBook, options)
@ -144,6 +147,36 @@ class Node extends libp2p {
`callback` is a function with the following `function (err) {}` signature, where `err` is an Error in case stopping the node fails. `callback` is a function with the following `function (err) {}` signature, where `err` is an Error in case stopping the node fails.
#### `libp2p.peerRouting.findPeer(id, callback)`
> Looks up for multiaddrs of a peer in the DHT
- `id`: instance of [PeerId][]
#### `libp2p.contentRouting.findProviders(key, timeout, callback)`
- `key`: Buffer
- `timeout`: Number miliseconds
#### `libp2p.contentRouting.provide(key, timeout, callback)`
- `key`: Buffer
- `timeout`: Number miliseconds
#### `libp2p.dht.put(key, value, callback)`
- `key`: Buffer
- `value`: Buffer
#### `libp2p.dht.get(key, callback)`
- `key`: Buffer
#### `libp2p.dht.getMany(key, nVals, callback)`
- `key`: Buffer
- `nVals`: Number
#### `libp2p.handle(protocol, handlerFunc [, matchFunc])` #### `libp2p.handle(protocol, handlerFunc [, matchFunc])`
> Handle new protocol > Handle new protocol
@ -158,12 +191,24 @@ class Node extends libp2p {
- `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0') - `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0')
#### `libp2p.on('peer', (peer) => {})` #### `libp2p.on('peer:discovery', (peer) => {})`
> Peer has been discovered. > Peer has been discovered.
- `peer`: instance of [PeerInfo][] - `peer`: instance of [PeerInfo][]
#### `libp2p.on('peer:connect', (peer) => {})`
> We connected to a new peer
- `peer`: instance of [PeerInfo][]
#### `libp2p.on('peer:disconnect', (peer) => {})`
> We disconnected from Peer
- `peer`: instance of [PeerInfo][]
#### `libp2p.isOn()` #### `libp2p.isOn()`
> Check if libp2p is started > Check if libp2p is started

View File

@ -1,6 +1,6 @@
{ {
"name": "libp2p", "name": "libp2p",
"version": "0.6.0", "version": "0.9.0",
"description": "JavaScript Skeleton for libp2p bundles", "description": "JavaScript Skeleton for libp2p bundles",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {
@ -41,11 +41,12 @@
}, },
"dependencies": { "dependencies": {
"libp2p-ping": "~0.3.2", "libp2p-ping": "~0.3.2",
"libp2p-swarm": "~0.26.19", "libp2p-swarm": "~0.29.1",
"multiaddr": "^2.2.3", "mafmt": "^2.1.8",
"peer-book": "~0.3.2", "multiaddr": "^2.3.0",
"peer-id": "~0.8.5", "peer-book": "~0.4.0",
"peer-info": "~0.8.5" "peer-id": "~0.8.7",
"peer-info": "~0.9.2"
}, },
"contributors": [ "contributors": [
"David Dias <daviddias.p@gmail.com>", "David Dias <daviddias.p@gmail.com>",

View File

@ -1,14 +1,19 @@
'use strict' 'use strict'
const EventEmitter = require('events').EventEmitter
const assert = require('assert')
const setImmediate = require('async/setImmediate')
const each = require('async/each')
const series = require('async/series')
const Ping = require('libp2p-ping')
const Swarm = require('libp2p-swarm') const Swarm = require('libp2p-swarm')
const PeerId = require('peer-id') const PeerId = require('peer-id')
const PeerInfo = require('peer-info') const PeerInfo = require('peer-info')
const PeerBook = require('peer-book') const PeerBook = require('peer-book')
const mafmt = require('mafmt')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const EventEmitter = require('events').EventEmitter
const assert = require('assert')
const Ping = require('libp2p-ping')
const setImmediate = require('async/setImmediate')
exports = module.exports exports = module.exports
@ -25,27 +30,26 @@ class Node extends EventEmitter {
this.peerBook = _peerBook || new PeerBook() this.peerBook = _peerBook || new PeerBook()
this.isOnline = false this.isOnline = false
this.swarm = new Swarm(this.peerInfo) this.swarm = new Swarm(this.peerInfo, this.peerBook)
// Attach stream multiplexers // Attach stream multiplexers
if (this.modules.connection.muxer) { if (this.modules.connection.muxer) {
let muxers = this.modules.connection.muxer let muxers = this.modules.connection.muxer
muxers = Array.isArray(muxers) ? muxers : [muxers] muxers = Array.isArray(muxers) ? muxers : [muxers]
muxers.forEach((muxer) => { muxers.forEach((muxer) => this.swarm.connection.addStreamMuxer(muxer))
this.swarm.connection.addStreamMuxer(muxer)
})
// If muxer exists, we can use Identify // If muxer exists, we can use Identify
this.swarm.connection.reuse() this.swarm.connection.reuse()
// Received incommind dial and muxer upgrade happened, reuse this // Received incommind dial and muxer upgrade happened,
// muxed connection // reuse this muxed connection
this.swarm.on('peer-mux-established', (peerInfo) => { this.swarm.on('peer-mux-established', (peerInfo) => {
this.emit('peer:connect', peerInfo)
this.peerBook.put(peerInfo) this.peerBook.put(peerInfo)
}) })
this.swarm.on('peer-mux-closed', (peerInfo) => { this.swarm.on('peer-mux-closed', (peerInfo) => {
this.peerBook.removeByB58String(peerInfo.id.toB58String()) this.emit('peer:disconnect', peerInfo)
}) })
} }
@ -62,17 +66,58 @@ class Node extends EventEmitter {
if (this.modules.discovery) { if (this.modules.discovery) {
let discoveries = this.modules.discovery let discoveries = this.modules.discovery
discoveries = Array.isArray(discoveries) ? discoveries : [discoveries] discoveries = Array.isArray(discoveries) ? discoveries : [discoveries]
discoveries.forEach((discovery) => { discoveries.forEach((discovery) => {
discovery.on('peer', (peerInfo) => this.emit('peer', peerInfo)) discovery.on('peer', (peerInfo) => this.emit('peer:discovery', peerInfo))
}) })
} }
// Mount default protocols // Mount default protocols
Ping.mount(this.swarm) Ping.mount(this.swarm)
// Not fully implemented in js-libp2p yet // dht provided components (peerRouting, contentRouting, dht)
this.routing = undefined if (_modules.DHT) {
this.records = undefined this._dht = new this.modules.DHT(this, 20, _options.DHT && _options.DHT.datastore)
}
this.peerRouting = {
findPeer: (id, callback) => {
assert(this._dht, 'DHT is not available')
this._dht.findPeer(id, callback)
}
}
this.contentRouting = {
findProviders: (key, timeout, callback) => {
assert(this._dht, 'DHT is not available')
this._dht.findProviders(key, timeout, callback)
},
provide: (key, callback) => {
assert(this._dht, 'DHT is not available')
this._dht.provide(key, callback)
}
}
this.dht = {
put: (key, value, callback) => {
assert(this._dht, 'DHT is not available')
this._dht.put(key, value, callback)
},
get: (key, callback) => {
assert(this._dht, 'DHT is not available')
this._dht.get(key, callback)
},
getMany (key, nVals, callback) {
assert(this._dht, 'DHT is not available')
this._dht.getMany(key, nVals, callback)
}
}
} }
/* /*
@ -88,7 +133,19 @@ class Node extends EventEmitter {
let transports = this.modules.transport let transports = this.modules.transport
transports = Array.isArray(transports) ? transports : [transports] transports = Array.isArray(transports) ? transports : [transports]
const multiaddrs = this.peerInfo.multiaddrs
// so that we can have webrtc-star addrs without adding manually the id
const maOld = []
const maNew = []
this.peerInfo.multiaddrs.forEach((ma) => {
if (!mafmt.IPFS.matches(ma)) {
maOld.push(ma)
maNew.push(ma.encapsulate('/ipfs/' + this.peerInfo.id.toB58String()))
}
})
this.peerInfo.multiaddrs.replace(maOld, maNew)
const multiaddrs = this.peerInfo.multiaddrs.toArray()
transports.forEach((transport) => { transports.forEach((transport) => {
if (transport.filter(multiaddrs).length > 0) { if (transport.filter(multiaddrs).length > 0) {
@ -102,24 +159,30 @@ class Node extends EventEmitter {
} }
}) })
this.swarm.listen((err) => { series([
if (err) { (cb) => this.swarm.listen(cb),
return callback(err) (cb) => {
} // listeners on, libp2p is on
if (ws) { this.isOnline = true
this.swarm.transport.add(ws.tag || ws.constructor.name, ws)
}
this.isOnline = true if (ws) {
// always add dialing on websockets
this.swarm.transport.add(ws.tag || ws.constructor.name, ws)
}
if (this.modules.discovery) { // all transports need to be setup before discover starts
this.modules.discovery.forEach((discovery) => { if (this.modules.discovery) {
setImmediate(() => discovery.start(() => {})) return each(this.modules.discovery, (d, cb) => d.start(cb), cb)
}) }
cb()
},
(cb) => {
if (this._dht) {
return this._dht.start(cb)
}
cb()
} }
], callback)
callback()
})
} }
/* /*
@ -134,7 +197,15 @@ class Node extends EventEmitter {
}) })
} }
this.swarm.close(callback) series([
(cb) => {
if (this._dht) {
return this._dht.stop(cb)
}
cb()
},
(cb) => this.swarm.close(cb)
], callback)
} }
isOn () { isOn () {
@ -143,34 +214,48 @@ class Node extends EventEmitter {
ping (peer, callback) { ping (peer, callback) {
assert(this.isOn(), OFFLINE_ERROR_MESSAGE) assert(this.isOn(), OFFLINE_ERROR_MESSAGE)
const peerInfo = this._getPeerInfo(peer) this._getPeerInfo(peer, (err, peerInfo) => {
callback(null, new Ping(this.swarm, peerInfo)) if (err) {
return callback(err)
}
callback(null, new Ping(this.swarm, peerInfo))
})
} }
dial (peer, protocol, callback) { dial (peer, protocol, callback) {
assert(this.isOn(), OFFLINE_ERROR_MESSAGE) assert(this.isOn(), OFFLINE_ERROR_MESSAGE)
const peerInfo = this._getPeerInfo(peer)
if (typeof protocol === 'function') { if (typeof protocol === 'function') {
callback = protocol callback = protocol
protocol = undefined protocol = undefined
} }
this.swarm.dial(peerInfo, protocol, (err, conn) => { this._getPeerInfo(peer, (err, peerInfo) => {
if (err) { if (err) {
return callback(err) return callback(err)
} }
this.peerBook.put(peerInfo)
callback(null, conn) this.swarm.dial(peerInfo, protocol, (err, conn) => {
if (err) {
return callback(err)
}
this.peerBook.put(peerInfo)
callback(null, conn)
})
}) })
} }
hangUp (peer, callback) { hangUp (peer, callback) {
assert(this.isOn(), OFFLINE_ERROR_MESSAGE) assert(this.isOn(), OFFLINE_ERROR_MESSAGE)
const peerInfo = this._getPeerInfo(peer)
this.peerBook.removeByB58String(peerInfo.id.toB58String()) this._getPeerInfo(peer, (err, peerInfo) => {
this.swarm.hangUp(peerInfo, callback) if (err) {
return callback(err)
}
this.swarm.hangUp(peerInfo, callback)
})
} }
handle (protocol, handlerFunc, matchFunc) { handle (protocol, handlerFunc, matchFunc) {
@ -184,31 +269,33 @@ class Node extends EventEmitter {
/* /*
* Helper method to check the data type of peer and convert it to PeerInfo * Helper method to check the data type of peer and convert it to PeerInfo
*/ */
_getPeerInfo (peer) { _getPeerInfo (peer, callback) {
let p let p
// PeerInfo
if (PeerInfo.isPeerInfo(peer)) { if (PeerInfo.isPeerInfo(peer)) {
p = peer p = peer
// Multiaddr instance (not string)
} else if (multiaddr.isMultiaddr(peer)) { } else if (multiaddr.isMultiaddr(peer)) {
const peerIdB58Str = peer.getPeerId() const peerIdB58Str = peer.getPeerId()
try { try {
p = this.peerBook.getByB58String(peerIdB58Str) p = this.peerBook.get(peerIdB58Str)
} catch (err) { } catch (err) {
p = new PeerInfo(PeerId.createFromB58String(peerIdB58Str)) p = new PeerInfo(PeerId.createFromB58String(peerIdB58Str))
} }
p.multiaddr.add(peer) p.multiaddrs.add(peer)
// PeerId
} else if (PeerId.isPeerId(peer)) { } else if (PeerId.isPeerId(peer)) {
const peerIdB58Str = peer.toB58String() const peerIdB58Str = peer.toB58String()
try { try {
p = this.peerBook.getByB58String(peerIdB58Str) p = this.peerBook.get(peerIdB58Str)
} catch (err) { } catch (err) {
// TODO this is where PeerRouting comes into place return this.peerRouting.findPeer(peer, callback)
throw new Error('No knowledge about: ' + peerIdB58Str)
} }
} else { } else {
throw new Error('peer type not recognized') return setImmediate(() => callback(new Error('peer type not recognized')))
} }
return p setImmediate(() => callback(null, p))
} }
} }