96 lines
2.6 KiB
TypeScript
96 lines
2.6 KiB
TypeScript
import { WebSocket, WebSocketServer } from 'ws';
|
|
import { ulid } from 'ulid';
|
|
|
|
const wss = new WebSocketServer({ port: 8080 });
|
|
|
|
const rooms = new Map<string, Set<string>>();
|
|
const sockets = new Map<string, WebSocket>();
|
|
|
|
wss.on('connection', (ws) => {
|
|
let peerId = ulid();
|
|
|
|
const join = (room: string) => {
|
|
if (!rooms.has(room)) {
|
|
rooms.set(room, new Set([peerId]));
|
|
} else {
|
|
rooms.get(room)!.add(peerId);
|
|
}
|
|
};
|
|
|
|
const unjoinAll = () => {
|
|
rooms.entries().forEach(([room, peers]) => {
|
|
peers.delete(peerId);
|
|
if (!peers.size) rooms.delete(room);
|
|
});
|
|
};
|
|
|
|
ws.on('message', (message) => {
|
|
try {
|
|
const text = message.toString('utf8');
|
|
const data = JSON.parse(text);
|
|
|
|
if (data.type === 'self') {
|
|
ws.send(JSON.stringify({
|
|
type: 'self',
|
|
id: peerId.toString(),
|
|
}));
|
|
|
|
return;
|
|
}
|
|
|
|
if (data.type === 'join' && typeof data.room === 'string') {
|
|
unjoinAll();
|
|
join(data.room);
|
|
|
|
const peers = rooms.get(data.room) ?? [];
|
|
peers.forEach((peer) => {
|
|
sockets.get(peer)!.send(JSON.stringify({
|
|
type: 'peers',
|
|
peers: peers,
|
|
}));
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
if (data.type === 'offer' && typeof data.peer === 'string' && typeof data.offer === 'object') {
|
|
const otherWS = sockets.get(data.peer);
|
|
if (!otherWS) return;
|
|
|
|
otherWS.send(JSON.stringify({
|
|
type: 'offer',
|
|
from: peerId,
|
|
offer: data.offer,
|
|
}));
|
|
|
|
return;
|
|
}
|
|
|
|
if (data.type === 'accept' && typeof data.peer === 'string' && typeof data.counterOffer === 'object') {
|
|
const otherWS = sockets.get(data.peer);
|
|
if (!otherWS) return;
|
|
|
|
otherWS.send(JSON.stringify({
|
|
type: 'accept',
|
|
from: peerId,
|
|
counterOffer: data.counterOffer,
|
|
}));
|
|
|
|
return;
|
|
}
|
|
|
|
throw 0;
|
|
} catch (e) {
|
|
ws.send(JSON.stringify({
|
|
type: 'error',
|
|
message: 'Bad Request',
|
|
}));
|
|
}
|
|
});
|
|
|
|
ws.on('close', () => {
|
|
unjoinAll();
|
|
sockets.delete(peerId);
|
|
});
|
|
});
|