From 3584209947bfce8ea0635538a92859d2d82f1fd0 Mon Sep 17 00:00:00 2001 From: David Dias Date: Fri, 24 Mar 2017 16:02:57 +0000 Subject: [PATCH 1/6] docs: update readme, add base class extending example and start listing API calls --- README.md | 70 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 31d04266..a5d60abf 100644 --- a/README.md +++ b/README.md @@ -56,24 +56,78 @@ npm install --save libp2p ## Usage -> **Disclaimer - We haven't solidified [libp2p interface](https://github.com/libp2p/interface-libp2p) yet, it might change at anytime.** - ### Extending libp2p skeleton libp2p becomes very simple and basically acts as a glue for every module that compose this library. Since it can be highly customized, it requires some setup. What we recommend is to have a libp2p build for the system you are developing taking into account in your needs (e.g. for a browser working version of libp2p that acts as the network layer of IPFS, we have a built and minified version that browsers can require). -### libp2p API +**Example:** -Defined by [interface-libp2p](https://github.com/libp2p/interface-libp2p) +```JavaScript +// Creating a bundle that adds: +// transport: websockets + tcp +// stream-muxing: SPDY +// crypto-channel: secio +// discovery: multicast-dns -## Development +const libp2p = require('libp2p') +const TCP = require('libp2p-tcp') +const WS = require('libp2p-websockets') +const spdy = require('libp2p-spdy') +const secio = require('libp2p-secio') +const MulticastDNS = require('libp2p-mdns') -## Linting +class Node extends libp2p { + constructor (peerInfo, peerBook, options) { + options = options || {} -```sh -> npm run lint + const modules = { + transport: [ + new TCP(), + new WS() + ], + connection: { + muxer: [ + spdy + ], + crypto: [ + secio + ] + }, + discovery: [ + new MulticastDNS(peerInfo, 'your-identifier') + ] + } + + super(modules, peerInfo, peerBook, options) + } +} + +// Now all the nodes you create, will have TCP, WebSockets, SPDY, SECIO and MulticastDNS support. ``` +### API + +#### Create a Node - `new libp2p.Node()` + +#### `libp2p.start(callback)` + +#### `libp2p.stop(callback)` + +#### `libp2p.dial(peer [, protocol, callback])` + +#### `libp2p.hangUp(peer, callback) + +#### `libp2p.handle(protocol, handlerFunc [, matchFunc])` + +#### `libp2p.unhandle(protocol) + +#### `libp2p.on('peer', (peer) => {})` + +#### `libp2p.isOn()` + +#### `libp2p.peers` + + ### Packages List of packages currently in existence for libp2p From a4b97b962787f2dc994e93e916624490b6cf03b6 Mon Sep 17 00:00:00 2001 From: David Dias Date: Fri, 24 Mar 2017 17:07:08 +0000 Subject: [PATCH 2/6] docs: libp2p API --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index a5d60abf..bc65e22d 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,17 @@ class Node extends libp2p { #### `libp2p.peers` +--------------------- + +`FUTURE™` + +#### `libp2p.findPeers` + +#### `libp2p.findProviders` + +#### `libp2p.record.put` + +#### `libp2p.record.get` ### Packages From 5d4d94e75f77a86ad2c0a9583ae5eea0a548d660 Mon Sep 17 00:00:00 2001 From: David Dias Date: Fri, 24 Mar 2017 18:20:14 +0000 Subject: [PATCH 3/6] docs: finish API documentation --- README.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bc65e22d..771e2e1a 100644 --- a/README.md +++ b/README.md @@ -107,29 +107,78 @@ class Node extends libp2p { ### API -#### Create a Node - `new libp2p.Node()` +#### Create a Node - `new libp2p.Node([peerInfo, peerBook, options])` + +> Creates an instance of the libp2p.Node. + +- `peerInfo`: instance of [PeerInfo][] that contains the [PeerId][], Keys and [multiaddrs][multiaddr] of the libp2p Node. Optional. +- `peerBook`: instance of [PeerBook][] that contains the [PeerInfo][] of known peers. Optional. +- `options`: Object containing custom options for the bundle. #### `libp2p.start(callback)` +> Start the libp2p Node. + +`callback` is a function with the following `function (err) {}` signature, where `err` is an Error in case starting the node fails. + #### `libp2p.stop(callback)` +> Stop the libp2p Node. + +`callback` is a function with the following `function (err) {}` signature, where `err` is an Error in case stopping the node fails. + #### `libp2p.dial(peer [, protocol, callback])` +> Dials to another peer in the network. + +- `peer`: can be an instance of [PeerInfo][], [PeerId][] or [multiaddr][] +- `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0') + +`callback` is a function with the following `function (err, conn) {}` signature, where `err` is an Error in of failure to dial the connection and `conn` is a [Connection][] instance in case of a protocol selected, if not it is undefined. + #### `libp2p.hangUp(peer, callback) +> Closes an open connection with a peer, graciously. + +- `peer`: can be an instance of [PeerInfo][], [PeerId][] or [multiaddr][] + +`callback` is a function with the following `function (err) {}` signature, where `err` is an Error in case stopping the node fails. + #### `libp2p.handle(protocol, handlerFunc [, matchFunc])` +> Handle new protocol + +- `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0') +- `handlerFunc`: Function with signature `function (protocol, conn) {}` +- `matchFunc`: Function for matching on protocol (exact matching, semver, etc). Default to exact match. + #### `libp2p.unhandle(protocol) +> Stop handling protocol + +- `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0') + #### `libp2p.on('peer', (peer) => {})` +> Peer has been discovered. + +- `peer`: instance of [PeerInfo][] + #### `libp2p.isOn()` -#### `libp2p.peers` +> Check if libp2p is started + +#### `libp2p.peerBook` + +> PeerBook instance of the node + +#### `libp2p.peerInfo` + +> PeerInfo instance of the node --------------------- -`FUTURE™` +`SOON™` #### `libp2p.findPeers` @@ -139,6 +188,13 @@ class Node extends libp2p { #### `libp2p.record.get` +[PeerInfo]: https://github.com/libp2p/js-peer-info +[PeerId]: https://github.com/libp2p/js-peer-id +[PeerBook]: https://github.com/libp2p/js-peer-book +[multiaddr]: https://github.com/multiformats/js-multiaddr +[Connection]: https://github.com/libp2p/interface-connection + + ### Packages List of packages currently in existence for libp2p From a6623c1ba20e189e769e12f7bf304610a7e38e6c Mon Sep 17 00:00:00 2001 From: David Dias Date: Mon, 27 Mar 2017 12:26:34 +0100 Subject: [PATCH 4/6] feat: new super simplified API --- README.md | 4 ++ package.json | 7 +-- src/index.js | 166 ++++++++++++++------------------------------------- 3 files changed, 53 insertions(+), 124 deletions(-) diff --git a/README.md b/README.md index 771e2e1a..a632d28c 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,10 @@ class Node extends libp2p { > Check if libp2p is started +#### `libp2p.ping(peer [, options], callback)` + +> Ping a node in the network + #### `libp2p.peerBook` > PeerBook instance of the node diff --git a/package.json b/package.json index 3d0a4757..ec4696d5 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ }, "homepage": "https://github.com/libp2p/js-libp2p", "devDependencies": { - "aegir": "^11.0.0", + "aegir": "^11.0.1", "chai": "^3.5.0", "dirty-chai": "^1.2.2", "pre-commit": "^1.2.2" @@ -42,8 +42,7 @@ "dependencies": { "libp2p-ping": "~0.3.2", "libp2p-swarm": "~0.26.19", - "mafmt": "^2.1.6", - "multiaddr": "^2.2.2", + "multiaddr": "^2.2.3", "peer-book": "~0.3.1", "peer-id": "~0.8.4", "peer-info": "~0.8.4" @@ -55,4 +54,4 @@ "greenkeeperio-bot ", "mayerwin " ] -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js index 47984055..8aab1da8 100644 --- a/src/index.js +++ b/src/index.js @@ -5,8 +5,7 @@ const PeerId = require('peer-id') const PeerInfo = require('peer-info') const PeerBook = require('peer-book') const multiaddr = require('multiaddr') -const mafmt = require('mafmt') -const EE = require('events').EventEmitter +const EventEmitter = require('events').EventEmitter const assert = require('assert') const Ping = require('libp2p-ping') const setImmediate = require('async/setImmediate') @@ -14,10 +13,10 @@ const setImmediate = require('async/setImmediate') exports = module.exports const OFFLINE_ERROR_MESSAGE = 'The libp2p node is not started yet' -const IPFS_CODE = 421 -class Node { +class Node extends EventEmitter { constructor (_modules, _peerInfo, _peerBook, _options) { + super() assert(_modules, 'requires modules to equip libp2p with features') assert(_peerInfo, 'requires a PeerInfo instance') @@ -26,8 +25,6 @@ class Node { this.peerBook = _peerBook || new PeerBook() this.isOnline = false - this.discovery = new EE() - this.swarm = new Swarm(this.peerInfo) // Attach stream multiplexers @@ -66,9 +63,7 @@ class Node { let discoveries = this.modules.discovery discoveries = Array.isArray(discoveries) ? discoveries : [discoveries] discoveries.forEach((discovery) => { - discovery.on('peer', (peerInfo) => { - this.discovery.emit('peer', peerInfo) - }) + discovery.on('peer', (peerInfo) => this.emit('peer', peerInfo)) }) } @@ -142,88 +137,26 @@ class Node { this.swarm.close(callback) } - // - // Ping - // - - // TODO - pingById (id, callback) { - assert(this.isOnline, OFFLINE_ERROR_MESSAGE) - callback(new Error('not implemented yet')) + isOn () { + return this.isOnline } - // TODO - pingByMultiaddr (maddr, callback) { - assert(this.isOnline, OFFLINE_ERROR_MESSAGE) - callback(new Error('not implemented yet')) - } - - pingByPeerInfo (peerInfo, callback) { - assert(this.isOnline, OFFLINE_ERROR_MESSAGE) + ping (peer, callback) { + assert(this.isOn, OFFLINE_ERROR_MESSAGE) + const peerInfo = this._getPeerInfo(peer) callback(null, new Ping(this.swarm, peerInfo)) } - // - // Dialing methods - // - - // TODO - dialById (id, protocol, callback) { - // NOTE: dialById only works if a previous dial was made. This will - // change once we have PeerRouting - + dial (peer, protocol, callback) { assert(this.isOnline, OFFLINE_ERROR_MESSAGE) + const peerInfo = this._getPeerInfo(peer) if (typeof protocol === 'function') { callback = protocol protocol = undefined } - callback(new Error('not implemented yet')) - } - - dialByMultiaddr (maddr, protocol, callback) { - assert(this.isOnline, OFFLINE_ERROR_MESSAGE) - - if (typeof protocol === 'function') { - callback = protocol - protocol = undefined - } - - if (typeof maddr === 'string') { - maddr = multiaddr(maddr) - } - - if (!mafmt.IPFS.matches(maddr.toString())) { - return callback(new Error('multiaddr not valid')) - } - - const ipfsIdB58String = maddr.stringTuples().filter((tuple) => { - if (tuple[0] === IPFS_CODE) { - return true - } - })[0][1] - - let peer - try { - peer = this.peerBook.getByB58String(ipfsIdB58String) - } catch (err) { - peer = new PeerInfo(PeerId.createFromB58String(ipfsIdB58String)) - } - - peer.multiaddr.add(maddr) - this.dialByPeerInfo(peer, protocol, callback) - } - - dialByPeerInfo (peer, protocol, callback) { - assert(this.isOnline, OFFLINE_ERROR_MESSAGE) - - if (typeof protocol === 'function') { - callback = protocol - protocol = undefined - } - - this.swarm.dial(peer, protocol, (err, conn) => { + this.swarm.dial(peerInfo, protocol, (err, conn) => { if (err) { return callback(err) } @@ -232,52 +165,14 @@ class Node { }) } - // - // Disconnecting (hangUp) methods - // - - hangUpById (id, callback) { - // TODO - callback(new Error('not implemented yet')) - } - - hangUpByMultiaddr (maddr, callback) { + hangUp (peer, callback) { assert(this.isOnline, OFFLINE_ERROR_MESSAGE) + const peerInfo = this._getPeerInfo(peer) - if (typeof maddr === 'string') { - maddr = multiaddr(maddr) - } - - if (!mafmt.IPFS.matches(maddr.toString())) { - return callback(new Error('multiaddr not valid')) - } - - const ipfsIdB58String = maddr.stringTuples().filter((tuple) => { - if (tuple[0] === IPFS_CODE) { - return true - } - })[0][1] - - try { - const pi = this.peerBook.getByB58String(ipfsIdB58String) - this.hangUpByPeerInfo(pi, callback) - } catch (err) { - // already disconnected - callback() - } - } - - hangUpByPeerInfo (peer, callback) { - assert(this.isOnline, OFFLINE_ERROR_MESSAGE) - - this.peerBook.removeByB58String(peer.id.toB58String()) + this.peerBook.removeByB58String(peerInfo.id.toB58String()) this.swarm.hangUp(peer, callback) } - // - // Protocol multiplexing handling - // - handle (protocol, handlerFunc, matchFunc) { this.swarm.handle(protocol, handlerFunc, matchFunc) } @@ -285,6 +180,37 @@ class Node { unhandle (protocol) { this.swarm.unhandle(protocol) } + + /* + * Helper method to check the data type of peer and convert it to PeerInfo + */ + _getPeerInfo (peer) { + let p + switch (peer) { + case PeerInfo.isPeerInfo(peer): p = peer; break + case multiaddr.isMultiaddr(peer): { + const peerIdB58Str = multiaddr.getPeerId(peer) + try { + p = this.peerBook.getByB58String(peerIdB58Str) + } catch (err) { + p = new PeerInfo(PeerId.createFromB58String(peerIdB58Str)) + } + p.multiaddr.add(peer) + } break + case PeerId.isPeerId(peer): { + const peerIdB58Str = peer.toB58String() + try { + p = this.peerBook.getByB58String(peerIdB58Str) + } catch (err) { + // TODO this is where PeerRouting comes into place + throw new Error('No knowledge about: ' + peerIdB58Str) + } + } break + default: throw new Error('Peer type not recognized') + } + + return p + } } module.exports = Node From 2c23d9a718158c786bd2a7a61509f1e74dd02812 Mon Sep 17 00:00:00 2001 From: David Dias Date: Mon, 27 Mar 2017 14:42:05 +0100 Subject: [PATCH 5/6] fix: last touches --- package.json | 4 ++-- src/index.js | 45 ++++++++++++++++++++++----------------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index ec4696d5..43f0bc60 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "libp2p-swarm": "~0.26.19", "multiaddr": "^2.2.3", "peer-book": "~0.3.1", - "peer-id": "~0.8.4", - "peer-info": "~0.8.4" + "peer-id": "~0.8.5", + "peer-info": "~0.8.5" }, "contributors": [ "David Dias ", diff --git a/src/index.js b/src/index.js index 8aab1da8..27ad69d4 100644 --- a/src/index.js +++ b/src/index.js @@ -160,7 +160,7 @@ class Node extends EventEmitter { if (err) { return callback(err) } - this.peerBook.put(peer) + this.peerBook.put(peerInfo) callback(null, conn) }) } @@ -170,7 +170,7 @@ class Node extends EventEmitter { const peerInfo = this._getPeerInfo(peer) this.peerBook.removeByB58String(peerInfo.id.toB58String()) - this.swarm.hangUp(peer, callback) + this.swarm.hangUp(peerInfo, callback) } handle (protocol, handlerFunc, matchFunc) { @@ -186,27 +186,26 @@ class Node extends EventEmitter { */ _getPeerInfo (peer) { let p - switch (peer) { - case PeerInfo.isPeerInfo(peer): p = peer; break - case multiaddr.isMultiaddr(peer): { - const peerIdB58Str = multiaddr.getPeerId(peer) - try { - p = this.peerBook.getByB58String(peerIdB58Str) - } catch (err) { - p = new PeerInfo(PeerId.createFromB58String(peerIdB58Str)) - } - p.multiaddr.add(peer) - } break - case PeerId.isPeerId(peer): { - const peerIdB58Str = peer.toB58String() - try { - p = this.peerBook.getByB58String(peerIdB58Str) - } catch (err) { - // TODO this is where PeerRouting comes into place - throw new Error('No knowledge about: ' + peerIdB58Str) - } - } break - default: throw new Error('Peer type not recognized') + if (PeerInfo.isPeerInfo(peer)) { + p = peer + } else if (multiaddr.isMultiaddr(peer)) { + const peerIdB58Str = peer.getPeerId() + try { + p = this.peerBook.getByB58String(peerIdB58Str) + } catch (err) { + p = new PeerInfo(PeerId.createFromB58String(peerIdB58Str)) + } + p.multiaddr.add(peer) + } else if (PeerId.isPeerId(peer)) { + const peerIdB58Str = peer.toB58String() + try { + p = this.peerBook.getByB58String(peerIdB58Str) + } catch (err) { + // TODO this is where PeerRouting comes into place + throw new Error('No knowledge about: ' + peerIdB58Str) + } + } else { + throw new Error('peer type not recognized') } return p From d27bd2b912d630fa0a475a2ddc70cb5ee884278a Mon Sep 17 00:00:00 2001 From: David Dias Date: Mon, 27 Mar 2017 15:43:08 +0100 Subject: [PATCH 6/6] cr --- src/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index 27ad69d4..3719d9e7 100644 --- a/src/index.js +++ b/src/index.js @@ -142,13 +142,13 @@ class Node extends EventEmitter { } ping (peer, callback) { - assert(this.isOn, OFFLINE_ERROR_MESSAGE) + assert(this.isOn(), OFFLINE_ERROR_MESSAGE) const peerInfo = this._getPeerInfo(peer) callback(null, new Ping(this.swarm, peerInfo)) } dial (peer, protocol, callback) { - assert(this.isOnline, OFFLINE_ERROR_MESSAGE) + assert(this.isOn(), OFFLINE_ERROR_MESSAGE) const peerInfo = this._getPeerInfo(peer) if (typeof protocol === 'function') { @@ -166,7 +166,7 @@ class Node extends EventEmitter { } hangUp (peer, callback) { - assert(this.isOnline, OFFLINE_ERROR_MESSAGE) + assert(this.isOn(), OFFLINE_ERROR_MESSAGE) const peerInfo = this._getPeerInfo(peer) this.peerBook.removeByB58String(peerInfo.id.toB58String())