mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-05-02 14:02:14 +00:00
internal transport interface + libp2p-tcp tests
This commit is contained in:
parent
1fd6a3885d
commit
c8f2fdd077
13
README.md
13
README.md
@ -18,18 +18,23 @@ libp2p-swarm is used by libp2p but it can be also used as a standalone module.
|
||||
libp2p-swarm is available on npm and so, like any other npm module, just:
|
||||
|
||||
```bash
|
||||
$ npm install libp2p-swarm --save
|
||||
> npm install libp2p-swarm --save
|
||||
```
|
||||
|
||||
And use it in your Node.js code as:
|
||||
|
||||
```JavaScript
|
||||
var Swarm = require('libp2p-swarm')
|
||||
const Swarm = require('libp2p-swarm')
|
||||
|
||||
var sw = new Swarm(peerInfoSelf)
|
||||
const sw = new Swarm(peerInfo)
|
||||
```
|
||||
|
||||
peerInfoSelf is a [PeerInfo](https://github.com/diasdavid/js-peer-info) object that represents the peer creating this swarm instance.
|
||||
peerInfo is a [PeerInfo](https://github.com/diasdavid/js-peer-info) object that represents the peer creating this swarm instance.
|
||||
|
||||
|
||||
----------
|
||||
BELOW NEEDS AN UPDATE
|
||||
|
||||
|
||||
### Support a transport
|
||||
|
||||
|
14
package.json
14
package.json
@ -26,28 +26,26 @@
|
||||
"test"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^4.0.0"
|
||||
"node": "^4.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bl": "^1.1.2",
|
||||
"chai": "^3.5.0",
|
||||
"istanbul": "^0.4.2",
|
||||
"libp2p-spdy": "^0.1.0",
|
||||
"libp2p-tcp": "^0.1.1",
|
||||
"libp2p-tcp": "^0.2.1",
|
||||
"mocha": "^2.4.5",
|
||||
"multiaddr": "^1.1.1",
|
||||
"peer-id": "^0.5.1",
|
||||
"peer-info": "^0.5.2",
|
||||
"pre-commit": "^1.1.2",
|
||||
"sinon": "^1.15.4",
|
||||
"standard": "^6.0.7",
|
||||
"stream-pair": "^1.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^1.3.0",
|
||||
"ip-address": "^5.0.2",
|
||||
"ipfs-logger": "^0.1.0",
|
||||
"multiaddr": "^1.0.0",
|
||||
"multiplex-stream-muxer": "^0.2.0",
|
||||
"multistream-select": "^0.6.1",
|
||||
"peer-id": "^0.3.3",
|
||||
"peer-info": "^0.3.2",
|
||||
"protocol-buffers-stream": "^1.2.0"
|
||||
}
|
||||
}
|
||||
|
162
src/index.js
162
src/index.js
@ -1,14 +1,161 @@
|
||||
var multistream = require('multistream-select')
|
||||
var async = require('async')
|
||||
var identify = require('./identify')
|
||||
// const multistream = require('multistream-select')
|
||||
// const async = require('async')
|
||||
// const identify = require('./identify')
|
||||
const PassThrough = require('stream').PassThrough
|
||||
|
||||
exports = module.exports = Swarm
|
||||
|
||||
function Swarm (peerInfo) {
|
||||
var self = this
|
||||
if (!(this instanceof Swarm)) {
|
||||
return new Swarm(peerInfo)
|
||||
}
|
||||
|
||||
if (!(self instanceof Swarm)) {
|
||||
throw new Error('Swarm must be called with new')
|
||||
if (!peerInfo) {
|
||||
throw new Error('You must provide a value for `peerInfo`')
|
||||
}
|
||||
|
||||
// transports --
|
||||
|
||||
// { key: transport }; e.g { tcp: <tcp> }
|
||||
this.transports = {}
|
||||
|
||||
this.transport = {}
|
||||
|
||||
this.transport.add = (key, transport, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
if (!callback) { callback = noop }
|
||||
|
||||
if (this.transports[key]) {
|
||||
throw new Error('There is already a transport with this key')
|
||||
}
|
||||
this.transports[key] = transport
|
||||
callback()
|
||||
}
|
||||
|
||||
this.transport.dial = (key, multiaddrs, callback) => {
|
||||
const t = this.transports[key]
|
||||
|
||||
// a) if multiaddrs.length = 1, return the conn from the
|
||||
// transport, otherwise, create a passthrough
|
||||
if (!Array.isArray(multiaddrs)) {
|
||||
multiaddrs = [multiaddrs]
|
||||
}
|
||||
if (multiaddrs.length === 1) {
|
||||
const conn = t.dial(multiaddrs.shift(), {ready: () => {
|
||||
const cb = callback
|
||||
callback = noop // this is done to avoid connection drops as connect errors
|
||||
cb(null, conn)
|
||||
}})
|
||||
conn.once('error', () => {
|
||||
callback(new Error('failed to connect to every multiaddr'))
|
||||
})
|
||||
return conn
|
||||
}
|
||||
|
||||
// b) multiaddrs should already be a filtered list
|
||||
// specific for the transport we are using
|
||||
const pt = new PassThrough()
|
||||
|
||||
next(multiaddrs.shift())
|
||||
return pt
|
||||
function next (multiaddr) {
|
||||
const conn = t.dial(multiaddr, {ready: () => {
|
||||
pt.pipe(conn).pipe(pt)
|
||||
const cb = callback
|
||||
callback = noop // this is done to avoid connection drops as connect errors
|
||||
cb(null, pt)
|
||||
}})
|
||||
|
||||
conn.once('error', () => {
|
||||
if (multiaddrs.length === 0) {
|
||||
return callback(new Error('failed to connect to every multiaddr'))
|
||||
}
|
||||
next(multiaddrs.shift())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.transport.listen = (key, options, handler, callback) => {
|
||||
// if no callback is passed, we pass conns to connHandler
|
||||
if (!handler) { handler = connHandler }
|
||||
|
||||
const multiaddrs = peerInfo.multiaddrs.filter((m) => {
|
||||
if (m.toString().indexOf('tcp') !== -1) {
|
||||
return m
|
||||
}
|
||||
})
|
||||
|
||||
this.transports[key].createListener(multiaddrs, handler, (err, maUpdate) => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
if (maUpdate) {
|
||||
// because we can listen on port 0...
|
||||
peerInfo.multiaddr.replace(multiaddrs, maUpdate)
|
||||
}
|
||||
|
||||
callback()
|
||||
})
|
||||
}
|
||||
|
||||
this.transport.close = (key, callback) => {
|
||||
this.transports[key].close(callback)
|
||||
}
|
||||
|
||||
// connections --
|
||||
|
||||
// { peerIdB58: { conn: <conn> }}
|
||||
this.conns = {}
|
||||
|
||||
// {
|
||||
// peerIdB58: {
|
||||
// muxerName: {
|
||||
// muxer: <muxer>
|
||||
// rawSocket: socket // to abstract info required for the Identify Protocol
|
||||
// }
|
||||
// }
|
||||
this.muxedConns = {}
|
||||
|
||||
this.connection = {}
|
||||
this.connection.addUpgrade = () => {}
|
||||
this.connection.addStreamMuxer = () => {}
|
||||
|
||||
// enable the Identify protocol
|
||||
this.connection.reuse = () => {}
|
||||
|
||||
// main API - higher level abstractions --
|
||||
|
||||
this.dial = () => {
|
||||
// TODO
|
||||
}
|
||||
this.handle = (protocol, callback) => {
|
||||
// TODO
|
||||
}
|
||||
this.close = (callback) => {
|
||||
var count = 0
|
||||
|
||||
Object.keys(this.transports).forEach((key) => {
|
||||
this.transports[key].close(() => {
|
||||
if (++count === Object.keys(this.transports).length) {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function connHandler (conn) {
|
||||
// do all the multistream select handshakes (this should be probably done recursively
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
function Swarm (peerInfo) {
|
||||
var self = this
|
||||
if (!(this instanceof Swarm)) {
|
||||
return new Swarm(peerInfo)
|
||||
}
|
||||
|
||||
if (!peerInfo) {
|
||||
@ -341,3 +488,6 @@ function Swarm (peerInfo) {
|
||||
})
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
function noop () {}
|
||||
|
354
tests/swarm-old.js
Normal file
354
tests/swarm-old.js
Normal file
@ -0,0 +1,354 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
var async = require('async')
|
||||
var expect = require('chai').expect
|
||||
|
||||
var multiaddr = require('multiaddr')
|
||||
var Id = require('peer-id')
|
||||
var Peer = require('peer-info')
|
||||
var Swarm = require('../src')
|
||||
var tcp = require('libp2p-tcp')
|
||||
var Spdy = require('libp2p-spdy')
|
||||
|
||||
// because of Travis-CI
|
||||
process.on('uncaughtException', function (err) {
|
||||
console.log('Caught exception: ' + err)
|
||||
})
|
||||
|
||||
describe('Basics', function () {
|
||||
it('enforces creation with new', function (done) {
|
||||
expect(function () {
|
||||
Swarm()
|
||||
}).to.throw()
|
||||
done()
|
||||
})
|
||||
|
||||
it('it throws an exception without peerSelf', function (done) {
|
||||
expect(function () {
|
||||
var sw = new Swarm()
|
||||
sw.close()
|
||||
}).to.throw(Error)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
describe('When dialing', function () {
|
||||
describe('if the swarm does add any of the peer transports', function () {
|
||||
it('it returns an error', function (done) {
|
||||
var peerOne = new Peer(Id.create(), [multiaddr('/ip4/127.0.0.1/tcp/8090')])
|
||||
var peerTwo = new Peer(Id.create(), [multiaddr('/ip4/127.0.0.1/tcp/8091')])
|
||||
var swarm = new Swarm(peerOne)
|
||||
|
||||
swarm.dial(peerTwo, {}, function (err) {
|
||||
expect(err).to.exist
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Without a Stream Muxer', function () {
|
||||
describe('and one swarm over tcp', function () {
|
||||
it('add the transport', function (done) {
|
||||
var mh = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
var p = new Peer(Id.create(), [])
|
||||
var sw = new Swarm(p)
|
||||
|
||||
sw.addTransport('tcp', tcp, { multiaddr: mh }, {}, {port: 8010}, ready)
|
||||
|
||||
function ready () {
|
||||
expect(sw.transports['tcp'].options).to.deep.equal({})
|
||||
expect(sw.transports['tcp'].dialOptions).to.deep.equal({})
|
||||
expect(sw.transports['tcp'].listenOptions).to.deep.equal({port: 8010})
|
||||
expect(sw.transports['tcp'].transport).to.deep.equal(tcp)
|
||||
|
||||
sw.close(done)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('and two swarms over tcp', function () {
|
||||
var mh1, p1, sw1, mh2, p2, sw2
|
||||
|
||||
beforeEach(function (done) {
|
||||
mh1 = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
p1 = new Peer(Id.create(), [])
|
||||
sw1 = new Swarm(p1)
|
||||
|
||||
mh2 = multiaddr('/ip4/127.0.0.1/tcp/8020')
|
||||
p2 = new Peer(Id.create(), [])
|
||||
sw2 = new Swarm(p2)
|
||||
|
||||
async.parallel([
|
||||
function (cb) {
|
||||
sw1.addTransport('tcp', tcp, { multiaddr: mh1 }, {}, {port: 8010}, cb)
|
||||
},
|
||||
function (cb) {
|
||||
sw2.addTransport('tcp', tcp, { multiaddr: mh2 }, {}, {port: 8020}, cb)
|
||||
}
|
||||
], done)
|
||||
})
|
||||
|
||||
afterEach(function (done) {
|
||||
async.parallel([sw1.close, sw2.close], done)
|
||||
})
|
||||
|
||||
it('dial a conn', function (done) {
|
||||
sw1.dial(p2, {}, function (err) {
|
||||
expect(err).to.equal(undefined)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(1)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('dial a conn on a protocol', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
conn.end()
|
||||
conn.on('end', done)
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
|
||||
it('dial a protocol on a previous created conn', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
conn.end()
|
||||
conn.on('end', done)
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, function (err) {
|
||||
expect(err).to.equal(undefined)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(1)
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// it('add an upgrade', function (done) { done() })
|
||||
// it('dial a conn on top of a upgrade', function (done) { done() })
|
||||
// it('dial a conn on a protocol on top of a upgrade', function (done) { done() })
|
||||
})
|
||||
|
||||
/* TODO
|
||||
describe('udp', function () {
|
||||
it('add the transport', function (done) { done() })
|
||||
it('dial a conn', function (done) { done() })
|
||||
it('dial a conn on a protocol', function (done) { done() })
|
||||
it('add an upgrade', function (done) { done() })
|
||||
it('dial a conn on top of a upgrade', function (done) { done() })
|
||||
it('dial a conn on a protocol on top of a upgrade', function (done) { done() })
|
||||
}) */
|
||||
|
||||
/* TODO
|
||||
describe('udt', function () {
|
||||
it('add the transport', function (done) { done() })
|
||||
it('dial a conn', function (done) { done() })
|
||||
it('dial a conn on a protocol', function (done) { done() })
|
||||
it('add an upgrade', function (done) { done() })
|
||||
it('dial a conn on top of a upgrade', function (done) { done() })
|
||||
it('dial a conn on a protocol on top of a upgrade', function (done) { done() })
|
||||
}) */
|
||||
|
||||
/* TODO
|
||||
describe('utp', function () {
|
||||
it('add the transport', function (done) { done() })
|
||||
it('dial a conn', function (done) { done() })
|
||||
it('dial a conn on a protocol', function (done) { done() })
|
||||
it('add an upgrade', function (done) { done() })
|
||||
it('dial a conn on top of a upgrade', function (done) { done() })
|
||||
it('dial a conn on a protocol on top of a upgrade', function (done) { done() })
|
||||
}) */
|
||||
})
|
||||
|
||||
describe('With a SPDY Stream Muxer', function () {
|
||||
describe('and one swarm over tcp', function () {
|
||||
// TODO: What is the it here?
|
||||
it('add Stream Muxer', function (done) {
|
||||
// var mh = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
var p = new Peer(Id.create(), [])
|
||||
var sw = new Swarm(p)
|
||||
sw.addStreamMuxer('spdy', Spdy, {})
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
describe('and two swarms over tcp', function () {
|
||||
var mh1, p1, sw1, mh2, p2, sw2
|
||||
|
||||
beforeEach(function (done) {
|
||||
mh1 = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
p1 = new Peer(Id.create(), [])
|
||||
sw1 = new Swarm(p1)
|
||||
sw1.addStreamMuxer('spdy', Spdy, {})
|
||||
|
||||
mh2 = multiaddr('/ip4/127.0.0.1/tcp/8020')
|
||||
p2 = new Peer(Id.create(), [])
|
||||
sw2 = new Swarm(p2)
|
||||
sw2.addStreamMuxer('spdy', Spdy, {})
|
||||
|
||||
async.parallel([
|
||||
function (cb) {
|
||||
sw1.addTransport('tcp', tcp, { multiaddr: mh1 }, {}, {port: 8010}, cb)
|
||||
},
|
||||
function (cb) {
|
||||
sw2.addTransport('tcp', tcp, { multiaddr: mh2 }, {}, {port: 8020}, cb)
|
||||
}
|
||||
], done)
|
||||
})
|
||||
|
||||
function afterEach (done) {
|
||||
var cleaningCounter = 0
|
||||
sw1.closeConns(cleaningUp)
|
||||
sw2.closeConns(cleaningUp)
|
||||
|
||||
sw1.closeListener('tcp', cleaningUp)
|
||||
sw2.closeListener('tcp', cleaningUp)
|
||||
|
||||
function cleaningUp () {
|
||||
cleaningCounter++
|
||||
// TODO FIX: here should be 4, but because super wrapping of
|
||||
// streams, it makes it so hard to properly close the muxed
|
||||
// streams - https://github.com/indutny/spdy-transport/issues/14
|
||||
if (cleaningCounter < 3) {
|
||||
return
|
||||
}
|
||||
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
it('dial a conn on a protocol', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
// formallity so that the conn starts flowing
|
||||
conn.on('data', function (chunk) {})
|
||||
|
||||
conn.end()
|
||||
conn.on('end', function () {
|
||||
expect(Object.keys(sw1.muxedConns).length).to.equal(1)
|
||||
expect(Object.keys(sw2.muxedConns).length).to.equal(0)
|
||||
afterEach(done)
|
||||
})
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
conn.on('data', function () {})
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
|
||||
it('dial two conns (transport reuse)', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
// formality so that the conn starts flowing
|
||||
conn.on('data', function (chunk) {})
|
||||
|
||||
conn.end()
|
||||
conn.on('end', function () {
|
||||
expect(Object.keys(sw1.muxedConns).length).to.equal(1)
|
||||
expect(Object.keys(sw2.muxedConns).length).to.equal(0)
|
||||
|
||||
afterEach(done)
|
||||
})
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
// TODO Improve clarity
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
conn.on('data', function () {})
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
|
||||
conn.end()
|
||||
})
|
||||
|
||||
conn.on('data', function () {})
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('and two identity enabled swarms over tcp', function () {
|
||||
var mh1, p1, sw1, mh2, p2, sw2
|
||||
|
||||
beforeEach(function (done) {
|
||||
mh1 = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
p1 = new Peer(Id.create(), [])
|
||||
sw1 = new Swarm(p1)
|
||||
sw1.addStreamMuxer('spdy', Spdy, {})
|
||||
sw1.enableIdentify()
|
||||
|
||||
mh2 = multiaddr('/ip4/127.0.0.1/tcp/8020')
|
||||
p2 = new Peer(Id.create(), [])
|
||||
sw2 = new Swarm(p2)
|
||||
sw2.addStreamMuxer('spdy', Spdy, {})
|
||||
sw2.enableIdentify()
|
||||
|
||||
async.parallel([
|
||||
function (cb) {
|
||||
sw1.addTransport('tcp', tcp, { multiaddr: mh1 }, {}, {port: 8010}, cb)
|
||||
},
|
||||
function (cb) {
|
||||
sw2.addTransport('tcp', tcp, { multiaddr: mh2 }, {}, {port: 8020}, cb)
|
||||
}
|
||||
], done)
|
||||
})
|
||||
|
||||
afterEach(function (done) {
|
||||
var cleaningCounter = 0
|
||||
sw1.closeConns(cleaningUp)
|
||||
sw2.closeConns(cleaningUp)
|
||||
|
||||
sw1.closeListener('tcp', cleaningUp)
|
||||
sw2.closeListener('tcp', cleaningUp)
|
||||
|
||||
function cleaningUp () {
|
||||
cleaningCounter++
|
||||
// TODO FIX: here should be 4, but because super wrapping of
|
||||
// streams, it makes it so hard to properly close the muxed
|
||||
// streams - https://github.com/indutny/spdy-transport/issues/14
|
||||
if (cleaningCounter < 3) {
|
||||
return
|
||||
}
|
||||
// give time for identify to finish
|
||||
setTimeout(function () {
|
||||
expect(Object.keys(sw2.muxedConns).length).to.equal(1)
|
||||
done()
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
|
||||
it('identify', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
// formallity so that the conn starts flowing
|
||||
conn.on('data', function (chunk) {})
|
||||
|
||||
conn.end()
|
||||
conn.on('end', function () {
|
||||
expect(Object.keys(sw1.muxedConns).length).to.equal(1)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
conn.on('data', function () {})
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@ -1,354 +1,246 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
var async = require('async')
|
||||
var expect = require('chai').expect
|
||||
const expect = require('chai').expect
|
||||
// const async = require('async')
|
||||
|
||||
var multiaddr = require('multiaddr')
|
||||
var Id = require('peer-id')
|
||||
var Peer = require('peer-info')
|
||||
var Swarm = require('../src')
|
||||
var tcp = require('libp2p-tcp')
|
||||
var Spdy = require('libp2p-spdy')
|
||||
const multiaddr = require('multiaddr')
|
||||
// const Id = require('peer-id')
|
||||
const Peer = require('peer-info')
|
||||
const Swarm = require('../src')
|
||||
const TCP = require('libp2p-tcp')
|
||||
const bl = require('bl')
|
||||
// var SPDY = require('libp2p-spdy')
|
||||
|
||||
// because of Travis-CI
|
||||
process.on('uncaughtException', function (err) {
|
||||
console.log('Caught exception: ' + err)
|
||||
})
|
||||
|
||||
describe('Basics', function () {
|
||||
it('enforces creation with new', function (done) {
|
||||
expect(function () {
|
||||
Swarm()
|
||||
}).to.throw()
|
||||
done()
|
||||
})
|
||||
|
||||
it('it throws an exception without peerSelf', function (done) {
|
||||
expect(function () {
|
||||
var sw = new Swarm()
|
||||
sw.close()
|
||||
}).to.throw(Error)
|
||||
describe('basics', () => {
|
||||
it('throws on missing peerInfo', (done) => {
|
||||
expect(Swarm).to.throw(Error)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
describe('When dialing', function () {
|
||||
describe('if the swarm does add any of the peer transports', function () {
|
||||
it('it returns an error', function (done) {
|
||||
var peerOne = new Peer(Id.create(), [multiaddr('/ip4/127.0.0.1/tcp/8090')])
|
||||
var peerTwo = new Peer(Id.create(), [multiaddr('/ip4/127.0.0.1/tcp/8091')])
|
||||
var swarm = new Swarm(peerOne)
|
||||
describe('transport - tcp', function () {
|
||||
this.timeout(10000)
|
||||
|
||||
swarm.dial(peerTwo, {}, function (err) {
|
||||
expect(err).to.exist
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
var swarmA
|
||||
var swarmB
|
||||
var peerA = new Peer()
|
||||
var peerB = new Peer()
|
||||
|
||||
describe('Without a Stream Muxer', function () {
|
||||
describe('and one swarm over tcp', function () {
|
||||
it('add the transport', function (done) {
|
||||
var mh = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
var p = new Peer(Id.create(), [])
|
||||
var sw = new Swarm(p)
|
||||
|
||||
sw.addTransport('tcp', tcp, { multiaddr: mh }, {}, {port: 8010}, ready)
|
||||
|
||||
function ready () {
|
||||
expect(sw.transports['tcp'].options).to.deep.equal({})
|
||||
expect(sw.transports['tcp'].dialOptions).to.deep.equal({})
|
||||
expect(sw.transports['tcp'].listenOptions).to.deep.equal({port: 8010})
|
||||
expect(sw.transports['tcp'].transport).to.deep.equal(tcp)
|
||||
|
||||
sw.close(done)
|
||||
}
|
||||
})
|
||||
before((done) => {
|
||||
peerA.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9888'))
|
||||
peerB.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9999'))
|
||||
swarmA = new Swarm(peerA)
|
||||
swarmB = new Swarm(peerB)
|
||||
done()
|
||||
})
|
||||
|
||||
describe('and two swarms over tcp', function () {
|
||||
var mh1, p1, sw1, mh2, p2, sw2
|
||||
|
||||
beforeEach(function (done) {
|
||||
mh1 = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
p1 = new Peer(Id.create(), [])
|
||||
sw1 = new Swarm(p1)
|
||||
|
||||
mh2 = multiaddr('/ip4/127.0.0.1/tcp/8020')
|
||||
p2 = new Peer(Id.create(), [])
|
||||
sw2 = new Swarm(p2)
|
||||
|
||||
async.parallel([
|
||||
function (cb) {
|
||||
sw1.addTransport('tcp', tcp, { multiaddr: mh1 }, {}, {port: 8010}, cb)
|
||||
},
|
||||
function (cb) {
|
||||
sw2.addTransport('tcp', tcp, { multiaddr: mh2 }, {}, {port: 8020}, cb)
|
||||
}
|
||||
], done)
|
||||
})
|
||||
|
||||
afterEach(function (done) {
|
||||
async.parallel([sw1.close, sw2.close], done)
|
||||
})
|
||||
|
||||
it('dial a conn', function (done) {
|
||||
sw1.dial(p2, {}, function (err) {
|
||||
expect(err).to.equal(undefined)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(1)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('dial a conn on a protocol', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
conn.end()
|
||||
conn.on('end', done)
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
|
||||
it('dial a protocol on a previous created conn', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
conn.end()
|
||||
conn.on('end', done)
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, function (err) {
|
||||
expect(err).to.equal(undefined)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(1)
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// it('add an upgrade', function (done) { done() })
|
||||
// it('dial a conn on top of a upgrade', function (done) { done() })
|
||||
// it('dial a conn on a protocol on top of a upgrade', function (done) { done() })
|
||||
})
|
||||
|
||||
/* TODO
|
||||
describe('udp', function () {
|
||||
it('add the transport', function (done) { done() })
|
||||
it('dial a conn', function (done) { done() })
|
||||
it('dial a conn on a protocol', function (done) { done() })
|
||||
it('add an upgrade', function (done) { done() })
|
||||
it('dial a conn on top of a upgrade', function (done) { done() })
|
||||
it('dial a conn on a protocol on top of a upgrade', function (done) { done() })
|
||||
}) */
|
||||
|
||||
/* TODO
|
||||
describe('udt', function () {
|
||||
it('add the transport', function (done) { done() })
|
||||
it('dial a conn', function (done) { done() })
|
||||
it('dial a conn on a protocol', function (done) { done() })
|
||||
it('add an upgrade', function (done) { done() })
|
||||
it('dial a conn on top of a upgrade', function (done) { done() })
|
||||
it('dial a conn on a protocol on top of a upgrade', function (done) { done() })
|
||||
}) */
|
||||
|
||||
/* TODO
|
||||
describe('utp', function () {
|
||||
it('add the transport', function (done) { done() })
|
||||
it('dial a conn', function (done) { done() })
|
||||
it('dial a conn on a protocol', function (done) { done() })
|
||||
it('add an upgrade', function (done) { done() })
|
||||
it('dial a conn on top of a upgrade', function (done) { done() })
|
||||
it('dial a conn on a protocol on top of a upgrade', function (done) { done() })
|
||||
}) */
|
||||
})
|
||||
|
||||
describe('With a SPDY Stream Muxer', function () {
|
||||
describe('and one swarm over tcp', function () {
|
||||
// TODO: What is the it here?
|
||||
it('add Stream Muxer', function (done) {
|
||||
// var mh = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
var p = new Peer(Id.create(), [])
|
||||
var sw = new Swarm(p)
|
||||
sw.addStreamMuxer('spdy', Spdy, {})
|
||||
|
||||
it('add', (done) => {
|
||||
swarmA.transport.add('tcp', new TCP())
|
||||
expect(Object.keys(swarmA.transports).length).to.equal(1)
|
||||
swarmB.transport.add('tcp', new TCP(), () => {
|
||||
expect(Object.keys(swarmB.transports).length).to.equal(1)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
describe('and two swarms over tcp', function () {
|
||||
var mh1, p1, sw1, mh2, p2, sw2
|
||||
|
||||
beforeEach(function (done) {
|
||||
mh1 = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
p1 = new Peer(Id.create(), [])
|
||||
sw1 = new Swarm(p1)
|
||||
sw1.addStreamMuxer('spdy', Spdy, {})
|
||||
|
||||
mh2 = multiaddr('/ip4/127.0.0.1/tcp/8020')
|
||||
p2 = new Peer(Id.create(), [])
|
||||
sw2 = new Swarm(p2)
|
||||
sw2.addStreamMuxer('spdy', Spdy, {})
|
||||
|
||||
async.parallel([
|
||||
function (cb) {
|
||||
sw1.addTransport('tcp', tcp, { multiaddr: mh1 }, {}, {port: 8010}, cb)
|
||||
},
|
||||
function (cb) {
|
||||
sw2.addTransport('tcp', tcp, { multiaddr: mh2 }, {}, {port: 8020}, cb)
|
||||
}
|
||||
], done)
|
||||
})
|
||||
|
||||
function afterEach (done) {
|
||||
var cleaningCounter = 0
|
||||
sw1.closeConns(cleaningUp)
|
||||
sw2.closeConns(cleaningUp)
|
||||
|
||||
sw1.closeListener('tcp', cleaningUp)
|
||||
sw2.closeListener('tcp', cleaningUp)
|
||||
|
||||
function cleaningUp () {
|
||||
cleaningCounter++
|
||||
// TODO FIX: here should be 4, but because super wrapping of
|
||||
// streams, it makes it so hard to properly close the muxed
|
||||
// streams - https://github.com/indutny/spdy-transport/issues/14
|
||||
if (cleaningCounter < 3) {
|
||||
return
|
||||
}
|
||||
it('listen', (done) => {
|
||||
var count = 0
|
||||
swarmA.transport.listen('tcp', {}, (conn) => {
|
||||
conn.pipe(conn)
|
||||
}, ready)
|
||||
swarmB.transport.listen('tcp', {}, (conn) => {
|
||||
conn.pipe(conn)
|
||||
}, ready)
|
||||
|
||||
function ready () {
|
||||
if (++count === 2) {
|
||||
expect(peerA.multiaddrs.length).to.equal(1)
|
||||
expect(peerA.multiaddrs[0]).to.deep.equal(multiaddr('/ip4/127.0.0.1/tcp/9888'))
|
||||
expect(peerB.multiaddrs.length).to.equal(1)
|
||||
expect(peerB.multiaddrs[0]).to.deep.equal(multiaddr('/ip4/127.0.0.1/tcp/9999'))
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
it('dial a conn on a protocol', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
// formallity so that the conn starts flowing
|
||||
conn.on('data', function (chunk) {})
|
||||
|
||||
conn.end()
|
||||
conn.on('end', function () {
|
||||
expect(Object.keys(sw1.muxedConns).length).to.equal(1)
|
||||
expect(Object.keys(sw2.muxedConns).length).to.equal(0)
|
||||
afterEach(done)
|
||||
})
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
conn.on('data', function () {})
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
|
||||
it('dial two conns (transport reuse)', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
// formality so that the conn starts flowing
|
||||
conn.on('data', function (chunk) {})
|
||||
|
||||
conn.end()
|
||||
conn.on('end', function () {
|
||||
expect(Object.keys(sw1.muxedConns).length).to.equal(1)
|
||||
expect(Object.keys(sw2.muxedConns).length).to.equal(0)
|
||||
|
||||
afterEach(done)
|
||||
})
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
// TODO Improve clarity
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
conn.on('data', function () {})
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
|
||||
conn.end()
|
||||
})
|
||||
|
||||
conn.on('data', function () {})
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('and two identity enabled swarms over tcp', function () {
|
||||
var mh1, p1, sw1, mh2, p2, sw2
|
||||
|
||||
beforeEach(function (done) {
|
||||
mh1 = multiaddr('/ip4/127.0.0.1/tcp/8010')
|
||||
p1 = new Peer(Id.create(), [])
|
||||
sw1 = new Swarm(p1)
|
||||
sw1.addStreamMuxer('spdy', Spdy, {})
|
||||
sw1.enableIdentify()
|
||||
|
||||
mh2 = multiaddr('/ip4/127.0.0.1/tcp/8020')
|
||||
p2 = new Peer(Id.create(), [])
|
||||
sw2 = new Swarm(p2)
|
||||
sw2.addStreamMuxer('spdy', Spdy, {})
|
||||
sw2.enableIdentify()
|
||||
|
||||
async.parallel([
|
||||
function (cb) {
|
||||
sw1.addTransport('tcp', tcp, { multiaddr: mh1 }, {}, {port: 8010}, cb)
|
||||
},
|
||||
function (cb) {
|
||||
sw2.addTransport('tcp', tcp, { multiaddr: mh2 }, {}, {port: 8020}, cb)
|
||||
}
|
||||
], done)
|
||||
it('dial to a multiaddr', (done) => {
|
||||
const conn = swarmA.transport.dial('tcp', multiaddr('/ip4/127.0.0.1/tcp/9999'), (err, conn) => {
|
||||
expect(err).to.not.exist
|
||||
})
|
||||
conn.pipe(bl((err, data) => {
|
||||
expect(err).to.not.exist
|
||||
done()
|
||||
}))
|
||||
conn.write('hey')
|
||||
conn.end()
|
||||
})
|
||||
|
||||
afterEach(function (done) {
|
||||
var cleaningCounter = 0
|
||||
sw1.closeConns(cleaningUp)
|
||||
sw2.closeConns(cleaningUp)
|
||||
it('dial to set of multiaddr, only one is available', (done) => {
|
||||
const conn = swarmA.transport.dial('tcp', [
|
||||
multiaddr('/ip4/127.0.0.1/tcp/9910'),
|
||||
multiaddr('/ip4/127.0.0.1/tcp/9999'),
|
||||
multiaddr('/ip4/127.0.0.1/tcp/9309')
|
||||
], (err, conn) => {
|
||||
expect(err).to.not.exist
|
||||
})
|
||||
conn.pipe(bl((err, data) => {
|
||||
expect(err).to.not.exist
|
||||
done()
|
||||
}))
|
||||
conn.write('hey')
|
||||
conn.end()
|
||||
})
|
||||
|
||||
sw1.closeListener('tcp', cleaningUp)
|
||||
sw2.closeListener('tcp', cleaningUp)
|
||||
it('close', (done) => {
|
||||
var count = 0
|
||||
swarmA.transport.close('tcp', closed)
|
||||
swarmB.transport.close('tcp', closed)
|
||||
|
||||
function cleaningUp () {
|
||||
cleaningCounter++
|
||||
// TODO FIX: here should be 4, but because super wrapping of
|
||||
// streams, it makes it so hard to properly close the muxed
|
||||
// streams - https://github.com/indutny/spdy-transport/issues/14
|
||||
if (cleaningCounter < 3) {
|
||||
return
|
||||
}
|
||||
// give time for identify to finish
|
||||
setTimeout(function () {
|
||||
expect(Object.keys(sw2.muxedConns).length).to.equal(1)
|
||||
done()
|
||||
}, 500)
|
||||
function closed () {
|
||||
if (++count === 2) {
|
||||
done()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
it('identify', function (done) {
|
||||
sw2.handleProtocol('/sparkles/1.0.0', function (conn) {
|
||||
// formallity so that the conn starts flowing
|
||||
conn.on('data', function (chunk) {})
|
||||
it('support port 0', (done) => {
|
||||
var swarm
|
||||
var peer = new Peer()
|
||||
peer.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/0'))
|
||||
swarm = new Swarm(peer)
|
||||
swarm.transport.add('tcp', new TCP())
|
||||
swarm.transport.listen('tcp', {}, (conn) => {
|
||||
conn.pipe(conn)
|
||||
}, ready)
|
||||
|
||||
conn.end()
|
||||
conn.on('end', function () {
|
||||
expect(Object.keys(sw1.muxedConns).length).to.equal(1)
|
||||
done()
|
||||
})
|
||||
})
|
||||
function ready () {
|
||||
expect(peer.multiaddrs.length).to.equal(1)
|
||||
expect(peer.multiaddrs[0]).to.not.deep.equal(multiaddr('/ip4/127.0.0.1/tcp/0'))
|
||||
swarm.close(done)
|
||||
}
|
||||
})
|
||||
|
||||
sw1.dial(p2, {}, '/sparkles/1.0.0', function (err, conn) {
|
||||
conn.on('data', function () {})
|
||||
expect(err).to.equal(null)
|
||||
expect(Object.keys(sw1.conns).length).to.equal(0)
|
||||
conn.end()
|
||||
})
|
||||
})
|
||||
it('support addr /ip4/0.0.0.0/tcp/9050', (done) => {
|
||||
var swarm
|
||||
var peer = new Peer()
|
||||
peer.multiaddr.add(multiaddr('/ip4/0.0.0.0/tcp/9050'))
|
||||
swarm = new Swarm(peer)
|
||||
swarm.transport.add('tcp', new TCP())
|
||||
swarm.transport.listen('tcp', {}, (conn) => {
|
||||
conn.pipe(conn)
|
||||
}, ready)
|
||||
|
||||
function ready () {
|
||||
expect(peer.multiaddrs.length).to.equal(1)
|
||||
expect(peer.multiaddrs[0]).to.deep.equal(multiaddr('/ip4/0.0.0.0/tcp/9050'))
|
||||
swarm.close(done)
|
||||
}
|
||||
})
|
||||
|
||||
it('support addr /ip4/0.0.0.0/tcp/0', (done) => {
|
||||
var swarm
|
||||
var peer = new Peer()
|
||||
peer.multiaddr.add(multiaddr('/ip4/0.0.0.0/tcp/0'))
|
||||
swarm = new Swarm(peer)
|
||||
swarm.transport.add('tcp', new TCP())
|
||||
swarm.transport.listen('tcp', {}, (conn) => {
|
||||
conn.pipe(conn)
|
||||
}, ready)
|
||||
|
||||
function ready () {
|
||||
expect(peer.multiaddrs.length).to.equal(1)
|
||||
expect(peer.multiaddrs[0]).to.not.deep.equal(multiaddr('/ip4/0.0.0.0/tcp/0'))
|
||||
swarm.close(done)
|
||||
}
|
||||
})
|
||||
|
||||
it('listen in several addrs', (done) => {
|
||||
var swarm
|
||||
var peer = new Peer()
|
||||
peer.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9001'))
|
||||
peer.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9002'))
|
||||
peer.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9003'))
|
||||
swarm = new Swarm(peer)
|
||||
swarm.transport.add('tcp', new TCP())
|
||||
swarm.transport.listen('tcp', {}, (conn) => {
|
||||
conn.pipe(conn)
|
||||
}, ready)
|
||||
|
||||
function ready () {
|
||||
expect(peer.multiaddrs.length).to.equal(3)
|
||||
swarm.close(done)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('transport - udt', () => {
|
||||
before((done) => { done() })
|
||||
|
||||
it.skip('add', (done) => {})
|
||||
it.skip('listen', (done) => {})
|
||||
it.skip('dial', (done) => {})
|
||||
it.skip('close', (done) => {})
|
||||
})
|
||||
|
||||
describe('transport - websockets', () => {
|
||||
before((done) => { done() })
|
||||
|
||||
it.skip('add', (done) => {})
|
||||
it.skip('listen', (done) => {})
|
||||
it.skip('dial', (done) => {})
|
||||
it.skip('close', (done) => {})
|
||||
})
|
||||
|
||||
describe('high level API - 1st stage, without stream multiplexing (on TCP)', () => {
|
||||
it.skip('handle a protocol', (done) => {})
|
||||
it.skip('dial on protocol', (done) => {})
|
||||
it.skip('dial to warm conn', (done) => {})
|
||||
it.skip('dial on protocol, reuse warmed conn', (done) => {})
|
||||
it.skip('close', (done) => {})
|
||||
})
|
||||
|
||||
describe('stream muxing (on TCP)', () => {
|
||||
describe('multiplex', () => {
|
||||
before((done) => { done() })
|
||||
it.skip('add', (done) => {})
|
||||
it.skip('handle + dial on protocol', (done) => {})
|
||||
it.skip('dial to warm conn', (done) => {})
|
||||
it.skip('dial on protocol, reuse warmed conn', (done) => {})
|
||||
it.skip('enable identify to reuse incomming muxed conn', (done) => {})
|
||||
it.skip('close', (done) => {})
|
||||
})
|
||||
describe('spdy', () => {
|
||||
it.skip('add', (done) => {})
|
||||
it.skip('handle + dial on protocol', (done) => {})
|
||||
it.skip('dial to warm conn', (done) => {})
|
||||
it.skip('dial on protocol, reuse warmed conn', (done) => {})
|
||||
it.skip('enable identify to reuse incomming muxed conn', (done) => {})
|
||||
it.skip('close', (done) => {})
|
||||
})
|
||||
})
|
||||
|
||||
describe('conn upgrades', () => {
|
||||
describe('secio on tcp', () => {
|
||||
before((done) => { done() })
|
||||
|
||||
it.skip('add', (done) => {})
|
||||
it.skip('dial', (done) => {})
|
||||
it.skip('tls on a muxed stream (not the full conn)', (done) => {})
|
||||
})
|
||||
describe('tls on tcp', () => {
|
||||
before((done) => { done() })
|
||||
|
||||
it.skip('add', (done) => {})
|
||||
it.skip('dial', (done) => {})
|
||||
it.skip('tls on a muxed stream (not the full conn)', (done) => {})
|
||||
})
|
||||
})
|
||||
|
||||
describe('high level API = 2nd stage, with everything all together!', () => {
|
||||
before((done) => { done() })
|
||||
|
||||
it.skip('add tcp', (done) => {})
|
||||
it.skip('add utp', (done) => {})
|
||||
it.skip('add websockets', (done) => {})
|
||||
it.skip('dial', (done) => {})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user