Compare commits

...

106 Commits

Author SHA1 Message Date
d10166cdcb chore: release version v0.19.3 2016-05-29 09:12:53 +01:00
9faba46061 chore: update contributors 2016-05-29 09:12:53 +01:00
ad3fd30cf3 update-deps 2016-05-29 09:06:59 +01:00
744061b7d2 chore: release version v0.19.2 2016-05-28 19:22:41 +01:00
aa80c86b0a chore: update contributors 2016-05-28 19:22:41 +01:00
0d53d93149 spdy sends too many closes, listen to only one 2016-05-28 19:14:54 +01:00
12e15ef236 chore: release version v0.19.1 2016-05-28 18:49:06 +01:00
d92bad28a0 chore: update contributors 2016-05-28 18:49:06 +01:00
a997237a2d Merge pull request #70 from diasdavid/feat/hangUp
add hangup feature
2016-05-28 18:46:22 +01:00
bcc669028e add hangup feature 2016-05-28 18:26:48 +01:00
896fe7ab0e chore: release version v0.19.0 2016-05-27 10:08:59 +01:00
e78f035a1c chore: update contributors 2016-05-27 10:08:59 +01:00
d32e52fb11 Merge pull request #69 from diasdavid/update-deps
update deps
2016-05-27 10:03:05 +01:00
5393b25b22 update deps 2016-05-27 09:51:33 +01:00
665f7c6d66 chore: release version v0.18.2 2016-05-24 14:08:13 +01:00
03e02dfba9 chore: update contributors 2016-05-24 14:08:12 +01:00
019f84885d Merge pull request #68 from diasdavid/fix/identify
Make identify not freak out on missing pubkey, it is ok.. this enables webrtc-star discovery to work fine
2016-05-24 14:04:48 +01:00
ceaae4c53f Make identify not freak out on missing pubkey, it is ok.. this enables webrtc-star discovery to work fine 2016-05-24 13:51:34 +01:00
8e5d5c5694 chore: release version v0.18.1 2016-05-23 18:16:38 +01:00
53bb2d3e07 chore: update contributors 2016-05-23 18:16:37 +01:00
47f72296ed kick the machine 2016-05-23 16:47:32 +01:00
2d20a75114 fix everything™ 2016-05-23 16:46:35 +01:00
8212c09088 This makes things go nuts 2016-05-23 11:09:48 +01:00
c69254b00e chore: release version v0.18.0 2016-05-23 08:38:08 +01:00
4f36eda28f chore: update contributors 2016-05-23 08:38:08 +01:00
c53068c803 Merge pull request #64 from diasdavid/add/webrtc-star
restructure and add spdy to browser tests
2016-05-23 08:06:36 +01:00
d771a12d86 add webrtc-star transport tests 2016-05-22 18:32:05 +01:00
3cd5cbb8ec restructure and add spdy to browser tests 2016-05-22 14:52:08 +01:00
09acdab0d3 chore: release version v0.17.0 2016-05-21 11:47:07 +01:00
54128c228c chore: update contributors 2016-05-21 11:47:07 +01:00
872dfb2c03 s/identify/id/ 2016-05-21 11:32:28 +01:00
5f406c6ea0 chore: release version v0.16.0 2016-05-20 12:00:39 +01:00
8f785284dc chore: update contributors 2016-05-20 12:00:39 +01:00
ee0b1eaea5 Merge pull request #61 from diasdavid/update-spdy
update spdy
2016-05-20 11:57:50 +01:00
1791c19c8c update spdy 2016-05-20 11:03:22 +01:00
ea94a81a52 chore: release version v0.15.0 2016-05-19 00:50:59 +01:00
f3e705acc7 chore: update contributors 2016-05-19 00:50:59 +01:00
510b458de2 Merge pull request #60 from diasdavid/feat/crypto-not-crypto
plaintext proto to be compatible with go-ipfs
2016-05-18 23:14:37 +01:00
5aa74ee25d plaintext proto to be compatible with go-ipfs 2016-05-18 22:59:58 +01:00
d991c475df chore: release version v0.14.0 2016-05-18 11:16:01 +01:00
40da1ec2b1 chore: update contributors 2016-05-18 11:16:01 +01:00
7789f5da19 Merge pull request #59 from diasdavid/update/multistream
WIP add new version of multistream
2016-05-18 10:56:48 +01:00
a224b0bc54 add new version of multistream 2016-05-18 10:47:55 +01:00
9d958c3209 chore: release version v0.13.0 2016-05-18 04:23:59 +01:00
dc518f4178 chore: update contributors 2016-05-18 04:23:59 +01:00
1eacc5bc7b Merge pull request #58 from diasdavid/update-deps
update deps to support latest multiaddr
2016-05-18 04:21:32 +01:00
f6193301a5 update deps to support latest multiaddr 2016-05-17 23:28:25 +01:00
8d792fe954 chore: release version v0.12.11 2016-05-11 12:54:39 +01:00
de506873e7 chore: update contributors 2016-05-11 12:54:39 +01:00
61340e3909 Merge pull request #56 from diasdavid/fix/ws-ipfs
fix: handling of ipfs addresses in available transports
2016-05-11 12:52:33 +01:00
8e1413b984 fix: handling of ipfs addresses in available transports
and some refactoring into multiple files
2016-05-11 13:29:52 +02:00
163624c218 chore: release version v0.12.10 2016-05-10 10:26:54 +01:00
6fd8b076e2 chore: update contributors 2016-05-10 10:26:53 +01:00
e54ebb65fe Merge pull request #54 from diasdavid/feat/listen
Feat/listen
2016-05-10 11:14:04 +02:00
9c8a8bb26b feat: add .listen method 2016-05-10 11:06:48 +02:00
3f29ff5d33 chore: release version v0.12.9 2016-05-09 10:59:04 +01:00
a712fd6d22 chore: update contributors 2016-05-09 10:59:04 +01:00
7079f10bcc Merge pull request #53 from diasdavid/test-fixes
test: cleanup and fix hanging tests
2016-05-09 10:52:40 +01:00
1210a9f613 test: cleanup and fix hanging tests 2016-05-09 11:37:24 +02:00
5c76907f3d Merge pull request #52 from diasdavid/fix/warm-a-warm-up-the-other-way-around
make sure it does not try to dial on empty proto and write tests for it
2016-05-09 08:16:41 +01:00
074e7e323b make sure it does not try to dial on empty proto and write tests for it 2016-05-09 07:56:06 +01:00
20994f5320 chore: release version v0.12.8 2016-05-08 22:48:43 +01:00
eac00292f2 chore: update contributors 2016-05-08 22:48:43 +01:00
bf768d3585 Merge pull request #51 from diasdavid/fix-errs
Cleaning up some things
2016-05-08 22:22:23 +01:00
05f799f983 update deps 2016-05-08 23:10:09 +02:00
a81c328bf7 actually fix things 2016-05-08 22:58:08 +02:00
a6ba60a5c4 handle errors when closing 2016-05-08 22:22:46 +02:00
594b770d8e try to appease the travis gods 2016-05-08 22:19:43 +02:00
dbf0d2c422 fix dependencies 2016-05-08 21:44:22 +02:00
275434f873 cleanup close handling 2016-05-08 21:35:04 +02:00
631dad8647 chore: release version v0.12.7 2016-05-06 18:28:37 +01:00
3eac0e0dd6 chore: update contributors 2016-05-06 18:28:37 +01:00
30d4bb641e one more test to check if connected endpoints are closed correctly 2016-05-06 18:27:19 +01:00
b0aeff8f53 chore: release version v0.12.6 2016-05-06 14:29:24 +01:00
998c71fc84 chore: update contributors 2016-05-06 14:29:24 +01:00
b31245adc8 Merge pull request #49 from diasdavid/fix/close-count
fix: call cb in close after all transport are closed
2016-05-06 14:19:13 +01:00
85a064765a fix: call cb in close after all transport are closed 2016-05-06 15:05:34 +02:00
fb56cc3c30 Merge pull request #48 from diasdavid/feat/unhandle
unhandle a protocol
2016-05-06 13:11:58 +01:00
03d0c52d4d unhandle a protocol 2016-05-06 12:49:31 +01:00
0aa7bb72e7 Merge pull request #47 from diasdavid/test/swarm-dial-no-proto
dialing in no proto is fine
2016-05-06 12:43:26 +01:00
e9b3d3496f dialing in no proto is fine 2016-05-06 12:31:23 +01:00
58e18dd01b chore: release version v0.12.5 2016-05-05 00:44:53 +01:00
fb017ebb07 chore: update contributors 2016-05-05 00:44:53 +01:00
08c4c169d6 remove unnecessary console.log 2016-05-05 00:13:48 +01:00
de927e8052 chore: release version v0.12.4 2016-05-04 20:13:00 +01:00
df8e61632b chore: update contributors 2016-05-04 20:13:00 +01:00
b453bd4f83 Merge pull request #46 from diasdavid/feat/improve-identify
Freeze handling conns till identify is finished on the incomming multiplexed streams
2016-05-04 21:11:22 +02:00
0143ab6449 freeze handling conns till identify is finished on the incomming multiplexed streams 2016-05-04 19:42:53 +01:00
02dd32e7df chore: release version v0.12.3 2016-05-04 16:57:00 +01:00
4fe91796cd chore: update contributors 2016-05-04 16:57:00 +01:00
352876cade Merge pull request #45 from diasdavid/feat/id-on-conns
attach peerId to the conn
2016-05-04 17:11:50 +02:00
41b700f509 attach peerId to the conn 2016-05-04 14:55:40 +01:00
eea7e91b15 chore: release version v0.12.2 2016-04-27 10:09:24 +01:00
b11a7972f5 chore: update contributors 2016-04-27 10:09:24 +01:00
15d5bc53fb update deps and npm scripts 2016-04-27 10:08:02 +01:00
9d911af8e0 Merge pull request #44 from diasdavid/feature/events
feature/events
2016-04-27 10:03:29 +01:00
9f1f3c82dc add peer-mux-closed event 2016-04-27 09:44:16 +01:00
d6a1f52962 add peer-mux-established event 2016-04-26 20:47:31 +01:00
7b536819b1 chore: update contributors 2016-04-25 02:29:18 +01:00
7158aaf702 chore: release version v0.12.1 2016-04-25 02:29:18 +01:00
bc87fad5f9 update deps 2016-04-25 02:27:34 +01:00
c9418399a7 bump version manually 2016-04-25 00:20:23 +01:00
2cac123405 chore: update contributors 2016-04-25 00:18:30 +01:00
ff47a9c228 chore: release version v0.11.8 2016-04-25 00:18:30 +01:00
f86a981eb2 update npm scripts 2016-04-25 00:17:07 +01:00
674d68000b chore: update contributors 2016-04-24 23:29:15 +01:00
27 changed files with 1108 additions and 609 deletions

16
.aegir.js Normal file
View File

@ -0,0 +1,16 @@
'use strict'
const path = require('path')
module.exports = {
webpack: {
resolve: {
alias: {
'node-forge': path.resolve(
path.dirname(require.resolve('libp2p-crypto')),
'../vendor/forge.bundle.js'
)
}
}
}
}

View File

@ -6,10 +6,10 @@ libp2p-swarm JavaScript implementation
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
[![Build Status](https://img.shields.io/travis/diasdavid/js-libp2p-swarm/master.svg?style=flat-square)](https://travis-ci.org/diasdavid/js-libp2p-swarm)
[![Coverage Status](https://coveralls.io/repos/github/diasdavid/js-libp2p-swarm/badge.svg?branch=master)](https://coveralls.io/github/diasdavid/js-libp2p-swarm?branch=master)
[![Dependency Status](https://david-dm.org/diasdavid/js-libp2p-swarm.svg?style=flat-square)](https://david-dm.org/ipfs/js-libp2p-swarm)
[![Dependency Status](https://david-dm.org/diasdavid/js-libp2p-swarm.svg?style=flat-square)](https://david-dm.org/diasdavid/js-libp2p-swarm)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
> libp2p swarm implementation in JavaScript
> libp2p swarm implementation in JavaScript.
# Description
@ -47,10 +47,10 @@ peerInfo is a [PeerInfo](https://github.com/diasdavid/js-peer-info) object that
libp2p-swarm expects transports that implement [interface-transport](https://github.com/diasdavid/abstract-transport). For example [libp2p-tcp](https://github.com/diasdavid/js-libp2p-tcp).
- `key` - the transport identifier
- `key` - the transport identifier.
- `transport` -
- `options`
- `callback`
- `options` -
- `callback` -
##### `swarm.transport.dial(key, multiaddrs, callback)`
@ -102,6 +102,17 @@ dial uses the best transport (whatever works first, in the future we can have so
- `protocol`
- `callback`
### `swarm.hangUp(pi, callback)`
hangUp the muxedConn we have with the peer
- `pi` - peer info project
- `callback`
### `swarm.listen(callback)`
Start listening on all added transports that are available on the current `peerInfo`.
### `swarm.handle(protocol, handler)`
handle a new protocol.
@ -109,6 +120,12 @@ handle a new protocol.
- `protocol`
- `handler` - function called when we receive a dial on `protocol. Signature must be `function (conn) {}`
### `swarm.unhandle(protocol)`
unhandle a protocol.
- `protocol`
### `swarm.close(callback)`
close all the listeners and muxers.

View File

@ -1,21 +1,31 @@
'use strict'
const gulp = require('gulp')
const Peer = require('peer-info')
const Id = require('peer-id')
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const WebSockets = require('libp2p-websockets')
const Swarm = require('./src')
const spdy = require('libp2p-spdy')
const multiaddr = require('multiaddr')
const fs = require('fs')
const path = require('path')
const sigServer = require('libp2p-webrtc-star/src/signalling-server')
let swarmA
let swarmB
let sigS
gulp.task('test:browser:before', (done) => {
function createListenerA (cb) {
const b58IdA = 'QmWg2L4Fucx1x4KXJTfKHGixBJvveubzcd7DdhB2Mqwfh1'
const peerA = new Peer(Id.createFromB58String(b58IdA))
const maA = multiaddr('/ip4/127.0.0.1/tcp/9100/websockets')
const id = PeerId.createFromJSON(
JSON.parse(
fs.readFileSync(
path.join(__dirname, './test/test-data/id-1.json'))))
const peerA = new PeerInfo(id)
const maA = multiaddr('/ip4/127.0.0.1/tcp/9100/ws')
peerA.multiaddr.add(maA)
swarmA = new Swarm(peerA)
@ -24,23 +34,30 @@ gulp.task('test:browser:before', (done) => {
}
function createListenerB (cb) {
const b58IdB = 'QmRy1iU6BHmG5Hd8rnPhPL98cy1W1przUSTAMcGDq9yAAV'
const maB = multiaddr('/ip4/127.0.0.1/tcp/9200/websockets')
const peerB = new Peer(Id.createFromB58String(b58IdB))
const id = PeerId.createFromJSON(
JSON.parse(
fs.readFileSync(
path.join(__dirname, './test/test-data/id-2.json'))))
const peerB = new PeerInfo(id)
const maB = multiaddr('/ip4/127.0.0.1/tcp/9200/ws')
peerB.multiaddr.add(maB)
swarmB = new Swarm(peerB)
swarmB.transport.add('ws', new WebSockets())
swarmB.transport.listen('ws', {}, null, cb)
swarmB.connection.addStreamMuxer(spdy)
swarmB.connection.reuse()
swarmB.listen(cb)
swarmB.handle('/echo/1.0.0', echo)
}
let count = 0
const ready = () => ++count === 2 ? done() : null
const ready = () => ++count === 3 ? done() : null
createListenerA(ready)
createListenerB(ready)
sigS = sigServer.start(15555, ready)
function echo (conn) {
conn.pipe(conn)
@ -49,10 +66,11 @@ gulp.task('test:browser:before', (done) => {
gulp.task('test:browser:after', (done) => {
let count = 0
const ready = () => ++count === 2 ? done() : null
const ready = () => ++count === 3 ? done() : null
swarmA.transport.close('ws', ready)
swarmB.transport.close('ws', ready)
swarmB.close(ready)
sigS.stop(ready)
})
require('aegir/gulp')(gulp)

View File

@ -1,6 +1,6 @@
{
"name": "libp2p-swarm",
"version": "0.10.7",
"version": "0.19.3",
"description": "libp2p swarm implementation in JavaScript",
"main": "lib/index.js",
"jsnext:main": "src/index.js",
@ -11,8 +11,8 @@
"test:node": "gulp test:node",
"test:browser": "gulp test:browser",
"release": "gulp release",
"release-minor": "gulp release --minor",
"release-major": "gulp release --major",
"release-minor": "gulp release --type minor",
"release-major": "gulp release --type major",
"coverage": "gulp coverage",
"coverage-publish": "aegir-coverage publish"
},
@ -37,38 +37,33 @@
"node": "^4.3.0"
},
"devDependencies": {
"aegir": "^3.0.4",
"bl": "^1.1.2",
"buffer-loader": "0.0.1",
"chai": "^3.5.0",
"aegir": "^2.1.1",
"gulp": "^3.9.1",
"istanbul": "^0.4.3",
"libp2p-multiplex": "^0.2.1",
"libp2p-spdy": "^0.3.1",
"libp2p-tcp": "^0.4.0",
"libp2p-websockets": "^0.3.2",
"multiaddr": "^1.4.0",
"peer-id": "^0.6.6",
"peer-info": "^0.6.2",
"libp2p-spdy": "^0.6.1",
"libp2p-tcp": "^0.6.1",
"libp2p-webrtc-star": "^0.2.0",
"libp2p-websockets": "^0.6.1",
"pre-commit": "^1.1.2",
"stream-pair": "^1.0.3"
"stream-pair": "^1.0.3",
"webrtcsupport": "^2.2.0"
},
"dependencies": {
"babel-runtime": "^6.6.1",
"browserify-zlib": "github:ipfs/browserify-zlib",
"duplex-passthrough": "github:diasdavid/duplex-passthrough",
"ip-address": "^5.8.0",
"lodash.contains": "^2.4.3",
"multistream-select": "^0.6.5",
"protocol-buffers-stream": "^1.3.1"
},
"aegir": {
"webpack": {
"resolve": {
"alias": {
"node-forge": "../vendor/forge.bundle.js"
}
}
}
"multiaddr": "^2.0.0",
"multistream-select": "^0.9.0",
"peer-id": "^0.7.0",
"peer-info": "^0.7.0",
"protocol-buffers-stream": "^1.3.1",
"run-parallel": "^1.1.6"
},
"contributors": [
"David Dias <daviddias.p@gmail.com>",

65
src/connection.js Normal file
View File

@ -0,0 +1,65 @@
'use strict'
const connHandler = require('./default-handler')
const identify = require('./identify')
module.exports = function connection (swarm) {
return {
addUpgrade () {},
addStreamMuxer (muxer) {
// for dialing
swarm.muxers[muxer.multicodec] = muxer
// for listening
swarm.handle(muxer.multicodec, (conn) => {
const muxedConn = muxer(conn, true)
var peerIdForConn
muxedConn.on('stream', (conn) => {
function gotId () {
if (peerIdForConn) {
conn.peerId = peerIdForConn
connHandler(swarm.protocols, conn)
} else {
setTimeout(gotId, 100)
}
}
if (swarm.identify) {
return gotId()
}
connHandler(swarm.protocols, conn)
})
// if identify is enabled, attempt to do it for muxer reuse
if (swarm.identify) {
identify.exec(conn, muxedConn, swarm._peerInfo, (err, pi) => {
if (err) {
return console.log('Identify exec failed', err)
}
peerIdForConn = pi.id
swarm.muxedConns[pi.id.toB58String()] = {}
swarm.muxedConns[pi.id.toB58String()].muxer = muxedConn
swarm.muxedConns[pi.id.toB58String()].conn = conn // to be able to extract addrs
swarm.emit('peer-mux-established', pi)
muxedConn.on('close', () => {
delete swarm.muxedConns[pi.id.toB58String()]
swarm.emit('peer-mux-closed', pi)
})
})
}
})
},
reuse () {
swarm.identify = true
swarm.handle(identify.multicodec, identify.handler(swarm._peerInfo, swarm))
}
}
}

21
src/default-handler.js Normal file
View File

@ -0,0 +1,21 @@
'use strict'
const multistream = require('multistream-select')
// incomming connection handler
module.exports = function connHandler (protocols, conn) {
const ms = new multistream.Listener()
Object.keys(protocols).forEach((protocol) => {
if (!protocol) {
return
}
ms.addHandler(protocol, protocols[protocol])
})
ms.handle(conn, (err) => {
if (err) {
return // the multistream handshake failed
}
})
}

179
src/dial.js Normal file
View File

@ -0,0 +1,179 @@
'use strict'
const multistream = require('multistream-select')
const DuplexPassThrough = require('duplex-passthrough')
const connHandler = require('./default-handler')
module.exports = function dial (swarm) {
return (pi, protocol, callback) => {
if (typeof protocol === 'function') {
callback = protocol
protocol = null
}
if (!callback) {
callback = function noop () {}
}
const pt = new DuplexPassThrough()
const b58Id = pi.id.toB58String()
if (!swarm.muxedConns[b58Id]) {
if (!swarm.conns[b58Id]) {
attemptDial(pi, (err, conn) => {
if (err) {
return callback(err)
}
gotWarmedUpConn(conn)
})
} else {
const conn = swarm.conns[b58Id]
swarm.conns[b58Id] = undefined
gotWarmedUpConn(conn)
}
} else {
if (!protocol) {
return callback()
}
gotMuxer(swarm.muxedConns[b58Id].muxer)
}
return pt
function gotWarmedUpConn (conn) {
attemptMuxerUpgrade(conn, (err, muxer) => {
if (!protocol) {
if (err) {
swarm.conns[b58Id] = conn
}
return callback()
}
if (err) {
// couldn't upgrade to Muxer, it is ok
protocolHandshake(conn, protocol, callback)
} else {
gotMuxer(muxer)
}
})
}
function gotMuxer (muxer) {
openConnInMuxedConn(muxer, (conn) => {
protocolHandshake(conn, protocol, callback)
})
}
function attemptDial (pi, cb) {
const tKeys = swarm.availableTransports(pi)
if (tKeys.length === 0) {
return cb(new Error('No available transport to dial to'))
}
nextTransport(tKeys.shift())
function nextTransport (key) {
const multiaddrs = pi.multiaddrs.slice()
swarm.transport.dial(key, multiaddrs, (err, conn) => {
if (err) {
if (tKeys.length === 0) {
return cb(new Error('Could not dial in any of the transports'))
}
return nextTransport(tKeys.shift())
}
cryptoDial()
function cryptoDial () {
// currently, js-libp2p-swarm doesn't implement any crypto
const ms = new multistream.Dialer()
ms.handle(conn, (err) => {
if (err) {
return cb(err)
}
ms.select('/plaintext/1.0.0', cb)
})
}
})
}
}
function attemptMuxerUpgrade (conn, cb) {
const muxers = Object.keys(swarm.muxers)
if (muxers.length === 0) {
return cb(new Error('no muxers available'))
}
// 1. try to handshake in one of the muxers available
// 2. if succeeds
// - add the muxedConn to the list of muxedConns
// - add incomming new streams to connHandler
nextMuxer(muxers.shift())
function nextMuxer (key) {
const ms = new multistream.Dialer()
ms.handle(conn, (err) => {
if (err) {
return callback(new Error('multistream not supported'))
}
ms.select(key, (err, conn) => {
if (err) {
if (muxers.length === 0) {
cb(new Error('could not upgrade to stream muxing'))
} else {
nextMuxer(muxers.shift())
}
return
}
const muxedConn = swarm.muxers[key](conn, false)
swarm.muxedConns[b58Id] = {}
swarm.muxedConns[b58Id].muxer = muxedConn
swarm.muxedConns[b58Id].conn = conn
swarm.emit('peer-mux-established', pi)
muxedConn.once('close', () => {
delete swarm.muxedConns[pi.id.toB58String()]
swarm.emit('peer-mux-closed', pi)
})
// in case identify is on
muxedConn.on('stream', (conn) => {
conn.peerId = pi.id
connHandler(swarm.protocols, conn)
})
cb(null, muxedConn)
})
})
}
}
function openConnInMuxedConn (muxer, cb) {
cb(muxer.newStream())
}
function protocolHandshake (conn, protocol, cb) {
const ms = new multistream.Dialer()
ms.handle(conn, (err) => {
if (err) {
return callback(err)
}
ms.select(protocol, (err, conn) => {
if (err) {
return callback(err)
}
pt.wrapStream(conn)
pt.peerId = pi.id
callback(null, pt)
})
})
}
}
}

View File

@ -19,7 +19,7 @@ const identity = fs.readFileSync(path.join(__dirname, 'identify.proto'))
const pbStream = require('protocol-buffers-stream')(identity)
exports = module.exports
exports.multicodec = '/ipfs/identify/1.0.0'
exports.multicodec = '/ipfs/id/1.0.0'
exports.exec = (rawConn, muxer, peerInfo, callback) => {
// 1. open a stream
@ -30,9 +30,13 @@ exports.exec = (rawConn, muxer, peerInfo, callback) => {
const conn = muxer.newStream()
var msI = new multistream.Interactive()
msI.handle(conn, () => {
msI.select(exports.multicodec, (err, ds) => {
const ms = new multistream.Dialer()
ms.handle(conn, (err) => {
if (err) {
return callback(err)
}
ms.select(exports.multicodec, (err, ds) => {
if (err) {
return callback(err)
}
@ -55,10 +59,15 @@ exports.exec = (rawConn, muxer, peerInfo, callback) => {
const obsMultiaddr = rawConn.getObservedAddrs()[0]
let publicKey = new Buffer(0)
if (peerInfo.id.pubKey) {
publicKey = peerInfo.id.pubKey.bytes
}
pbs.identify({
protocolVersion: 'na',
agentVersion: 'na',
publicKey: peerInfo.id.pubKey,
publicKey: publicKey,
listenAddrs: peerInfo.multiaddrs.map((mh) => mh.buffer),
observedAddr: obsMultiaddr ? obsMultiaddr.buffer : new Buffer('')
})
@ -75,7 +84,6 @@ exports.handler = (peerInfo, swarm) => {
// 2. update my own information (on peerInfo)
// 3. send back what I see from the other (get from swarm.muxedConns[incPeerID].conn.getObservedAddrs()
var pbs = pbStream()
pbs.on('identify', (msg) => {
if (msg.observedAddr.length > 0) {
peerInfo.multiaddr.addSafe(multiaddr(msg.observedAddr))
@ -85,15 +93,21 @@ exports.handler = (peerInfo, swarm) => {
const conn = swarm.muxedConns[peerId.toB58String()].conn
const obsMultiaddr = conn.getObservedAddrs()[0]
let publicKey = new Buffer(0)
if (peerInfo.id.pubKey) {
publicKey = peerInfo.id.pubKey.bytes
}
pbs.identify({
protocolVersion: 'na',
agentVersion: 'na',
publicKey: peerInfo.id.pubKey,
publicKey: publicKey,
listenAddrs: peerInfo.multiaddrs.map((ma) => ma.buffer),
observedAddr: obsMultiaddr ? obsMultiaddr.buffer : new Buffer('')
})
pbs.finalize()
})
pbs.pipe(conn).pipe(pbs)
}
}

View File

@ -1,12 +1,19 @@
'use strict'
const multistream = require('multistream-select')
const identify = require('./identify')
const DuplexPassThrough = require('duplex-passthrough')
const util = require('util')
const EE = require('events').EventEmitter
const parallel = require('run-parallel')
const contains = require('lodash.contains')
const transport = require('./transport')
const connection = require('./connection')
const dial = require('./dial')
const connHandler = require('./default-handler')
exports = module.exports = Swarm
util.inherits(Swarm, EE)
function Swarm (peerInfo) {
if (!(this instanceof Swarm)) {
return new Swarm(peerInfo)
@ -16,106 +23,13 @@ function Swarm (peerInfo) {
throw new Error('You must provide a value for `peerInfo`')
}
this._peerInfo = 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]
if (!Array.isArray(multiaddrs)) {
multiaddrs = [multiaddrs]
}
// a) filter the multiaddrs that are actually valid for this transport (use a func from the transport itself) (maybe even make the transport do that)
multiaddrs = t.filter(multiaddrs)
// b) if multiaddrs.length = 1, return the conn from the
// transport, otherwise, create a passthrough
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
}
// c) multiaddrs should already be a filtered list
// specific for the transport we are using
const pt = new DuplexPassThrough()
next(multiaddrs.shift())
return pt
function next (multiaddr) {
const conn = t.dial(multiaddr, {ready: () => {
pt.wrapStream(conn)
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 = this.transports[key].filter(
peerInfo.multiaddrs.map((addr) => {
// ipfs multiaddrs are not dialable so we drop them here
if (contains(addr.protoNames(), 'ipfs')) {
return addr.decapsulate('ipfs')
}
return addr
})
)
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> }}
@ -132,204 +46,84 @@ function Swarm (peerInfo) {
// { protocol: handler }
this.protocols = {}
this.connection = {}
this.connection.addUpgrade = () => {}
// { muxerCodec: <muxer> } e.g { '/spdy/0.3.1': spdy }
this.muxers = {}
this.connection.addStreamMuxer = (muxer) => {
// for dialing
this.muxers[muxer.multicodec] = muxer
// for listening
this.handle(muxer.multicodec, (conn) => {
const muxedConn = muxer(conn, true)
muxedConn.on('stream', (conn) => {
connHandler(conn)
// is the Identify protocol enabled?
this.identify = false
this.transport = transport(this)
this.connection = connection(this)
this.availableTransports = (pi) => {
const addrs = pi.multiaddrs
// Only listen on transports we actually have addresses for
return Object.keys(this.transports).filter((ts) => {
// ipfs multiaddrs are not dialable so we drop them here
let dialable = addrs.map((addr) => {
// webrtc-star needs the /ipfs/QmHash
if (addr.toString().indexOf('webrtc-star') > 0) {
return addr
}
if (contains(addr.protoNames(), 'ipfs')) {
return addr.decapsulate('ipfs')
}
return addr
})
// if identify is enabled, attempt to do it for muxer reuse
if (this.identify) {
identify.exec(conn, muxedConn, peerInfo, (err, pi) => {
if (err) {
return console.log('Identify exec failed', err)
}
this.muxedConns[pi.id.toB58String()] = {}
this.muxedConns[pi.id.toB58String()].muxer = muxedConn
this.muxedConns[pi.id.toB58String()].conn = conn // to be able to extract addrs
})
}
return this.transports[ts].filter(dialable).length > 0
})
}
// enable the Identify protocol
this.identify = false
this.connection.reuse = () => {
this.identify = true
this.handle(identify.multicodec, identify.handler(peerInfo, this))
}
const self = this // prefered this to bind
// incomming connection handler
function connHandler (conn) {
var msS = new multistream.Select()
Object.keys(self.protocols).forEach((protocol) => {
if (!protocol) { return }
msS.addHandler(protocol, self.protocols[protocol])
})
msS.handle(conn)
}
// higher level (public) API
this.dial = (pi, protocol, callback) => {
var pt = null
if (typeof protocol === 'function') {
callback = protocol
protocol = null
} else {
pt = new DuplexPassThrough()
}
this.dial = dial(this)
const b58Id = pi.id.toB58String()
if (!this.muxedConns[b58Id]) {
if (!this.conns[b58Id]) {
attemptDial(pi, (err, conn) => {
if (err) {
return callback(err)
}
gotWarmedUpConn(conn)
})
} else {
const conn = this.conns[b58Id]
this.conns[b58Id] = undefined
gotWarmedUpConn(conn)
}
} else {
gotMuxer(this.muxedConns[b58Id].muxer)
}
return pt
function gotWarmedUpConn (conn) {
attemptMuxerUpgrade(conn, (err, muxer) => {
if (!protocol) {
if (err) {
self.conns[b58Id] = conn
}
return callback()
}
if (err) {
// couldn't upgrade to Muxer, it is ok
protocolHandshake(conn, protocol, callback)
} else {
gotMuxer(muxer)
}
})
}
function gotMuxer (muxer) {
openConnInMuxedConn(muxer, (conn) => {
protocolHandshake(conn, protocol, callback)
})
}
function attemptDial (pi, cb) {
const tKeys = Object.keys(self.transports)
nextTransport(tKeys.shift())
function nextTransport (key) {
const multiaddrs = pi.multiaddrs.slice()
self.transport.dial(key, multiaddrs, (err, conn) => {
if (err) {
if (tKeys.length === 0) {
return cb(new Error('Could not dial in any of the transports'))
}
return nextTransport(tKeys.shift())
}
cb(null, conn)
})
}
}
function attemptMuxerUpgrade (conn, cb) {
const muxers = Object.keys(self.muxers)
if (muxers.length === 0) {
return cb(new Error('no muxers available'))
}
// 1. try to handshake in one of the muxers available
// 2. if succeeds
// - add the muxedConn to the list of muxedConns
// - add incomming new streams to connHandler
nextMuxer(muxers.shift())
function nextMuxer (key) {
var msI = new multistream.Interactive()
msI.handle(conn, function () {
msI.select(key, (err, conn) => {
if (err) {
if (muxers.length === 0) {
cb(new Error('could not upgrade to stream muxing'))
} else {
nextMuxer(muxers.shift())
}
return
}
const muxedConn = self.muxers[key](conn, false)
self.muxedConns[b58Id] = {}
self.muxedConns[b58Id].muxer = muxedConn
self.muxedConns[b58Id].conn = conn
// in case identify is on
muxedConn.on('stream', connHandler)
cb(null, muxedConn)
})
})
}
}
function openConnInMuxedConn (muxer, cb) {
cb(muxer.newStream())
}
function protocolHandshake (conn, protocol, cb) {
var msI = new multistream.Interactive()
msI.handle(conn, function () {
msI.select(protocol, (err, conn) => {
if (err) {
return callback(err)
}
pt.wrapStream(conn)
callback(null, pt)
})
})
}
// Start listening on all available transports
this.listen = (callback) => {
parallel(this.availableTransports(peerInfo).map((ts) => (cb) => {
// Listen on the given transport
this.transport.listen(ts, {}, null, cb)
}), callback)
}
this.handle = (protocol, handler) => {
this.protocols[protocol] = handler
}
this.close = (callback) => {
var count = 0
// our crypto handshake :)
this.handle('/plaintext/1.0.0', (conn) => {
connHandler(this.protocols, conn)
})
this.unhandle = (protocol, handler) => {
if (this.protocols[protocol]) {
delete this.protocols[protocol]
}
}
this.hangUp = (peerInfo, callback) => {
const key = peerInfo.id.toB58String()
if (this.muxedConns[key]) {
const muxer = this.muxedConns[key].muxer
muxer.end()
muxer.once('close', () => {
delete this.muxedConns[key]
callback()
})
} else {
callback()
}
}
this.close = (callback) => {
Object.keys(this.muxedConns).forEach((key) => {
this.muxedConns[key].muxer.end()
})
Object.keys(this.transports).forEach((key) => {
this.transports[key].close(() => {
if (++count === Object.keys(this.transports).length) {
callback()
}
})
})
parallel(Object.keys(this.transports).map((key) => {
return (cb) => this.transports[key].close(cb)
}), callback)
}
}
function noop () {}

122
src/transport.js Normal file
View File

@ -0,0 +1,122 @@
'use strict'
const contains = require('lodash.contains')
const DuplexPassThrough = require('duplex-passthrough')
const connHandler = require('./default-handler')
module.exports = function (swarm) {
return {
add (key, transport, options, callback) {
if (typeof options === 'function') {
callback = options
options = {}
}
if (!callback) { callback = noop }
if (swarm.transports[key]) {
throw new Error('There is already a transport with this key')
}
swarm.transports[key] = transport
callback()
},
dial (key, multiaddrs, callback) {
const t = swarm.transports[key]
if (!Array.isArray(multiaddrs)) {
multiaddrs = [multiaddrs]
}
// a) filter the multiaddrs that are actually valid for this transport (use a func from the transport itself) (maybe even make the transport do that)
multiaddrs = dialables(t, multiaddrs)
// b) if multiaddrs.length = 1, return the conn from the
// transport, otherwise, create a passthrough
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
}
// c) multiaddrs should already be a filtered list
// specific for the transport we are using
const pt = new DuplexPassThrough()
next(multiaddrs.shift())
return pt
function next (multiaddr) {
const conn = t.dial(multiaddr, {ready: () => {
pt.wrapStream(conn)
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())
})
}
},
listen (key, options, handler, callback) {
// if no callback is passed, we pass conns to connHandler
if (!handler) {
handler = connHandler.bind(null, swarm.protocols)
}
const multiaddrs = dialables(swarm.transports[key], swarm._peerInfo.multiaddrs)
swarm.transports[key].createListener(multiaddrs, handler, (err, maUpdate) => {
if (err) {
return callback(err)
}
if (maUpdate) {
// because we can listen on port 0...
swarm._peerInfo.multiaddr.replace(multiaddrs, maUpdate)
}
callback()
})
},
close (key, callback) {
const transport = swarm.transports[key]
if (!transport) {
return callback(new Error(`Trying to close non existing transport: ${key}`))
}
transport.close(callback)
}
}
}
// transform given multiaddrs to a list of dialable addresses
// for the given transport `tp`.
function dialables (tp, multiaddrs) {
return tp.filter(multiaddrs.map((addr) => {
// webrtc-star needs the /ipfs/QmHash
if (addr.toString().indexOf('webrtc-star') > 0) {
return addr
}
// ipfs multiaddrs are not dialable so we drop them here
if (contains(addr.protoNames(), 'ipfs')) {
return addr.decapsulate('ipfs')
}
return addr
}))
}
function noop () {}

View File

@ -6,8 +6,7 @@ const expect = require('chai').expect
const Swarm = require('../src')
describe('basics', () => {
it('throws on missing peerInfo', (done) => {
expect(Swarm).to.throw(Error)
done()
it('throws on missing peerInfo', () => {
expect(() => Swarm()).to.throw(Error)
})
})

View File

@ -3,6 +3,7 @@
const expect = require('chai').expect
const parallel = require('run-parallel')
const multiaddr = require('multiaddr')
const Peer = require('peer-info')
const Swarm = require('../src')
@ -76,7 +77,7 @@ describe('transport - tcp', function () {
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/websockets'), // not valid on purpose
multiaddr('/ip4/127.0.0.1/tcp/9910/ws'), // not valid on purpose
multiaddr('/ip4/127.0.0.1/tcp/9910'),
multiaddr('/ip4/127.0.0.1/tcp/9999'),
multiaddr('/ip4/127.0.0.1/tcp/9309')
@ -92,15 +93,10 @@ describe('transport - tcp', function () {
})
it('close', (done) => {
var count = 0
swarmA.transport.close('tcp', closed)
swarmB.transport.close('tcp', closed)
function closed () {
if (++count === 2) {
done()
}
}
parallel([
(cb) => swarmA.transport.close('tcp', cb),
(cb) => swarmB.transport.close('tcp', cb)
], done)
})
it('support port 0', (done) => {

View File

@ -3,6 +3,7 @@
const expect = require('chai').expect
const parallel = require('run-parallel')
const multiaddr = require('multiaddr')
const Peer = require('peer-info')
const Swarm = require('../src')
@ -17,12 +18,11 @@ describe('transport - websockets', function () {
var peerA = new Peer()
var peerB = new Peer()
before((done) => {
peerA.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9888/websockets'))
peerB.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9999/websockets'))
before(() => {
peerA.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9888/ws'))
peerB.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9999/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC'))
swarmA = new Swarm(peerA)
swarmB = new Swarm(peerB)
done()
})
it('add', (done) => {
@ -35,35 +35,32 @@ describe('transport - websockets', function () {
})
it('listen', (done) => {
var count = 0
swarmA.transport.listen('ws', {}, (conn) => {
conn.pipe(conn)
}, ready)
swarmB.transport.listen('ws', {}, (conn) => {
conn.pipe(conn)
}, ready)
function ready () {
if (++count === 2) {
expect(peerA.multiaddrs.length).to.equal(1)
expect(
peerA.multiaddrs[0].equals(multiaddr('/ip4/127.0.0.1/tcp/9888/websockets'))
).to.be.equal(
true
)
expect(peerB.multiaddrs.length).to.equal(1)
expect(
peerB.multiaddrs[0].equals(multiaddr('/ip4/127.0.0.1/tcp/9999/websockets'))
).to.equal(
true
)
done()
}
}
parallel([
(cb) => swarmA.transport.listen('ws', {}, (conn) => {
conn.pipe(conn)
}, cb),
(cb) => swarmB.transport.listen('ws', {}, (conn) => {
conn.pipe(conn)
}, cb)
], () => {
expect(peerA.multiaddrs.length).to.equal(1)
expect(
peerA.multiaddrs[0].equals(multiaddr('/ip4/127.0.0.1/tcp/9888/ws'))
).to.be.equal(
true
)
expect(peerB.multiaddrs.length).to.equal(1)
expect(
peerB.multiaddrs[0].equals(multiaddr('/ip4/127.0.0.1/tcp/9999/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC'))
).to.equal(
true
)
done()
})
})
it('dial', (done) => {
const conn = swarmA.transport.dial('ws', multiaddr('/ip4/127.0.0.1/tcp/9999/websockets'), (err, conn) => {
const conn = swarmA.transport.dial('ws', multiaddr('/ip4/127.0.0.1/tcp/9999/ws'), (err, conn) => {
expect(err).to.not.exist
})
conn.pipe(bl((err, data) => {
@ -75,7 +72,7 @@ describe('transport - websockets', function () {
})
it('dial (conn from callback)', (done) => {
swarmA.transport.dial('ws', multiaddr('/ip4/127.0.0.1/tcp/9999/websockets'), (err, conn) => {
swarmA.transport.dial('ws', multiaddr('/ip4/127.0.0.1/tcp/9999/ws'), (err, conn) => {
expect(err).to.not.exist
conn.pipe(bl((err, data) => {
@ -88,14 +85,9 @@ describe('transport - websockets', function () {
})
it('close', (done) => {
var count = 0
swarmA.transport.close('ws', closed)
swarmB.transport.close('ws', closed)
function closed () {
if (++count === 2) {
done()
}
}
parallel([
(cb) => swarmA.transport.close('ws', cb),
(cb) => swarmB.transport.close('ws', cb)
], done)
})
})

View File

@ -3,6 +3,7 @@
const expect = require('chai').expect
const parallel = require('run-parallel')
const multiaddr = require('multiaddr')
const Peer = require('peer-info')
const Swarm = require('../src')
@ -10,7 +11,7 @@ const TCP = require('libp2p-tcp')
const multiplex = require('libp2p-spdy')
describe('stream muxing with multiplex (on TCP)', function () {
this.timeout(20000)
this.timeout(60 * 1000)
var swarmA
var peerA
@ -37,35 +38,22 @@ describe('stream muxing with multiplex (on TCP)', function () {
swarmC = new Swarm(peerC)
swarmA.transport.add('tcp', new TCP())
swarmA.transport.listen('tcp', {}, null, ready)
swarmB.transport.add('tcp', new TCP())
swarmB.transport.listen('tcp', {}, null, ready)
swarmC.transport.add('tcp', new TCP())
swarmC.transport.listen('tcp', {}, null, ready)
var counter = 0
function ready () {
if (++counter === 3) {
done()
}
}
parallel([
(cb) => swarmA.transport.listen('tcp', {}, null, cb),
(cb) => swarmB.transport.listen('tcp', {}, null, cb),
(cb) => swarmC.transport.listen('tcp', {}, null, cb)
], done)
})
after((done) => {
var counter = 0
swarmA.close(closed)
swarmB.close(closed)
swarmC.close(closed)
function closed () {
if (++counter === 3) {
done()
}
}
parallel([
(cb) => swarmA.close(cb),
(cb) => swarmB.close(cb),
(cb) => swarmC.close(cb)
], done)
})
it('add', (done) => {

View File

@ -3,6 +3,7 @@
const expect = require('chai').expect
const parallel = require('run-parallel')
const multiaddr = require('multiaddr')
const Peer = require('peer-info')
const Swarm = require('../src')
@ -10,7 +11,7 @@ const TCP = require('libp2p-tcp')
const spdy = require('libp2p-spdy')
describe('stream muxing with spdy (on TCP)', function () {
this.timeout(20000)
this.timeout(60 * 1000)
var swarmA
var peerA
@ -37,42 +38,28 @@ describe('stream muxing with spdy (on TCP)', function () {
swarmC = new Swarm(peerC)
swarmA.transport.add('tcp', new TCP())
swarmA.transport.listen('tcp', {}, null, ready)
swarmB.transport.add('tcp', new TCP())
swarmB.transport.listen('tcp', {}, null, ready)
swarmC.transport.add('tcp', new TCP())
swarmC.transport.listen('tcp', {}, null, ready)
var counter = 0
function ready () {
if (++counter === 3) {
done()
}
}
parallel([
(cb) => swarmA.transport.listen('tcp', {}, null, cb),
(cb) => swarmB.transport.listen('tcp', {}, null, cb),
(cb) => swarmC.transport.listen('tcp', {}, null, cb)
], done)
})
after((done) => {
var counter = 0
swarmA.close(closed)
swarmB.close(closed)
swarmC.close(closed)
function closed () {
if (++counter === 3) {
done()
}
}
parallel([
(cb) => swarmA.close(cb),
(cb) => swarmB.close(cb)
// (cb) => swarmC.close(cb)
], done)
})
it('add', (done) => {
it('add', () => {
swarmA.connection.addStreamMuxer(spdy)
swarmB.connection.addStreamMuxer(spdy)
swarmC.connection.addStreamMuxer(spdy)
done()
})
it('handle + dial on protocol', (done) => {
@ -128,4 +115,12 @@ describe('stream muxing with spdy (on TCP)', function () {
}, 500)
})
})
it('close one end, make sure the other does not blow', (done) => {
swarmC.close((err) => {
if (err) throw err
// to make sure it has time to propagate
setTimeout(done, 1000)
})
})
})

View File

@ -4,9 +4,6 @@
describe('secio conn upgrade (on TCP)', function () {
this.timeout(20000)
before((done) => { done() })
after((done) => { done() })
it.skip('add', (done) => {})
it.skip('dial', (done) => {})
it.skip('tls on a muxed stream (not the full conn)', (done) => {})

View File

@ -2,9 +2,6 @@
'use strict'
describe('tls conn upgrade (on TCP)', function () {
before((done) => { done() })
after((done) => { done() })
it.skip('add', (done) => {})
it.skip('dial', (done) => {})
it.skip('tls on a muxed stream (not the full conn)', (done) => {})

View File

@ -3,6 +3,7 @@
const expect = require('chai').expect
const parallel = require('run-parallel')
const multiaddr = require('multiaddr')
const Peer = require('peer-info')
const Swarm = require('../src')
@ -27,38 +28,26 @@ describe('high level API - 1st without stream multiplexing (on TCP)', function (
swarmB = new Swarm(peerB)
swarmA.transport.add('tcp', new TCP())
swarmA.transport.listen('tcp', {}, null, ready)
swarmB.transport.add('tcp', new TCP())
swarmB.transport.listen('tcp', {}, null, ready)
var counter = 0
function ready () {
if (++counter === 2) {
done()
}
}
parallel([
(cb) => swarmA.transport.listen('tcp', {}, null, cb),
(cb) => swarmB.transport.listen('tcp', {}, null, cb)
], done)
})
after((done) => {
var counter = 0
swarmA.close(closed)
swarmB.close(closed)
function closed () {
if (++counter === 2) {
done()
}
}
parallel([
(cb) => swarmA.close(cb),
(cb) => swarmB.close(cb)
], done)
})
it('handle a protocol', (done) => {
swarmB.handle('/bananas/1.0.0', (conn) => {
conn.pipe(conn)
})
expect(Object.keys(swarmB.protocols).length).to.equal(1)
expect(Object.keys(swarmB.protocols).length).to.equal(2)
done()
})
@ -103,4 +92,11 @@ describe('high level API - 1st without stream multiplexing (on TCP)', function (
conn.on('end', done)
})
})
it('unhandle', (done) => {
const proto = '/bananas/1.0.0'
swarmA.unhandle(proto)
expect(swarmA.protocols[proto]).to.not.exist
done()
})
})

View File

@ -3,6 +3,7 @@
const expect = require('chai').expect
const parallel = require('run-parallel')
const multiaddr = require('multiaddr')
const Peer = require('peer-info')
const Swarm = require('../src')
@ -45,19 +46,13 @@ describe('high level API - with everything mixed all together!', function () {
})
after((done) => {
var counter = 0
swarmA.close(closed)
swarmB.close(closed)
swarmC.close(closed)
swarmD.close(closed)
swarmE.close(closed)
function closed () {
if (++counter === 4) {
done()
}
}
parallel([
(cb) => swarmA.close(cb),
(cb) => swarmB.close(cb),
// (cb) => swarmC.close(cb),
(cb) => swarmD.close(cb),
(cb) => swarmE.close(cb)
], done)
})
it('add tcp', (done) => {
@ -66,53 +61,42 @@ describe('high level API - with everything mixed all together!', function () {
peerC.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/0'))
swarmA.transport.add('tcp', new TCP())
swarmA.transport.listen('tcp', {}, null, ready)
swarmB.transport.add('tcp', new TCP())
swarmB.transport.listen('tcp', {}, null, ready)
swarmC.transport.add('tcp', new TCP())
swarmC.transport.listen('tcp', {}, null, ready)
var counter = 0
function ready () {
if (++counter === 3) {
done()
}
}
parallel([
(cb) => swarmA.transport.listen('tcp', {}, null, cb),
(cb) => swarmB.transport.listen('tcp', {}, null, cb)
// (cb) => swarmC.transport.listen('tcp', {}, null, cb)
], done)
})
it.skip('add utp', (done) => {})
it('add websockets', (done) => {
peerB.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9012/websockets'))
peerC.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9022/websockets'))
peerD.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9032/websockets'))
peerE.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9042/websockets'))
peerB.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9012/ws'))
peerC.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9022/ws'))
peerD.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9032/ws'))
peerE.multiaddr.add(multiaddr('/ip4/127.0.0.1/tcp/9042/ws'))
swarmB.transport.add('ws', new WebSockets())
swarmB.transport.listen('ws', {}, null, ready)
swarmC.transport.add('ws', new WebSockets())
swarmC.transport.listen('ws', {}, null, ready)
swarmD.transport.add('ws', new WebSockets())
swarmD.transport.listen('ws', {}, null, ready)
swarmE.transport.add('ws', new WebSockets())
swarmE.transport.listen('ws', {}, null, ready)
var counter = 0
function ready () {
if (++counter === 4) {
done()
}
}
parallel([
(cb) => swarmB.transport.listen('ws', {}, null, cb),
// (cb) => swarmC.transport.listen('ws', {}, null, cb),
(cb) => swarmD.transport.listen('ws', {}, null, cb),
(cb) => swarmE.transport.listen('ws', {}, null, cb)
], done)
})
it('add spdy', (done) => {
it('listen automatically', (done) => {
swarmC.listen(done)
})
it('add spdy', () => {
swarmA.connection.addStreamMuxer(spdy)
swarmB.connection.addStreamMuxer(spdy)
swarmC.connection.addStreamMuxer(spdy)
@ -124,13 +108,37 @@ describe('high level API - with everything mixed all together!', function () {
swarmC.connection.reuse()
swarmD.connection.reuse()
swarmE.connection.reuse()
done()
})
it.skip('add multiplex', (done) => {})
it.skip('add multiplex', () => {})
it('dial from tcp to tcp+ws', (done) => {
it('warm up from A to B on tcp to tcp+ws', (done) => {
parallel([
(cb) => swarmB.once('peer-mux-established', (peerInfo) => {
expect(peerInfo.id.toB58String()).to.equal(peerA.id.toB58String())
cb()
}),
(cb) => swarmA.once('peer-mux-established', (peerInfo) => {
expect(peerInfo.id.toB58String()).to.equal(peerB.id.toB58String())
cb()
}),
(cb) => swarmA.dial(peerB, (err) => {
expect(err).to.not.exist
expect(Object.keys(swarmA.muxedConns).length).to.equal(1)
cb()
})
], done)
})
it('warm up a warmed up, from B to A', (done) => {
swarmB.dial(peerA, (err) => {
expect(err).to.not.exist
expect(Object.keys(swarmA.muxedConns).length).to.equal(1)
done()
})
})
it('dial from tcp to tcp+ws, on protocol', (done) => {
swarmB.handle('/anona/1.0.0', (conn) => {
conn.pipe(conn)
})
@ -145,6 +153,14 @@ describe('high level API - with everything mixed all together!', function () {
})
})
it('dial from ws to ws no proto', (done) => {
swarmD.dial(peerE, (err) => {
expect(err).to.not.exist
expect(Object.keys(swarmD.muxedConns).length).to.equal(1)
done()
})
})
it('dial from ws to ws', (done) => {
swarmE.handle('/abacaxi/1.0.0', (conn) => {
conn.pipe(conn)
@ -182,11 +198,13 @@ describe('high level API - with everything mixed all together!', function () {
it('dial from tcp+ws to tcp+ws', (done) => {
swarmC.handle('/mamao/1.0.0', (conn) => {
expect(conn.peerId).to.exist
conn.pipe(conn)
})
swarmA.dial(peerC, '/mamao/1.0.0', (err, conn) => {
expect(err).to.not.exist
expect(conn.peerId).to.exist
expect(Object.keys(swarmA.muxedConns).length).to.equal(2)
conn.end()
@ -194,4 +212,31 @@ describe('high level API - with everything mixed all together!', function () {
conn.on('end', done)
})
})
it('hangUp', (done) => {
let count = 0
const ready = () => ++count === 3 ? done() : null
swarmB.once('peer-mux-closed', (peerInfo) => {
expect(Object.keys(swarmB.muxedConns).length).to.equal(0)
ready()
})
swarmA.once('peer-mux-closed', (peerInfo) => {
expect(Object.keys(swarmA.muxedConns).length).to.equal(1)
ready()
})
swarmA.hangUp(peerB, (err) => {
expect(err).to.not.exist
ready()
})
})
it('close a muxer emits event', (done) => {
parallel([
(cb) => swarmC.close(cb),
(cb) => swarmA.once('peer-mux-closed', (peerInfo) => cb())
], done)
})
})

View File

@ -0,0 +1,48 @@
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const multiaddr = require('multiaddr')
const Id = require('peer-id')
const Peer = require('peer-info')
const WebSockets = require('libp2p-websockets')
const bl = require('bl')
const Swarm = require('../src')
describe('transport - websockets', function () {
this.timeout(10000)
var swarm
before(() => {
const b58IdSrc = 'QmYzgdesgjdvD3okTPGZT9NPmh1BuH5FfTVNKjsvaAprhb'
// use a pre generated Id to save time
const idSrc = Id.createFromB58String(b58IdSrc)
const peerSrc = new Peer(idSrc)
swarm = new Swarm(peerSrc)
})
it('add', (done) => {
swarm.transport.add('ws', new WebSockets(), () => {
expect(Object.keys(swarm.transports).length).to.equal(1)
done()
})
})
it('dial', (done) => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/9100/ws')
const conn = swarm.transport.dial('ws', ma, (err, conn) => {
expect(err).to.not.exist
})
conn.pipe(bl((err, data) => {
expect(err).to.not.exist
expect(data.toString()).to.equal('hey')
done()
}))
conn.write('hey')
conn.end()
})
})

View File

@ -0,0 +1,90 @@
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const multiaddr = require('multiaddr')
const peerId = require('peer-id')
const PeerInfo = require('peer-info')
const WebRTCStar = require('libp2p-webrtc-star')
const bl = require('bl')
const parallel = require('run-parallel')
const Swarm = require('../src')
describe('transport - webrtc-star', function () {
this.timeout(10000)
let swarm1
let peer1
let swarm2
let peer2
before(() => {
const id1 = peerId.createFromB58String('QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSooooA')
peer1 = new PeerInfo(id1)
const mh1 = multiaddr('/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSooooA')
peer1.multiaddr.add(mh1)
const id2 = peerId.createFromB58String('QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSooooB')
peer2 = new PeerInfo(id2)
const mh2 = multiaddr('/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSooooB')
peer2.multiaddr.add(mh2)
swarm1 = new Swarm(peer1)
swarm2 = new Swarm(peer2)
})
it('add WebRTCStar transport to swarm 1', (done) => {
swarm1.transport.add('wstar', new WebRTCStar(), () => {
expect(Object.keys(swarm1.transports).length).to.equal(1)
done()
})
})
it('add WebRTCStar transport to swarm 2', (done) => {
swarm2.transport.add('wstar', new WebRTCStar(), () => {
expect(Object.keys(swarm2.transports).length).to.equal(1)
done()
})
})
it('listen on swarm 1', (done) => {
swarm1.transport.listen('wstar', {}, (conn) => {
conn.pipe(conn)
}, done)
})
it('listen on swarm 2', (done) => {
swarm2.transport.listen('wstar', {}, (conn) => {
conn.pipe(conn)
}, done)
})
it('dial', (done) => {
swarm1.transport.dial('wstar', peer2.multiaddrs[0], (err, conn) => {
expect(err).to.not.exist
const text = 'Hello World'
conn.pipe(bl((err, data) => {
expect(err).to.not.exist
expect(data.toString()).to.equal(text)
done()
}))
conn.write(text)
conn.end()
})
})
it('close', (done) => {
parallel([
(cb) => {
swarm1.transport.close('wstar', cb)
},
(cb) => {
swarm2.transport.close('wstar', cb)
}
], done)
})
})

View File

@ -0,0 +1,74 @@
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const multiaddr = require('multiaddr')
const PeerId = require('peer-id')
const PeerInfo = require('peer-info')
const WebSockets = require('libp2p-websockets')
const spdy = require('libp2p-spdy')
const fs = require('fs')
const path = require('path')
const Swarm = require('../src')
describe('high level API (swarm with spdy + websockets)', function () {
this.timeout(60 * 1000)
var swarm
var peerDst
before(() => {
const peerSrc = new PeerInfo()
swarm = new Swarm(peerSrc)
})
it('add spdy', () => {
swarm.connection.addStreamMuxer(spdy)
swarm.connection.reuse()
})
it('add ws', () => {
swarm.transport.add('ws', new WebSockets())
expect(Object.keys(swarm.transports).length).to.equal(1)
})
it('create Dst peer info', () => {
const id = PeerId.createFromJSON(
JSON.parse(
fs.readFileSync(
path.join(__dirname, './test-data/id-2.json'))))
peerDst = new PeerInfo(id)
const ma = multiaddr('/ip4/127.0.0.1/tcp/9200/ws')
peerDst.multiaddr.add(ma)
})
it('dial to warm a conn', (done) => {
swarm.dial(peerDst, (err) => {
expect(err).to.not.exist
done()
})
})
it('dial on protocol, use warmed conn', (done) => {
swarm.dial(peerDst, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist
conn.end()
conn.on('data', () => {}) // let it flow.. let it flooooow
conn.on('end', done)
})
})
it('close', (done) => {
// cause CI is slow
setTimeout(() => {
swarm.close(done)
}, 1000)
})
// TODO - test that the listener (node.js peer) can dial back
// do that by dialing on a protocol to activate that behaviour
// like libp2p-spdy tests
})

View File

@ -0,0 +1,129 @@
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const multiaddr = require('multiaddr')
const peerId = require('peer-id')
const PeerInfo = require('peer-info')
const WebRTCStar = require('libp2p-webrtc-star')
const spdy = require('libp2p-spdy')
const bl = require('bl')
const parallel = require('run-parallel')
const Swarm = require('../src')
describe('high level API (swarm with spdy + webrtc-star)', function () {
this.timeout(60 * 1000)
let swarm1
let peer1
let wstar1
let swarm2
let peer2
let wstar2
before(() => {
const id1 = peerId.create()
peer1 = new PeerInfo(id1)
const mh1 = multiaddr('/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + id1.toB58String())
peer1.multiaddr.add(mh1)
const id2 = peerId.create()
peer2 = new PeerInfo(id2)
const mh2 = multiaddr('/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + id2.toB58String())
peer2.multiaddr.add(mh2)
swarm1 = new Swarm(peer1)
swarm2 = new Swarm(peer2)
})
it('add WebRTCStar transport to swarm 1', () => {
wstar1 = new WebRTCStar()
swarm1.transport.add('wstar', wstar1)
expect(Object.keys(swarm1.transports).length).to.equal(1)
})
it('add WebRTCStar transport to swarm 2', () => {
wstar2 = new WebRTCStar()
swarm2.transport.add('wstar', wstar2)
expect(Object.keys(swarm2.transports).length).to.equal(1)
})
it('listen on swarm 1', (done) => {
swarm1.listen(done)
})
it('listen on swarm 2', (done) => {
swarm2.listen(done)
})
it('add spdy', () => {
swarm1.connection.addStreamMuxer(spdy)
swarm1.connection.reuse()
swarm2.connection.addStreamMuxer(spdy)
swarm2.connection.reuse()
})
it('handle proto', () => {
swarm2.handle('/echo/1.0.0', (conn) => {
conn.pipe(conn)
})
})
it('dial on proto', (done) => {
swarm1.dial(peer2, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist
expect(Object.keys(swarm1.muxedConns).length).to.equal(1)
const text = 'Hello World'
conn.pipe(bl((err, data) => {
expect(err).to.not.exist
expect(data.toString()).to.equal(text)
expect(Object.keys(swarm2.muxedConns).length).to.equal(1)
done()
}))
conn.write(text)
conn.end()
})
})
it('create a third node and check that discovery works', (done) => {
wstar1.discovery.on('peer', (peerInfo) => {
expect(Object.keys(swarm1.muxedConns).length).to.equal(1)
swarm1.dial(peerInfo, () => {
expect(Object.keys(swarm1.muxedConns).length).to.equal(2)
})
})
wstar2.discovery.on('peer', (peerInfo) => {
swarm2.dial(peerInfo)
})
const id3 = peerId.create()
const peer3 = new PeerInfo(id3)
const mh3 = multiaddr('/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + id3.toB58String())
peer3.multiaddr.add(mh3)
const swarm3 = new Swarm(peer3)
const wstar3 = new WebRTCStar()
swarm3.transport.add('wstar', wstar3)
swarm3.connection.addStreamMuxer(spdy)
swarm3.connection.reuse()
swarm3.listen(() => {
setTimeout(() => {
expect(Object.keys(swarm1.muxedConns).length).to.equal(2)
expect(Object.keys(swarm2.muxedConns).length).to.equal(2)
expect(Object.keys(swarm3.muxedConns).length).to.equal(2)
swarm3.close(done)
}, 8000)
})
})
it('close', (done) => {
parallel([
swarm1.close,
swarm2.close
], done)
})
})

View File

@ -2,11 +2,7 @@
'use strict'
const expect = require('chai').expect
const multiaddr = require('multiaddr')
const Id = require('peer-id')
const Peer = require('peer-info')
const WebSockets = require('libp2p-websockets')
const bl = require('bl')
const w = require('webrtcsupport')
const Swarm = require('../src')
@ -17,109 +13,15 @@ describe('basics', () => {
})
})
describe('transport - websockets', function () {
this.timeout(10000)
require('./browser-00-transport-websockets.js')
var swarm
if (w.support) {
require('./browser-01-transport-webrtc-star.js')
}
before((done) => {
const b58IdSrc = 'QmYzgdesgjdvD3okTPGZT9NPmh1BuH5FfTVNKjsvaAprhb'
// use a pre generated Id to save time
const idSrc = Id.createFromB58String(b58IdSrc)
const peerSrc = new Peer(idSrc)
swarm = new Swarm(peerSrc)
require('./browser-02-swarm-with-muxing-plus-websockets.js')
done()
})
it('add', (done) => {
swarm.transport.add('ws', new WebSockets(), () => {
expect(Object.keys(swarm.transports).length).to.equal(1)
done()
})
})
it('dial', (done) => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/9100/websockets')
const conn = swarm.transport.dial('ws', ma, (err, conn) => {
expect(err).to.not.exist
})
conn.pipe(bl((err, data) => {
expect(err).to.not.exist
expect(data.toString()).to.equal('hey')
done()
}))
conn.write('hey')
conn.end()
})
})
describe('high level API - 1st without stream multiplexing (on websockets)', function () {
this.timeout(10000)
var swarm
var peerDst
before((done) => {
const b58IdSrc = 'QmYzgdesgjdvD3okTPGZT9NPmh1BuH5FfTVNKjsvaAprhb'
// use a pre generated Id to save time
const idSrc = Id.createFromB58String(b58IdSrc)
const peerSrc = new Peer(idSrc)
swarm = new Swarm(peerSrc)
done()
})
after((done) => {
done()
// swarm.close(done)
})
it('add ws', (done) => {
swarm.transport.add('ws', new WebSockets())
expect(Object.keys(swarm.transports).length).to.equal(1)
done()
})
it('create Dst peer info', (done) => {
const b58IdDst = 'QmYzgdesgjdvD3okTPGZT9NPmh1BuH5FfTVNKjsvaAprhb'
// use a pre generated Id to save time
const idDst = Id.createFromB58String(b58IdDst)
peerDst = new Peer(idDst)
const ma = multiaddr('/ip4/127.0.0.1/tcp/9200/websockets')
peerDst.multiaddr.add(ma)
done()
})
it('dial on protocol', (done) => {
swarm.dial(peerDst, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist
conn.pipe(bl((err, data) => {
expect(err).to.not.exist
expect(data.toString()).to.equal('hey')
done()
}))
conn.write('hey')
conn.end()
})
})
it('dial to warm a conn', (done) => {
swarm.dial(peerDst, (err) => {
expect(err).to.not.exist
done()
})
})
it('dial on protocol, reuse warmed conn', (done) => {
swarm.dial(peerDst, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist
conn.end()
conn.on('data', () => {}) // let it flow.. let it flooooow
conn.on('end', done)
})
})
})
if (w.support) {
require('./browser-03-swarm-with-muxing-plus-webrtc-star.js')
require('./browser-04-swarm-with-muxing-plus-websockets-and-webrtc-star.js')
}

5
test/test-data/id-1.json Normal file
View File

@ -0,0 +1,5 @@
{
"id": "QmYmfUS4A3E64BzU8DsCmCWpPhcXWU2KTKNRGtdtN4oCgU",
"privKey": "CAASqAkwggSkAgEAAoIBAQCYtGLh+ow9WEJMn50voPGa6MsqSgJx8pNXGtk5kMSktWxfYHrejLZJjN0+br2CwpFMtf9JW6dAIpxb3qViBCFXjzEK8JuYaXM2sHC6sapyCxeZUbZJtGAXNWQW3qV7m8s8cJTOu2s1euT/G6uf/mIVFIzCkQDx+Ejh5Aie+BTAEf1WbLmcoDDxVESe22gpTxtMG8WTocMV34BxKn8d8vhcZZsi8LLkjg172QwQr3Q68jKgdja3K1YYm6fnso6H3+H06IHgPFAvVhycBbmlyR3bL/hFBl6+ElwBxeIrlM/oAY93KCs622SLYWFHb+J2q7WofSbUSscp3gWj7c8KJqHvAgMBAAECggEBAJZi4BcpBj/L0c9gSg8D86zZomvNY0cQ3GYmPNPibKbBPS9Y9uiBr2wT3DeGHADQ2QOxIO7/4mDZNR+Mz1cONj/i9yuM9c9N2nd7oClcmz2hCualgF5p01BH9oBHWLW5IpgtT3+hN939X9SVTZpNjg6wpEdhQosKN8yvJIZaTyUvh/ZMRIJvbnbLg13gIF7Lpyn1rtFovQg0dET0C8zhTCDPacJIOLp8BIBMknPfOl0SrvOMZjufzVZLvbt0YraXhLK8EWe87ffTMoBlIktWpEKdPBOCuFf4E4WRXJ78tcbvNtx3f5zGi+ZVbKcLA1axu+OqbjHCG6yrlywcVBoTuxECgYEA56yDBaM0VFD1CqsqwYIWmAyYBjV7dkM+ogMb+mfQn+ja6QSt+U/APXB3dP+EDvysh5AZR0wpUrmz14xC1yB1/XAKIfMLQZB8DdUkuj5UcsKjkzLJkIFYGOXIutU7IHTma7s/0fLxwp8SvkEL+6nHuZskf77yjDAvWLZeSD/CYWsCgYEAqL0mKeyyhBBFvNJyE3CyyhDfzgf+NrvrNJcx73nAzLDE44BPc/3lHYn2AJJhasNnjJfRiFzW90PNgCjZLLXqeHkX4xixoibvRtb31WHR2UyxXe/KQZwBy11mPzStnI4Y83C2A8OXsx4xAPq69nX9foSFD6cuLkWUGeb8f7Jxbo0CgYB25mfcJdW+jEom7pAj/kLgSF5hmWNC3+IuPhBG5K8C0vw+6ULsmEyee7EjX9wD4RQfAwqmN+VhaqNtNbQ8OpGzv6PDprwZKzEv3DtcRo8K0vAmpMMkIe334T6y/Kq6zqRPmCt58gi4DPIOqM2gnJM/o+sIkRRkdHpoOjiLNgXp/wKBgQCNrGpLjwl/am4zEHppKhljIPHX+cwORo8/06ZAi/g9pDlbThLnr4fb2kaqyjxyuGfLmnh5xoFSkCINdb6KFJ8t0XYl3UjffVMvJjRle0EG8qaE2Vz24zZ6egvsC52ssX3vf3XDCUjoQfQg/2NUpVJWFIvnzZUvkom7ib38tWUZzQKBgDe0+OqdJEIdajkwCMEYbmZDYqkbw4pgmwSqCwK7HeCi8dvACW5OCCutnN0L57eEltyWy0XP2XmRlfsD0atkKBq3KgNfSawx6/t/K3OtZa8VAtg2M0PbCZljW/8Bz6xlxiyPXFTRgr9zr4yM1homMmPA39hURmXNNedXUh3IMkH7",
"pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYtGLh+ow9WEJMn50voPGa6MsqSgJx8pNXGtk5kMSktWxfYHrejLZJjN0+br2CwpFMtf9JW6dAIpxb3qViBCFXjzEK8JuYaXM2sHC6sapyCxeZUbZJtGAXNWQW3qV7m8s8cJTOu2s1euT/G6uf/mIVFIzCkQDx+Ejh5Aie+BTAEf1WbLmcoDDxVESe22gpTxtMG8WTocMV34BxKn8d8vhcZZsi8LLkjg172QwQr3Q68jKgdja3K1YYm6fnso6H3+H06IHgPFAvVhycBbmlyR3bL/hFBl6+ElwBxeIrlM/oAY93KCs622SLYWFHb+J2q7WofSbUSscp3gWj7c8KJqHvAgMBAAE="
}

5
test/test-data/id-2.json Normal file
View File

@ -0,0 +1,5 @@
{
"id": "QmQAbW9j3wQ8JDFmg8JRid82EpZabuCngVDmhqzCmJwqt6",
"privKey": "CAASpgkwggSiAgEAAoIBAQCAQjiCzMF+PQaDUuNa7avUsj2xnNTQcUrs4yHz/L+JI/AY2ij0iXsBSE0chK1KtBu24gZzWs3/BDyNl28E0Sd41QpK6oTVMHjUfLovO+h7G78bqpI83vk5CEOKt29VihQs282fivbQb5ALYwzBIW2lsIoWwrQq1btsNA5NXJ43OAcPZ9SybBUg49f5gWf/kmh/J6e1rvwyVjQc7cmmpzcQUc+XNL7db6T3ArokXZMyBK6oQCOaJc1bqwgHwYSI3parjds9k8Z6fXA2ub3Va//1EgjQ50lRZH03PGYS42HR1QSSz1eLjMmdrbJrZZj7IbXgqAO6gT6wlGLr5xMQudabAgMBAAECggEAQ9NBESJ4fGqHJDFUG8St5pevelqGTAhtZ+IhFWamXz6K/Il5uP9u9dmnNZqQDX47XbYfVSdC4kX6Q6I+SlzUs9htTfrA7gBpFW00BEB5C4k7wcSs+tWrE9bj6NpiXOjdDG/cSC9zn/wvP2ZM22DzG/jEvY6POku2hlzs50pAPNB7bBaKysA/e52J0Tu/Wf/+sZyp2MiYQJmIkfbYeDF2rqm5y04S6Z31O3SMQIETNcBK8T+L2jwx+Q0msB8toam7hRf1KjxD0yZe+Vff9tPfwjgEoWF+O27g3+rjDq/QqUfzOPMgvAFgELBMpv6CCM8/3l9gUu+7itBxDq65sDCoCQKBgQC6FTLTQA3ux3WV0/7MKXJIHgYZ4b8lIbiiWuO/6t2ZnwvLfTbiU5br/8bcRPL5ygFuIdzkx8VHcbkOmld/VE7qaRZoJb94JVvC6N+5MQxr+pzbWQSNcE+cKJgy1RADea8nad698ifls/39kZGCc6Srt2TqxTBuoZ3c9jEMs3N2pwKBgQCwcxNSw7Wkq302lKc/7QdtfegrwlLjRClLYaW9ESQeErayRY8pxLgl/XKap1HPyc0aQ+78W6w+DAxvcToGBsLak0ujJjzP7b8G6fo+cexuIr8NiGL4LVzpZfQjkfQU4DDwsOdedeKzGelIdstMMtAZDFG9eNPe99XeJBnYfIDS7QKBgH8xFjiHQ/6+n4T2DueGPPNGcm0mfPzoe8ed0KbR5v6mU+2XfPheon5VqpvNFTff9/JLey11z0byWMe+f6gs/HQFuKcfhiydfIdRnfp7qD32Y1kbE52J8yCOLtowAG4fsrWCDBpRdyvvR+EWqxs76IbnKDfA6UX1em4aaZSA5J9pAoGAE8aB5ue6Rt9VZDWa3QZCq9nNmIHp6kCsZB9ohN0T8C7mvOog1myOuutB2eVgvOoAC66LbUsU7ctJ5X+KIjzFv9t8Qae6bw9VNoAopLD974YDZY/gj7H91Maxav8jnOdXdNJOy/5oTuxbgdyWgk67leMUkiiljjq2hHQFVYb2pS0CgYBam0ZJ5Trds1LijE2eoYPyiJdhWEsHYFDzoV17cyjhbSrmlWJBNKQfw6q6UtnxSNFMvsPOZv53d3B8iIDnZ/UHFvw1et+yQk/QrxTfXurqn8lJcMCfKzm3ORKibgJPMmtcPbLoxuEKXMXx18iwoCsMnapijJ0Qj5HofluiupSfxg==",
"pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCAQjiCzMF+PQaDUuNa7avUsj2xnNTQcUrs4yHz/L+JI/AY2ij0iXsBSE0chK1KtBu24gZzWs3/BDyNl28E0Sd41QpK6oTVMHjUfLovO+h7G78bqpI83vk5CEOKt29VihQs282fivbQb5ALYwzBIW2lsIoWwrQq1btsNA5NXJ43OAcPZ9SybBUg49f5gWf/kmh/J6e1rvwyVjQc7cmmpzcQUc+XNL7db6T3ArokXZMyBK6oQCOaJc1bqwgHwYSI3parjds9k8Z6fXA2ub3Va//1EgjQ50lRZH03PGYS42HR1QSSz1eLjMmdrbJrZZj7IbXgqAO6gT6wlGLr5xMQudabAgMBAAE="
}