From: Ruben Beltran del Rio Date: Wed, 30 Aug 2023 16:11:57 +0000 (+0200) Subject: Add new RTC code X-Git-Url: https://git.r.bdr.sh/rbdr/junction/commitdiff_plain/284fc661dc7f18aa32d0dbcd8e7f98cb16af4bb7?ds=sidebyside;hp=8c7fb565690890d57b6af20ad0771a48cf82b4c7 Add new RTC code --- diff --git a/extension/content_script.js b/extension/content_script.js index 6785a65..8ca721a 100644 --- a/extension/content_script.js +++ b/extension/content_script.js @@ -40,9 +40,9 @@ const internals = { internals.socket.on('connect', function() { - console.log("Connected to signaling server, group: ", data.currentUrl); + console.log('Connected to signaling server, group: ', data.currentUrl); internals.socket.emit('join', { - 'url': data.currentUrl, + room: data.currentUrl, }); }); @@ -53,58 +53,80 @@ const internals = { internals.socket.on('addPeer', function(data) { - console.log(data); - Peers.add(data.peer_id, internals.tada); - const peerId = data.peer_id; + Peers.add(data.peerId, internals.tada); + const peerId = data.peerId; - const peerConn = new RTCPeerConnection( - {"iceServers": internals.kIceServers}, - {"optional": [{"DtlsSrtpKeyAgreement": true}]} + const peerConnection = new RTCPeerConnection( + { iceServers: internals.kIceServers }, + { optional: [{ DtlsSrtpKeyAgreement: true }] } ); - internals.peers[peerId] = peerConn; + internals.peers[peerId] = peerConnection; + mediaStream.getTracks().forEach((track) => { + peerConnection.addTrack(track, localStream); + }); - peerConn.onicecandidate = (event) => { + peerConnection.onicecandidate = (event) => { if (event.candidate) { internals.socket.emit('relayICECandidate', { - 'peer_id': peerId, - 'ice_candidate': { - 'sdpMLineIndex': event.candidate.sdpMLineIndex, - 'candidate': event.candidate.candidate - } + peerId: peerId, + candidate: event.candidate }); } } - peerConn.onaddstream = (stream) => { - console.log(`Received stream for peer ${peerId}`); - console.log(stream); - } + const remoteStream = new MediaStream(); + peerConnection.ontrack = (event) => { + remoteStream.addTrack(event.track); + const remoteAudioElement = new Audio(); + remoteAudioElement.srcObject = remoteStream; + remoteAudioElement.play(); + }; + + peerConnection.onnegotiationneeded = async () => { + console.log("Creating RTC offer to ", peerId); + const offer = await peerConnection.createOffer(); + await peerConnection.setLocalDescription(offer); + + // Emit the offer to the peer + socket.emit('relayOffer', { offer, peerId }); + }; - peerConn.addStream(mediaStream); - - if (data.should_create_offer) { - console.log("Creating RTC offer to ", peerId); - peerConn.createOffer((local_description) => { - console.log("Local offer description is: ", local_description); - peerConn.setLocalDescription(local_description, () => { - internals.socket.emit('relaySessionDescription', { - 'peer_id': peerId, - 'session_description': local_description - }); - - console.log("Offer setLocalDescription succeeded"); - }, () => { console.log("Offer setLocalDescription failed!"); } - ); - }, - (error) => { console.log("Error sending offer: ", error) } - ); - } console.log(`There are now ${Peers.count()} participants`); }); + socket.on('offerReceived', async (data) => { + + const peerConnection = internals.peers[data.peerId]; + + const offer = new RTCSessionDescription(data.offer); + await peerConnection.setRemoteDescription(offer); + + const answer = await peerConnection.createAnswer(); + await peerConnection.setLocalDescription(answer); + + // Send the answer to the peer + socket.emit('relayAnswer', { answer, peerId: data.peerId }); + }); + + socket.on('answerReceived', async (data) => { + + const peerConnection = internals.peers[data.peerId]; + const answer = new RTCSessionDescription(data.answer); + await peerConnection.setRemoteDescription(answer); + }); + + socket.on('ICECandidateReceived', async (data) => { + + const peerConnection = internals.peers[data.peerId]; + const candidate = new RTCIceCandidate(data.candidate); + await peerConnection.addIceCandidate(candidate); + }); + + internals.socket.on('removePeer', function() { + delete internals.peers[data.peerId]; Peers.remove('id-'+(Peers.count() - 1)); // This is only for testing, don't use count to remove ids. console.log(`There are now ${Peers.count()} participants`); }); diff --git a/server/events.js b/server/events.js index 99e6b37..3ef21a9 100644 --- a/server/events.js +++ b/server/events.js @@ -1,27 +1,41 @@ export function addPeer(peerId, shouldCreateOffer) { - return { - peer_id: peerId, - should_create_offer: shouldCreateOffer, - } + return { + peerId, + shouldCreateOffer, + } } export function removePeer(peerId) { return { - peer_id: peerId, + peerId, } } export function SessionDescriptionReceived(peerId, sessionDescription) { return { - peer_id: peerId, - session_description: sessionDescription, + peerId, + sessionDescription, + } +} + +export function ICECandidateReceived(peerId, candidate) { + return { + peerId, + candidate + } +} + +export function offerReceived(peerId, offer) { + return { + peerId, + offer } } -export function ICECandidateReceived(peerId, ICECandidate) { +export function answerReceived(peerId, answer) { return { - peer_id: peerId, - ice_candidate: ICECandidate, + peerId, + answer } } @@ -30,6 +44,8 @@ export const types = { REMOVE_PEER: 'removePeer', RELAY_SESSION_DESCRIPTION: 'relaySessionDescription', RELAY_ICE_CANDIDATE: 'relayICECandidate', + OFFER_RECEIVED: 'offerReceived', + ANSWER_RECEIVED: 'answerReceived', ICE_CANDIDATE_RECEIVED: 'ICECandidateReceived', SESSION_DESCRIPTION_RECEIVED: 'SessionDescriptionReceived', }; diff --git a/server/index.js b/server/index.js index b5d5d1b..e6a37c7 100644 --- a/server/index.js +++ b/server/index.js @@ -5,51 +5,62 @@ import * as events from './events.js'; const server = new Server(port); console.log(`Listening on port ${port}`); -const sockets = {}; +const rooms = {}; server.on('connection', (socket) => { - sockets[socket.id] = socket; const me = socket.id; console.log(`[CONNECT] New client connected with ID ${me}`); socket.on('join', async (data) => { - socket.join(data.url); - const sockets = await server.in(data.url).fetchSockets() - console.log(sockets); - sockets.forEach((peer) => { - if (peer.id !== me) { - peer.emit(events.types.ADD_PEER, events.addPeer(me, false)); - socket.emit(events.types.ADD_PEER, events.addPeer(peer.id, true)); - } - }); - console.log(`[CONNECT] Client ${me} added to room ${data.url}`); + const room = data.room; + socket.join(room); + + if (!rooms[room]) { + rooms[room] = {}; + } + + rooms[room].push(socket.id); + + const sockets = await server.in(data.url).fetchSockets() + sockets.forEach((peer) => { + if (peer.id !== me) { + peer.emit(events.types.ADD_PEER, events.addPeer(me, false)); + socket.emit(events.types.ADD_PEER, events.addPeer(peer.id, true)); + } + }); + console.log(`[CONNECT] Client ${me} added to room ${data.url}`); }); socket.on('disconnecting', () => { - const rooms = Object.keys(socket.rooms); - rooms.forEach(room => server.to(room).emit(events.types.REMOVE_PEER, events.removePeer(me))); - console.log(`[DISCONNECT] Client ${me} has disconnected and has been removed from all rooms`); + for (const room in rooms) { + if (rooms[room].includes(me)) { + rooms[room] = rooms[room].filter(id => id !== me); + socket.to(room).emit(events.types.REMOVE_PEER, events.removePeer(me)); + if (rooms[room].length === 0) { + delete rooms[room]; + } + } + } + console.log(`[DISCONNECT] Client ${me} has disconnected and has been removed from all rooms`); }); socket.on('relayICECandidate', async (data) => { - const sockets = await server.in(data.url).fetchSockets() - console.log(sockets); - sockets.forEach((peer) => { - peer.emit(events.types.ICE_CANDIDATE_RECEIVED, events.ICECandidateReceived(me, data.ice_candidate)) - }); + socket.to(data.peerId).emit(events.types.ICE_CANDIDATE_RECEIVED, events.ICECandidateReceived(me, data.candidate)) console.log(`[RELAY_ICE_CANDIDATE] ICE candidate for client ${me} has been relayed to all peers`); }); - socket.on('relaySessionDescription', async (data) => { - const sockets = await server.in(data.url).fetchSockets() - console.log(sockets); - sockets.forEach((peer) => { - peer.emit(events.types.SESSION_DESCRIPTION_RECEIVED, events.SessionDescriptionReceived(me, data.session_description)) - }); + socket.on('relayOffer', async (data) => { + + socket.to(data.peerId).emit(events.types.OFFER_RECEIVED, events.offerReceived(me, data.offer)) + console.log(`[RELAY_OFFER] ICE offer for client ${me} has been relayed to all peers`); + }); + + socket.on('relayAnswer', async (data) => { - console.log(`[RELAY_SESSION_DESCRIPTION] Session description for client ${me} has been relayed to all peers`); + socket.to(data.peerId).emit(events.types.ANSWER_RECEIVED, events.answerReceived(me, data.answer)) + console.log(`[RELAY_OFFER] ICE offer for client ${me} has been relayed to all peers`); }); });