diff --git a/index.js b/index.js index 05076b5..b5c2cce 100644 --- a/index.js +++ b/index.js @@ -1,73 +1,73 @@ require('dotenv').config(); -// Twilio init -var twilio = require('twilio')( - process.env.TWILIO_ACCOUNT_SID, - process.env.TWILIO_AUTH_TOKEN -); +var twilio = require('twilio')(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN); var express = require('express'); var app = express(); var http = require('http').createServer(app); var io = require('socket.io')(http); app.use(express.static('public')); + +function log(msg, room) { + console.log(room + ": " + msg) +} + // When a socket connects, set up the specific listeners we will use. -io.on('connection', function(socket){ - // When a client tries to join a room, only allow them if they are first or - // second in the room. Otherwise it is full. - socket.on('join', function(room){ - console.log('A client joined room:' + room); - var clients = io.sockets.adapter.rooms[room]; - var numClients = typeof clients !== 'undefined' ? clients.length : 0; - if(numClients === 0){ - socket.join(room); - }else if(numClients === 1){ - socket.join(room); - // When the client is second to join the room, both clients are ready. - console.log('Broadcasting ready message') - socket.broadcast.emit('willInitiateCall', room); - socket.emit('ready', room); - socket.broadcast.emit('ready', room); - }else{ - console.log("room full"); - socket.emit('full', room); - } - }); - - // When receiving the token message, use the Twilio REST API to request an - // token to get ephemeral credentials to use the TURN server. - socket.on('token', function(){ - console.log('Received token request'); - twilio.tokens.create(function(err, response){ - if(err){ - console.log(err); - }else{ - // Return the token to the browser. - console.log('Token generated. Returning it to the client'); - socket.emit('token', response); - } +io.on('connection', function (socket) { + // When a client tries to join a room, only allow them if they are first or + // second in the room. Otherwise it is full. + socket.on('join', function (room) { + log('A client joined the room', room); + var clients = io.sockets.adapter.rooms[room]; + var numClients = typeof clients !== 'undefined' ? clients.length : 0; + if (numClients === 0) { + socket.join(room); + } else if (numClients === 1) { + socket.join(room); + // When the client is second to join the room, both clients are ready. + log('Broadcasting ready message', room); + socket.broadcast.to(room).emit('willInitiateCall', room); + socket.emit('ready', room).to(room); + socket.broadcast.to(room).emit('ready', room); + } else { + log("room already full", room); + socket.emit('full', room); + } }); - }); - // Relay candidate messages - socket.on('candidate', function(candidate){ - console.log('Received candidate. Broadcasting...'); - socket.broadcast.emit('candidate', candidate); - }); + // When receiving the token message, use the Twilio REST API to request an + // token to get ephemeral credentials to use the TURN server. + socket.on('token', function (room) { + log('Received token request', room); + twilio.tokens.create(function (err, response) { + if (err) { + log(err, room); + } else { + log('Token generated. Returning it to the browser client', room); + socket.emit('token', response).to(room); + } + }); + }); - // Relay offers - socket.on('offer', function(offer){ - console.log('Received offer. Broadcasting...'); - socket.broadcast.emit('offer', offer); - }); + // Relay candidate messages + socket.on('candidate', function (candidate, room) { + log('Received candidate. Broadcasting...', room); + socket.broadcast.to(room).emit('candidate', candidate); + }); - // Relay answers - socket.on('answer', function(answer){ - console.log('Received answer. Broadcasting...'); - socket.broadcast.emit('answer', answer); - }); + // Relay offers + socket.on('offer', function (offer, room) { + log('Received offer. Broadcasting...', room); + socket.broadcast.to(room).emit('offer', offer); + }); + + // Relay answers + socket.on('answer', function (answer, room) { + log('Received answer. Broadcasting...', room); + socket.broadcast.to(room).emit('answer', answer); + }); }); -http.listen(3000, function() { - console.log("http://localhost:3000"); +http.listen(3000, function () { + console.log("http://localhost:3000"); }); diff --git a/public/app.js b/public/app.js index 180a786..b047680 100644 --- a/public/app.js +++ b/public/app.js @@ -2,10 +2,9 @@ if (!location.hash) { // Generate random room name if needed var adjectives = ["small", "big", "large", "smelly", "new", "happy", "shiny", "old", "clean", "nice", "bad", "cool", "hot", "cold", "warm", "hungry", "slow", "fast"] var nouns = ["dog", "bat", "wrench", "apple", "pear", "ghost", "cat", "wolf", "squid", "goat", "snail", "hat", "sock", "plum", "bear", "snake", "turtle", "horse","spoon","fork","spider","tree","chair","table"] - var adjective = adjectives[Math.floor(Math.random() * adjectives.length)] - var noun = nouns[Math.floor(Math.random() * nouns.length)] - // var num = Math.floor(Math.ran1dom() * 100) - location.hash = adjective + "-" + noun + var adjective = adjectives[Math.floor(Math.random() * adjectives.length)]; + var noun = nouns[Math.floor(Math.random() * nouns.length)]; + location.hash = adjective + noun } const roomHash = location.hash.substring(1); @@ -72,7 +71,9 @@ var VideoChat = { VideoChat.localVideo.srcObject = stream; // Now we're ready to join the chat room. VideoChat.socket.emit('join', roomHash); - // VideoChat.socket.emit('join', 'test'); default + // VideoChat.socket.on('roomtest', (passedRoom) => alert("youre in room: " + passedRoom)); + VideoChat.socket.on('temp', () => alert("temp called")); + VideoChat.socket.on('full', VideoChat.chatRoomFull); VideoChat.socket.on('offer', VideoChat.onOffer); VideoChat.socket.on('ready', VideoChat.readyToCall); VideoChat.socket.on('willInitiateCall', () => VideoChat.willInitiateCall = true); @@ -83,6 +84,12 @@ var VideoChat = { logIt('No media stream for us.'); }, + chatRoomFull: function(){ + alert("Chat room is full. Check to make sure you don't have multiple open tabs"); + // VideoChat.socket.disconnect() + // todo handle this better + }, + // When we are ready to call, enable the Call button. readyToCall: function (event) { console.log("readyToCall"); @@ -97,7 +104,7 @@ var VideoChat = { console.log("startCall"); logIt('>>> Sending token request...'); VideoChat.socket.on('token', VideoChat.onToken(VideoChat.createOffer)); - VideoChat.socket.emit('token'); + VideoChat.socket.emit('token', roomHash); // VideoChat.callButton.disabled = true }, @@ -130,7 +137,7 @@ var VideoChat = { logIt(`<<< Received local ICE candidate from STUN/TURN server (${event.candidate.address})`); if (VideoChat.connected) { logIt(`>>> Sending local ICE candidate (${event.candidate.address})`); - VideoChat.socket.emit('candidate', JSON.stringify(event.candidate)); + VideoChat.socket.emit('candidate', JSON.stringify(event.candidate), roomHash); } else { // If we are not 'connected' to the other peer, we are buffering the local ICE candidates. // This most likely is happening on the "caller" side. @@ -160,7 +167,7 @@ var VideoChat = { // and send it over the socket connection to initiate the peerConnection // on the other side. VideoChat.peerConnection.setLocalDescription(offer); - VideoChat.socket.emit('offer', JSON.stringify(offer)); + VideoChat.socket.emit('offer', JSON.stringify(offer), roomHash); }, function (err) { logIt("failed offer creation"); @@ -184,7 +191,7 @@ var VideoChat = { VideoChat.peerConnection.createAnswer( function (answer) { VideoChat.peerConnection.setLocalDescription(answer); - VideoChat.socket.emit('answer', JSON.stringify(answer)); + VideoChat.socket.emit('answer', JSON.stringify(answer), roomHash); }, function (err) { logIt("Failed answer creation."); @@ -200,7 +207,7 @@ var VideoChat = { console.log("onOffer"); logIt('<<< Received offer'); VideoChat.socket.on('token', VideoChat.onToken(VideoChat.createAnswer(offer))); - VideoChat.socket.emit('token'); + VideoChat.socket.emit('token', roomHash); }, // When an answer is received, add it to the peerConnection as the remote @@ -214,7 +221,7 @@ var VideoChat = { VideoChat.localICECandidates.forEach(candidate => { // The caller now knows that the callee is ready to accept new ICE candidates, so sending the buffer over logIt(`>>> Sending local ICE candidate (${candidate.address})`); - VideoChat.socket.emit('candidate', JSON.stringify(candidate)); + VideoChat.socket.emit('candidate', JSON.stringify(candidate), roomHash); }); // Reset the buffer of local ICE candidates. This is not really needed // in this specific client, but it's good practice