I am learning webRTC and tried to implement signaling service through websockets. I am still a beginner in backend development so not sure how correct my code is. Can you please review it and let me know the mistakes and how can I make scale it for multiple users using the service in real-time?
server code
const express = require('express');
const app = express();
const http = require('http');
const path = require('path');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
const fs = require("fs");
console.log(path.join(__dirname, "../public"));
// Express Middleware for serving static files
app.use(express.static(path.join(__dirname, "../client")));
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '../client/client1.html'));
});
var users = 0;
var roomCount = 1;
io.on('connection', (socket) => {
console.log('a user connected');
socket.join("room" + roomCount);
users++;
if (users == 1) {
users++;
io.to(Array.from(socket.rooms)[1]).emit("becomeClient1");
} else {
users = 0;
roomCount++; // assuming roomCount won't overflow
socket.emit("becomeClient2");
io.to(Array.from(socket.rooms)[1]).emit("notifyClient1");
}
socket.on("client1offer", (client1offer) => {
console.log("cl1 offer--------" + JSON.stringify(client1offer));
socket.broadcast.to(Array.from(socket.rooms)[1]).emit("client1offer", client1offer);
});
socket.on("client1IceCandidates", (client1iceCandidate) => {
console.log("ice--------" + client1iceCandidate);
socket.broadcast.to(Array.from(socket.rooms)[1]).emit("client1IceCandidates", client1iceCandidate);
});
socket.on("client2answer", answer => {
console.log("cl2 answer emit");
socket.broadcast.to(Array.from(socket.rooms)[1]).emit("client2answer", answer);
});
socket.on("disconnect", () => {
console.log("----socket close----------");
});
});
server.listen(8082, () => {
console.log('listening on *:8082');
});
user end code for video calling feature
let localStream;
let remoteStream;
const servers = [{
urls: [
"stun.l.google.com:19302",
"stun1.l.google.com:19302",
"stun2.l.google.com:19302"
]
}];
const lc = new RTCPeerConnection(servers);
const dc = lc.createDataChannel("channel");
const rc = new RTCPeerConnection(servers);
async function init() {
try {
localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false });
document.getElementById("user-1").srcObject = localStream;
console.log("Local stream obtained successfully.");
} catch (error) {
console.error("Error accessing local media stream:", error);
}
}
init().then(() => {
console.log("--------------->>>>>>>>>>>>>>>>>>>>>>>>>>");
var socket = io();
socket.on("connect", () => {
console.log("WebSocket connected");
rc.addEventListener("track", e => {
console.log("Track received:", e.track);
if (e.streams && e.streams[0]) {
document.getElementById("user-2").srcObject = e.streams[0];
}
});
lc.addEventListener("track", e => {
console.log("Track received from remote:", e.track);
if (e.streams && e.streams[0]) {
document.getElementById("user-2").srcObject = e.streams[0];
}
});
localStream.getTracks().forEach(track => {
lc.addTrack(track, localStream);
console.log("Tracks added to lc.");
});
localStream.getTracks().forEach(track => {
rc.addTrack(track, localStream);
console.log("Tracks added to rc.");
});
});
socket.on("error", (error) => {
console.error("WebSocket error:", error);
});
socket.on("becomeClient1", () => {
console.log("Received becomeClient1 event");
socket.on("notifyClient1", () => {
console.log("Client 2 joined.");
try {
dc.onmessage = e => console.log("Received message: " + e.data);
dc.onopen = e => {
console.log("Data channel connection opened.");
dc.send("heyyyyyy");
socket.disconnect();
};
lc.createOffer().then(o => {
lc.setLocalDescription(o);
console.log("Local description set successfully." + JSON.stringify(o));
socket.emit("client1offer", o);
});
lc.onicecandidate = event => {
console.log("New ICE candidate. " + JSON.stringify(event));
if (event.candidate) {
socket.emit("client1IceCandidates", event.candidate);
}
};
} catch (error) {
console.error("Error setting up client 1:", error);
}
});
socket.on("client2answer", answer => {
lc.setRemoteDescription(answer).then(() => {
console.log("remote description for cl1 set");
});
});
});
socket.on("becomeClient2", () => {
console.log("Received becomeClient2 event");
try {
rc.onicecandidate = e => {
console.log("New ICE candidate.");
};
rc.ondatachannel = e => {
rc.dc = e.channel;
rc.dc.onmessage = e => {
console.log("Received message from client 1: " + e.data);
rc.dc.send("supp");
};
rc.dc.onopen = e => {
console.log("Data channel connection opened.");
};
socket.close();
};
socket.on("client1offer", offer => {
console.log("-------------<<>>>>>>");
rc.setRemoteDescription(offer).then(() => {
console.log("cl1 offer set");
rc.createAnswer().then(answer => {
rc.setLocalDescription(answer);
socket.emit("client2answer", answer);
}).then(() => {
console.log("Local description for cl2 set.");
});
});
});
socket.on("client1IceCandidates", client1IceCandidate => {
console.log("cl1 ice ---> " + client1IceCandidate);
rc.addIceCandidate(client1IceCandidate);
});
} catch (error) {
console.error("Error setting up client 2:", error);
}
});
});
I opened several tabs in my browser and its working properly but not sure how reliable the app will be if deployed. Please point out the mistakes and things I need to improve/learn.