"My application is designed to mimic functionality similar to Omegle, where it supports both peer-to-peer (P2P) connections and server-based connections using a Selective Forwarding Unit (SFU). I’m developing this application using a tech stack comprising JavaScript, Socket.io, jQuery, Mediasoup, WebRTC, Node.js, and Express.
Currently, I’m attempting to add a feature where users can create rooms, and other users can join these rooms. However, I’m facing difficulties in implementing this feature and need help. Specifically, I want to enforce a user limit per room, which can be defined by the user who creates the room. I would appreciate any advice on how to allow users to join these user-created rooms, respecting the set user limit."
This is my server.js require('dotenv').config();
const express = require("express");
const path = require("path");
const bodyparser = require("body-parser");
const http = require("http");
const cors = require('cors');
const dotenv = require("dotenv");
const connectDB = require("./Server/database/connection");
const { v4: uuidv4 } = require('uuid');
const app = express();
const rooms = new Map();
const maxUsersPerRoom = 10;
const socketToRoom = new Map();
dotenv.config({ path: "config.env" });
const PORT = process.env.PORT || 8080;
app.use(cors());
const corsOptions = {
origin: 'https://dialoguedome.com',
optionsSuccessStatus: 200
}
app.use(cors(corsOptions));
app.use(express.static('public'));
connectDB();
app.use(bodyparser.urlencoded({ extended: true }));
app.use(bodyparser.json());
app.set("view engine", "ejs");
app.use("/css", express.static(path.resolve(__dirname, "Assets/css")));
app.use("/img", express.static(path.resolve(__dirname, "Assets/img")));
app.use("/js", express.static(path.resolve(__dirname, "Assets/js")));
const routes = require("./Server/routes/router");
app.use("/", routes);
const server = http.createServer(app);
const io = require("socket.io")(server, {
allowEIO3: true,
});
server.listen(PORT, '0.0.0.0', () => {
console.log(`Server running on ${'0.0.0.0'}:${PORT}`);
});
const mediasoup = require('mediasoup');
const os = require('os');
const mediaCodecs = [
{
kind: 'audio',
mimeType: 'audio/opus',
clockRate: 48000,
channels: 2
},
{
kind: 'video',
mimeType: 'video/VP8',
clockRate: 90000,
parameters:
{
'x-google-start-bitrate': 1000
},
},
];
let router = null
async function startServer() {
const worker = await mediasoup.createWorker({
logLevel: 'warn',
rtcMinPort: 10000,
rtcMaxPort: 10100,
});
router = await worker.createRouter({ mediaCodecs });
}
startServer().catch(console.error);
const ioSFU = io.of('/sfu');
// Your 'connectTransport', 'produce' and 'consume' events here
ioSFU.on('connection', async (socket) => {
let roomId
socket.on('createRoom', async () => {
// get an array of all rooms that have less than maxUsersPerRoom
const availableRooms = [...rooms.entries()].filter(([roomId, room]) => room.peers.size < maxUsersPerRoom);
if (availableRooms.length > 0) {
// if there are available rooms, join the first one
roomId = availableRooms[0][0];
socketToRoom.set(socket.id, roomId);
socket.emit('roomJoined', { roomId });
} else {
// if there are no available rooms, create a new one
roomId = uuidv4();
rooms.set(roomId, {
router: router,
peers: new Map(),
});
socketToRoom.set(socket.id, roomId);
socket.emit('roomCreated', { roomId });
}
});
// ... other events here ...
socket.on('connectTransport', async ({ roomId, transportId, dtlsParameters }) => {
const room = rooms.get(roomId);
const peer = room.peers.get(socket.id);
await peer.transport.connect({ dtlsParameters });
socket.emit('transportConnected');
});
socket.on('produce', async ({ roomId, kind, rtpParameters }) => {
const room = rooms.get(roomId);
const peer = room.peers.get(socket.id);
const transport = peer.transport;
const producer = await transport.produce({ kind, rtpParameters });
peer.producers.set(producer.id, producer);
producer.on('transportclose', () => {
peer.producers.delete(producer.id);
});
socket.emit('produceResponse', { producerId: producer.id });
});
socket.on('consume', async ({ roomId, producerId, rtpCapabilities }) => {
const room = rooms.get(roomId);
const peer = room.peers.get(socket.id);
const transport = peer.transport;
if (!room.router.canConsume({ producerId, rtpCapabilities })) {
socket.emit('error', 'cannot consume');
return;
}
const consumer = await transport.consume({ producerId, rtpCapabilities });
peer.consumers.set(consumer.id, consumer);
consumer.on('transportclose', () => {
peer.consumers.delete(consumer.id);
});
socket.emit('consumeResponse', {
producerId,
id: consumer.id,
kind: consumer.kind,
rtpParameters: consumer.rtpParameters
});
});
socket.on('disconnect', () => {
// Get the room ID for this socket
const roomId = socketToRoom.get(socket.id);
if (roomId) {
const room = rooms.get(roomId);
if (room) {
room.peers.delete(socket.id);
if (room.peers.size === 0) {
rooms.delete(roomId);
}
socket.broadcast.to(roomId).emit('user-disconnected', socket.id);
}
// Notify other users in the room that this user has left
socket.broadcast.to(roomId).emit('user-disconnected', socket.id);
// Remove the socket ID -> room ID mapping
socketToRoom.delete(socket.id);
}
// This loop is the same as before
for (const [roomId, room] of rooms.entries()) {
if (room.peers.size === 0) {
console.log(`Room ${roomId} deleted.`);
rooms.delete(roomId);
}
}
});
//.. below is P2p part web rtc
//.. below is P2p part web rtc
//.. below is P2p part web rtc
//.. below is P2p part web rtc
//.. below is P2p part web rtc
const ioP2P = io.of('/p2p');
var userConnection = [];
ioP2P.on("connection", (socket) => {
console.log("Socket id is: ", socket.id);
socket.on("userconnect", (data) => {
console.log("Logged in username", data.displayName);
userConnection.push({
connectionId: socket.id,
user_id: data.displayName,
});
var userCount = userConnection.length;
console.log("UserCount", userCount);
});
socket.on("offerSentToRemote", (data) => {
var offerReceiver = userConnection.find(
(o) => o.user_id === data.remoteUser
);
if (offerReceiver) {
console.log("OfferReceiver user is: ", offerReceiver.connectionId);
socket.to(offerReceiver.connectionId).emit("ReceiveOffer", data);
}
});
socket.on("answerSentToUser1", (data) => {
var answerReceiver = userConnection.find(
(o) => o.user_id === data.receiver
);
if (answerReceiver) {
console.log("answerReceiver user is: ", answerReceiver.connectionId);
socket.to(answerReceiver.connectionId).emit("ReceiveAnswer", data);
}
});
socket.on("candidateSentToUser", (data) => {
var candidateReceiver = userConnection.find(
(o) => o.user_id === data.remoteUser
);
if (candidateReceiver) {
console.log(
"candidateReceiver user is: ",
candidateReceiver.connectionId
);
socket.to(candidateReceiver.connectionId).emit("candidateReceiver", data);
}
});
socket.on("disconnect", () => {
console.log("User disconnected");
userConnection = userConnection.filter((p) => p.connectionId !== socket.id);
console.log(
"Rest users username are: ",
userConnection.map(function (user) {
return user.user_id;
})
);
});
socket.on("remoteUserClosed", (data) => {
var closedUser = userConnection.find((o) => o.user_id === data.remoteUser);
if (closedUser) {
console.log("closedUser user is: ", closedUser.connectionId);
socket.to(closedUser.connectionId).emit("closedRemoteUser", data);
}
});
});
});
this is my client side code or index.js let localStream;
let username;
let remoteUser;
let url = new URL(window.location.href);
// // username = url.searchParams.get("username");
// remoteUser = url.searchParams.get("remoteuser");
let peerConnection;
let remoteStream;
let sendChannel;
let receiveChannel;
var msgInput = document.querySelector("#msg-input");
var msgSendBtn = document.querySelector(".msg-send-button");
var chatTextArea = document.querySelector(".chat-text-area");
let awsServerUrl = "https://dialoguedome.com";
var omeID = localStorage.getItem("omeID");
if (omeID) {
username = omeID;
$.ajax({
url: awsServerUrl + "/new-user-update/" + omeID + "",
type: "PUT",
success: function (response) {
console.log(response);
},
});
} else {
var postData = "Demo Data";
$.ajax({
type: "POST",
url: awsServerUrl + "/api/users",
data: postData,
success: function (response) {
console.log(response);
localStorage.setItem("omeID", response);
username = response;
omeID = response;
},
error: function (error) {
console.log(error);
},
});
}
let init = async () => {
try {
localStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
});
document.getElementById("user-1").srcObject = localStream;
$.post(awsServerUrl + "/get-remote-users", { omeID: omeID })
.done(function (data) {
console.log("Remoteuser id from Init() /get-remote-users: ", data[0]._id);
if (data[0]) {
if (data[0]._id == remoteUser || data[0]._id == username) {
} else {
remoteUser = data[0]._id;
createOffer(data[0]._id);
}
}
})
.fail(function (xhr, textStatus, errorThrown) {
console.log(xhr.responseText);
});
} catch (error) {
console.error("Error initializing video stream", error);
}
};
init();
let socket = io.connect('/p2p');
socket.on("connect", () => {
if (socket.connected) {
socket.emit("userconnect", {
displayName: username,
});
}
});
let servers = {
iceServers: [
{
urls: ["stun:stun1.1.google.com:19302", "stun:stun2.1.google.com:19302"],
},
],
};
let createPeerConnection = async () => {
peerConnection = new RTCPeerConnection(servers);
remoteStream = new MediaStream();
document.getElementById("user-2").srcObject = remoteStream;
localStream.getTracks().forEach((track) => {
peerConnection.addTrack(track, localStream);
});
peerConnection.ontrack = async (event) => {
event.streams[0].getTracks().forEach((track) => {
remoteStream.addTrack(track);
});
};
remoteStream.oninactive = () => {
remoteStream.getTracks().forEach((track) => {
track.enabled = !track.enabled;
});
peerConnection.close();
};
peerConnection.onicecandidate = async (event) => {
if (event.candidate) {
socket.emit("candidateSentToUser", {
username: username,
remoteUser: remoteUser,
iceCandidateData: event.candidate,
});
}
};
sendChannel = peerConnection.createDataChannel("sendDataChannel");
sendChannel.onopen = () => {
console.log("Data channel is now open and ready to use");
onSendChannelStateChange();
};
peerConnection.ondatachannel = receiveChannelCallback;
// sendChannel.onmessage=onSendChannelMessageCallBack;
};
function sendData() {
const msgData = msgInput.value;
chatTextArea.innerHTML +=
"<div style='margin-top:2px; margin-bottom:2px;'><b>Me: </b>" +
msgData +
"</div>";
if (sendChannel) {
onSendChannelStateChange();
sendChannel.send(msgData);
msgInput.value = "";
} else {
receiveChannel.send(msgData);
msgInput.value = "";
}
}
function receiveChannelCallback(event) {
console.log("Receive Channel Callback");
receiveChannel = event.channel;
receiveChannel.onmessage = onReceiveChannelMessageCallback;
receiveChannel.onopen = onReceiveChannelStateChange;
receiveChannel.onclose = onReceiveChannelStateChange;
}
function onReceiveChannelMessageCallback(event) {
console.log("Received Message");
chatTextArea.innerHTML +=
"<div style='margin-top:2px; margin-bottom:2px;'><b>Stranger: </b>" +
event.data +
"</div>";
}
function onReceiveChannelStateChange() {
const readystate = receiveChannel.readystate;
console.log("Receive channel state is: " + readystate);
if (readystate === "open") {
console.log(
"Data channel ready state is open - onReceiveChannelStateChange"
);
} else {
console.log(
"Data channel ready state is NOT open - onReceiveChannelStateChange"
);
}
}
function onSendChannelStateChange() {
const readystate = sendChannel.readystate;
console.log("Send channel state is: " + readystate);
if (readystate === "open") {
console.log("Data channel ready state is open - onSendChannelStateChange");
} else {
console.log(
"Data channel ready state is NOT open - onSendChannelStateChange"
);
}
}
function fetchNextUser(remoteUser) {
$.post(
awsServerUrl + "/get-next-user",
{ omeID: omeID, remoteUser: remoteUser },
function (data) {
console.log("Next user is: ", data);
if (data[0]) {
if (data[0]._id == remoteUser || data[0]._id == username) {
} else {
remoteUser = data[0]._id;
createOffer(data[0]._id);
}
}
}
);
}
let createOffer = async (remoteU) => {
createPeerConnection();
let offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
socket.emit("offerSentToRemote", {
username: username,
remoteUser: remoteU,
offer: peerConnection.localDescription,
});
console.log("from Offer");
};
let createAnswer = async (data) => {
remoteUser = data.username;
createPeerConnection();
await peerConnection.setRemoteDescription(data.offer);
let answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);
socket.emit("answerSentToUser1", {
answer: answer,
sender: data.remoteUser,
receiver: data.username,
});
console.log("from answer");
document.querySelector(".next-chat").style.pointerEvents = "auto";
$.ajax({
url: "/update-on-engagement/" + username + "",
type: "PUT",
success: function (response) {},
});
};
socket.on("ReceiveOffer", function (data) {
createAnswer(data);
});
let addAnswer = async (data) => {
if (!peerConnection.currentRemoteDescription) {
peerConnection.setRemoteDescription(data.answer);
}
document.querySelector(".next-chat").style.pointerEvents = "auto";
$.ajax({
url: "/update-on-engagement/" + username + "",
type: "PUT",
success: function (response) {},
});
};
socket.on("ReceiveAnswer", function (data) {
addAnswer(data);
});
socket.on("closedRemoteUser", function (data) {
// .................Newly Added..........................
const remoteStream = peerConnection.getRemoteStreams()[0];
remoteStream.getTracks().forEach((track) => track.stop());
peerConnection.close();
const remoteVid = document.getElementById("user-2");
if (remoteVid.srcObject) {
remoteVid.srcObject.getTracks().forEach((track) => track.stop());
remoteVid.srcObject = null;
}
// .................Newly Added..........................
$.ajax({
url: "/update-on-next/" + username + "",
type: "PUT",
success: function (response) {
fetchNextUser(remoteUser);
},
});
});
socket.on("candidateReceiver", function (data) {
peerConnection.addIceCandidate(data.iceCandidateData);
console.log("from candidateReceiver");
});
msgSendBtn.addEventListener("click", function (event) {
sendData();
});
window.addEventListener("unload", function (event) {
if (navigator.userAgent.indexOf("Chrome") != -1) {
$.ajax({
url: "/leaving-user-update/" + username + "",
type: "PUT",
success: function (response) {
console.log(response);
},
});
console.log("Leaving local user is: ", username);
// ..........................Newly Edited
$.ajax({
url: "/update-on-otherUser-closing/" + remoteUser + "",
type: "PUT",
success: function (response) {
console.log(response);
},
});
console.log("Leaving remote user is: ", remoteUser);
// ..........................Newly Edited
console.log("This is Chrome");
} else if (navigator.userAgent.indexOf("Firefox") != -1) {
// The browser is Firefox
$.ajax({
url: "/leaving-user-update/" + username + "",
type: "PUT",
async: false,
success: function (response) {
console.log(response);
},
});
console.log("Leaving local user is: ", username);
// ..........................Newly Edited
$.ajax({
url: "/update-on-otherUser-closing/" + remoteUser + "",
type: "PUT",
async: false,
success: function (response) {
console.log(response);
},
});
console.log("Leaving remote user is: ", remoteUser);
// ..........................Newly Edited
console.log("This is Firefox");
} else {
// The browser is not Chrome or Firefox
console.log("This is not Chrome or Firefox");
}
});
async function closeConnection() {
// .................Newly Added..........................
const remoteStream = peerConnection.getRemoteStreams()[0];
remoteStream.getTracks().forEach((track) => track.stop());
await peerConnection.close();
const remoteVid = document.getElementById("user-2");
if (remoteVid.srcObject) {
remoteVid.srcObject.getTracks().forEach((track) => track.stop());
remoteVid.srcObject = null;
}
// .................Newly Added..........................
socket.emit("remoteUserClosed", {
username: username,
remoteUser: remoteUser,
});
$.ajax({
url: "/update-on-next/" + username + "",
type: "PUT",
success: function (response) {
fetchNextUser(remoteUser);
},
});
console.log("From closeConnection");
}
$(document).on("click", ".next-chat", function () {
document.querySelector(".chat-text-area").innerHTML = "";
// if (
// peerConnection.connectionState === "connected" ||
// peerConnection.iceCandidateState === "connected"
// ) {
closeConnection();
peerConnection.oniceconnectionstatechange = (event) => {
if (
peerConnection.iceConnectionState === "disconnected" ||
peerConnection.iceConnectionState === "closed"
) {
// Peer connection is closed
console.log("Peer connection closed.");
}
};
// console.log("User closed");
// } else {
// fetchNextUser(remoteUser);
// console.log("Moving to next user");
// }
});
//ABOVE IS P2P BELOW IS SFU
//ABOVE IS P2P BELOW IS SFU
//ABOVE IS P2P BELOW IS SFU
//ABOVE IS P2P BELOW IS SFU
const ioSFU = io('/sfu');
// Use the Socket.IO 'connection' event to get a reference to the socket
ioSFU.on('connect', async () => {
console.log(`Connected to SFU with ID: ${ioSFU.id}`);
const sfuRoomId = username
// Send a 'createRoom' event to the server
ioSFU.emit('createRoom', { roomId: sfuRoomId }); // assuming username is unique
});
// Add your socket event handlers here:
ioSFU.on('transportCreated', ({ transportId, iceParameters, iceCandidates, dtlsParameters, currentUsers }) => {
// Handle transport creation...
// Assign the existing users' streams to the video elements
currentUsers.forEach((userId, i) => {
// This assumes that you have a way of getting a user's video stream. You will need to implement this function.
const stream = getVideoStreamForUser(userId);
const videoElement = document.getElementById(`user-${i+1}`);
videoElement.srcObject = stream;
});
});
ioSFU.on('user-connected', userId => {
// Get the next available video element
const videoElement = getAvailableVideoElement();
if (videoElement) {
// Assign the new user's stream to the video element
const stream = getVideoStreamForUser(userId); // You will need to implement this function
videoElement.srcObject = stream;
}
});
ioSFU.on('user-disconnected', userId => {
// Find the video element for this user and clear it
const videoElement = getVideoElementForUser(userId); // You will need to implement this function
if (videoElement) {
videoElement.srcObject = null;
}
});
// Helper function to get the next available video element
function getAvailableVideoElement() {
for(let i = 1; i <= 10; i++) {
const videoElement = document.getElementById(`user-${i}`);
if (!videoElement.srcObject) {
return videoElement;
}
}
return null;
}
ioSFU.on('error', (error) => {
console.error(`Error: ${error}`);
});
ioSFU.on('roomCreated', (data) => {
console.log(`Room created with ID: ${data.roomId}`);
console.log(`Room created with ID: ${data.roomId}`);
});
ioSFU.on('transportCreated', async (data) => {
// Create the WebRTC transport using the parameters provided by the server
const transport = new WebRTCTransport(data.transportId, data.iceParameters, data.iceCandidates, data.dtlsParameters);
// Connect the transport
await transport.connect();
ioSFU.emit('connectTransport', { roomId: 'roomId', transportId: data.transportId, dtlsParameters: transport.localParameters.dtlsParameters });
});
ioSFU.on('transportConnected', () => {
console.log('Transport connected');
// Here you can start sending/receiving media
});
// Handle the 'consume' event
ioSFU.on('consumeResponse', (data) => {
const { producerId, id, kind, rtpParameters } = data;
// Here you need to use the data to consume the producer
// It depends on how you are handling the media streams on the client side
});
// Create a WebRTC connection and setup event handlers
class WebRTCTransport {
constructor(id, iceParameters, iceCandidates, dtlsParameters) {
this.id = id;
this.peerConnection = new RTCPeerConnection({
iceServers: [
{
urls: ["stun:stun.l.google.com:19302"]
}
],
iceParameters,
iceCandidates,
dtlsParameters
});
// Listen for 'icecandidate' events
this.peerConnection.onicecandidate = event => {
if (event.candidate) {
ioSFU.emit('candidate', { id: this.id, candidate: event.candidate });
}
};
}
// Add tracks from local stream to the connection
addTracks(stream) {
stream.getTracks().forEach(track => {
this.peerConnection.addTrack(track, stream);
});
}
// Create an offer and set local description
async createOffer() {
let offer = await this.peerConnection.createOffer();
await this.peerConnection.setLocalDescription(offer);
return this.peerConnection.localDescription;
}
// Set remote description with answer from remote peer
async setRemoteAnswer(answer) {
await this.peerConnection.setRemoteDescription(answer);
}
// Add a remote track to the local stream
addRemoteTrack(track, stream) {
stream.addTrack(track);
}
// Close the connection
close() {
this.peerConnection.close();
}
}
// The 'consumeResponse' event handler
ioSFU.on('consumeResponse', (data) => {
const { producerId, id, kind, rtpParameters } = data;
// Assuming you have a 'remoteStream' MediaStream object that will receive the remote video
let transport = new WebRTCTransport(id, rtpParameters.iceParameters, rtpParameters.iceCandidates, rtpParameters.dtlsParameters);
transport.addTracks(remoteStream);
remoteVideoElement.srcObject = remoteStream; // Assuming 'remoteVideoElement' is a video element for displaying the remote video
ioSFU.emit('consume', { id: transport.id, producerId: producerId });
});
// ... existing code ...
// Click event handler for the 'Join Room' button
$(document).on('click', '.join-room-button', function() {
// Get the room ID from the input field
let roomId = $('#name').val();
// Get the user ID. Replace this with actual user id.
let userId = 'username';
// Send a request to the server to join the room
fetch('https://dialoguedome.com/join-room/' + sfuRoomId, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ userId: userId }),
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Joined the room successfully
console.log('Joined the room');
} else {
// Failed to join the room
console.log('Failed to join the room:', data.error);
}
})
.catch((error) => {
console.error('Error:', error);
});
});
// Click event handler for the 'Leave Room' button
$(document).on('click', '.leave-room-button', function() {
// Get the room ID from the input field
let roomId = $('#name').val();
// Get the user ID. Replace this with actual user id.
let userId = 'username';
// Send a request to the server to leave the room
fetch('https://dialoguedome.com/leave-room/' + sfuRoomId, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ userId: userId }),
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Left the room successfully
console.log('Left the room');
} else {
// Failed to leave the room
console.log('Failed to leave the room:', data.error);
}
})
.catch((error) => {
console.error('Error:', error);
});
// Get the room ID from the server-side injected roomId
// Use the Socket.IO 'connection' event to get a reference to the socket
ioSFU.on('connect', async () => {
console.log(`Connected to SFU with ID: ${ioSFU.id}`);
// Send a 'joinRoom' event to the server
ioSFU.emit('joinRoom', { roomId: roomId });
});
// ... rest of the code ...
// Click event handler for the 'Join Room' button
$(document).on('click', '.join-room-button', function() {
// Get the user ID. Replace this with actual user id.
let userId = 'username';
// Send a request to the server to join the room
ioSFU.emit('joinRoom', { roomId: sfuRoomId, userId: userId });
});
// Click event handler for the 'Leave Room' button
$(document).on('click', '.leave-room-button', function() {
// Get the user ID. Replace this with actual user id.
let userId = 'username';
// Send a request to the server to leave the room
ioSFU.emit('leaveRoom', { roomId: sfuRoomId, userId: userId });
});
// Emit join room event using roomId
socket.emit('joinRoom', roomId);
socket.on('userJoined', userId => {
socket.broadcast.to(roomId).emit('userJoined', userId);
});
io.on('connection', socket => {
socket.on('joinRoom', roomId => {
socket.join(roomId);
});
});
});
// ... existing code ...
below is my ejs files `
<!DOCTYPE html>
<html lang="en">
<head> //this is for the rooms users can see
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rooms</title>
</head>
<body>
<% rooms.forEach((room) => { %>
<div>
<h2><%= room.name %></h2>
<p><%= room.description %></p>
<p>User limit: <%= room.userLimit %></p>
<button class="join-room-button" data-room-id="<%= room._id %>">Join Room</button>
</div>
<% }) %>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).on('click', '.join-room-button', function() {
// Get the room ID from the button data
let roomId = $(this).attr('data-room-id');
if (roomId.startsWith("sfu-")) {
// Redirect to the SFU implementation
window.location.href = "/video_chat/sfu/" + roomId;
} else {
// Redirect to the P2P implementation
window.location.href = "/video_chat/p2p/" + roomId;
}
});
</script>
</body>
</html>
below should change dynamically based on who what is put in the form```
Room ID: <%= roomId %>
<div id="video-container"></div>
<button class="msg-send-button">Send Message</button> <!-- Here is your button -->
<script src="/socket.io/socket.io.js"></script> <!-- Include Socket.io -->
<script>
document.addEventListener("DOMContentLoaded", function() {
// your code
var msgSendBtn = document.querySelector(".msg-send-button");
msgSendBtn.addEventListener("click", function (event) {
sendData();
});
// Generate video elements for 10 users
const videoContainer = document.getElementById('video-container');
for(let i = 1; i <= 10; i++) {
const videoElement = document.createElement('video');
videoElement.id = `user-${i}`;
videoElement.autoplay = true;
videoContainer.appendChild(videoElement);
}
});
const roomId = '<%= roomId %>'; // Assign server-side roomId to a client-side JavaScript variable
</script>
<script src="/js/index.js"></script> <!-- Include your JavaScript code for WebRTC -->
```
below is form.ejs
``
Create Room
Room Name:
<label for="description">Description:</label>
<input type="text" id="description" name="description">
<label for="userLimit">User Limit:</label>
<input type="number" id="userLimit" name="userLimit">
<input type="submit" value="Create Room">
</form>
</body>
```