DNS support (#56)

* feat: dns support
This commit is contained in:
David Dias 2017-03-23 15:09:06 +00:00 committed by GitHub
parent ec467377e6
commit bdfd042ace
6 changed files with 173 additions and 45 deletions

View File

@ -4,25 +4,22 @@ const connect = require('pull-ws/client')
const mafmt = require('mafmt') const mafmt = require('mafmt')
const includes = require('lodash.includes') const includes = require('lodash.includes')
const Connection = require('interface-connection').Connection const Connection = require('interface-connection').Connection
const maToUrl = require('./ma-to-url')
const debug = require('debug') const debug = require('debug')
const log = debug('libp2p:websockets:dialer') const log = debug('libp2p:websockets:dialer')
const createListener = require('./listener') const createListener = require('./listener')
module.exports = class WebSockets { class WebSockets {
dial (ma, options, callback) { dial (ma, options, callback) {
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options callback = options
options = {} options = {}
} }
if (!callback) { callback = callback || function () {}
callback = () => {}
}
const maOpts = ma.toOptions() const url = maToUrl(ma)
const url = `ws://${maOpts.host}:${maOpts.port}`
log('dialing %s', url) log('dialing %s', url)
const socket = connect(url, { const socket = connect(url, {
binary: true, binary: true,
@ -30,8 +27,8 @@ module.exports = class WebSockets {
}) })
const conn = new Connection(socket) const conn = new Connection(socket)
conn.getObservedAddrs = (cb) => cb(null, [ma]) conn.getObservedAddrs = (callback) => callback(null, [ma])
conn.close = (cb) => socket.close(cb) conn.close = (callback) => socket.close(callback)
return conn return conn
} }
@ -54,7 +51,9 @@ module.exports = class WebSockets {
if (includes(ma.protoNames(), 'ipfs')) { if (includes(ma.protoNames(), 'ipfs')) {
ma = ma.decapsulate('ipfs') ma = ma.decapsulate('ipfs')
} }
return mafmt.WebSockets.matches(ma) return mafmt.WebSockets.matches(ma) || mafmt.WebSocketsSecure.matches(ma)
}) })
} }
} }
module.exports = WebSockets

View File

@ -2,20 +2,14 @@
const Connection = require('interface-connection').Connection const Connection = require('interface-connection').Connection
const includes = require('lodash.includes') const includes = require('lodash.includes')
function noop () {}
// const IPFS_CODE = 421 const createServer = require('pull-ws/server') || noop
let createServer = require('pull-ws/server')
if (!createServer) {
createServer = () => {}
}
module.exports = (options, handler) => { module.exports = (options, handler) => {
const listener = createServer((socket) => { const listener = createServer((socket) => {
socket.getObservedAddrs = (cb) => { socket.getObservedAddrs = (callback) => {
// TODO research if we can reuse the address in anyway // TODO research if we can reuse the address in anyway
return cb(null, []) return callback(null, [])
} }
handler(new Connection(socket)) handler(new Connection(socket))
@ -24,19 +18,19 @@ module.exports = (options, handler) => {
let listeningMultiaddr let listeningMultiaddr
listener._listen = listener.listen listener._listen = listener.listen
listener.listen = (ma, cb) => { listener.listen = (ma, callback) => {
cb = cb || (() => {}) callback = callback || noop
listeningMultiaddr = ma listeningMultiaddr = ma
if (includes(ma.protoNames(), 'ipfs')) { if (includes(ma.protoNames(), 'ipfs')) {
ma = ma.decapsulate('ipfs') ma = ma.decapsulate('ipfs')
} }
listener._listen(ma.toOptions(), cb) listener._listen(ma.toOptions(), callback)
} }
listener.getAddrs = (cb) => { listener.getAddrs = (callback) => {
cb(null, [listeningMultiaddr]) callback(null, [listeningMultiaddr])
} }
return listener return listener

22
src/ma-to-url.js Normal file
View File

@ -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

View File

@ -3,21 +3,22 @@
const tests = require('interface-transport') const tests = require('interface-transport')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const Ws = require('../src') const WS = require('../src')
describe('compliance', () => { describe('compliance', () => {
tests({ tests({
setup (cb) { setup (callback) {
let ws = new Ws() let ws = new WS()
const addrs = [ const addrs = [
multiaddr('/ip4/127.0.0.1/tcp/9091/ws'), 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/9092/wss')
multiaddr('/ip4/127.0.0.1/tcp/9093/ws') // 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) { teardown (callback) {
cb() callback()
} }
}) })
}) })

View File

@ -30,6 +30,7 @@ describe('listen', () => {
it('listen, check for callback', (done) => { it('listen, check for callback', (done) => {
const listener = ws.createListener((conn) => {}) const listener = ws.createListener((conn) => {})
listener.listen(ma, () => { listener.listen(ma, () => {
listener.close(done) listener.close(done)
}) })
@ -37,24 +38,30 @@ describe('listen', () => {
it('listen, check for listening event', (done) => { it('listen, check for listening event', (done) => {
const listener = ws.createListener((conn) => {}) const listener = ws.createListener((conn) => {})
listener.on('listening', () => { listener.on('listening', () => {
listener.close(done) listener.close(done)
}) })
listener.listen(ma) listener.listen(ma)
}) })
it('listen, check for the close event', (done) => { it('listen, check for the close event', (done) => {
const listener = ws.createListener((conn) => {}) const listener = ws.createListener((conn) => {})
listener.on('listening', () => { listener.on('listening', () => {
listener.on('close', done) listener.on('close', done)
listener.close() listener.close()
}) })
listener.listen(ma) listener.listen(ma)
}) })
it('listen on addr with /ipfs/QmHASH', (done) => { it('listen on addr with /ipfs/QmHASH', (done) => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const listener = ws.createListener((conn) => {}) const listener = ws.createListener((conn) => {})
listener.listen(ma, () => { listener.listen(ma, () => {
listener.close(done) listener.close(done)
}) })
@ -77,7 +84,8 @@ describe('listen', () => {
}) })
it('getAddrs', (done) => { it('getAddrs', (done) => {
const listener = ws.createListener((conn) => {}) const listener = ws.createListener((conn) => {
})
listener.listen(ma, () => { listener.listen(ma, () => {
listener.getAddrs((err, addrs) => { listener.getAddrs((err, addrs) => {
expect(err).to.not.exist() 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 ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const listener = ws.createListener((conn) => {}) const listener = ws.createListener((conn) => {})
listener.listen(ma, () => { listener.listen(ma, () => {
listener.getAddrs((err, addrs) => { listener.getAddrs((err, addrs) => {
expect(err).to.not.exist() expect(err).to.not.exist()
@ -177,17 +186,120 @@ describe('filter addrs', () => {
ws = new WS() ws = new WS()
}) })
it('filter valid addrs for this transport', (done) => { describe('filter valid addrs for this transport', function () {
const mh1 = multiaddr('/ip4/127.0.0.1/tcp/9090') it('should fail invalid WS addresses', function () {
const mh2 = multiaddr('/ip4/127.0.0.1/udp/9090') const ma1 = multiaddr('/ip4/127.0.0.1/tcp/9090')
const mh3 = multiaddr('/ip4/127.0.0.1/tcp/9090/ws') const ma2 = multiaddr('/ip4/127.0.0.1/udp/9090')
const mh4 = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma3 = multiaddr('/ip6/::1/tcp/80')
const ma4 = multiaddr('/dns/ipfs.io/tcp/80')
const valid = ws.filter([mh1, mh2, mh3, mh4]) 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.length).to.equal(2)
expect(valid[0]).to.deep.equal(mh3) expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(mh4) expect(valid[1]).to.deep.equal(ma2)
done() })
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) => { it('filter a single addr for this transport', (done) => {