WebRTC Call throwing a error during hangup - node.js

I am implementing a peer-2-peer call with WebRTC but I have encountered an error when leaving the call.
The connection is gone through but when I leave I get an error
The error is saying
connect.otherUser = null;
^
TypeError: Cannot set property 'otherUser' of undefined
This is the server.js
var webSocketServ = require('ws').Server;
var wss = new webSocketServ({
port: 9090
})
var users = {};
var otherUser;
wss.on('connection', function (conn) {
console.log("User connected");
conn.on('message', function (message) {
var data;
try {
data = JSON.parse(message);
} catch (e) {
console.log("Invalid JSON");
data = {};
}
switch (data.type) {
case "login":
if (users[data.name]) {
sendToOtherUser(conn, {
type: "login",
success: false
})
} else {
users[data.name] = conn;
conn.name = data.name
sendToOtherUser(conn, {
type: "login",
success: true
})
}
break;
case "offer":
var connect = users[data.name];
if (connect != null) {
conn.otherUser = data.name;
sendToOtherUser(connect, {
type: "offer",
offer: data.offer,
name: conn.name
})
}
break;
case "answer":
var connect = users[data.name];
if (connect != null) {
conn.otherUser = data.name
sendToOtherUser(connect, {
type: "answer",
answer: data.answer
})
}
break
case "candidate":
var connect = users[data.name];
if (connect != null) {
sendToOtherUser(connect, {
type: "candidate",
candidate: data.candidate
})
}
break;
case "reject":
var connect = users[data.name];
if (connect != null) {
sendToOtherUser(connect, {
type: "reject",
name: conn.name
})
}
break;
case "accept":
var connect = users[data.name];
if (connect != null) {
sendToOtherUser(connect, {
type: "accept",
name: conn.name
})
}
break;
case "leave":
var connect = users[data.name];
connect.otherUser = null;
if (connect != null) {
sendToOtherUser(connect, {
type: "leave"
})
}
break;
default:
sendToOtherUser(conn, {
type: "error",
message: "Command not found: " + data.type
});
break;
}
})
conn.on('close', function () {
console.log('Connection closed');
if(conn.name){
delete users[conn.name];
if(conn.otherUser){
var connect = users[conn.otherUser];
conn.otherUser = null;
if(conn != null){
sendToOtherUser(connect, {
type:"leave"
});
}
}
}
})
conn.send("Hello World");
});
function sendToOtherUser(connection, message) {
connection.send(JSON.stringify(message))
}
Also var otherUser; is declared but its value is never read
I don't know why there is an error when leaving the call

Related

The parameter name '' has already been declared. Parameter names must be unique

I have here an API created in NodeJS. When I run the API, it works on the first time, but if run it again its give me an error The parameter name Username has already been declared. Parameter names must be unique at Request.input. I checked other threads on how to fix this thing. Some answers that it needs to be cleared, but I think there is no function in NodeJS mssql library that clears parameter.(correct me if I'm wrong)
My code:
const res = require("express/lib/response")
const {sql,request} = require("../config/connection")
module.exports = {
checkExist: (data,callBack) => {
if(data.key == process.env.KEY) {
var username = data.username
var firstname = data.firstname
var middlename = data.middlename
var lastname = data.lastname
if(username == "" || firstname == "" || middlename == "" || lastname == "") {
return callBack("Invalid Input")
}
else {
request.input('Username', sql.VarChar(50), username);
request.input('FirstName', sql.VarChar(50), firstname);
request.input('MiddleName', sql.VarChar(50), middlename);
request.input('LastName', sql.VarChar(50), lastname);
request.output('Result', sql.Int);
request.execute('sp_INS_User').then(function(recordsets, returnValue, affected) {
if(recordsets.output.Result == -100) {
return callBack("Player Exist with different Username")
}
else if(recordsets.output.Result == -4) {
return callBack("Something went wrong while processing your request, please try again later.")
}
else {
if(recordsets.output.Result == 1000) {
return callBack(null,recordsets)
}
}
// console.dir(err);
}).catch(function(err) {
//return callBack(err)
return callBack("Something went wrong while processing your request, please try again later.")
});
}
}
else {
return callBack("Invalid Access")
}
}
}
My code in : ../config/connection/
const sql = require("mssql")
require("dotenv").config()
const sqlConfig = {
user: process.env.USER,
password: process.env.PASS,
database: process.env.DB_MAIN,
server: process.env.HOST,
pool: {
max: 10,
min: 0,
idleTimeoutMillis: 30000
},
options: {
encrypt:false,
trustServerCertificate: true
}
}
const con = sql.connect(sqlConfig).then(function() {
console.log(`Database connection successful!`);
}).catch(function(err) {
console.log(`Database connection ${err}!`);
});
const request = new sql.Request();
module.exports = {
sql,request
}
This looks like an issue of reusing the request object so the second time this function gets called, you're using the same request object that was previously used the first time this function was called. As such, you're registering duplicate names with request.input().
Apparently, you will need a new copy of const request = new sql.Request(); each time you want to use it because the error message is telling you that you can't repeat statements like request.input('Username',...) over and over on the same request object. So, export a function to get a new request object rather than exporting just one pre-made object.
You can do that like this:
../config/connection/
const sql = require("mssql")
require("dotenv").config()
const sqlConfig = {
user: process.env.USER,
password: process.env.PASS,
database: process.env.DB_MAIN,
server: process.env.HOST,
pool: {
max: 10,
min: 0,
idleTimeoutMillis: 30000
},
options: {
encrypt:false,
trustServerCertificate: true
}
}
const con = sql.connect(sqlConfig).then(function() {
console.log(`Database connection successful!`);
}).catch(function(err) {
console.log(`Database connection ${err}!`);
});
const getRequest = function() { return new sql.Request(); };
module.exports = {
sql, getRequest
};
And, your other code:
const res = require("express/lib/response")
const { sql, getRequest } = require("../config/connection")
module.exports = {
checkExist: (data, callBack) => {
const request = getRequest();
if (data.key == process.env.CAMS_INPLAY_KEY) {
var username = data.username
var firstname = data.firstname
var middlename = data.middlename
var lastname = data.lastname
if (username == "" || firstname == "" || middlename == "" || lastname == "") {
return callBack("Invalid Input")
} else {
request.input('Username', sql.VarChar(50), username);
request.input('FirstName', sql.VarChar(50), firstname);
request.input('MiddleName', sql.VarChar(50), middlename);
request.input('LastName', sql.VarChar(50), lastname);
request.output('Result', sql.Int);
request.execute('sp_INS_User').then(function(recordsets, returnValue, affected) {
if (recordsets.output.Result == -100) {
return callBack("Player Exist with different Username")
} else if (recordsets.output.Result == -4) {
return callBack(
"Something went wrong while processing your request, please try again later."
)
} else {
if (recordsets.output.Result == 1000) {
return callBack(null, recordsets)
}
}
// console.dir(err);
}).catch(function(err) {
//return callBack(err)
return callBack(
"Something went wrong while processing your request, please try again later."
)
});
}
} else {
return callBack("Invalid Access")
}
}
}

webRTC datachannel is not working in chrome62

I am newbie to webRTC. I tried to create a Chat application, sending a simple text message.
But getting this error:
Uncaught DOMException: Failed to execute 'send' on 'RTCDataChannel': RTCDataChannel.readyState is not 'open'
at HTMLButtonElement.
Here is my code.
index.html
<div class = "row">
<div class = "col-md-4 col-md-offset-4">
<h2> Please sign in</h2>
<input type = "email" id = "usernameInput"
class = "form-control formgroup" placeholder = "Enter Name"
required = "" autofocus = "" title="please Enter name">
<button id = "loginBtn" class = "btn btn-lg btn-primary btnblock">
Sign in</button>
</div>
</div>
</div>
<div id = "callPage" class = "call-page container">
<div class = "row">
<div class = "col-md-4 col-md-offset-4 text-center">
<div class = "panel panel-primary">
<div class = "panel-heading">Text chat</div>
<div id = "chatarea" class = "panel-body text-left"></div>
</div>
</div>
</div>
<div class = "row text-center">
<div class = "col-md-12">
<input id = "msgInput" type = "text" placeholder = "Enter message" />
<button id = "sendMsgBtn" class = "btn-success btn">Send</button>
</div>
</div>
</div>
<script >
var name;
var connectedUser;
var conn = new WebSocket('ws://localhost:8000');
conn.onopen = function () {
console.log("Connected to the signaling server");
};
//when we got a message from a signaling server
conn.onmessage = function (msg) {
console.log("Got message", msg.data);
var data =JSON.parse( msg.data);
// console.log(data.type);
switch(data.type) {
case "login":
handleLogin(data.success);
break;
//when somebody wants to call us
case "offer":
handleOffer(data.offer, data.name);
break;
case "answer":
handleAnswer(data.answer);
break;
//when a remote peer sends an ice candidate to us
case "candidate":
handleCandidate(data.candidate);
console.log('candidate');
break;
case "leave":
handleLeave();
break;
default:
break;
}
};
conn.onerror = function (err) {
console.log("Got error", err);
};
//alias for sending JSON encoded messages
function send(message) {
//attach the other peer username to our messages
if (connectedUser) {
message.name = connectedUser;
}
conn.send(JSON.stringify(message));
};
var loginPage = document.querySelector('#loginPage');
var usernameInput = document.querySelector('#usernameInput');
var loginBtn = document.querySelector('#loginBtn');
var callPage = document.querySelector('#callPage');
var callToUsernameInput = document.querySelector('#callToUsernameInput');
// var callBtn = document.querySelector('#callBtn');
// var hangUpBtn = document.querySelector('#hangUpBtn');
var msgInput = document.querySelector('#msgInput');
var sendMsgBtn = document.querySelector('#sendMsgBtn');
var chatArea = document.querySelector('#chatarea');
var yourConn;
var dataChannel;
callPage.style.display = "none";
// Login when the user clicks the button
loginBtn.addEventListener("click", function (event) {
name = usernameInput.value;
if (name.length > 0) {
send({
type: "login",
name: name
});
}
});
function handleLogin(success) {
if (success === false) {
alert("Ooops...try a different username");
} else {
loginPage.style.display = "none";
callPage.style.display = "block";
//using Google public stun server
var configuration = {
"iceServers": [{ "url": "stun:stun2.1.google.com:19302" }]
};
yourConn = new RTCPeerConnection(configuration,{optional: [{RtpDataChannels: true}]});
// Setup ice handling
yourConn.onicecandidate = function (event) {
console.log('enter into login');
if (event.candidate) {
send({
type: "candidate",
candidate: event.candidate
});
}
};
//creating data channel
dataChannel = yourConn.createDataChannel("channel", {reliable:true});
dataChannel.onerror = function (error) {
console.log("Ooops...error:", error);
};
//when we receive a message from the other peer, display it on the screen
dataChannel.onmessage = function (event) {
chatArea.innerHTML += connectedUser + ": " + event.data + "<br />";
};
dataChannel.onclose = function () {
console.log("data channel is closed");
};
}
};
//when we got an answer from a remote user
function handleAnswer(answer) {
yourConn.setRemoteDescription(new RTCSessionDescription(answer));
};
//when we got an ice candidate from a remote user
function handleCandidate(candidate) {
yourConn.addIceCandidate(new RTCIceCandidate(candidate));
};
//when user clicks the "send message" button
sendMsgBtn.addEventListener("click", function (event) {
var val = msgInput.value;
chatArea.innerHTML += name + ": " + val + "<br />";
//sending a message to a connected peer
dataChannel.send(val);
msgInput.value = "";
});
</script>
server.js
var WebSocket = require('ws').Server;
var Port= 8000;
//creating a websocket server at port 9090
var wss = new WebSocket({port: Port});
var fs=require('fs');
var http=require('http');
console.log("STARTED");
var server = http.createServer(function (req, resp) {
fs.readFile("index.html", function (error, pgResp) {
if (error) {
resp.write('Contents you are looking are Not Found');
} else {
resp.end(pgResp);
}
});
});
server.listen(3000);
//all connected to the server users
var users = {};
//when a user connects to our sever
wss.on('connection', function(connection) {
console.log("User connected");
//when server gets a message from a connected user
connection.on('message', function(message) {
var data;
//accepting only JSON messages
try {
data = JSON.parse(message);
} catch (e) {
console.log("Invalid JSON");
data = {};
}
//switching type of the user message
switch (data.type) {
//when a user tries to login
case "login":
console.log("User logged", data.name);
//if anyone is logged in with this username then refuse
if(users[data.name]) {
sendTo(connection, {
type: "login",
success: false
});
} else {
//save user connection on the server
users[data.name] = connection;
connection.name = data.name;
sendTo(connection, {
type: "login",
success: true
});
}
break;
case "offer":
//for ex. UserA wants to call UserB
console.log("Sending offer to: ", data.name);
//if UserB exists then send him offer details
var conn = users[data.name];
if(conn != null) {
//setting that UserA connected with UserB
connection.otherName = data.name;
sendTo(conn, {
type: "offer",
offer: data.offer,
name: connection.name
});
}
break;
case "answer":
console.log("Sending answer to: ", data.name);
//for ex. UserB answers UserA
var conn = users[data.name];
if(conn != null) {
connection.otherName = data.name;
sendTo(conn, {
type: "answer",
answer: data.answer
});
}
break;
case "candidate":
console.log("Sending candidate to:",data.name);
var conn = users[data.name];
if(conn != null) {
sendTo(conn, {
type: "candidate",
candidate: data.candidate
});
}
break;
case "leave":
console.log("Disconnecting from", data.name);
var conn = users[data.name];
conn.otherName = null;
//notify the other user so he can disconnect his peer connection
if(conn != null) {
sendTo(conn, {
type: "leave"
});
}
break;
default:
sendTo(connection, {
type: "error",
message: "Command not found: " + data.type
});
break;
}
});
//when user exits, for example closes a browser window
//this may help if we are still in "offer","answer" or "candidate" state
connection.on("close", function() {
if(connection.name) {
delete users[connection.name];
if(connection.otherName) {
console.log("Disconnecting from ", connection.otherName);
var conn = users[connection.otherName];
conn.otherName = null;
if(conn != null) {
sendTo(conn, {
type: "leave"
});
}
}
}
});
connection.send(JSON.stringify("Hello world"));
});
function sendTo(connection, message) {
connection.send(JSON.stringify(message));
}
I have searched many posts and tried removing "{optional: [{RtpDataChannels: true}]}" ,set reliable=false. But still facing the same problem.Is it the chrome version problem? I am using Version 62.0.3202.75 (Official Build) (32-bit) of chrome.

Host signalling server on heroku

I have built a signalling server using webrtc, nodejs, web-socket.
I am able to run the server locally but i want to host the server on heroku.
O have looked all over the internet but i cannot find anything relevant.
How can i host this server on Heroku?
Here is my code
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({port: 9090});
var users = {};
wss.on('connection', function(connection) {
console.log("User connected");
//when server gets a message from a connected user
connection.on('message', function(message) {
var data;
//accepting only JSON messages
try {
data = JSON.parse(message);
} catch (e) {
console.log("Invalid JSON");
data = {};
}
//switching type of the user message
switch (data.type) {
//when a user tries to login
case "login":
console.log("User logged", data.name);
//if anyone is logged in with this username then refuse
if(users[data.name]) {
sendTo(connection, {
type: "login",
success: false
});
} else {
//save user connection on the server
users[data.name] = connection;
connection.name = data.name;
sendTo(connection, {
type: "login",
success: true
});
}
break;
case "offer":
//for ex. UserA wants to call UserB
console.log("Sending offer to: ", data.name);
//if UserB exists then send him offer details
var conn = users[data.name];
if(conn != null) {
//setting that UserA connected with UserB
connection.otherName = data.name;
sendTo(conn, {
type: "offer",
offer: data.offer,
name: connection.name
});
}
break;
case "answer":
console.log("Sending answer to: ", data.name);
//for ex. UserB answers UserA
var conn = users[data.name];
if(conn != null) {
connection.otherName = data.name;
sendTo(conn, {
type: "answer",
answer: data.answer
});
}
break;
case "candidate":
console.log("Sending candidate to:",data.name);
var conn = users[data.name];
if(conn != null) {
sendTo(conn, {
type: "candidate",
candidate: data.candidate
});
}
break;
case "leave":
console.log("Disconnecting from", data.name);
var conn = users[data.name];
conn.otherName = null;
//notify the other user so he can disconnect his peer connection
if(conn != null) {
sendTo(conn, {
type: "leave"
});
}
break;
default:
sendTo(connection, {
type: "error",
message: "Command not found: " + data.type
});
break;
}
});
//when user exits, for example closes a browser window
//this may help if we are still in "offer","answer" or "candidate" state
connection.on("close", function() {
if(connection.name) {
delete users[connection.name];
if(connection.otherName) {
console.log("Disconnecting from ", connection.otherName);
var conn = users[connection.otherName];
conn.otherName = null;
if(conn != null) {
sendTo(conn, {
type: "leave"
});
}
}
}
});
connection.send("Hello world");
});
function sendTo(connection, message) {
connection.send(JSON.stringify(message));
}
Above is the code sample of server.js file.
Any help will be appreciated?
Here it is:
Step1: Push you code on github.
Before pushing make changes in your package.json.
Package.json is really important file to run your server on any cloud. Mainly start script, dependencies and node version is important.
Also in your code use process.env.PORT instead of any hard coded port number.
Step2: Create a heroku project through cli.
Now push you branch on heroku.
I know this is pretty brief steps. But I can help you more. If you are able to do it then good, otherwise I can help you in detail.

Solve Socket.io connection in a external module with expressjs

I have the following case: When I try to connect the module called 'Signaling-Server.js'
in the view of html the console says: GET ERROR [HTTP/1.1 400 Bad Request 1ms]
But this only happens when I add these Module. When I try to connect without him the socket.io connections works perfectly.
app.js
//Modules
var express = require("express"),
http = require("http"),
morgan= require("morgan"),
bodyParser = require('body-parser'),
methodOverride = require('method-override'),
app = express(),
server = http.createServer(app),
io = require("socket.io").listen(server);
app.use(express.static(__dirname + '/public'));
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({ extended:false}));
app.use(bodyParser.json());
app.use(methodOverride());
app.set("views",__dirname + "/views");
//I need to 'onnect with this module
//require('./Signaling-Server.js')(myServerOrPort);
require('./Signaling-Server.js')(server);
//Server is ready
server.listen(3000);
The code of Signaling-Server is here (Cortesy of MuazKhan Proyect "RTCMultiConnection")
Signaling-Server.js
// Muaz Khan - www.MuazKhan.com
// MIT License - www.WebRTC-Experiment.com/licence
// Documentation - github.com/muaz-khan/RTCMultiConnection
module.exports = exports = function(app, socketCallback) {
var io = require('socket.io').listen(app, {
log: false,
origins: '*:*'
});
io.set('transports', [
'websocket', // 'disconnect' EVENT will work only with 'websocket'
'xhr-polling',
'jsonp-polling'
]);
var listOfUsers = {};
var shiftedModerationControls = {};
var ScalableBroadcast;
io.sockets.on('connection', function(socket) {
var params = socket.handshake.query;
var socketMessageEvent = params.msgEvent || 'RTCMultiConnection-Message';
if (params.enableScalableBroadcast) {
if (!ScalableBroadcast) {
ScalableBroadcast = require('./Scalable-Broadcast.js');
}
var singleBroadcastAttendees = params.singleBroadcastAttendees;
ScalableBroadcast(socket, singleBroadcastAttendees);
}
socket.userid = params.userid;
listOfUsers[socket.userid] = {
socket: socket,
connectedWith: {},
isPublic: false, // means: isPublicModerator
extra: {}
};
socket.on('extra-data-updated', function(extra) {
try {
if (!listOfUsers[socket.userid]) return;
listOfUsers[socket.userid].extra = extra;
for (var user in listOfUsers[socket.userid].connectedWith) {
listOfUsers[user].socket.emit('extra-data-updated', socket.userid, extra);
}
} catch (e) {}
});
socket.on('become-a-public-moderator', function() {
try {
if (!listOfUsers[socket.userid]) return;
listOfUsers[socket.userid].isPublic = true;
} catch (e) {}
});
socket.on('get-public-moderators', function(userIdStartsWith, callback) {
try {
userIdStartsWith = userIdStartsWith || '';
var allPublicModerators = [];
for (var moderatorId in listOfUsers) {
if (listOfUsers[moderatorId].isPublic && moderatorId.indexOf(userIdStartsWith) === 0 && moderatorId !== socket.userid) {
var moderator = listOfUsers[moderatorId];
allPublicModerators.push({
userid: moderatorId,
extra: moderator.extra
});
}
}
callback(allPublicModerators);
} catch (e) {}
});
socket.on('changed-uuid', function(newUserId) {
try {
if (listOfUsers[socket.userid] && listOfUsers[socket.userid].socket.id == socket.userid) {
if (newUserId === socket.userid) return;
var oldUserId = socket.userid;
listOfUsers[newUserId] = listOfUsers[oldUserId];
listOfUsers[newUserId].socket.userid = socket.userid = newUserId;
delete listOfUsers[oldUserId];
return;
}
socket.userid = newUserId;
listOfUsers[socket.userid] = {
socket: socket,
connectedWith: {},
isPublic: false,
extra: {}
};
} catch (e) {}
});
socket.on('set-password', function(password) {
try {
if (listOfUsers[socket.userid]) {
listOfUsers[socket.userid].password = password;
}
} catch (e) {}
});
socket.on('disconnect-with', function(remoteUserId, callback) {
try {
if (listOfUsers[socket.userid] && listOfUsers[socket.userid].connectedWith[remoteUserId]) {
delete listOfUsers[socket.userid].connectedWith[remoteUserId];
socket.emit('user-disconnected', remoteUserId);
}
if (!listOfUsers[remoteUserId]) return callback();
if (listOfUsers[remoteUserId].connectedWith[socket.userid]) {
delete listOfUsers[remoteUserId].connectedWith[socket.userid];
listOfUsers[remoteUserId].socket.emit('user-disconnected', socket.userid);
}
callback();
} catch (e) {}
});
function onMessageCallback(message) {
try {
if (!listOfUsers[message.sender]) {
socket.emit('user-not-found', message.sender);
return;
}
if (!listOfUsers[message.sender].connectedWith[message.remoteUserId] && !!listOfUsers[message.remoteUserId]) {
listOfUsers[message.sender].connectedWith[message.remoteUserId] = listOfUsers[message.remoteUserId].socket;
listOfUsers[message.sender].socket.emit('user-connected', message.remoteUserId);
if (!listOfUsers[message.remoteUserId]) {
listOfUsers[message.remoteUserId] = {
socket: null,
connectedWith: {},
isPublic: false,
extra: {}
};
}
listOfUsers[message.remoteUserId].connectedWith[message.sender] = socket;
if (listOfUsers[message.remoteUserId].socket) {
listOfUsers[message.remoteUserId].socket.emit('user-connected', message.sender);
}
}
if (listOfUsers[message.sender].connectedWith[message.remoteUserId] && listOfUsers[socket.userid]) {
message.extra = listOfUsers[socket.userid].extra;
listOfUsers[message.sender].connectedWith[message.remoteUserId].emit(socketMessageEvent, message);
}
} catch (e) {}
}
var numberOfPasswordTries = 0;
socket.on(socketMessageEvent, function(message, callback) {
if (message.remoteUserId && message.remoteUserId === socket.userid) {
// remoteUserId MUST be unique
return;
}
try {
if (message.remoteUserId && message.remoteUserId != 'system' && message.message.newParticipationRequest) {
if (listOfUsers[message.remoteUserId] && listOfUsers[message.remoteUserId].password) {
if (numberOfPasswordTries > 3) {
socket.emit('password-max-tries-over', message.remoteUserId);
return;
}
if (!message.password) {
numberOfPasswordTries++;
socket.emit('join-with-password', message.remoteUserId);
return;
}
if (message.password != listOfUsers[message.remoteUserId].password) {
numberOfPasswordTries++;
socket.emit('invalid-password', message.remoteUserId, message.password);
return;
}
}
}
if (message.message.shiftedModerationControl) {
if (!message.message.firedOnLeave) {
onMessageCallback(message);
return;
}
shiftedModerationControls[message.sender] = message;
return;
}
if (message.remoteUserId == 'system') {
if (message.message.detectPresence) {
if (message.message.userid === socket.userid) {
callback(false, socket.userid);
return;
}
callback(!!listOfUsers[message.message.userid], message.message.userid);
return;
}
}
if (!listOfUsers[message.sender]) {
listOfUsers[message.sender] = {
socket: socket,
connectedWith: {},
isPublic: false,
extra: {}
};
}
// if someone tries to join a person who is absent
if (message.message.newParticipationRequest) {
var waitFor = 120; // 2 minutes
var invokedTimes = 0;
(function repeater() {
invokedTimes++;
if (invokedTimes > waitFor) {
socket.emit('user-not-found', message.remoteUserId);
return;
}
if (listOfUsers[message.remoteUserId] && listOfUsers[message.remoteUserId].socket) {
onMessageCallback(message);
return;
}
setTimeout(repeater, 1000);
})();
return;
}
onMessageCallback(message);
} catch (e) {}
});
socket.on('disconnect', function() {
try {
var message = shiftedModerationControls[socket.userid];
if (message) {
delete shiftedModerationControls[message.userid];
onMessageCallback(message);
}
} catch (e) {}
try {
// inform all connected users
if (listOfUsers[socket.userid]) {
for (var s in listOfUsers[socket.userid].connectedWith) {
listOfUsers[socket.userid].connectedWith[s].emit('user-disconnected', socket.userid);
if (listOfUsers[s] && listOfUsers[s].connectedWith[socket.userid]) {
delete listOfUsers[s].connectedWith[socket.userid];
listOfUsers[s].socket.emit('user-disconnected', socket.userid);
}
}
}
} catch (e) {}
delete listOfUsers[socket.userid];
});
if (socketCallback) {
socketCallback(socket);
}
});
};
Anybody knows whats the fix?
You can either try Ahmed's solution i.e. passing server object here:
require('./Signaling-Server.js') (server);
In your codes, the server object is using http.
I'll suggest trying this instead:
var fs = require('fs');
var options = {
key: fs.readFileSync('fake-keys/privatekey.pem'),
cert: fs.readFileSync('fake-keys/certificate.pem')
};
var express = require("express"),
http = require("https"), // Use HTTPs here -------------
app = express(),
server = http.createServer(options, app);
require('./Signaling-Server.js')(server);
You can either try valid SSL certificate keys or fake-keys.
Here is how to use valid certificates:
var options = {
key: fs.readFileSync('../ssl/private/domain.com.key'),
cert: fs.readFileSync('../ssl/certs/domain.com.crt'),
ca: fs.readFileSync('../ssl/certs/domain.com.cabundle')
};
In Express 3, you should pass the app object to socket.io not the server like in Express 2. Assuming you are using Express 3 and not 2. You just need to change one line to set up socket.io correctly
Try replacing this
require('./Signaling-Server.js')(server);
with this
require('./Signaling-Server.js')(app);

WebRTC: One to one Audio call not working in different machine

I am trying to implement a one to one audio call using webRTC (signalling using websockets) . But it works when i try it in one system using multiple tabs of chrome (localhost). When I try to hit my server from another machine it does initial handshakes , but call doesn't happen.
But when i try to change the tag to and changed the constraints to video constraints . it works even if the we try to access from other machine (i.e video call works ).
I initially thought it was because if firewall but when video call worked I was puzzled .
Here is my code:
// Constraints to get audio stream only
$scope.constraints = {
audio: {
mandatory: {
googEchoCancellation: true
},
optional: []
},
video:false
};
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// success Callback of getUserMedia(), stream variable is the audio stream.
$scope.successCallback = function (stream) {
if (window.URL) {
myVideo.src = window.URL.createObjectURL(stream); // converting media stream to Blob URL.
} else {
myVideo.src = stream;
}
//attachMediaStream(audioTag, stream);
localStream = stream;
if (initiator)
maybeStart();
else
doAnswer();
};
// failure Callback of getUserMedia()
$scope.failureCallback = function (error) {
console.log('navigator.getUserMedia Failed: ', error);
};
var initiator, started = false;
$("#call").click(function () {
socket.emit("message", undefined);
initiator = true;
navigator.getUserMedia($scope.constraints, $scope.successCallback, $scope.failureCallback);
});
var channelReady = false;
socket.on('message', function (data) {
channelReady = true;
if (data) {
if (data.type === 'offer') {
if (!initiator) {
$("#acceptCall").show();
$("#acceptCall").click(function(){
if (!initiator && !started) {
var pc_config = {
iceServers: [
{ url: "stun:stun.l.google.com:19302" },
{ url: "turn:numb.viagenie.ca", credential: "drfunk", username: "toadums#hotmail.com"}
]
};
pc = new webkitRTCPeerConnection(pc_config);
pc.onicecandidate = onIceCandidate;
pc.onaddstream = onRemoteStreamAdded;
}
pc.setRemoteDescription(new RTCSessionDescription(data));
$scope.acceptCall();
});
}
} else if (data.type === 'answer' && started) {
pc.onaddstream = onRemoteStreamAdded;
pc.setRemoteDescription(new RTCSessionDescription(data));
} else if (data.type === 'candidate' && started) {
var candidate = new RTCIceCandidate({
sdpMLineIndex: data.label,
candidate: data.candidate
});
pc.addIceCandidate(candidate);
} else if (data.type === 'bye' && started) {
console.log("Bye");
}
}
});
function onRemoteStreamAdded(event) {
othersVideo.src = URL.createObjectURL(event.stream);
};
var sdpConstraints = {
'mandatory': {
'OfferToReceiveAudio': true,
'OfferToReceiveVideo': false
}
};
function doAnswer() {
pc.addStream(localStream);
pc.createAnswer(gotDescription,null,sdpConstraints);
}
function gotDescription(desc) {
pc.setLocalDescription(desc);
socket.send(desc);
}
function maybeStart() {
if (!started && localStream && channelReady)
createPeerConnection();
pc.addStream(localStream);
started = true;
if (initiator)
doCall();
}
$scope.acceptCall = function () {
navigator.getUserMedia($scope.constraints, $scope.successCallback, $scope.failureCallback);
}
function createPeerConnection() {
var pc_config = {
iceServers: [
{ url: "stun:stun.l.google.com:19302" },
{ url: "turn:numb.viagenie.ca", credential: "drfunk", username: "toadums#hotmail.com"}
]
};
pc = new webkitRTCPeerConnection(pc_config);
pc.onicecandidate = onIceCandidate;
console.log("Created RTCPeerConnnection with config:\n" + " \"" +
JSON.stringify(pc_config) + "\".");
};
function doCall() {
$scope.caller = true;
pc.createOffer(setLocalAndSendMessage,null,sdpConstraints);
};
function setLocalAndSendMessage(sessionDescription) {
pc.setLocalDescription(sessionDescription);
socket.send(sessionDescription);
}
function onIceCandidate(event) {
if (event.candidate) {
socket.emit('message', {
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate
});
} else {
console.log("End of candidates.");
}
}
If navigator.mediaDevices is undefined, this because work only in secure context (https)
see:
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia

Resources