import { globalLogger } from "@config/logger";
import { WebSocketServer } from "ws";
import { handleWebSocketConnection } from "./websocket-handlers";
/**
* Create a general-purpose WebSocket server for Unity WebGL and other platforms
* @param {HTTPServer} httpServer - HTTP server instance to attach WebSocket server to
* @returns {WebSocketServer} WebSocketServer instance
*/
export function createWebSocketServer(httpServer) {
const wss = new WebSocketServer({
server: httpServer,
path: "/ws",
perMessageDeflate: false, // Lower latency
maxPayload: 1 * 1024 * 1024, // 1MB limit
});
wss.on("connection", (ws, request) => {
const socket = ws;
socket.isAlive = true;
ws.on("pong", () => {
socket.isAlive = true;
globalLogger.debug({ remoteAddress: request.socket.remoteAddress }, "WebSocket pong");
});
ws.on("error", (error) => {
globalLogger.error({ error }, "WebSocket connection error");
});
ws.on("close", (code, reason) => {
globalLogger.info({ code, reason: reason?.toString("utf8") }, "WebSocket connection closed");
});
handleWebSocketConnection(ws, request);
});
const heartbeat = setInterval(() => {
wss.clients.forEach((client) => {
const socket = client;
if (socket.isAlive === false) {
globalLogger.warn("WebSocket heartbeat failed, terminating client");
socket.terminate();
return;
}
socket.isAlive = false;
globalLogger.debug("WebSocket ping");
socket.ping();
});
}, 30000);
wss.on("close", () => {
clearInterval(heartbeat);
});
wss.on("error", (error) => {
globalLogger.error({ error }, "WebSocket server error");
});
globalLogger.info("General-purpose WebSocket server initialized on /ws");
return wss;
}
Source