1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| "use strict"; const PORT = process.env.PORT || 3000; const MAX_CONNECTIONS = 2000; const MAX_PER_IP = 50; const MOVE_INTERVAL = 40; const IDLE_TIMEOUT = 60000; const connectionCount = new Map(); const lastMoveCache = new Map(); const lastActive = new Map(); const io = require("socket.io")(PORT, { cors: { origin: ["http://localhost", "https://iloli.moe"], methods: ["GET", "POST"] }, maxHttpBufferSize: 1024, pingTimeout: 20000, pingInterval: 25000 }); io.use((socket, next) => { try { const ip = socket.handshake.address || "unknown"; if (io.engine.clientsCount > MAX_CONNECTIONS) { return next(new Error("server full")); } const count = connectionCount.get(ip) || 0; if (count > MAX_PER_IP) { return next(new Error("too many connections")); } connectionCount.set(ip, count + 1); socket._ip = ip; next(); } catch { next(new Error("auth fail")); } }); io.on("connection", (socket) => { console.log("握握手", socket.id); lastActive.set(socket.id, Date.now()); socket.on("mouse_move", (data) => { try { const now = Date.now(); const lastMove = lastMoveCache.get(socket.id) || 0; if (now - lastMove < MOVE_INTERVAL) return; if (!data) return; if (typeof data.x !== "number") return; if (typeof data.y !== "number") return; if (data.x < 0 || data.x > 1) return; if (data.y < 0 || data.y > 1) return; lastMoveCache.set(socket.id, now); lastActive.set(socket.id, now); socket.broadcast.volatile.emit("update_mouse", { id: socket.id, x: data.x, y: data.y }); } catch {} }); socket.on("disconnect", () => { try { console.log("握握双手", socket.id); lastMoveCache.delete(socket.id); lastActive.delete(socket.id); const ip = socket._ip; if (ip && connectionCount.has(ip)) { const c = connectionCount.get(ip) - 1; if (c <= 0) connectionCount.delete(ip); else connectionCount.set(ip, c); } io.emit("user_left", socket.id); } catch {} }); }); setInterval(() => { const now = Date.now(); for (const [id, time] of lastActive.entries()) { if (now - time > IDLE_TIMEOUT) { const socket = io.sockets.sockets.get(id); if (socket) socket.disconnect(true); } } }, 30000); console.log("hexo-live-mouse-secure:", PORT);
|