internal transport interface + libp2p-tcp tests

This commit is contained in:
David Dias 2016-03-03 16:35:05 +00:00
parent 1fd6a3885d
commit c8f2fdd077
5 changed files with 739 additions and 340 deletions

View File

@ -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

View File

@ -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"
}
}

View File

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

View File

@ -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) => {})
})