Skip to content
This repository has been archived by the owner on Apr 29, 2020. It is now read-only.

WIP: Use the base class #41

Merged
merged 5 commits into from
Nov 28, 2016
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
12 changes: 2 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ libp2p-ipfs
![](https://img.shields.io/badge/npm-%3E%3D3.0.0-orange.svg?style=flat-square)
![](https://img.shields.io/badge/Node.js-%3E%3D4.0.0-orange.svg?style=flat-square)

> libp2p build (module) used in js-ipfs
> libp2p bundle (module) used in js-ipfs when run in Node.js

This libp2p build has support for:

Expand Down Expand Up @@ -45,21 +45,13 @@ This libp2p build has support for:
### Use in Node.js

```js
const lip2p = require('libp2p-ipfs')
const Node = require('libp2p-ipfs')
```

## Usage

## API

## Examples

- Start two libp2p Nodes (create and make them listen)
- Set up a handler for a protocol (through multistream)
- Dial from one Node to the other using just one transport (TCP or uTP, and without SPDY or Yamux)
- Dial from one Node to the other using one transport and one Stream Multiplexer
- Dial from one Node to the other having set up secio

## Contribute

Feel free to join in. All welcome. Open an [issue](https://github.com/ipfs/js-libp2p-ipfs/issues)!
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"pull-stream": "^3.5.0"
},
"dependencies": {
"libp2p": "^0.2.1",
"libp2p-secio": "^0.6.3",
"libp2p-spdy": "^0.10.0",
"libp2p-swarm": "^0.26.3",
Expand Down
215 changes: 22 additions & 193 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,202 +1,31 @@
'use strict'

const Swarm = require('libp2p-swarm')
const TCP = require('libp2p-tcp')
// const UTP = require('libp2p-utp')
const WS = require('libp2p-websockets')
const spdy = require('libp2p-spdy')
const secio = require('libp2p-secio')
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

exports = module.exports

const OFFLINE_ERROR_MESSAGE = 'The libp2p node is not started yet'
const IPFS_CODE = 421

exports.Node = function Node (pInfo, pBook) {
if (!(this instanceof Node)) {
return new Node(pInfo, pBook)
}

if (!pInfo) {
throw new Error('missing peer info')
}

if (!pBook) {
pBook = new PeerBook()
}

this.peerInfo = pInfo
this.peerBook = pBook

// Swarm
this.swarm = new Swarm(pInfo)
this.swarm.connection.addStreamMuxer(spdy)
this.swarm.connection.reuse()

this.swarm.connection.crypto(secio.tag, secio.encrypt)

this.swarm.on('peer-mux-established', (peerInfo) => {
this.peerBook.put(peerInfo)
})

this.swarm.on('peer-mux-closed', (peerInfo) => {
this.peerBook.removeByB58String(peerInfo.id.toB58String())
})

let isOnline = false

this.start = (callback) => {
const ws = new WS()
const tcp = new TCP()

// Do not activate the dialer if no listener is going to be present
if (ws.filter(this.peerInfo.multiaddrs).length > 0) {
this.swarm.transport.add('ws', new WS())
}
if (tcp.filter(this.peerInfo.multiaddrs).length > 0) {
this.swarm.transport.add('tcp', new TCP())
}

this.swarm.listen((err) => {
if (err) {
return callback(err)
}

isOnline = true
callback()
})
}

this.stop = (callback) => {
isOnline = false
this.swarm.close(callback)
const libp2p = require('libp2p')

class Node extends libp2p.Node {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes inheritance is just awesome :)

constructor (peerInfo, peerBook) {
const modules = {
transport: [
new TCP(),
new WS()
],
connection: {
muxer: [
spdy
],
crypto: [
secio
]
},
discovery: []
}
super(modules, peerInfo, peerBook)
}

this.dialById = (id, protocol, callback) => {
if (typeof protocol === 'function') {
callback = protocol
protocol = undefined
}

if (!isOnline) {
return callback(new Error(OFFLINE_ERROR_MESSAGE))
}
// NOTE, these dialById only works if a previous dial
// was made until we have PeerRouting
// TODO support PeerRouting when it is Ready
callback(new Error('not implemented yet'))
}

this.dialByMultiaddr = (maddr, protocol, callback) => {
if (typeof protocol === 'function') {
callback = protocol
protocol = undefined
}

if (!isOnline) {
return callback(new Error(OFFLINE_ERROR_MESSAGE))
}

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)
}

this.dialByPeerInfo = (peer, protocol, callback) => {
if (typeof protocol === 'function') {
callback = protocol
protocol = undefined
}
if (!isOnline) {
return callback(new Error(OFFLINE_ERROR_MESSAGE))
}

this.swarm.dial(peer, protocol, (err, conn) => {
if (err) {
return callback(err)
}
this.peerBook.put(peer)
callback(null, conn)
})
}

this.hangUpById = (id, callback) => {
callback(new Error('not implemented yet'))
// TODO
}

this.hangUpByMultiaddr = (maddr, callback) => {
if (!isOnline) {
return callback(new Error(OFFLINE_ERROR_MESSAGE))
}

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()
}
}

this.hangUpByPeerInfo = (peer, callback) => {
if (!isOnline) {
return callback(new Error(OFFLINE_ERROR_MESSAGE))
}

this.peerBook.removeByB58String(peer.id.toB58String())
this.swarm.hangUp(peer, callback)
}

this.handle = (protocol, handlerFunc, matchFunc) => {
return this.swarm.handle(protocol, handlerFunc, matchFunc)
}

this.unhandle = (protocol) => {
return this.swarm.unhandle(protocol)
}

this.discovery = new EE()
this.routing = null
this.records = null
}

module.exports = Node
43 changes: 23 additions & 20 deletions test/libp2p.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* eslint-env mocha */

const expect = require('chai').expect
const libp2p = require('../src')
const Node = require('../src')
const PeerInfo = require('peer-info')
const multiaddr = require('multiaddr')
const parallel = require('async/parallel')
Expand Down Expand Up @@ -44,11 +44,11 @@ describe('libp2p-ipfs', () => {
info.multiaddr.add(multiaddr('/ip4/0.0.0.0/tcp/0'))
})

nodeA = new libp2p.Node(infos[0])
nodeB = new libp2p.Node(infos[1])
nodeC = new libp2p.Node(infos[2])
nodeD = new libp2p.Node(infos[3])
nodeE = new libp2p.Node(infos[4])
nodeA = new Node(infos[0])
nodeB = new Node(infos[1])
nodeC = new Node(infos[2])
nodeD = new Node(infos[3])
nodeE = new Node(infos[4])
const maddrWS1 = multiaddr('/ip4/127.0.0.1/tcp/25001/ws')
nodeE.peerInfo.multiaddr.add(maddrWS1)

Expand All @@ -61,7 +61,7 @@ describe('libp2p-ipfs', () => {
const maddrWS2 = multiaddr('/ip4/127.0.0.1/tcp/25002/ws')
pInfo.multiaddr.add(maddrWS2)

nodeF = new libp2p.Node(pInfo)
nodeF = new Node(pInfo)

nodeFMultiaddrWebSockets = multiaddr(
nodeF.peerInfo.multiaddrs[0].toString() +
Expand All @@ -74,12 +74,12 @@ describe('libp2p-ipfs', () => {

it('start 6 nodes', (done) => {
parallel([
nodeA.start,
nodeB.start,
nodeC.start,
nodeD.start,
nodeE.start,
nodeF.start
(cb) => nodeA.start(cb),
(cb) => nodeB.start(cb),
(cb) => nodeC.start(cb),
(cb) => nodeD.start(cb),
(cb) => nodeE.start(cb),
(cb) => nodeF.start(cb)
], (err) => {
expect(err).to.not.exist
expect(nodeA.peerInfo.multiaddrs.length > 1).to.equal(true)
Expand Down Expand Up @@ -344,7 +344,9 @@ describe('libp2p-ipfs', () => {
})
})

it('nodeA fails to dial to nodeF', (done) => {
// Until https://github.com/libp2p/js-libp2p/issues/46 is resolved
// Everynode will be able to dial in WebSockets
it.skip('nodeA fails to dial to nodeF', (done) => {
nodeA.dialByMultiaddr(nodeFMultiaddrWebSockets, (err) => {
expect(err).to.exist
const peers = nodeA.peerBook.getAll()
Expand Down Expand Up @@ -388,6 +390,7 @@ describe('libp2p-ipfs', () => {
nodeA.dialByMultiaddr(maddr, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist
const peers = nodeA.peerBook.getAll()

expect(Object.keys(peers)).to.have.length(4)

pull(
Expand Down Expand Up @@ -416,12 +419,12 @@ describe('libp2p-ipfs', () => {

it('stop', (done) => {
parallel([
nodeA.stop,
nodeB.stop,
nodeC.stop,
nodeD.stop,
nodeE.stop,
nodeF.stop
(cb) => nodeA.stop(cb),
(cb) => nodeB.stop(cb),
(cb) => nodeC.stop(cb),
(cb) => nodeD.stop(cb),
(cb) => nodeE.stop(cb),
(cb) => nodeF.stop(cb)
], done)
})
})
4 changes: 2 additions & 2 deletions test/spawn-libp2p-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

'use strict'

const libp2p = require('../src')
const Node = require('../src')
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const multiaddr = require('multiaddr')
Expand All @@ -19,7 +19,7 @@ PeerId.createFromJSON(idBak, (err, id) => {

pInfo.multiaddr.add(maddr)

const node = new libp2p.Node(pInfo)
const node = new Node(pInfo)

node.handle('/echo/1.0.0', (protocol, conn) => {
pull(conn, conn)
Expand Down
3 changes: 0 additions & 3 deletions test/stress.spec.js

This file was deleted.