const socket = io(); const params = new URLSearchParams(location.search); const roomId = params.get("room"); const name = params.get("name"); document.getElementById("roomTitle").innerText = "Room: " + roomId; let peers = {}; let channels = {}; socket.emit("join-room", { roomId, name }); socket.on("user-joined", ({ id }) => { createPeer(id, true); }); socket.on("signal", async ({ from, data }) => { if (!peers[from]) createPeer(from, false); if (data.sdp) { await peers[from].setRemoteDescription(data.sdp); if (data.sdp.type === "offer") { const answer = await peers[from].createAnswer(); await peers[from].setLocalDescription(answer); socket.emit("signal", { to: from, data: { sdp: peers[from].localDescription } }); } } if (data.candidate) { await peers[from].addIceCandidate(data.candidate); } }); function createPeer(id, initiator) { const peer = new RTCPeerConnection({ iceServers: [{ urls: "stun:stun.l.google.com:19302" }] }); if (initiator) { const channel = peer.createDataChannel("chat"); setupChannel(id, channel); } else { peer.ondatachannel = (e) => { setupChannel(id, e.channel); }; } peer.onicecandidate = (e) => { if (e.candidate) { socket.emit("signal", { to: id, data: { candidate: e.candidate } }); } }; peers[id] = peer; if (initiator) { peer.createOffer().then(offer => { peer.setLocalDescription(offer); socket.emit("signal", { to: id, data: { sdp: offer } }); }); } } function setupChannel(id, channel) { channels[id] = channel; channel.onmessage = (e) => { addMessage("Peer", e.data); }; } function send() { const msgInput = document.getElementById("msg"); const msg = msgInput.value; addMessage("Me", msg); for (let id in channels) { channels[id].send(msg); } msgInput.value = ""; } function addMessage(sender, text) { const chat = document.getElementById("chat"); chat.innerHTML += `

${sender}: ${text}

`; chat.scrollTop = chat.scrollHeight; }