mirror of
https://github.com/fluencelabs/js-libp2p-websockets
synced 2025-04-25 08:22:24 +00:00
88 lines
2.2 KiB
JavaScript
88 lines
2.2 KiB
JavaScript
'use strict'
|
|
|
|
const connect = require('it-ws/client')
|
|
const mafmt = require('mafmt')
|
|
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')
|
|
const createListener = require('./listener')
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
createListener (options, handler) {
|
|
return createListener(options, handler)
|
|
}
|
|
|
|
filter (multiaddrs) {
|
|
multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
|
|
|
|
return multiaddrs.filter((ma) => {
|
|
if (ma.protoNames().includes('p2p-circuit')) {
|
|
return false
|
|
}
|
|
|
|
if (ma.protoNames().includes('ipfs')) {
|
|
ma = ma.decapsulate('ipfs')
|
|
}
|
|
|
|
return mafmt.WebSockets.matches(ma) || mafmt.WebSocketsSecure.matches(ma)
|
|
})
|
|
}
|
|
}
|
|
|
|
module.exports = withIs(WebSockets, {
|
|
className: 'WebSockets',
|
|
symbolName: '@libp2p/js-libp2p-websockets/websockets'
|
|
})
|