dht-relay-wss
Version:
hyperswarm-dht-relay websocket server with some instrumentation
117 lines (95 loc) • 3.71 kB
JavaScript
require('dotenv').config()
const pino = require('pino')
const goodbye = require('graceful-goodbye')
const DHT = require('hyperdht')
const fastify = require('fastify')
const idEnc = require('hypercore-id-encoding')
const DhtRelayWss = require('./index')
const instrument = require('./lib/instrument')
const safetyCatch = require('safety-catch')
function loadConfig () {
const res = {
wsPort: parseInt(process.env.DHT_RELAY_WS_PORT || 0),
dhtPort: parseInt(process.env.DHT_RELAY_DHT_PORT || 0),
logLevel: process.env.DHT_RELAY_LOG_LEVEL || 'info',
wsHost: process.env.DHT_RELAY_WS_HOST || '127.0.0.1',
// Should be < 10s, lest it interfere with a fastify timeout
// (logs a caught error if it does, so not dramatic)
sShutdownMargin: process.env.DHT_RELAY_S_SHUTDOWN_MARGIN == null
? 5
: parseInt(process.env.DHT_RELAY_S_SHUTDOWN_MARGIN)
}
if (process.env.DHT_RELAY_BOOTSTRAP_PORT) { // For tests
res.bootstrap = [{
port: parseInt(process.env.DHT_RELAY_BOOTSTRAP_PORT),
host: '127.0.0.1'
}]
}
if (process.env.DHT_RELAY_PROMETHEUS_ALIAS) {
res.prometheusAlias = process.env.DHT_RELAY_PROMETHEUS_ALIAS
try {
res.prometheusSharedSecret = idEnc.decode(process.env.DHT_RELAY_PROMETHEUS_SHARED_SECRET)
res.prometheusScraperPublicKey = idEnc.decode(process.env.DHT_RELAY_PROMETHEUS_SCRAPER_PUBLIC_KEY)
res.prometheusServiceName = 'dht-relay-wss'
} catch (error) {
console.error(error)
console.error('If DHT_RELAY_PROMETHEUS_ALIAS is set, then DHT_RELAY_PROMETHEUS_SHARED_SECRET and DHT_RELAY_PROMETHEUS_SCRAPER_PUBLIC_KEY must be set to valid keys')
process.exit(1)
}
}
return res
}
async function main () {
const config = loadConfig()
const { wsPort, wsHost, dhtPort, logLevel, sShutdownMargin, bootstrap } = config
const logger = pino({ level: logLevel })
logger.info('Starting DHT relay')
const dht = new DHT({ port: dhtPort, bootstrap })
const app = fastify({ logger })
const dhtRelay = new DhtRelayWss(app, dht, {
sShutdownMargin,
wsPort,
wsHost
})
setupLogging(dhtRelay, logger)
const { prometheusAlias, prometheusSharedSecret, prometheusScraperPublicKey, prometheusServiceName } = config
const dhtPromClient = instrument(dhtRelay, logger, {
prometheusAlias, prometheusSharedSecret, prometheusScraperPublicKey, prometheusServiceName
})
goodbye(async () => {
try {
if (dhtPromClient) dhtPromClient.close().catch(safetyCatch)
logger.info('Closing the relay')
await dhtRelay.close()
logger.info('Exiting program')
} catch (e) {
console.error('error while shutting down', e)
}
})
await dhtRelay.ready()
if (dhtPromClient) await dhtPromClient.ready()
logger.info(`DHT: ${dht.host}:${dht.port} (firewalled: ${dht.firewalled})`)
}
function setupLogging (dhtRelay, logger) {
dhtRelay.on('conn-open', ({ id }) => {
logger.info(`Started relaying to ${id}`)
})
dhtRelay.on('conn-error', ({ error, id }) => {
// Usually expected (timeouts etc)
logger.info(`Relay connection error on connection ${id}: ${error.stack}`)
})
dhtRelay.on('conn-close', ({ id }) => {
logger.info(`Stopped relaying to ${id}`)
})
dhtRelay.on('ws-closing-signal', ({ sShutdownMargin, nrClients }) => {
logger.info(`Signalling ${nrClients} clients that we are shutting down in max ${sShutdownMargin}s`)
})
dhtRelay.on('ws-closing-force', ({ nrRemainingClients }) => {
logger.warn(`force-closing connection to ${nrRemainingClients} clients`)
})
dhtRelay.on('ws-closing-done', () => {
logger.info('Closed websocket server connections')
})
}
main()