Skip to content
This repository was archived by the owner on Aug 23, 2019. It is now read-only.

Commit

Permalink
update to latest dependencies and add new crypto api
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire committed Sep 7, 2016
1 parent 381d3c2 commit c28b845
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 81 deletions.
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ const sw = new Swarm(peerInfo)

## API

peerInfo 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/libp2p/js-peer-info) object that represents the peer creating this swarm instance.

### Transports

##### `swarm.transport.add(key, transport, options, callback)`

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).
libp2p-swarm expects transports that implement [interface-transport](https://github.com/libp2p/abstract-transport). For example [libp2p-tcp](https://github.com/libp2p/js-libp2p-tcp).

- `key` - the transport identifier.
- `transport` -
Expand Down Expand Up @@ -100,20 +100,31 @@ Close the listeners of a given transport.

##### `swarm.connection.addUpgrade()`

A connection upgrade must be able to receive and return something that implements the [interface-connection](https://github.com/diasdavid/interface-connection) specification.
A connection upgrade must be able to receive and return something that implements the [interface-connection](https://github.com/libp2p/interface-connection) specification.

> **WIP**
##### `swarm.connection.addStreamMuxer(muxer)`

Upgrading a connection to use a stream muxer is still considered an upgrade, but a special case since once this connection is applied, the returned obj will implement the [interface-stream-muxer](https://github.com/diasdavid/interface-stream-muxer) spec.
Upgrading a connection to use a stream muxer is still considered an upgrade, but a special case since once this connection is applied, the returned obj will implement the [interface-stream-muxer](https://github.com/libp2p/interface-stream-muxer) spec.

- `muxer`

##### `swarm.connection.reuse()`

Enable the identify protocol.

##### `swarm.connection.crypto([tag, encrypt])`

Enable a specified crypto protocol. By default no encryption is used, aka `plaintext`. If called with no arguments it resets to use `plaintext`.

You can use for example [libp2p-secio](https://github.com/libp2p/js-libp2p-secio) like this

```js
const secio = require('libp2p-secio')
swarm.connection.crypto(secio.tag, secio.encrypt)
```

### `swarm.dial(pi, protocol, callback)`

dial uses the best transport (whatever works first, in the future we can have some criteria), and jump starts the connection until the point where we have to negotiate the protocol. If a muxer is available, then drop the muxer onto that connection. Good to warm up connections or to check for connectivity. If we have already a muxer for that peerInfo, then do nothing.
Expand Down Expand Up @@ -158,11 +169,11 @@ Close all the listeners and muxers.

libp2p is designed to support multiple transports at the same time. While peers are identified by their ID (which are generated from their public keys), the addresses of each pair may vary, depending the device where they are being run or the network in which they are accessible through.

In order for a transport to be supported, it has to follow the [interface-transport](https://github.com/diasdavid/interface-transport) spec.
In order for a transport to be supported, it has to follow the [interface-transport](https://github.com/libp2p/interface-transport) spec.

### Connection upgrades

Each connection in libp2p follows the [interface-connection](https://github.com/diasdavid/interface-connection) spec. This design decision enables libp2p to have upgradable transports.
Each connection in libp2p follows the [interface-connection](https://github.com/libp2p/interface-connection) spec. This design decision enables libp2p to have upgradable transports.

We think of `upgrade` as a very important notion when we are talking about connections, we can see mechanisms like: stream multiplexing, congestion control, encrypted channels, multipath, simulcast, etc, as `upgrades` to a connection. A connection can be a simple and with no guarantees, drop a packet on the network with a destination thing, a transport in the other hand can be a connection and or a set of different upgrades that are mounted on top of each other, giving extra functionality to that connection and therefore `upgrading` it.

Expand Down
29 changes: 15 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "libp2p-swarm",
"version": "0.22.3",
"description": "libp2p swarm implementation in JavaScript",
"main": "src/index.js",
"main": "lib/index.js",
"jsnext:main": "src/index.js",
"scripts": {
"lint": "gulp lint",
Expand Down Expand Up @@ -37,35 +37,36 @@
"node": "^4.3.0"
},
"devDependencies": {
"aegir": "^6.0.1",
"aegir": "^8.0.0",
"buffer-loader": "0.0.1",
"chai": "^3.5.0",
"gulp": "^3.9.1",
"libp2p-multiplex": "^0.2.1",
"libp2p-spdy": "^0.8.1",
"libp2p-tcp": "^0.7.4",
"libp2p-webrtc-star": "^0.3.2",
"libp2p-websockets": "^0.7.1",
"libp2p-spdy": "^0.9.0",
"libp2p-tcp": "^0.8.1",
"libp2p-webrtc-star": "^0.4.1",
"libp2p-websockets": "^0.8.1",
"pre-commit": "^1.1.3",
"pull-goodbye": "0.0.1",
"pull-stream": "^3.4.3",
"pull-stream": "^3.4.5",
"webrtcsupport": "^2.2.0"
},
"dependencies": {
"babel-runtime": "^6.9.0",
"babel-runtime": "^6.11.6",
"browserify-zlib": "github:ipfs/browserify-zlib",
"debug": "^2.2.0",
"interface-connection": "^0.1.7",
"ip-address": "^5.8.0",
"libp2p-identify": "^0.1.3",
"libp2p-secio": "^0.3.0",
"interface-connection": "^0.2.1",
"ip-address": "^5.8.2",
"libp2p-identify": "^0.2.0",
"libp2p-secio": "^0.4.2",
"lodash.contains": "^2.4.3",
"multiaddr": "^2.0.2",
"multistream-select": "^0.10.0",
"multistream-select": "^0.11.0",
"peer-id": "^0.7.0",
"peer-info": "^0.7.0",
"protocol-buffers": "^3.1.6",
"run-parallel": "^1.1.6"
"run-parallel": "^1.1.6",
"run-waterfall": "^1.1.3"
},
"contributors": [
"David Dias <daviddias.p@gmail.com>",
Expand Down
48 changes: 31 additions & 17 deletions src/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

const identify = require('libp2p-identify')
const multistream = require('multistream-select')
const waterfall = require('run-waterfall')
const debug = require('debug')
const log = debug('libp2p:swarm:connection')

const protocolMuxer = require('./protocol-muxer')
const plaintext = require('./plaintext')

module.exports = function connection (swarm) {
return {
Expand All @@ -17,7 +19,7 @@ module.exports = function connection (swarm) {

// for listening
swarm.handle(muxer.multicodec, (conn) => {
const muxedConn = muxer.listen(conn)
const muxedConn = muxer.listener(conn)

muxedConn.on('stream', (conn) => {
protocolMuxer(swarm.protocols, conn)
Expand All @@ -32,23 +34,18 @@ module.exports = function connection (swarm) {
conn.getPeerInfo = (cb) => {
const conn = muxedConn.newStream()
const ms = new multistream.Dialer()
ms.handle(conn, (err) => {
if (err) { return cb(err) }

ms.select(identify.multicodec, (err, conn) => {
if (err) { return cb(err) }

identify.listen(conn, (err, peerInfo, observedAddrs) => {
if (err) { return cb(err) }

observedAddrs.forEach((oa) => {
swarm._peerInfo.multiaddr.addSafe(oa)
})

cb(null, peerInfo)
waterfall([
(cb) => ms.handle(conn, cb),
(cb) => ms.select(identify.multicodec, cb),
(conn, cb) => identify.dialer(conn, cb),
(peerInfo, observedAddrs, cb) => {
observedAddrs.forEach((oa) => {
swarm._peerInfo.multiaddr.addSafe(oa)
})
})
})
cb(null, peerInfo)
}
], cb)
}

conn.getPeerInfo((err, peerInfo) => {
Expand All @@ -74,8 +71,25 @@ module.exports = function connection (swarm) {
reuse () {
swarm.identify = true
swarm.handle(identify.multicodec, (conn) => {
identify.dial(conn, swarm._peerInfo)
identify.listener(conn, swarm._peerInfo)
})
},

crypto (tag, encrypt) {
if (!tag && !encrypt) {
tag = plaintext.tag
encrypt = plaintext.encrypt
}

swarm.unhandle(swarm.crypto.tag)
swarm.handle(tag, (conn) => {
const id = swarm._peerInfo.id
const secure = encrypt(id, id.privKey, conn)

protocolMuxer(swarm.protocols, secure)
})

swarm.crypto = {tag, encrypt}
}
}
}
13 changes: 5 additions & 8 deletions src/dial.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ const debug = require('debug')
const log = debug('libp2p:swarm:dial')

const protocolMuxer = require('./protocol-muxer')
const secio = require('./secio')
const tags = require('./tags')

module.exports = function dial (swarm) {
return (pi, protocol, callback) => {
Expand Down Expand Up @@ -108,16 +106,15 @@ module.exports = function dial (swarm) {
}

const id = swarm._peerInfo.id
if (id.privKey == null || swarm.encrypt === false) {
return ms.select(tags.plaintext, cb)
}

ms.select(tags.secio, (err, conn) => {
log('selecting crypto: %s', swarm.crypto.tag)
ms.select(swarm.crypto.tag, (err, conn) => {
if (err) {
return cb(err)
}

cb(null, secio.create(id, conn))
const wrapped = swarm.crypto.encrypt(id, id.privKey, conn)
cb(null, wrapped)
})
})
}
Expand Down Expand Up @@ -155,7 +152,7 @@ module.exports = function dial (swarm) {
return
}

const muxedConn = swarm.muxers[key].dial(conn)
const muxedConn = swarm.muxers[key].dialer(conn)
swarm.muxedConns[b58Id] = {}
swarm.muxedConns[b58Id].muxer = muxedConn
// should not be needed anymore - swarm.muxedConns[b58Id].conn = conn
Expand Down
25 changes: 8 additions & 17 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ const transport = require('./transport')
const connection = require('./connection')
const dial = require('./dial')
const protocolMuxer = require('./protocol-muxer')
const secio = require('./secio')
const tags = require('./tags')
const plaintext = require('./plaintext')

exports = module.exports = Swarm

Expand Down Expand Up @@ -52,8 +51,8 @@ function Swarm (peerInfo) {
// is the Identify protocol enabled?
this.identify = false

// is encryption enabled?
this.encrypt = true
// Crypto details
this.crypto = plaintext

this.transport = transport(this)
this.connection = connection(this)
Expand Down Expand Up @@ -95,21 +94,13 @@ function Swarm (peerInfo) {
this.protocols[protocol] = handler
}

let cryptoTag = tags.secio
if (this.encrypt === false) {
cryptoTag = tags.plaintext
}

this.handle(cryptoTag, (conn) => {
if (this.encrypt === false) {
return protocolMuxer(this.protocols, conn)
}

const secure = secio.create(this._peerInfo.id, conn)
protocolMuxer(this.protocols, secure)
this.handle(this.crypto.tag, (conn) => {
const id = this._peerInfo.id
const wrapped = this.crypto.encrypt(id, id.privKey, conn)
return protocolMuxer(this.protocols, wrapped)
})

this.unhandle = (protocol, handler) => {
this.unhandle = (protocol) => {
if (this.protocols[protocol]) {
delete this.protocols[protocol]
}
Expand Down
8 changes: 8 additions & 0 deletions src/plaintext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict'

module.exports = {
tag: '/plaintext/1.0.0',
encrypt (id, privKey, conn) {
return conn
}
}
10 changes: 0 additions & 10 deletions src/secio.js

This file was deleted.

6 changes: 0 additions & 6 deletions src/tags.js

This file was deleted.

12 changes: 9 additions & 3 deletions test/06-conn-upgrade-secio.node.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const Peer = require('peer-info')
const TCP = require('libp2p-tcp')
const multiplex = require('libp2p-spdy')
const pull = require('pull-stream')
const secio = require('libp2p-secio')

const Swarm = require('../src')

Expand Down Expand Up @@ -37,9 +38,9 @@ describe('secio conn upgrade (on TCP)', () => {
swarmB = new Swarm(peerB)
swarmC = new Swarm(peerC)

swarmA.encrypt = true
swarmB.encrypt = true
swarmC.encrypt = true
swarmA.connection.crypto(secio.tag, secio.encrypt)
swarmB.connection.crypto(secio.tag, secio.encrypt)
swarmC.connection.crypto(secio.tag, secio.encrypt)

swarmA.transport.add('tcp', new TCP())
swarmB.transport.add('tcp', new TCP())
Expand Down Expand Up @@ -113,4 +114,9 @@ describe('secio conn upgrade (on TCP)', () => {
}, 500)
})
})

it('switch back to plaintext if no arguments passed in', () => {
swarmA.connection.crypto()
expect(swarmA.crypto.tag).to.be.eql('/plaintext/1.0.0')
})
})

0 comments on commit c28b845

Please sign in to comment.