mirror of
https://github.com/imputnet/cobalt.git
synced 2025-06-28 17:38:31 +00:00
181 lines
5.9 KiB
JavaScript
181 lines
5.9 KiB
JavaScript
import { WebSocketServer } from 'ws';
|
|
import { Green } from '../misc/console-text.js';
|
|
|
|
export const setupSignalingServer = (httpServer) => {
|
|
const wss = new WebSocketServer({
|
|
server: httpServer,
|
|
path: '/ws'
|
|
});
|
|
|
|
const sessions = new Map(); // sessionId -> { creator, joiner, createdAt }
|
|
|
|
// 清理过期会话
|
|
setInterval(() => {
|
|
const now = Date.now();
|
|
for (const [sessionId, session] of sessions.entries()) {
|
|
if (now - session.createdAt > 30 * 60 * 1000) { // 30分钟过期
|
|
sessions.delete(sessionId);
|
|
console.log(`清理过期会话: ${sessionId}`);
|
|
}
|
|
}
|
|
}, 5 * 60 * 1000); // 每5分钟检查一次
|
|
|
|
wss.on('connection', (ws, req) => {
|
|
console.log('WebSocket连接建立:', req.socket.remoteAddress);
|
|
|
|
let sessionId = null;
|
|
let userRole = null; // 'creator' | 'joiner'
|
|
|
|
ws.on('message', (data) => {
|
|
try {
|
|
const message = JSON.parse(data);
|
|
|
|
switch (message.type) {
|
|
case 'create_session':
|
|
handleCreateSession(ws, message);
|
|
break;
|
|
case 'join_session':
|
|
handleJoinSession(ws, message);
|
|
break;
|
|
case 'offer':
|
|
case 'answer':
|
|
case 'ice_candidate':
|
|
handleSignaling(ws, message, sessionId, userRole);
|
|
break;
|
|
case 'disconnect':
|
|
handleDisconnect(sessionId, userRole);
|
|
break;
|
|
default:
|
|
ws.send(JSON.stringify({
|
|
type: 'error',
|
|
message: '未知消息类型'
|
|
}));
|
|
}
|
|
} catch (error) {
|
|
console.error('WebSocket消息处理错误:', error);
|
|
ws.send(JSON.stringify({
|
|
type: 'error',
|
|
message: '消息格式错误'
|
|
}));
|
|
}
|
|
});
|
|
|
|
ws.on('close', () => {
|
|
console.log('WebSocket连接关闭');
|
|
if (sessionId && userRole) {
|
|
handleDisconnect(sessionId, userRole);
|
|
}
|
|
});
|
|
|
|
ws.on('error', (error) => {
|
|
console.error('WebSocket错误:', error);
|
|
});
|
|
|
|
function handleCreateSession(ws, message) {
|
|
sessionId = Math.random().toString(36).substring(2, 10);
|
|
userRole = 'creator';
|
|
|
|
sessions.set(sessionId, {
|
|
creator: { ws, publicKey: message.publicKey },
|
|
joiner: null,
|
|
createdAt: Date.now()
|
|
});
|
|
|
|
ws.send(JSON.stringify({
|
|
type: 'session_created',
|
|
sessionId: sessionId
|
|
}));
|
|
|
|
console.log(`会话创建: ${sessionId}`);
|
|
}
|
|
|
|
function handleJoinSession(ws, message) {
|
|
const session = sessions.get(message.sessionId);
|
|
|
|
if (!session) {
|
|
ws.send(JSON.stringify({
|
|
type: 'error',
|
|
message: '会话不存在或已过期'
|
|
}));
|
|
return;
|
|
}
|
|
|
|
if (session.joiner) {
|
|
ws.send(JSON.stringify({
|
|
type: 'error',
|
|
message: '会话已满'
|
|
}));
|
|
return;
|
|
}
|
|
|
|
sessionId = message.sessionId;
|
|
userRole = 'joiner';
|
|
|
|
session.joiner = { ws, publicKey: message.publicKey };
|
|
|
|
// 通知创建者有人加入,并交换公钥
|
|
if (session.creator && session.creator.ws.readyState === ws.OPEN) {
|
|
session.creator.ws.send(JSON.stringify({
|
|
type: 'peer_joined',
|
|
publicKey: message.publicKey
|
|
}));
|
|
}
|
|
|
|
// 回复加入者创建者的公钥
|
|
ws.send(JSON.stringify({
|
|
type: 'session_joined',
|
|
publicKey: session.creator.publicKey
|
|
}));
|
|
|
|
console.log(`用户加入会话: ${sessionId}`);
|
|
}
|
|
|
|
function handleSignaling(ws, message, sessionId, userRole) {
|
|
if (!sessionId || !userRole) {
|
|
ws.send(JSON.stringify({
|
|
type: 'error',
|
|
message: '未加入会话'
|
|
}));
|
|
return;
|
|
}
|
|
|
|
const session = sessions.get(sessionId);
|
|
if (!session) {
|
|
ws.send(JSON.stringify({
|
|
type: 'error',
|
|
message: '会话不存在'
|
|
}));
|
|
return;
|
|
}
|
|
|
|
// 转发信令消息给对端
|
|
const peer = userRole === 'creator' ? session.joiner : session.creator;
|
|
if (peer && peer.ws.readyState === ws.OPEN) {
|
|
peer.ws.send(JSON.stringify(message));
|
|
}
|
|
}
|
|
|
|
function handleDisconnect(sessionId, userRole) {
|
|
if (!sessionId) return;
|
|
|
|
const session = sessions.get(sessionId);
|
|
if (!session) return;
|
|
|
|
// 通知对端连接断开
|
|
const peer = userRole === 'creator' ? session.joiner : session.creator;
|
|
if (peer && peer.ws.readyState === ws.OPEN) {
|
|
peer.ws.send(JSON.stringify({
|
|
type: 'peer_disconnected'
|
|
}));
|
|
}
|
|
|
|
// 清理会话
|
|
sessions.delete(sessionId);
|
|
console.log(`会话结束: ${sessionId}`);
|
|
}
|
|
});
|
|
|
|
console.log(`${Green('[✓]')} WebSocket信令服务器启动成功`);
|
|
return wss;
|
|
};
|