diff --git a/index.mjs b/index.mjs index cf18d94a..75e5fc88 100644 --- a/index.mjs +++ b/index.mjs @@ -17,11 +17,14 @@ const port = parseInt(process.env.PORT || "3000", 10); cluster.schedulingPolicy = cluster.SCHED_RR; function logInfo(message) { - console.info(`[INFO] ${message}`); + console.info(`[~] ${message}`); +} +function logSuccess(message) { + console.info(`[+] ${message}`); } function logError(error) { const msg = error instanceof Error ? error.message : error; - console.error(`[ERR] ${msg}`); + console.error(`[!] ${msg}`); } process.on("uncaughtException", (err) => logError(`Unhandled Exception: ${err}`)); @@ -29,14 +32,17 @@ process.on("unhandledRejection", (reason) => logError(`Unhandled Promise Rejecti if (cluster.isPrimary) { const numCPUs = os.cpus().length; - logInfo(`Master started. Forking ${numCPUs} workers.`); + logInfo(`Master started. Forking ${numCPUs} workers...`); + for (let i = 0; i < numCPUs; i++) { cluster.fork(); } + cluster.on("exit", (worker, code, signal) => { logError(`Worker ${worker.process.pid} terminated (code: ${code}, signal: ${signal}). Restarting...`); cluster.fork(); }); + let currentWorker = 0; const server = net.createServer({ pauseOnConnect: true }, (connection) => { const workerIds = Object.keys(cluster.workers); @@ -48,19 +54,18 @@ if (cluster.isPrimary) { currentWorker++; if (worker) worker.send("sticky-session:connection", connection); }); + server.on("error", (err) => logError(`Server error: ${err}`)); - server.listen(port, () => logInfo(`Server running at http://localhost:${port}`)); + server.listen(port, () => logSuccess(`Server running on port ${port}.`)); + } else { - - process.env.UV_THREADPOOL_SIZE = os.cpus().length * 2; - + process.env.UV_THREADPOOL_SIZE = String(os.cpus().length * 2); const __dirname = process.cwd(); const publicPath = path.join(__dirname, "public"); const app = express(); app.use(compression({ level: 9, threshold: 128, memLevel: 9 })); - const cache = new NodeCache({ stdTTL: 1, checkperiod: 1 }); app.use((req, res, next) => { const key = req.originalUrl; if (cache.has(key)) { @@ -76,20 +81,20 @@ if (cluster.isPrimary) { next(); }); - const staticOpts = { maxAge: "1s" }; + const staticOpts = { maxAge: "7d", immutable: true }; app.use("/baremux/", express.static(baremuxPath, staticOpts)); app.use("/epoxy/", express.static(epoxyPath, staticOpts)); app.use("/libcurl/", express.static(libcurlPath, staticOpts)); app.use(express.static(publicPath, staticOpts)); app.use("/wah/", express.static(uvPath, staticOpts)); - app.use(express.json()); - app.get("/", (req, res) => res.sendFile(path.join(publicPath, "$.html"))); - app.get("/g", (req, res) => res.sendFile(path.join(publicPath, "!.html"))); - app.get("/a", (req, res) => res.sendFile(path.join(publicPath, "!!.html"))); - app.get("/ai", (req, res) => res.sendFile(path.join(publicPath, "!!!.html"))); - app.get("/resent", (req, res) => res.sendFile(path.join(publicPath, "resent", "index.html"))); - app.use((req, res) => res.status(404).sendFile(path.join(publicPath, "404.html"))); + app.use(express.json()); + const sendHtml = (file) => (req, res) => res.sendFile(path.join(publicPath, file)); + app.get('/', sendHtml('$.html')); + app.get('/g', sendHtml('!.html')); + app.get('/a', sendHtml('!!.html')); + app.get('/resent', (req, res) => res.sendFile(path.join(publicPath, 'resent', 'index.html'))); + app.use((req, res) => res.status(404).sendFile(path.join(publicPath, '404.html'))); const server = createServer(app); server.keepAliveTimeout = 0; @@ -99,47 +104,52 @@ if (cluster.isPrimary) { pingWSS.on("connection", (ws, req) => { const remoteAddress = req.socket.remoteAddress || "unknown"; let latencies = []; - const pingInterval = setInterval(() => { + const interval = setInterval(() => { if (ws.readyState === WebSocket.OPEN) { - const timestamp = Date.now(); - ws.send(JSON.stringify({ type: "ping", timestamp })); + const ts = Date.now(); + ws.send(JSON.stringify({ type: 'ping', timestamp: ts })); } }, 1000); - ws.on("message", (message) => { + + ws.on('message', (message) => { try { const data = JSON.parse(message); - if (data.type === "pong" && data.timestamp) { + if (data.type === 'pong' && data.timestamp) { const latency = Date.now() - data.timestamp; latencies.push(latency); if (latencies.length > 5) latencies.shift(); - ws.send(JSON.stringify({ type: "latency", latency })); + ws.send(JSON.stringify({ type: 'latency', latency })); } - } catch (e) { - logError(`Ping error: ${e}`); + } catch (err) { + logError(`Ping handling error: ${err}`); } }); - ws.on("close", () => { - clearInterval(pingInterval); - const avgLatency = latencies.length ? latencies.reduce((a, b) => a + b) / latencies.length : 0; - logInfo(`Conn from ${remoteAddress} closed. Avg: ${avgLatency.toFixed(2)}ms.`); + + ws.on('close', () => { + clearInterval(interval); + const avg = latencies.length ? (latencies.reduce((a, b) => a + b) / latencies.length).toFixed(2) : 0; + logInfo(`Connection from ${remoteAddress} closed. Avg latency: ${avg}ms.`); }); }); - server.on("upgrade", (req, socket, head) => { - if (req.url === "/w/ping") { - pingWSS.handleUpgrade(req, socket, head, (ws) => pingWSS.emit("connection", ws, req)); - } else if (req.url.startsWith("/w/")) { + server.on('upgrade', (req, socket, head) => { + if (req.url === '/w/ping') { + pingWSS.handleUpgrade(req, socket, head, (ws) => pingWSS.emit('connection', ws, req)); + } else if (req.url.startsWith('/w/')) { wisp.routeRequest(req, socket, head); } else { socket.end(); } }); - server.on("error", (err) => logError(`Worker server error: ${err}`)); - server.listen(0, () => logInfo(`Worker ${process.pid} ready.`)); - process.on("message", (message, connection) => { - if (message === "sticky-session:connection") { - server.emit("connection", connection); - connection.resume(); + + server.on('error', (err) => logError(`Worker server error: ${err}`)); + + server.listen(0, () => logSuccess(`Worker ${process.pid} ready and listening.`)); + + process.on('message', (msg, conn) => { + if (msg === 'sticky-session:connection' && conn) { + server.emit('connection', conn); + conn.resume(); } }); } \ No newline at end of file