diff --git a/src/circuit/dialer.js b/src/circuit/dialer.js index 0c965f8..656e942 100644 --- a/src/circuit/dialer.js +++ b/src/circuit/dialer.js @@ -34,14 +34,23 @@ class Dialer { * Dial a peer over a relay * * @param {multiaddr} ma - the multiaddr of the peer to dial - * @param {Object} options - dial options * @param {Function} cb - a callback called once dialed * @returns {Connection} - the connection * * @memberOf Dialer */ - dial (ma, options, cb) { - throw new Error('abstract class, method not implemented') + dial (ma, cb) { + const dstConn = new Connection() + setImmediate(this.dialPeer.bind(this), multiaddr(ma), (err, conn) => { + if (err) { + log.err(err) + return cb(err) + } + dstConn.setInnerConn(conn) + cb(null, dstConn) + }) + + return dstConn } /** @@ -186,8 +195,22 @@ class Dialer { return cb(err) } - this.relayPeers.set(this.utils.getB58String(peer), peer) - cb(null) + streamHandler.read((err, msg) => { + if (err) { + log.err(err) + return cb(err) + } + + const response = proto.CircuitRelay.decode(msg) + + if (response.code !== proto.CircuitRelay.Status.SUCCESS) { + return log(`HOP not supported, skipping - ${this.utils.getB58String(peer)}`) + } + + log(`HOP supported adding as relay - ${this.utils.getB58String(peer)}`) + this.relayPeers.set(this.utils.getB58String(peer), peer) + cb(null) + }) }) }) } diff --git a/src/circuit/onion-dialer.js b/src/circuit/onion-dialer.js deleted file mode 100644 index 603b4d9..0000000 --- a/src/circuit/onion-dialer.js +++ /dev/null @@ -1,161 +0,0 @@ -'use strict' - -const setImmediate = require('async/setImmediate') - -const Dialer = require('./dialer') -const isFunction = require('lodash.isfunction') -const multiaddr = require('multiaddr') -const Connection = require('interface-connection').Connection -const multicodec = require('../multicodec') - -const debug = require('debug') -const log = debug('libp2p:circuit:oniondialer') -log.err = debug('libp2p:circuit:error:oniondialer') - -class OnionDialer extends Dialer { - /** - * Dial a peer over a relay - * - * @param {multiaddr} ma - the multiaddr of the peer to dial - * @param {Object} options - dial options - * @param {Function} cb - a callback called once dialed - * @returns {Connection} - the connection - * - * @memberOf Dialer - */ - dial (ma, options, cb) { - if (isFunction(options)) { - cb = options - options = {} - } - - if (!cb) { - cb = () => {} - } - - let maddrs = multiaddr(ma).toString().split('/p2p-circuit').filter((a) => a.length) - if (maddrs.length > 0) { - const id = multiaddr(maddrs[maddrs.length - 1]).getPeerId() - if (this.swarm._peerInfo.id.toB58String() === id) { - let err = `cant dial to self!` - log.err(err) - return cb(err) - } - } - - let dstConn = new Connection() - setImmediate(this._onionDial.bind(this), maddrs, (err, conn) => { - if (err) { - log.err(err) - return cb(err) - } - dstConn.setInnerConn(conn) - cb(null, dstConn) - }) - - return dstConn - } - - /** - * Dial a peer using onion dial - dial all relays in the ma - * in sequence and circuit dest over the all the pipes - * - * @param {multiaddr} maddrs - * @param {Connection} relay - * @param {Function} cb - * @return {void} - * @private - */ - _onionDial (maddrs, relay, cb) { - if (isFunction(relay)) { - cb = relay - relay = null - } - - const dial = (dstAddr, relayPeer) => { - if (maddrs.length) { - this._createRelayPipe(dstAddr, relayPeer, (err, upgraded) => { - if (err) { - log.err(err) - return cb(err) - } - return this._onionDial(maddrs, upgraded, cb) - }) - } else { - this.dialPeer(dstAddr, relayPeer, (err, conn) => { - if (err) { - return cb(err) - } - cb(null, conn) - }) - } - } - - if (maddrs.length >= 2) { - const relayAddr = multiaddr(maddrs.shift()) - const destAddr = multiaddr(maddrs.shift()) - dial(destAddr, relayAddr) - } else { - dial(multiaddr(maddrs.shift()), relay) - } - } - - /** - * Creates a relay connection that can be used explicitly from two multiaddrs - * - * @param {Multiaddr} dstAddr - * @param {Multiaddr} relayPeer - * @param {Function} cb - * @returns {void|Function} - * @private - */ - _createRelayPipe (dstAddr, relayPeer, cb) { - this.dialPeer(dstAddr, relayPeer, (err, conn) => { - if (err) { - log.err(err) - return cb(err) - } - - dstAddr = multiaddr(dstAddr) - this.relayPeers.set(dstAddr.getPeerId(), conn) - this._handshake(this.utils.peerInfoFromMa(dstAddr), conn, (err, upgraded) => { - if (err) { - log.err(err) - return cb(err) - } - - cb(null, upgraded) - }) - }) - } - - /** - * Upgrade a raw connection to a relayed link (hop) - * - * @param {PeerInfo} pi - * @param {Connection} conn - * @param {Function} cb - * - * @return {Function|void} - * @private - */ - _handshake (pi, conn, cb) { - const proxyConn = new Connection() - const handler = this.swarm.connHandler(pi, multicodec.relay, proxyConn) - handler.handleNew(conn, (err, upgradedConn) => { - if (err) { - log.err(err) - return cb(err) - } - - if (!upgradedConn) { - proxyConn.setInnerConn(conn) - upgradedConn = proxyConn - } - - cb(null, upgradedConn) - }) - } -} - -module.exports = OnionDialer diff --git a/src/dialer.js b/src/dialer.js index ec94912..fe14fee 100644 --- a/src/dialer.js +++ b/src/dialer.js @@ -3,7 +3,7 @@ const mafmt = require('mafmt') const multiaddr = require('multiaddr') -const OnionDialer = require('./circuit/onion-dialer') +const CircuitDialer = require('./circuit/dialer') const utilsFactory = require('./circuit/utils') const debug = require('debug') @@ -40,7 +40,7 @@ class Dialer { } // TODO: add flag for other types of dealers, ie telescope - this.dialer = new OnionDialer(swarm, options) + this.dialer = new CircuitDialer(swarm, options) this.swarm.on('peer-mux-established', this.dialer.canHop.bind(this.dialer)) this.swarm.on('peer-mux-closed', (peerInfo) => { diff --git a/src/index.js b/src/index.js index 4f6f02b..7f61d16 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,3 @@ 'use strict' -module.exports = { - Hop: require('./circuit/hop'), - Dialer: require('./dialer'), - multicodec: require('./multicodec'), - tag: 'Circuit' -} +module.exports = require('./dialer') diff --git a/test/onion-dialer.spec.js b/test/onion-dialer.spec.js deleted file mode 100644 index 902277e..0000000 --- a/test/onion-dialer.spec.js +++ /dev/null @@ -1,172 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const Dialer = require('../src/circuit/onion-dialer') -const nodes = require('./fixtures/nodes') -const Connection = require('interface-connection').Connection -const multiaddr = require('multiaddr') -const PeerInfo = require('peer-info') -const PeerId = require('peer-id') -const waterfall = require('async/waterfall') - -const sinon = require('sinon') -const expect = require('chai').expect - -describe('onion dialer tests', function () { - describe('dial', function () { - const dialer = sinon.createStubInstance(Dialer) - - beforeEach(function (done) { - waterfall([ - (cb) => PeerId.createFromJSON(nodes.node4, cb), - (peerId, cb) => PeerInfo.create(peerId, cb), - (peer, cb) => { - dialer.swarm = { - _peerInfo: peer - } - cb() - } - ], done) - - dialer.dial.callThrough() - }) - - afterEach(function () { - dialer.dial.reset() - dialer._onionDial.reset() - }) - - it(`split the multiaddr correctly`, function (done) { - dialer._onionDial.callsArgWith(1, null, new Connection()) - - const chainedAddr = multiaddr( - `/ip4/0.0.0.0/tcp/9033/ws/ipfs/${nodes.node2.id}/p2p-circuit` + - `/ip4/0.0.0.0/tcp/9031/ipfs/${nodes.node1.id}/p2p-circuit/`) - - dialer.dial(chainedAddr + `/ipfs/${nodes.node3.id}`, (err, conn) => { - expect(err).to.be.null - expect(dialer._onionDial.calledOnce).to.be.ok - expect(dialer._onionDial.calledWith([ - `/ip4/0.0.0.0/tcp/9033/ws/ipfs/${nodes.node2.id}`, - `/ip4/0.0.0.0/tcp/9031/ipfs/${nodes.node1.id}`, - `/ipfs/${nodes.node3.id}` - ])).to.be.ok - done() - }) - }) - - it(`not dial to itself`, function (done) { - const chainedAddr = multiaddr( - `/ip4/0.0.0.0/tcp/9033/ws/ipfs/${nodes.node2.id}/p2p-circuit` + - `/ip4/0.0.0.0/tcp/9031/ipfs/${nodes.node1.id}/p2p-circuit/`) - - dialer.dial(chainedAddr + `/ipfs/${nodes.node4.id}`, (err, conn) => { - expect(err).to.not.be.null - expect(err).to.be.equal(`cant dial to self!`) - expect(dialer._onionDial.calledOnce).to.not.be.ok - done() - }) - }) - }) - - describe('_onionDial', function () { - describe('_onionDial chained address', function () { - const dialer = sinon.createStubInstance(Dialer) - dialer.relayPeers = new Map() - - let swarm = null - let upgraded = null - beforeEach(function (done) { - waterfall([ - (cb) => PeerId.createFromJSON(nodes.node4, cb), - (peerId, cb) => PeerInfo.create(peerId, cb), - (peer, cb) => { - swarm = { - _peerInfo: peer, - _peerBook: { - get: () => new PeerInfo(PeerId.createFromB58String('QmSswe1dCFRepmhjAMR5VfHeokGLcvVggkuDJm7RMfJSrE')), - has: () => true - } - } - dialer.swarm = swarm - cb() - }, - (cb) => { - upgraded = new Connection() - dialer._onionDial.callThrough() - dialer.dialPeer.onCall(0).callsArgWith(2, null, new Connection()) - dialer._createRelayPipe.onCall(0).callsArgWith(2, null, upgraded) - dialer.dialPeer.onCall(1).callsArgWith(2, null, new Connection()) - cb() - } - ], done) - }) - - afterEach(function () { - dialer.dial.reset() - dialer.dialRelay.reset() - }) - - it(`dial chained multiaddr correctly`, function (done) { - const chainedAddrs = [ - `/ip4/0.0.0.0/tcp/9033/ws/ipfs/${nodes.node2.id}`, - `/ip4/0.0.0.0/tcp/9031/ipfs/${nodes.node1.id}`, - `/ipfs/${nodes.node3.id}` - ] - - const addr1 = multiaddr(chainedAddrs[0]) - const addr2 = multiaddr(chainedAddrs[1]) - const addr3 = multiaddr(chainedAddrs[2]) - - dialer._onionDial(chainedAddrs, (err, conn) => { - expect(err).to.be.null - expect(dialer._createRelayPipe.calledWith(addr2, addr1)).to.be.ok - expect(dialer.dialPeer.calledWith(addr3, upgraded)).to.be.ok - done() - }) - }) - }) - - describe('_onionDial non chained address', function () { - const dialer = sinon.createStubInstance(Dialer) - dialer.relayPeers = new Map() - - let swarm - beforeEach(function (done) { - waterfall([ - (cb) => PeerId.createFromJSON(nodes.node4, cb), - (peerId, cb) => PeerInfo.create(peerId, cb), - (peer, cb) => { - swarm = { - _peerInfo: peer, - _peerBook: { - get: () => new PeerInfo(PeerId.createFromB58String('QmSswe1dCFRepmhjAMR5VfHeokGLcvVggkuDJm7RMfJSrE')), - has: () => true - } - } - dialer.swarm = swarm - cb() - }, - (cb) => { - dialer._onionDial.callThrough() - dialer.dialPeer.onCall(0).callsArgWith(2, null, new Connection()) - cb() - } - ], done) - }) - - afterEach(function () { - dialer.dial.reset() - dialer.dialRelay.reset() - }) - - it(`dial chained multiaddr correctly`, function (done) { - dialer._onionDial([`/ip4/0.0.0.0/tcp/9033/ws/ipfs/${nodes.node2.id}`], (err, conn) => { - expect(err).to.be.null - expect(dialer.dialPeer.calledWith(multiaddr(`/ip4/0.0.0.0/tcp/9033/ws/ipfs/${nodes.node2.id}`))).to.be.ok - done() - }) - }) - }) - }) -})