pulsar/backend/server.js
2026-04-30 04:39:20 +01:00

104 lines
2.7 KiB
JavaScript

const { WebSocketServer } = require("ws");
const PORT = 3000;
const wss = new WebSocketServer({ port: PORT });
// rooms: { roomId: { host: WebSocket, viewer: WebSocket } }
const rooms = {};
console.log(`Pulsar signalling server listening on ws://localhost:${PORT}`);
wss.on("connection", (ws) => {
ws.roomId = null;
ws.role = null; // "host" or "viewer"
ws.on("message", (raw) => {
let msg;
try {
msg = JSON.parse(raw);
} catch {
return;
}
const { type, roomId, data } = msg;
switch (type) {
case "create": {
if (!roomId) return;
if (rooms[roomId]) {
ws.send(JSON.stringify({ type: "error", message: "Room already exists" }));
return;
}
rooms[roomId] = { host: ws, viewer: null };
ws.roomId = roomId;
ws.role = "host";
ws.send(JSON.stringify({ type: "created", roomId }));
console.log(`Room created: ${roomId}`);
break;
}
case "join": {
if (!roomId || !rooms[roomId]) {
ws.send(JSON.stringify({ type: "error", message: "Room not found" }));
return;
}
const room = rooms[roomId];
if (room.viewer) {
ws.send(JSON.stringify({ type: "error", message: "Room full" }));
return;
}
room.viewer = ws;
ws.roomId = roomId;
ws.role = "viewer";
ws.send(JSON.stringify({ type: "joined", roomId }));
room.host.send(JSON.stringify({ type: "peer_joined" }));
console.log(`Viewer joined room: ${roomId}`);
break;
}
case "signal": {
if (!ws.roomId || !rooms[ws.roomId]) return;
const room = rooms[ws.roomId];
const target = ws.role === "host" ? room.viewer : room.host;
if (target && target.readyState === 1) {
target.send(JSON.stringify({ type: "signal", data }));
}
break;
}
default:
break;
}
});
ws.on("close", () => {
if (!ws.roomId || !rooms[ws.roomId]) return;
const room = rooms[ws.roomId];
if (ws.role === "host") {
// notify viewer if connected
if (room.viewer && room.viewer.readyState === 1) {
room.viewer.send(JSON.stringify({ type: "host_disconnected" }));
}
delete rooms[ws.roomId];
console.log(`Room closed: ${ws.roomId}`);
} else if (ws.role === "viewer") {
room.viewer = null;
if (room.host && room.host.readyState === 1) {
room.host.send(JSON.stringify({ type: "peer_disconnected" }));
}
console.log(`Viewer left room: ${ws.roomId}`);
}
});
ws.on("error", (err) => {
console.error("WebSocket error:", err.message);
});
});