From bdfd042ace23b1156ead33fa80c433baf45a3987 Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 23 Mar 2017 15:09:06 +0000 Subject: [PATCH] DNS support (#56) * feat: dns support --- package.json | 2 +- src/index.js | 19 +++--- src/listener.js | 24 +++---- src/ma-to-url.js | 22 +++++++ test/compliance.node.js | 17 ++--- test/node.js | 134 ++++++++++++++++++++++++++++++++++++---- 6 files changed, 173 insertions(+), 45 deletions(-) create mode 100644 src/ma-to-url.js diff --git a/package.json b/package.json index abe6db3..d5ef43b 100644 --- a/package.json +++ b/package.json @@ -60,4 +60,4 @@ "Greenkeeper ", "Richard Littauer " ] -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js index 57da7b0..21a5a6f 100644 --- a/src/index.js +++ b/src/index.js @@ -4,25 +4,22 @@ const connect = require('pull-ws/client') const mafmt = require('mafmt') const includes = require('lodash.includes') const Connection = require('interface-connection').Connection +const maToUrl = require('./ma-to-url') const debug = require('debug') const log = debug('libp2p:websockets:dialer') const createListener = require('./listener') -module.exports = class WebSockets { +class WebSockets { dial (ma, options, callback) { if (typeof options === 'function') { callback = options options = {} } - if (!callback) { - callback = () => {} - } + callback = callback || function () {} - const maOpts = ma.toOptions() - - const url = `ws://${maOpts.host}:${maOpts.port}` + const url = maToUrl(ma) log('dialing %s', url) const socket = connect(url, { binary: true, @@ -30,8 +27,8 @@ module.exports = class WebSockets { }) const conn = new Connection(socket) - conn.getObservedAddrs = (cb) => cb(null, [ma]) - conn.close = (cb) => socket.close(cb) + conn.getObservedAddrs = (callback) => callback(null, [ma]) + conn.close = (callback) => socket.close(callback) return conn } @@ -54,7 +51,9 @@ module.exports = class WebSockets { if (includes(ma.protoNames(), 'ipfs')) { ma = ma.decapsulate('ipfs') } - return mafmt.WebSockets.matches(ma) + return mafmt.WebSockets.matches(ma) || mafmt.WebSocketsSecure.matches(ma) }) } } + +module.exports = WebSockets diff --git a/src/listener.js b/src/listener.js index bbe8bbd..e2cf9aa 100644 --- a/src/listener.js +++ b/src/listener.js @@ -2,20 +2,14 @@ const Connection = require('interface-connection').Connection const includes = require('lodash.includes') - -// const IPFS_CODE = 421 - -let createServer = require('pull-ws/server') - -if (!createServer) { - createServer = () => {} -} +function noop () {} +const createServer = require('pull-ws/server') || noop module.exports = (options, handler) => { const listener = createServer((socket) => { - socket.getObservedAddrs = (cb) => { + socket.getObservedAddrs = (callback) => { // TODO research if we can reuse the address in anyway - return cb(null, []) + return callback(null, []) } handler(new Connection(socket)) @@ -24,19 +18,19 @@ module.exports = (options, handler) => { let listeningMultiaddr listener._listen = listener.listen - listener.listen = (ma, cb) => { - cb = cb || (() => {}) + listener.listen = (ma, callback) => { + callback = callback || noop listeningMultiaddr = ma if (includes(ma.protoNames(), 'ipfs')) { ma = ma.decapsulate('ipfs') } - listener._listen(ma.toOptions(), cb) + listener._listen(ma.toOptions(), callback) } - listener.getAddrs = (cb) => { - cb(null, [listeningMultiaddr]) + listener.getAddrs = (callback) => { + callback(null, [listeningMultiaddr]) } return listener diff --git a/src/ma-to-url.js b/src/ma-to-url.js new file mode 100644 index 0000000..86beff6 --- /dev/null +++ b/src/ma-to-url.js @@ -0,0 +1,22 @@ +'use strict' + +const multiaddr = require('multiaddr') + +function maToUrl (ma) { + const maStrSplit = ma.toString().split('/') + const proto = ma.protos()[2].name + + if (!(proto === 'ws' || proto === 'wss')) { + throw new Error('invalid multiaddr' + ma.toString()) + } + + let url = ma.protos()[2].name + '://' + maStrSplit[2] + + if (!multiaddr.isName(ma)) { + url += ':' + maStrSplit[4] + } + + return url +} + +module.exports = maToUrl diff --git a/test/compliance.node.js b/test/compliance.node.js index 07c850d..1487ebe 100644 --- a/test/compliance.node.js +++ b/test/compliance.node.js @@ -3,21 +3,22 @@ const tests = require('interface-transport') const multiaddr = require('multiaddr') -const Ws = require('../src') +const WS = require('../src') describe('compliance', () => { tests({ - setup (cb) { - let ws = new Ws() + setup (callback) { + let ws = new WS() const addrs = [ multiaddr('/ip4/127.0.0.1/tcp/9091/ws'), - multiaddr('/ip4/127.0.0.1/tcp/9092/ws'), - multiaddr('/ip4/127.0.0.1/tcp/9093/ws') + multiaddr('/ip4/127.0.0.1/tcp/9092/wss') + // multiaddr('/dns4/awesome-dns-server.com/tcp/9092/ws'), + // multiaddr('/dns4/awesome-dns-server.com/tcp/9092/wss') ] - cb(null, ws, addrs) + callback(null, ws, addrs) }, - teardown (cb) { - cb() + teardown (callback) { + callback() } }) }) diff --git a/test/node.js b/test/node.js index 0a5a8aa..dc8a17a 100644 --- a/test/node.js +++ b/test/node.js @@ -30,6 +30,7 @@ describe('listen', () => { it('listen, check for callback', (done) => { const listener = ws.createListener((conn) => {}) + listener.listen(ma, () => { listener.close(done) }) @@ -37,24 +38,30 @@ describe('listen', () => { it('listen, check for listening event', (done) => { const listener = ws.createListener((conn) => {}) + listener.on('listening', () => { listener.close(done) }) + listener.listen(ma) }) it('listen, check for the close event', (done) => { const listener = ws.createListener((conn) => {}) + listener.on('listening', () => { listener.on('close', done) listener.close() }) + listener.listen(ma) }) it('listen on addr with /ipfs/QmHASH', (done) => { const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + const listener = ws.createListener((conn) => {}) + listener.listen(ma, () => { listener.close(done) }) @@ -77,7 +84,8 @@ describe('listen', () => { }) it('getAddrs', (done) => { - const listener = ws.createListener((conn) => {}) + const listener = ws.createListener((conn) => { + }) listener.listen(ma, () => { listener.getAddrs((err, addrs) => { expect(err).to.not.exist() @@ -104,6 +112,7 @@ describe('listen', () => { const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const listener = ws.createListener((conn) => {}) + listener.listen(ma, () => { listener.getAddrs((err, addrs) => { expect(err).to.not.exist() @@ -177,17 +186,120 @@ describe('filter addrs', () => { ws = new WS() }) - it('filter valid addrs for this transport', (done) => { - const mh1 = multiaddr('/ip4/127.0.0.1/tcp/9090') - const mh2 = multiaddr('/ip4/127.0.0.1/udp/9090') - const mh3 = multiaddr('/ip4/127.0.0.1/tcp/9090/ws') - const mh4 = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + describe('filter valid addrs for this transport', function () { + it('should fail invalid WS addresses', function () { + const ma1 = multiaddr('/ip4/127.0.0.1/tcp/9090') + const ma2 = multiaddr('/ip4/127.0.0.1/udp/9090') + const ma3 = multiaddr('/ip6/::1/tcp/80') + const ma4 = multiaddr('/dns/ipfs.io/tcp/80') - const valid = ws.filter([mh1, mh2, mh3, mh4]) - expect(valid.length).to.equal(2) - expect(valid[0]).to.deep.equal(mh3) - expect(valid[1]).to.deep.equal(mh4) - done() + const valid = ws.filter([ma1, ma2, ma3, ma4]) + expect(valid.length).to.equal(0) + }) + + it('should filter correct ipv4 addresses', function () { + const ma1 = multiaddr('/ip4/127.0.0.1/tcp/80/ws') + const ma2 = multiaddr('/ip4/127.0.0.1/tcp/443/wss') + + const valid = ws.filter([ma1, ma2]) + expect(valid.length).to.equal(2) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma2) + }) + + it('should filter correct ipv4 addresses with ipfs id', function () { + const ma1 = multiaddr('/ip4/127.0.0.1/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + const ma2 = multiaddr('/ip4/127.0.0.1/tcp/80/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + + const valid = ws.filter([ma1, ma2]) + expect(valid.length).to.equal(2) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma2) + }) + + it('should filter correct ipv6 address', function () { + const ma1 = multiaddr('/ip6/::1/tcp/80/ws') + const ma2 = multiaddr('/ip6/::1/tcp/443/wss') + + const valid = ws.filter([ma1, ma2]) + expect(valid.length).to.equal(2) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma2) + }) + + it('should filter correct ipv6 addresses with ipfs id', function () { + const ma1 = multiaddr('/ip6/::1/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + const ma2 = multiaddr('/ip6/::1/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + + const valid = ws.filter([ma1, ma2]) + expect(valid.length).to.equal(2) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma2) + }) + + it('should filter correct dns address', function () { + const ma1 = multiaddr('/dns/ipfs.io/ws') + const ma2 = multiaddr('/dns/ipfs.io/tcp/80/ws') + const ma3 = multiaddr('/dns/ipfs.io/tcp/80/wss') + + const valid = ws.filter([ma1, ma2, ma3]) + expect(valid.length).to.equal(3) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma2) + expect(valid[2]).to.deep.equal(ma3) + }) + + it('should filter correct dns address with ipfs id', function () { + const ma1 = multiaddr('/dns/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + const ma2 = multiaddr('/dns/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + + const valid = ws.filter([ma1, ma2]) + expect(valid.length).to.equal(2) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma2) + }) + + it('should filter correct dns4 address', function () { + const ma1 = multiaddr('/dns4/ipfs.io/tcp/80/ws') + const ma2 = multiaddr('/dns4/ipfs.io/tcp/443/wss') + + const valid = ws.filter([ma1, ma2]) + expect(valid.length).to.equal(2) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma2) + }) + + it('should filter correct dns6 address', function () { + const ma1 = multiaddr('/dns6/ipfs.io/tcp/80/ws') + const ma2 = multiaddr('/dns6/ipfs.io/tcp/443/wss') + + const valid = ws.filter([ma1, ma2]) + expect(valid.length).to.equal(2) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma2) + }) + + it('should filter correct dns6 address with ipfs id', function () { + const ma1 = multiaddr('/dns6/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + const ma2 = multiaddr('/dns6/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + + const valid = ws.filter([ma1, ma2]) + expect(valid.length).to.equal(2) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma2) + }) + + it('should filter mixed addresses', function () { + const ma1 = multiaddr('/dns6/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') + const ma2 = multiaddr('/ip4/127.0.0.1/tcp/9090') + const ma3 = multiaddr('/ip4/127.0.0.1/udp/9090') + const ma4 = multiaddr('/dns6/ipfs.io/ws') + + const valid = ws.filter([ma1, ma2, ma3, ma4]) + expect(valid.length).to.equal(2) + expect(valid[0]).to.deep.equal(ma1) + expect(valid[1]).to.deep.equal(ma4) + }) }) it('filter a single addr for this transport', (done) => {