2016-03-23 16:23:10 +01:00
|
|
|
'use strict'
|
|
|
|
|
2019-03-29 07:53:08 +00:00
|
|
|
const connect = require('it-ws/client')
|
2016-03-14 21:19:42 +00:00
|
|
|
const mafmt = require('mafmt')
|
2018-04-05 17:21:26 +01:00
|
|
|
const withIs = require('class-is')
|
2019-01-24 15:22:00 +00:00
|
|
|
const toUri = require('multiaddr-to-uri')
|
2019-03-29 07:53:08 +00:00
|
|
|
const log = require('debug')('libp2p:websockets:transport')
|
2019-04-18 09:52:49 +01:00
|
|
|
const abortable = require('abortable-iterator')
|
2019-04-18 15:42:17 +01:00
|
|
|
const { AbortError } = require('interface-transport')
|
2016-08-11 14:50:44 +02:00
|
|
|
const createListener = require('./listener')
|
2016-03-14 20:25:00 +00:00
|
|
|
|
2017-03-23 15:09:06 +00:00
|
|
|
class WebSockets {
|
2019-04-02 10:05:45 +01:00
|
|
|
async dial (ma, options) {
|
2019-04-18 09:52:49 +01:00
|
|
|
options = options || {}
|
2019-03-29 07:53:08 +00:00
|
|
|
log('dialing %s', ma)
|
2019-04-18 09:52:49 +01:00
|
|
|
|
2019-04-17 12:34:56 +01:00
|
|
|
const socket = connect(toUri(ma), Object.assign({ binary: true }, options))
|
2019-04-18 09:52:49 +01:00
|
|
|
const getObservedAddrs = () => [ma]
|
|
|
|
|
|
|
|
if (!options.signal) {
|
|
|
|
socket.getObservedAddrs = getObservedAddrs
|
|
|
|
await socket.connected()
|
|
|
|
log('connected %s', ma)
|
|
|
|
return socket
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allow abort via signal during connect
|
|
|
|
let onAbort
|
|
|
|
const abort = new Promise((resolve, reject) => {
|
|
|
|
onAbort = () => {
|
2019-04-18 13:31:26 +01:00
|
|
|
reject(new AbortError())
|
2019-04-18 09:52:49 +01:00
|
|
|
socket.close()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Already aborted?
|
|
|
|
if (options.signal.aborted) return onAbort()
|
|
|
|
options.signal.addEventListener('abort', onAbort)
|
|
|
|
})
|
|
|
|
|
|
|
|
try {
|
|
|
|
await Promise.race([abort, socket.connected()])
|
|
|
|
} finally {
|
|
|
|
options.signal.removeEventListener('abort', onAbort)
|
|
|
|
}
|
|
|
|
|
2019-03-29 07:53:08 +00:00
|
|
|
log('connected %s', ma)
|
2019-04-18 09:52:49 +01:00
|
|
|
return {
|
|
|
|
sink: async source => {
|
|
|
|
try {
|
|
|
|
await socket.sink(abortable(source, options.signal))
|
|
|
|
} catch (err) {
|
|
|
|
// Re-throw non-aborted errors
|
|
|
|
if (err.type !== 'aborted') throw err
|
|
|
|
// Otherwise, this is fine...
|
|
|
|
await socket.close()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
source: abortable(socket.source, options.signal),
|
|
|
|
getObservedAddrs
|
|
|
|
}
|
2016-03-14 20:25:00 +00:00
|
|
|
}
|
|
|
|
|
2016-08-11 14:50:44 +02:00
|
|
|
createListener (options, handler) {
|
|
|
|
return createListener(options, handler)
|
2016-03-14 20:25:00 +00:00
|
|
|
}
|
|
|
|
|
2016-08-11 14:50:44 +02:00
|
|
|
filter (multiaddrs) {
|
2019-04-01 14:27:25 +01:00
|
|
|
multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
|
2016-08-11 14:50:44 +02:00
|
|
|
|
2016-03-14 20:25:00 +00:00
|
|
|
return multiaddrs.filter((ma) => {
|
2018-12-15 22:00:29 +00:00
|
|
|
if (ma.protoNames().includes('p2p-circuit')) {
|
2017-10-20 04:12:35 -07:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2018-12-15 22:00:29 +00:00
|
|
|
if (ma.protoNames().includes('ipfs')) {
|
2016-05-29 09:00:26 +01:00
|
|
|
ma = ma.decapsulate('ipfs')
|
|
|
|
}
|
2017-10-20 04:12:35 -07:00
|
|
|
|
2019-04-01 14:27:25 +01:00
|
|
|
return mafmt.WebSockets.matches(ma) || mafmt.WebSocketsSecure.matches(ma)
|
2016-03-14 20:25:00 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2017-03-23 15:09:06 +00:00
|
|
|
|
2019-04-01 14:27:25 +01:00
|
|
|
module.exports = withIs(WebSockets, {
|
|
|
|
className: 'WebSockets',
|
|
|
|
symbolName: '@libp2p/js-libp2p-websockets/websockets'
|
|
|
|
})
|