replace socket.io usage with WebSockets
This commit is contained in:
64
lib/app.js
64
lib/app.js
@ -2,6 +2,7 @@ const Database = require('./database')
|
||||
const MojangUpdater = require('./mojang')
|
||||
const PingController = require('./ping')
|
||||
const Server = require('./server')
|
||||
const MessageOf = require('./message')
|
||||
|
||||
const config = require('../config')
|
||||
const minecraftVersions = require('../minecraft_versions')
|
||||
@ -36,43 +37,46 @@ class App {
|
||||
|
||||
handleClientConnection = (client) => {
|
||||
if (config.logToDatabase) {
|
||||
client.on('requestHistoryGraph', () => {
|
||||
// Send historical graphData built from all serverRegistrations
|
||||
const graphData = {}
|
||||
client.on('message', (message) => {
|
||||
if (message === 'requestHistoryGraph') {
|
||||
// Send historical graphData built from all serverRegistrations
|
||||
const graphData = {}
|
||||
|
||||
this.serverRegistrations.forEach((serverRegistration) => {
|
||||
graphData[serverRegistration.serverId] = serverRegistration.graphData
|
||||
})
|
||||
this.serverRegistrations.forEach((serverRegistration) => {
|
||||
graphData[serverRegistration.serverId] = serverRegistration.graphData
|
||||
})
|
||||
|
||||
client.emit('historyGraph', graphData)
|
||||
// Send graphData in object wrapper to avoid needing to explicity filter
|
||||
// any header data being appended by #MessageOf since the graph data is fed
|
||||
// directly into the flot.js graphing system
|
||||
client.send(MessageOf('historyGraph', {
|
||||
graphData: graphData
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
client.emit('setPublicConfig', (() => {
|
||||
// Remap minecraftVersion entries into name values
|
||||
const minecraftVersionNames = {}
|
||||
Object.keys(minecraftVersions).forEach(function (key) {
|
||||
minecraftVersionNames[key] = minecraftVersions[key].map(version => version.name)
|
||||
})
|
||||
const initMessage = {
|
||||
config: (() => {
|
||||
// Remap minecraftVersion entries into name values
|
||||
const minecraftVersionNames = {}
|
||||
Object.keys(minecraftVersions).forEach(function (key) {
|
||||
minecraftVersionNames[key] = minecraftVersions[key].map(version => version.name)
|
||||
})
|
||||
|
||||
// Send configuration data for rendering the page
|
||||
return {
|
||||
graphDuration: config.graphDuration,
|
||||
servers: this.serverRegistrations.map(serverRegistration => serverRegistration.data),
|
||||
minecraftVersions: minecraftVersionNames,
|
||||
isGraphVisible: config.logToDatabase
|
||||
}
|
||||
})())
|
||||
// Send configuration data for rendering the page
|
||||
return {
|
||||
graphDuration: config.graphDuration,
|
||||
servers: this.serverRegistrations.map(serverRegistration => serverRegistration.data),
|
||||
minecraftVersions: minecraftVersionNames,
|
||||
isGraphVisible: config.logToDatabase
|
||||
}
|
||||
})(),
|
||||
mojangServices: this.mojangUpdater.getLastUpdate(),
|
||||
servers: this.serverRegistrations.map(serverRegistration => serverRegistration.getPingHistory())
|
||||
}
|
||||
|
||||
// Send last Mojang update, if any
|
||||
this.mojangUpdater.sendLastUpdate(client)
|
||||
|
||||
// Send pingHistory of all ServerRegistrations
|
||||
client.emit('add', this.serverRegistrations.map(serverRegistration => serverRegistration.getPingHistory()))
|
||||
|
||||
// Always send last
|
||||
// This tells the frontend to do final processing and render
|
||||
client.emit('syncComplete')
|
||||
client.send(MessageOf('init', initMessage))
|
||||
}
|
||||
}
|
||||
|
||||
|
6
lib/message.js
Normal file
6
lib/message.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = function MessageOf (name, data) {
|
||||
return JSON.stringify({
|
||||
message: name,
|
||||
...data
|
||||
})
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
const request = require('request')
|
||||
|
||||
const logger = require('./logger')
|
||||
const MessageOf = require('./message')
|
||||
|
||||
const config = require('../config')
|
||||
|
||||
@ -65,14 +66,12 @@ class MojangUpdater {
|
||||
if (this._hasUpdated) {
|
||||
this._hasUpdated = false
|
||||
|
||||
this._app.server.broadcast('updateMojangServices', this._services)
|
||||
this._app.server.broadcast(MessageOf('updateMojangServices', this._services))
|
||||
}
|
||||
}
|
||||
|
||||
sendLastUpdate (client) {
|
||||
if (this._services) {
|
||||
client.emit('updateMojangServices', this._services)
|
||||
}
|
||||
getLastUpdate () {
|
||||
return this._services
|
||||
}
|
||||
|
||||
handleServiceUpdate (url, color) {
|
||||
|
@ -4,6 +4,7 @@ const minecraftJavaPing = require('mc-ping-updated')
|
||||
const minecraftBedrockPing = require('mcpe-ping-fixed')
|
||||
|
||||
const logger = require('./logger')
|
||||
const MessageOf = require('./message')
|
||||
|
||||
const config = require('../config')
|
||||
|
||||
@ -125,7 +126,9 @@ class PingController {
|
||||
// Generate a combined update payload
|
||||
// This includes any modified fields and flags used by the frontend
|
||||
// This will not be cached and can contain live metadata
|
||||
this._app.server.broadcast('update', serverRegistration.getUpdate(timestamp, resp, err, version, updateHistoryGraph))
|
||||
const updateMessage = serverRegistration.getUpdate(timestamp, resp, err, version, updateHistoryGraph)
|
||||
|
||||
this._app.server.broadcast(MessageOf('updateServer', updateMessage))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
const http = require('http')
|
||||
|
||||
const WebSocket = require('ws')
|
||||
const finalHttpHandler = require('finalhandler')
|
||||
const serveStatic = require('serve-static')
|
||||
const io = require('socket.io')
|
||||
|
||||
const logger = require('./logger')
|
||||
|
||||
@ -12,52 +12,65 @@ function getRemoteAddr (req) {
|
||||
|
||||
class Server {
|
||||
constructor (clientSocketHandler) {
|
||||
this._clientSocketHandler = clientSocketHandler
|
||||
this._connectedSockets = 0
|
||||
this.createHttpServer()
|
||||
this.createWebSocketServer(clientSocketHandler)
|
||||
}
|
||||
|
||||
this._http = http.createServer(this.handleHttpRequest)
|
||||
createHttpServer () {
|
||||
const distServeStatic = serveStatic('dist/')
|
||||
const faviconsServeStatic = serveStatic('favicons/')
|
||||
|
||||
this._distServeStatic = serveStatic('dist/')
|
||||
this._faviconsServeStatic = serveStatic('favicons/')
|
||||
this._http = http.createServer((req, res) => {
|
||||
logger.log('info', '%s requested: %s', getRemoteAddr(req), req.url)
|
||||
|
||||
// Attempt to handle req using distServeStatic, otherwise fail over to faviconServeStatic
|
||||
// If faviconServeStatic fails, pass to finalHttpHandler to terminate
|
||||
distServeStatic(req, res, () => {
|
||||
faviconsServeStatic(req, res, finalHttpHandler(req, res))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
createWebSocketServer (proxyClientSocketHandler) {
|
||||
this._wss = new WebSocket.Server({
|
||||
server: this._http
|
||||
})
|
||||
|
||||
this._wss.on('connection', (client, req) => {
|
||||
logger.log('info', '%s connected, total clients: %d', getRemoteAddr(req), this.getConnectedClients())
|
||||
|
||||
// Bind disconnect event for logging
|
||||
client.on('close', () => {
|
||||
logger.log('info', '%s disconnected, total clients: %d', getRemoteAddr(req), this.getConnectedClients())
|
||||
})
|
||||
|
||||
// Pass client off to proxy handler
|
||||
proxyClientSocketHandler(client)
|
||||
})
|
||||
}
|
||||
|
||||
listen (host, port) {
|
||||
this._http.listen(port, host)
|
||||
|
||||
this._io = io.listen(this._http)
|
||||
this._io.on('connect', this.handleClientSocket)
|
||||
|
||||
logger.log('info', 'Started on %s:%d', host, port)
|
||||
}
|
||||
|
||||
broadcast (event, payload) {
|
||||
this._io.sockets.emit(event, payload)
|
||||
}
|
||||
|
||||
handleHttpRequest = (req, res) => {
|
||||
logger.log('info', '%s requested: %s', getRemoteAddr(req), req.url)
|
||||
|
||||
// Attempt to handle req using distServeStatic, otherwise fail over to faviconServeStatic
|
||||
// If faviconServeStatic fails, pass to finalHttpHandler to terminate
|
||||
this._distServeStatic(req, res, () => {
|
||||
this._faviconsServeStatic(req, res, finalHttpHandler(req, res))
|
||||
broadcast (payload) {
|
||||
this._wss.clients.forEach(client => {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
client.send(payload)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleClientSocket = (client) => {
|
||||
this._connectedSockets++
|
||||
|
||||
logger.log('info', '%s connected, total clients: %d', getRemoteAddr(client.request), this._connectedSockets)
|
||||
|
||||
// Bind disconnect event for logging
|
||||
client.on('disconnect', () => {
|
||||
this._connectedSockets--
|
||||
|
||||
logger.log('info', '%s disconnected, total clients: %d', getRemoteAddr(client.request), this._connectedSockets)
|
||||
getConnectedClients () {
|
||||
let count = 0
|
||||
this._wss.clients.forEach(client => {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
count++
|
||||
}
|
||||
})
|
||||
|
||||
// Pass client off to proxy handler
|
||||
this._clientSocketHandler(client)
|
||||
return count
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user