2016-08-11 14:50:44 +02:00
|
|
|
'use strict'
|
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
const EventEmitter = require('events')
|
2017-10-20 04:12:35 -07:00
|
|
|
const os = require('os')
|
2019-09-30 12:14:28 +02:00
|
|
|
const multiaddr = require('multiaddr')
|
|
|
|
const { createServer } = require('it-ws')
|
2019-10-30 13:35:26 +01:00
|
|
|
const debug = require('debug')
|
|
|
|
const log = debug('libp2p:websockets:listener')
|
|
|
|
log.error = debug('libp2p:websockets:listener:error')
|
2017-10-20 04:12:35 -07:00
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
const toConnection = require('./socket-to-conn')
|
2016-08-11 14:50:44 +02:00
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
module.exports = ({ handler, upgrader }, options = {}) => {
|
|
|
|
const listener = new EventEmitter()
|
|
|
|
|
|
|
|
const server = createServer(options, async (stream) => {
|
2020-02-26 15:14:54 +01:00
|
|
|
let maConn, conn
|
2016-08-11 14:50:44 +02:00
|
|
|
|
2019-10-30 13:35:26 +01:00
|
|
|
try {
|
2020-02-26 15:14:54 +01:00
|
|
|
maConn = toConnection(stream)
|
|
|
|
log('new inbound connection %s', maConn.remoteAddr)
|
2019-10-30 13:35:26 +01:00
|
|
|
conn = await upgrader.upgradeInbound(maConn)
|
|
|
|
} catch (err) {
|
|
|
|
log.error('inbound connection failed to upgrade', err)
|
2020-02-26 15:14:54 +01:00
|
|
|
return maConn && maConn.close()
|
2019-10-30 13:35:26 +01:00
|
|
|
}
|
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
log('inbound connection %s upgraded', maConn.remoteAddr)
|
|
|
|
|
|
|
|
trackConn(server, maConn)
|
|
|
|
|
|
|
|
if (handler) handler(conn)
|
|
|
|
listener.emit('connection', conn)
|
2016-08-11 14:50:44 +02:00
|
|
|
})
|
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
server
|
|
|
|
.on('listening', () => listener.emit('listening'))
|
|
|
|
.on('error', err => listener.emit('error', err))
|
|
|
|
.on('close', () => listener.emit('close'))
|
|
|
|
|
|
|
|
// Keep track of open connections to destroy in case of timeout
|
|
|
|
server.__connections = []
|
|
|
|
|
2016-08-11 14:50:44 +02:00
|
|
|
let listeningMultiaddr
|
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
listener.close = () => {
|
|
|
|
server.__connections.forEach(maConn => maConn.close())
|
|
|
|
return server.close()
|
|
|
|
}
|
2016-08-11 14:50:44 +02:00
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
listener.listen = (ma) => {
|
|
|
|
listeningMultiaddr = ma
|
2016-08-11 14:50:44 +02:00
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
return server.listen(ma.toOptions())
|
2016-08-11 14:50:44 +02:00
|
|
|
}
|
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
listener.getAddrs = () => {
|
2017-10-20 04:12:35 -07:00
|
|
|
const multiaddrs = []
|
2019-09-30 12:14:28 +02:00
|
|
|
const address = server.address()
|
2017-10-20 04:12:35 -07:00
|
|
|
|
|
|
|
if (!address) {
|
2019-09-30 12:14:28 +02:00
|
|
|
throw new Error('Listener is not ready yet')
|
2017-10-20 04:12:35 -07:00
|
|
|
}
|
|
|
|
|
2019-07-22 04:29:00 -06:00
|
|
|
const ipfsId = listeningMultiaddr.getPeerId()
|
2017-10-20 04:12:35 -07:00
|
|
|
|
|
|
|
// Because TCP will only return the IPv6 version
|
|
|
|
// we need to capture from the passed multiaddr
|
|
|
|
if (listeningMultiaddr.toString().indexOf('ip4') !== -1) {
|
|
|
|
let m = listeningMultiaddr.decapsulate('tcp')
|
|
|
|
m = m.encapsulate('/tcp/' + address.port + '/ws')
|
|
|
|
if (listeningMultiaddr.getPeerId()) {
|
2019-09-30 12:14:28 +02:00
|
|
|
m = m.encapsulate('/p2p/' + ipfsId)
|
2017-10-20 04:12:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (m.toString().indexOf('0.0.0.0') !== -1) {
|
|
|
|
const netInterfaces = os.networkInterfaces()
|
|
|
|
Object.keys(netInterfaces).forEach((niKey) => {
|
|
|
|
netInterfaces[niKey].forEach((ni) => {
|
|
|
|
if (ni.family === 'IPv4') {
|
2021-04-09 17:49:30 +03:00
|
|
|
multiaddrs.push(new multiaddr.Multiaddr(m.toString().replace('0.0.0.0', ni.address)))
|
2017-10-20 04:12:35 -07:00
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
multiaddrs.push(m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-30 12:14:28 +02:00
|
|
|
return multiaddrs
|
2016-08-11 14:50:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return listener
|
|
|
|
}
|
2019-09-30 12:14:28 +02:00
|
|
|
|
|
|
|
function trackConn (server, maConn) {
|
|
|
|
server.__connections.push(maConn)
|
|
|
|
}
|