88 lines
2.2 KiB
JavaScript
Raw Normal View History

2016-03-23 16:23:10 +01:00
'use strict'
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')
const toUri = require('multiaddr-to-uri')
const log = require('debug')('libp2p:websockets:transport')
const abortable = require('abortable-iterator')
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 {
async dial (ma, options) {
options = options || {}
log('dialing %s', ma)
const socket = connect(toUri(ma), Object.assign({ binary: true }, options))
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 = () => {
reject(new AbortError())
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)
}
log('connected %s', ma)
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')) {
return false
}
2018-12-15 22:00:29 +00:00
if (ma.protoNames().includes('ipfs')) {
ma = ma.decapsulate('ipfs')
}
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'
})