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

Commit

Permalink
level up libp2p interface and error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddias committed May 29, 2016
1 parent 6e2c06a commit 7f0a0db
Show file tree
Hide file tree
Showing 6 changed files with 368 additions and 103 deletions.
4 changes: 2 additions & 2 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ gulp.task('libnode:start', (done) => {

node = new Node(peer)
node.start(() => {
node.swarm.handle('/echo/1.0.0', (conn) => {
node.handle('/echo/1.0.0', (conn) => {
conn.pipe(conn)
})
ready()
Expand All @@ -34,7 +34,7 @@ gulp.task('libnode:start', (done) => {

gulp.task('libnode:stop', (done) => {
setTimeout(() => {
node.swarm.close((err) => {
node.stop((err) => {
if (err) {
throw err
}
Expand Down
13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"bl": "^1.1.2",
"chai": "^3.5.0",
"gulp": "^3.9.1",
"libp2p-ipfs": "^0.9.0",
"libp2p-ipfs": "^0.10.0",
"peer-id": "^0.7.0",
"pre-commit": "^1.1.3",
"run-parallel": "^1.1.6",
Expand All @@ -44,15 +44,18 @@
"dependencies": {
"babel-runtime": "^6.9.0",
"libp2p-spdy": "^0.6.1",
"libp2p-swarm": "^0.19.0",
"libp2p-webrtc-star": "^0.2.0",
"libp2p-websockets": "^0.6.0",
"libp2p-swarm": "^0.19.4",
"libp2p-webrtc-star": "^0.2.1",
"libp2p-websockets": "^0.6.1",
"mafmt": "^2.1.1",
"multiaddr": "^2.0.2",
"peer-book": "^0.3.0",
"peer-id": "^0.7.0",
"peer-info": "^0.7.0"
},
"contributors": [
"David Dias <daviddias.p@gmail.com>",
"dignifiedquire <dignifiedquire@gmail.com>",
"greenkeeperio-bot <support@greenkeeper.io>"
]
}
}
167 changes: 156 additions & 11 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,57 @@

const Swarm = require('libp2p-swarm')
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const WS = require('libp2p-websockets')
const WebRTCStar = require('libp2p-webrtc-star')
const spdy = require('libp2p-spdy')
const EE = require('events').EventEmitter
const multiaddr = require('multiaddr')
const PeerBook = require('peer-book')
const mafmt = require('mafmt')

exports = module.exports

exports.Node = function Node (peerInfo) {
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(peerInfo)
return new Node(pInfo, pBook)
}

if (!pInfo) {
pInfo = new PeerInfo()
pInfo.multiaddr.add(multiaddr('/ip4/0.0.0.0/tcp/0'))
}
if (!peerInfo) {
peerInfo = new PeerInfo()

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

this.peerInfo = peerInfo
this.peerInfo = pInfo
this.peerBook = pBook

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

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) => {
// if we have `webrtc-star` addrs, then add
// the WebRTCStar transport
const wstar = new WebRTCStar()
if (wstar.filter(peerInfo.multiaddrs).length > 0) {
if (wstar.filter(this.peerInfo.multiaddrs).length > 0) {
this.swarm.transport.add('wstar', wstar)
wstar.discovery.on('peer', (peerInfo) => {
this.discovery.emit('peer', peerInfo)
Expand All @@ -40,20 +64,141 @@ exports.Node = function Node (peerInfo) {
// WebSockets needs to be added after because
// it can't have a listener on the browser
this.swarm.transport.add('ws', new WS())
isOnline = true
callback()
})
} else {
// if just WebSockets, no thing to listen
this.swarm.transport.add('ws', new WS())
isOnline = true
callback()
}
}

this.stop = (callback) => {
isOnline = false
this.swarm.close(callback)
}

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, handler) => {
return this.swarm.handle(protocol, handler)
}

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

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

this.dial = () => {
throw new Error('THIS WILL BE EQUIVALENT TO THE ROUTED HOST FEATURE, IT WILL FIGURE OUT EVERYTHING :D')
}
}
4 changes: 3 additions & 1 deletion test/peer.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{
"privKey": "CAASQDA+AgEAAgkAiZMWorfx3pkCAwEAAQIIbl57fDLjyaUCBQDi+1JLAgUAmymkKwIEKc9xkQIFAIoy+KkCBHBfslE="
"id": "Qmex1SSsueWFsUfjdkugJ5zhcnjddAt8TxcnDLUXKD9Sx7",
"privKey": "CAASqAkwggSkAgEAAoIBAQCXzV127CvVHOGMzvsn/U+/32JM58KA6k0FSCCeNFzNowiDS/vV5eezGN5AFoxsF6icWLoaczz7l9RdVD+I/t6PEt9X7XUdrDCtSS8WmAcCgvZWSSf7yAd3jT4GSZDUIgIEeRZsERDt/yVqTLwsZ1G9dMIeh8sbf2zwjTXZIWaRM6o4lq3DYFfzLvJUXlJodxPogU7l7nLkITPUv+yQAMcVHizbNwJvwiETKYeUj73/m/wEPAlnFESexDstxNiIwE/FH8Ao50QPZRO6E6Jb0hhYSI/4CLRdrzDFm/Vzplei3Wr2DokSROaNyeG37VAueyA+pDqn84um+L9uXLwbv5FbAgMBAAECggEAdBUzV/GaQ0nmoQrWvOnUxmFIho7kCjkh1NwnNVPNc+Msa1r7pcI9wJNPwap8j1w4L/cZuYhOJgcg+o2mWFiuULKZ4F9Ro/M89gZ038457g2/2pPu43c/Xoi/2YcAHXg0Gr+OCe2zCIyITBWKAFqyAzL6DubAxrJW2Ezj1LrZ+EZgMyzbh/go/eEGSJaaGkINeAkY144DqDWWWvzyhKhryipsGkZGEkVy9xJgMEI3ipVvuPez2XAvoyyeuinBBLe+Z2vY5G50XXzbIMhIQGLncHf9MwTv6wt1ilyOSLOXK0BoQbB76J3R3is5dSULXXP9r8VocjLBEkmBuf4FXAKzoQKBgQDNNS4F1XE1gxD8LPkL+aB/hi6eVHVPhr+w0I/9ATikcLGeUfBM2Gd6cZRPFtNVrv1p6ZF1D1UyGDknGbDBSQd9wLUgb0fDoo3jKYMGWq6G+VvaP5rzWQeBV8YV2EhSmUk1i6kiYe2ZE8WyrPie7iwpQIY60e2A8Ly0GKZiBZUcHQKBgQC9YDAVsGnEHFVFkTDpvw5HwEzCgTb2A3NgkGY3rTYZ7L6AFjqCYmUwFB8Fmbyc4kdFWNh8wfmq5Qrvl49NtaeukiqWKUUlB8uPdztB1P0IahA2ks0owStZlRifmwfgYyMd4xE17lhaOgQQJZZPxmP0F6mdOvb3YJafNURCdMS51wKBgEvvIM+h0tmFXXSjQ6kNvzlRMtD92ccKysYn9xAdMpOO6/r0wSH+dhQWEVZO0PcE4NsfReb2PIVj90ojtIdhebcr5xpQc1LORQjJJKXmSmzBux6AqNrhl+hhzXfp56FA/Zkly/lgGWaqrV5XqUxOP+Mn8EO1yNgMvRc7g94DyNB1AoGBAKLBuXHalXwDsdHBUB2Eo3xNLGt6bEcRfia+0+sEBdxQGQWylQScFkU09dh1YaIf44sZKa5HdBFJGpYCVxo9hmjFnK5Dt/Z0daHOonIY4INLzLVqg8KECoLKXkhGEIXsDjFQhukn+G1LMVTDSSU055DQiWjlVX4UWD9qo0jOXIkvAoGBAMP50p2X6PsWWZUuuR7i1JOJHRyQZPWdHh9p8SSLnCtEpHYZfJr4INXNmhnSiB/3TUnHix2vVKjosjMTCk/CjfzXV2H41WPOLZ2/Pi3SxCicWIRj4kCcWhkEuIF2jGkg1+jmNiCl/zNMaBOAIP3QbDPtqOWbYlPd2YIzdj6WQ6R4",
"pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXzV127CvVHOGMzvsn/U+/32JM58KA6k0FSCCeNFzNowiDS/vV5eezGN5AFoxsF6icWLoaczz7l9RdVD+I/t6PEt9X7XUdrDCtSS8WmAcCgvZWSSf7yAd3jT4GSZDUIgIEeRZsERDt/yVqTLwsZ1G9dMIeh8sbf2zwjTXZIWaRM6o4lq3DYFfzLvJUXlJodxPogU7l7nLkITPUv+yQAMcVHizbNwJvwiETKYeUj73/m/wEPAlnFESexDstxNiIwE/FH8Ao50QPZRO6E6Jb0hhYSI/4CLRdrzDFm/Vzplei3Wr2DokSROaNyeG37VAueyA+pDqn84um+L9uXLwbv5FbAgMBAAE="
}
51 changes: 38 additions & 13 deletions test/webrtc-star-only.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const bl = require('bl')
const libp2p = require('../src')

describe('libp2p-ipfs-browser (webrtc only)', function () {
this.timeout(60 * 1000)
this.timeout(15 * 1000)

let peer1
let peer2
Expand Down Expand Up @@ -46,23 +46,48 @@ describe('libp2p-ipfs-browser (webrtc only)', function () {
})

it('handle a protocol on the first node', (done) => {
node2.swarm.handle('/echo/1.0.0', (conn) => {
node2.handle('/echo/1.0.0', (conn) => {
conn.pipe(conn)
})
done()
})

it('dial from the second node to the first node', (done) => {
node1.swarm.dial(peer2, '/echo/1.0.0', (err, conn) => {
const text = 'hello'
node1.dialByPeerInfo(peer2, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist
conn.pipe(bl((err, data) => {
setTimeout(check, 500)

function check () {
const text = 'hello'
const peers1 = node1.peerBook.getAll()
expect(err).to.not.exist
expect(Object.keys(peers1)).to.have.length(1)
const peers2 = node2.peerBook.getAll()
expect(err).to.not.exist
expect(Object.keys(peers2)).to.have.length(1)
conn.pipe(bl((err, data) => {
expect(err).to.not.exist
expect(data.toString()).to.equal(text)
done()
}))
conn.write(text)
conn.end()
}
})
})

it('node1 hangUp node2', (done) => {
node1.hangUpByPeerInfo(peer2, (err) => {
expect(err).to.not.exist
setTimeout(check, 500)

function check () {
const peers = node1.peerBook.getAll()
expect(err).to.not.exist
expect(data.toString()).to.equal(text)
expect(Object.keys(peers)).to.have.length(0)
expect(Object.keys(node1.swarm.muxedConns)).to.have.length(0)
done()
}))
conn.write(text)
conn.end()
}
})
})

Expand All @@ -73,17 +98,17 @@ describe('libp2p-ipfs-browser (webrtc only)', function () {
peer3.multiaddr.add(mh3)

node1.discovery.on('peer', (peerInfo) => {
node1.swarm.dial(peerInfo)
node1.dialByPeerInfo(peerInfo, () => {})
})
node2.discovery.on('peer', (peerInfo) => {
node2.swarm.dial(peerInfo)
node2.dialByPeerInfo(peerInfo, () => {})
})

const node3 = new libp2p.Node(peer3)
node3.start(() => {
setTimeout(() => {
expect(Object.keys(node1.swarm.muxedConns).length).to.equal(2)
expect(Object.keys(node2.swarm.muxedConns).length).to.equal(2)
expect(Object.keys(node1.swarm.muxedConns).length).to.equal(1)
expect(Object.keys(node2.swarm.muxedConns).length).to.equal(1)
done()
}, 2000)
})
Expand Down
Loading

0 comments on commit 7f0a0db

Please sign in to comment.