|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import config from '../../config.js'; |
|
|
import { generateId } from '../utils/idGenerator.js'; |
|
|
|
|
|
const clients = new Map(); |
|
|
|
|
|
export const setupWebSocket = (wss) => { |
|
|
wss.on('connection', (ws) => { |
|
|
const clientId = generateId(); |
|
|
let clientSessionId = null; |
|
|
|
|
|
ws.clientId = clientId; |
|
|
ws.isAlive = true; |
|
|
|
|
|
ws.on('pong', () => { |
|
|
ws.isAlive = true; |
|
|
}); |
|
|
|
|
|
ws.on('message', (data) => { |
|
|
try { |
|
|
const message = JSON.parse(data.toString()); |
|
|
|
|
|
if (message.type === 'register' && message.sessionId) { |
|
|
clientSessionId = message.sessionId; |
|
|
|
|
|
if (clients.has(clientSessionId)) { |
|
|
const oldClient = clients.get(clientSessionId); |
|
|
if (oldClient && oldClient.readyState === 1) { |
|
|
oldClient.close(); |
|
|
} |
|
|
} |
|
|
|
|
|
clients.set(clientSessionId, ws); |
|
|
ws.sessionId = clientSessionId; |
|
|
|
|
|
ws.send(JSON.stringify({ |
|
|
type: 'registered', |
|
|
sessionId: clientSessionId |
|
|
})); |
|
|
} |
|
|
|
|
|
handleWebSocketMessage(ws, message); |
|
|
} catch (error) {} |
|
|
}); |
|
|
|
|
|
ws.on('close', () => { |
|
|
if (clientSessionId) { |
|
|
clients.delete(clientSessionId); |
|
|
} |
|
|
}); |
|
|
|
|
|
ws.on('error', () => { |
|
|
if (clientSessionId) { |
|
|
clients.delete(clientSessionId); |
|
|
} |
|
|
}); |
|
|
|
|
|
ws.send(JSON.stringify({ |
|
|
type: 'connected', |
|
|
clientId |
|
|
})); |
|
|
}); |
|
|
|
|
|
const interval = setInterval(() => { |
|
|
wss.clients.forEach((ws) => { |
|
|
if (ws.isAlive === false) { |
|
|
return ws.terminate(); |
|
|
} |
|
|
ws.isAlive = false; |
|
|
ws.ping(); |
|
|
}); |
|
|
}, config.websocket.heartbeat); |
|
|
|
|
|
wss.on('close', () => { |
|
|
clearInterval(interval); |
|
|
}); |
|
|
}; |
|
|
|
|
|
const handleWebSocketMessage = (ws, message) => { |
|
|
if (message.type === 'ping') { |
|
|
ws.send(JSON.stringify({ type: 'pong' })); |
|
|
} |
|
|
}; |
|
|
|
|
|
export const sendToSession = (sessionId, data) => { |
|
|
const client = clients.get(sessionId); |
|
|
if (client && client.readyState === 1) { |
|
|
client.send(JSON.stringify({ |
|
|
...data, |
|
|
sessionId |
|
|
})); |
|
|
} |
|
|
}; |
|
|
|
|
|
export const broadcastToAll = (data) => { |
|
|
clients.forEach((client, sessionId) => { |
|
|
if (client.readyState === 1) { |
|
|
client.send(JSON.stringify({ |
|
|
...data, |
|
|
sessionId |
|
|
})); |
|
|
} |
|
|
}); |
|
|
}; |