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

Commit 30fb36f

Browse files
dryajovdaviddias
authored andcommitted
feat: Circuit Relay (#224)
1 parent 4208f24 commit 30fb36f

22 files changed

+240
-54
lines changed

gulpfile.js renamed to .aegir.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict'
22

3-
const gulp = require('gulp')
43
const PeerInfo = require('peer-info')
54
const PeerId = require('peer-id')
65
const WebSockets = require('libp2p-websockets')
@@ -23,7 +22,7 @@ const options = {
2322
host: '127.0.0.1'
2423
}
2524

26-
gulp.task('test:browser:before', (done) => {
25+
function before (done) {
2726
function createListenerA (cb) {
2827
PeerId.createFromJSON(
2928
JSON.parse(
@@ -79,15 +78,22 @@ gulp.task('test:browser:before', (done) => {
7978
function echo (protocol, conn) {
8079
pull(conn, conn)
8180
}
82-
})
81+
}
8382

84-
gulp.task('test:browser:after', (done) => {
83+
function after (done) {
8584
let count = 0
8685
const ready = () => ++count === 3 ? done() : null
8786

8887
swarmA.transport.close('ws', ready)
8988
swarmB.close(ready)
9089
sigS.stop(ready)
91-
})
90+
}
9291

93-
require('aegir/gulp')(gulp)
92+
module.exports = {
93+
hooks: {
94+
browser: {
95+
pre: before,
96+
post: after
97+
}
98+
}
99+
}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
**/node_modules/
23
**/*.log
34
test/repo-tests*
@@ -38,5 +39,7 @@ test/test-data/go-ipfs-repo/LOCK
3839
test/test-data/go-ipfs-repo/LOG
3940
test/test-data/go-ipfs-repo/LOG.old
4041

42+
docs
4143
# while testing npm5
4244
package-lock.json
45+
yarn.lock

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ addons:
2929
sources:
3030
- ubuntu-toolchain-r-test
3131
packages:
32-
- g++-4.8
32+
- g++-4.8

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ const secio = require('libp2p-secio')
127127
swarm.connection.crypto(secio.tag, secio.encrypt)
128128
```
129129

130+
##### `swarm.connection.enableCircuitRelay(options)`
131+
132+
Enable circuit relaying.
133+
134+
- `options`
135+
- enabled - activates relay dialing and listening functionality
136+
- hop - an object with two properties
137+
- enabled - enables circuit relaying
138+
- active - is it an active or passive relay (default false)
139+
130140
### `swarm.dial(peer, protocol, callback)`
131141

132142
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.

circle.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ dependencies:
66
pre:
77
- google-chrome --version
88
- curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
9+
- for v in $(curl http://archive.ubuntu.com/ubuntu/pool/main/n/nss/ | grep "href=" | grep "libnss3.*deb\"" -o | grep -o "libnss3.*deb" | grep "3.28" | grep "14.04"); do curl -L -o $v http://archive.ubuntu.com/ubuntu/pool/main/n/nss/$v; done && rm libnss3-tools*_i386.deb libnss3-dev*_i386.deb
910
- sudo dpkg -i google-chrome.deb || true
11+
- sudo dpkg -i libnss3*.deb || true
1012
- sudo apt-get update
13+
- sudo apt-get install -f || true
14+
- sudo dpkg -i libnss3*.deb
1115
- sudo apt-get install -f
1216
- sudo apt-get install --only-upgrade lsb-base
1317
- sudo dpkg -i google-chrome.deb
14-
- google-chrome --version
18+
- google-chrome --version

package.json

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
"description": "libp2p swarm implementation in JavaScript",
55
"main": "src/index.js",
66
"scripts": {
7-
"lint": "gulp lint",
8-
"build": "gulp build",
9-
"test": "gulp test --dom",
10-
"test:node": "gulp test:node",
11-
"test:browser": "gulp test:browser --dom",
12-
"release": "gulp release --dom",
13-
"release-minor": "gulp release --type minor --dom",
14-
"release-major": "gulp release --type major --dom",
15-
"coverage": "gulp coverage",
16-
"coverage-publish": "aegir-coverage publish"
7+
"lint": "aegir lint",
8+
"build": "aegir build",
9+
"test": "aegir test --target node --target browser --no-parallel",
10+
"test:node": "aegir test --target node --no-parallel",
11+
"test:browser": "aegir test --target browser --no-parallel",
12+
"release": "aegir test release --target node --target browser --no-parallel",
13+
"release-minor": "aegir release --type minor --target node --target browser --no-parallel",
14+
"release-major": "aegir release --type major --target node --target browser --no-parallel",
15+
"coverage": "aegir coverage",
16+
"coverage-publish": "aegir coverage --provider coveralls"
1717
},
1818
"browser": {
19-
"zlib": "browserify-zlib-next"
19+
"zlib": "browserify-zlib"
2020
},
2121
"repository": {
2222
"type": "git",
@@ -40,35 +40,37 @@
4040
"npm": ">=3.0.0"
4141
},
4242
"devDependencies": {
43-
"aegir": "^11.0.2",
43+
"aegir": "^12.1.0",
4444
"buffer-loader": "0.0.1",
4545
"chai": "^4.1.2",
4646
"dirty-chai": "^2.0.1",
4747
"gulp": "^3.9.1",
4848
"libp2p-multiplex": "~0.5.0",
4949
"libp2p-secio": "~0.8.1",
5050
"libp2p-spdy": "~0.11.0",
51-
"libp2p-tcp": "~0.11.0",
51+
"libp2p-tcp": "~0.11.1",
5252
"libp2p-webrtc-star": "~0.13.2",
53-
"libp2p-websockets": "~0.10.1",
53+
"libp2p-websockets": "~0.10.2",
54+
"peer-book": "~0.5.1",
5455
"pre-commit": "^1.2.2",
5556
"pull-goodbye": "0.0.2",
56-
"peer-book": "~0.5.1",
57+
"sinon": "^4.0.1",
5758
"webrtcsupport": "^2.2.0"
5859
},
5960
"dependencies": {
6061
"async": "^2.5.0",
61-
"browserify-zlib-next": "^1.0.1",
62-
"debug": "^3.0.1",
62+
"browserify-zlib": "^0.2.0",
63+
"debug": "^3.1.0",
6364
"interface-connection": "~0.3.2",
6465
"ip-address": "^5.8.8",
66+
"libp2p-circuit": "~0.1.0",
6567
"libp2p-identify": "~0.6.1",
6668
"lodash.includes": "^4.3.0",
6769
"multiaddr": "^3.0.1",
6870
"multistream-select": "~0.13.5",
6971
"once": "^1.4.0",
70-
"peer-id": "~0.10.1",
71-
"peer-info": "~0.11.0",
72+
"peer-id": "^0.10.2",
73+
"peer-info": "^0.11.0",
7274
"pull-stream": "^3.6.1"
7375
},
7476
"contributors": [
@@ -88,4 +90,4 @@
8890
"greenkeeper[bot] <greenkeeper[bot]@users.noreply.github.com>",
8991
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>"
9092
]
91-
}
93+
}

src/connection.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const debug = require('debug')
77
const log = debug('libp2p:swarm:connection')
88
const setImmediate = require('async/setImmediate')
99

10+
const Circuit = require('libp2p-circuit')
11+
1012
const protocolMuxer = require('./protocol-muxer')
1113
const plaintext = require('./plaintext')
1214

@@ -92,6 +94,19 @@ module.exports = function connection (swarm) {
9294
})
9395
},
9496

97+
enableCircuitRelay (config) {
98+
config = config || {}
99+
100+
if (config.enabled) {
101+
if (!config.hop) {
102+
Object.assign(config, { hop: { enabled: false, active: false } })
103+
}
104+
105+
// TODO: should we enable circuit listener and dialer by default?
106+
swarm.transport.add(Circuit.tag, new Circuit(swarm, config))
107+
}
108+
},
109+
95110
crypto (tag, encrypt) {
96111
if (!tag && !encrypt) {
97112
tag = plaintext.tag

src/dial.js

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const multistream = require('multistream-select')
44
const Connection = require('interface-connection').Connection
55
const setImmediate = require('async/setImmediate')
66
const getPeerInfo = require('./get-peer-info')
7+
const Circuit = require('libp2p-circuit')
8+
79
const debug = require('debug')
810
const log = debug('libp2p:swarm:dial')
911

@@ -81,18 +83,22 @@ function dial (swarm) {
8183
function attemptDial (pi, cb) {
8284
const tKeys = swarm.availableTransports(pi)
8385

84-
if (tKeys.length === 0) {
85-
return cb(new Error('No available transport to dial to'))
86-
}
87-
8886
nextTransport(tKeys.shift())
8987

9088
function nextTransport (key) {
89+
if (!key) {
90+
return dialCircuit((err, circuit) => {
91+
if (err) {
92+
return cb(new Error('Could not dial in any of the transports or relays'))
93+
}
94+
95+
cb(null, circuit)
96+
})
97+
}
98+
99+
log(`dialing transport ${key}`)
91100
swarm.transport.dial(key, pi, (err, conn) => {
92101
if (err) {
93-
if (tKeys.length === 0) {
94-
return cb(new Error('Could not dial in any of the transports'))
95-
}
96102
return nextTransport(tKeys.shift())
97103
}
98104

@@ -121,6 +127,19 @@ function dial (swarm) {
121127
}
122128
}
123129

130+
function dialCircuit (cb) {
131+
log(`Falling back to dialing over circuit`)
132+
pi.multiaddrs.add(`/p2p-circuit/ipfs/${pi.id.toB58String()}`)
133+
swarm.transport.dial(Circuit.tag, pi, (err, conn) => {
134+
if (err) {
135+
log(err)
136+
return cb(err)
137+
}
138+
139+
cb(null, conn)
140+
})
141+
}
142+
124143
function attemptMuxerUpgrade (conn, cb) {
125144
const muxers = Object.keys(swarm.muxers)
126145
if (muxers.length === 0) {

src/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ function Swarm (peerInfo, peerBook) {
6565

6666
// Only listen on transports we actually have addresses for
6767
return myTransports.filter((ts) => this.transports[ts].filter(myAddrs).length > 0)
68+
// push Circuit to be the last proto to be dialed
69+
.sort((a) => {
70+
return a === 'Circuit' ? -1 : 0
71+
})
6872
}
6973

7074
// higher level (public) API

src/limit-dialer/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const map = require('async/map')
44
const debug = require('debug')
5+
const once = require('once')
56

67
const log = debug('libp2p:swarm:dialer')
78

@@ -37,6 +38,7 @@ class LimitDialer {
3738
log('dialMany:start')
3839
// we use a token to track if we want to cancel following dials
3940
const token = { cancel: false }
41+
callback = once(callback) // only call callback once
4042

4143
map(addrs, (m, cb) => {
4244
this.dialSingle(peer, transport, m, token, cb)

0 commit comments

Comments
 (0)