Signalling Error when doing peer connection using WebRTC - javascript

I have been trying to get my peer connection working for my application as seen in the picture below:
As you can see, it shows that the peer connection has happened but there's been some incompatibility error which may be due to adapter.js shown in the next picture.
Would be grateful if anyone knew how to fix this thanks!
I also added the code I'm using through pastebin for your viewing.
https://pastebin.com/WHCugjig
'use strict';
var localStream;
var remoteStream;
var pc;
var isInitiator;
var pcConfig = {
iceServers: [
{
urls: 'stun:stun.l.google.com:19302'
}
]
};
// Define action buttons.
const callButton = document.getElementById('callButton');
const hangupButton = document.getElementById('hangupButton');
/////////////////////////////////////////////
var socket = io.connect();
var room = prompt('Enter room name:');
socket.emit('create or join', room);
socket.on('created', function(room) {
console.log('Created room ' + room);
isInitiator = true;
startVideo();
});
socket.on('created', function(room) {
isInitiator = false;
startVideo();
createPeerConnection(isInitiator);
});
////////////////////////////////////////////////
function sendMessage(message) {
socket.emit('message', message);
}
// This client receives a message
socket.on('message', function(message) {
if (message.type === 'offer') {
pc.setRemoteDescription(
new RTCSessionDescription(message),
function() {},
onCreateSessionDescriptionError
);
pc.createAnswer(setLocalAndSendMessage, onCreateSessionDescriptionError);
} else if (message.type === 'answer') {
pc.setRemoteDescription(
new RTCSessionDescription(message),
function() {},
onCreateSessionDescriptionError
);
} else if (message.type === 'candidate') {
pc.addIceCandidate(
new RTCIceCandidate({
candidate: message.candidate
})
);
}
});
////////////////////////////////////////////////////
var localVideo = document.querySelector('#localVideo');
var remoteVideo = document.querySelector('#remoteVideo');
// Set up initial action buttons status: disable call and hangup.
callButton.disabled = true;
hangupButton.disabled = true;
// Add click event handlers for buttons.
callButton.addEventListener('click', callStart);
hangupButton.addEventListener('click', hangupCall);
function startVideo() {
navigator.mediaDevices
.getUserMedia({
audio: true,
video: true
})
.then(gotStream)
.catch(function(e) {
alert('getUserMedia() error: ' + e.name);
});
}
function gotStream(stream) {
try {
localVideo.srcObject = stream;
} catch (error) {
localVideo.src = window.URL.createObjectURL(stream);
}
localStream = stream;
callButton.disabled = false;
}
function callStart() {
createPeerConnection();
pc.addStream(localStream);
callButton.disabled = true;
hangupButton.disabled = false;
pc.createOffer(setLocalAndSendMessage, handleCreateOfferError);
}
/////////////////////////////////////////////////////////
function createPeerConnection() {
try {
pc = new RTCPeerConnection(null);
pc.onicecandidate = function(event) {
console.log('icecandidate event:', event);
if (event.candidate) {
sendMessage({
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate
});
} else {
console.log('End of candidates.');
}
};
pc.ontrack = handleRemoteStreamAdded;
console.log('Created RTCPeerConnnection');
} catch (e) {
console.log('Failed to create PeerConnection, exception: ' + e.message);
alert('Cannot create RTCPeerConnection object.');
return;
}
}
function handleRemoteStreamAdded(event) {
console.log('Remote stream added.');
try {
remoteVideo.srcObject = event.stream;
} catch (error) {
remoteVideo.src = window.URL.createObjectURL(event.stream);
}
remoteStream = event.stream;
}
function setLocalAndSendMessage(sessionDescription) {
pc.setLocalDescription(sessionDescription);
console.log('setLocalAndSendMessage sending message', sessionDescription);
sendMessage(sessionDescription);
}
function handleCreateOfferError(event) {
console.log('createOffer() error: ', event);
}
function onCreateSessionDescriptionError(error) {
console.log('Failed to create session description: ' + error.toString());
}
function hangupCall() {
pc.close();
pc = null;
}

Without a running version of the signaling server it is somewhat hard to debug this. Anyway...
You are calling setLocalAndSendMessage according to the debug log.
Then you get the "Failed to create session description" error twice which suggests that the code for receiving a message with type=offer is called.
Now why that happens depends on your signaling server.

Related

Node websockets missing reason in close event

I'm developing a websocket server with Node.Js v14.17.3 using "ws": "^7.4.5" package.
My server code is this:
const WebSocket = require("ws");
const url = "localhost";
const port = 8081;
const wss = new WebSocket.Server({ host: url, port });
wss.on("connection", function (ws) {
ws.on("message", function (data) {
console.log("received: %s", data);
});
function onSocketClose(code, reason) {
console.log("Closing open web socket", code, reason);
console.log("Closed web socket.");
}
ws.on("close", onSocketClose);
});
My client code is this:
window.onclose = function (event) {
console.log("Window closing.");
closeSocket("Window closed");
};
window.onunload = function (event) {
console.info("Window unloaded");
closeSocket("Window unloaded");
};
function closeSocket(reason) {
if (reason) {
console.info("Closing socket due to:", reason);
} else {
reason = "Unknown reason";
}
webSocket.onclose = function (ev) {
console.info("Websocket closed.");
};
webSocket.close(1001, reason);
}
In server on("close", ...) callback I get an empty reason, while I'm expecting the reason I've specified in client method.

Failed to create PeerConnection, exception: Failed to construct 'RTCSessionDescription': parameter 1 ('descriptionInitDict') is not an object

Frontend code:-
let socket = io();
socket.on(`connect`, () => {
console.log(`new User Connected`);
});
jQuery(`#video-form`).on(`submit`, (event) => {
event.preventDefault();
socket.emit(`offer`, () => {
console.log(`Starting call`);
});
});
/////////////////////////////
'use strict';
let isChannelReady = false;
let isInitiator = false;
let isStarted = false;
let localStream;
let pc;
let remoteStream;
let turnReady;
let pcConfig = {
'iceServers': [{
'url': 'stun:stun.1.google.com:19302'
}]
};
// Set up audio and video regardless of what devices are present.
let sdpConstraints = {
'mandatory': {
'OfferToReceiveAudio': true,
'OfferToReceiveVideo': true
}
};
/////////////////////////////////////////////
let room = 'foo';
// Could prompt for room name:
// room = prompt('Enter room name:');
if (room !== '') {
socket.emit('create or join', room);
console.log('Attempted to create or join room', room);
}
socket.on('created', function (room) {
console.log('Created room ' + room);
isInitiator = true;
});
socket.on('full', function (room) {
console.log('Room ' + room + ' is full');
});
socket.on('join', function (room) {
console.log('Another peer made a request to join room ' + room);
console.log('This peer is the initiator of room ' + room + '!');
isChannelReady = true;
});
socket.on('joined', function (room) {
console.log('joined: ' + room);
isChannelReady = true;
});
socket.on('log', function (array) {
console.log.apply(console, array);
});
////////////////////////////////////////////////
function sendMessage(message) {
console.log('Client sending message: ', message);
socket.emit('message', message);
}
// This client receives a message
socket.on('message', function (message) {
console.log('Client received message:', message);
if (message === 'got user media') {
//isStarted = true;
isInitiator = true;
isChannelReady = true;
maybeStart(message);
} else if (message.type === 'offer') {
if (!isInitiator && !isStarted) {
maybeStart(message);
}
pc.setRemoteDescription(new RTCSessionDescription(message));
doAnswer(message);
} else if (message.type === 'answer' && isStarted) {
pc.setRemoteDescription(new RTCSessionDescription(message));
} else if (message.type === 'candidate' && isStarted) {
let candidate = new RTCIceCandidate({
sdpMLineIndex: message.label,
candidate: message.candidate
});
pc.addIceCandidate(candidate);
} else if (message === 'bye' && isStarted) {
handleRemoteHangup();
}
});
////////////////////////////////////////////////////
let localVideo = document.querySelector('#localVideo');
let remoteVideo = document.querySelector('#remoteVideo');
navigator.getUserMedia = navigator.getUserMedia || navigator.mediaDevices.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
let constraints = {
audio: false,
video: true
};
navigator.mediaDevices.getUserMedia(constraints)
.then(gotStream)
.catch(function (e) {
alert('getUserMedia() error: ' + e.name);
});
function gotStream(stream) {
console.log('Adding local stream.');
// if (navigator.webkitGetUserMedia) {
localVideo.src = window.URL.createObjectURL(stream);
// }
// else {
// localStream.src = stream;
// }
localStream = stream;
sendMessage('got user media');
if (isInitiator) {
maybeStart();
}
}
console.log('Getting user media with constraints', constraints);
if (location.hostname !== 'localhost') {
requestTurn();
}
function maybeStart(message) {
// isChannelReady = true;
// isInitiator = true;
console.log('>>>>>>> maybeStart() ', isStarted, localStream, isChannelReady);
if (!isStarted && typeof localStream !== 'undefined' && isChannelReady) {
console.log('>>>>>> creating peer connection');
createPeerConnection(message);
pc.addStream(localStream);
isStarted = true;
console.log('isInitiator', isInitiator);
if (isInitiator) {
doCall();
}
}
}
window.onbeforeunload = function () {
sendMessage('bye');
};
/////////////////////////////////////////////////////////
function createPeerConnection(message) {
try {
//let msg = JSON.parse(message.data);
pc = new RTCPeerConnection(pcConfig) || webkitRTCPeerConnection(pcConfig) || mozRTCPeerConnection(pcConfig);
pc.setRemoteDescription(new RTCSessionDescription(message));
console.log(`SetRemomteDescription`);
pc.onicecandidate = handleIceCandidate;
console.log(`handleIceCandidate`);
pc.onaddstream = handleRemoteStreamAdded;
console.log(`handleRemoteStreamAdde`);
pc.onremovestream = handleRemoteStreamRemoved;
console.log('Created RTCPeerConnnection');
} catch (e) {
console.log('Failed to create PeerConnection, exception: ' + e.message);
alert('Cannot create RTCPeerConnection object.');
}
}
function handleIceCandidate(event) {
console.log('icecandidate event: ', event);
if (event.candidate) {
sendMessage({
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate
});
} else {
console.log('End of candidates.');
}
}
function handleRemoteStreamAdded(event) {
//if (navigator.webkitGetUserMedia) {
console.log('Remote stream added.');
remoteVideo.src = window.URL.createObjectURL(event.stream);
// }
// else {
// remoteStream.srcObject = event.stream;
// }
remoteStream = event.stream;
}
function handleCreateOfferError(event) {
console.log('createOffer() error: ', event);
}
function doCall() {
console.log('Sending offer to peer');
pc.createOffer(setLocalAndSendMessage, handleCreateOfferError);
}
function doAnswer(message) {
console.log('Sending answer to peer.');
pc.createAnswer(message.id).then(
setLocalAndSendMessage).catch(
onCreateSessionDescriptionError);
}
function setLocalAndSendMessage(sessionDescription) {
// Set Opus as the preferred codec in SDP if Opus is present.
// sessionDescription.sdp = preferOpus(sessionDescription.sdp);
pc.setLocalDescription(sessionDescription);
console.log('setLocalAndSendMessage sending message', sessionDescription);
sendMessage(sessionDescription);
}
function onCreateSessionDescriptionError(error) {
trace('Failed to create session description: ' + error.toString());
}
function requestTurn(turnURL) {
let turnExists = false;
for (let i in pcConfig.iceServers) {
if (pcConfig.iceServers[i].url.substr(0, 5) === 'turn:') {
turnExists = true;
turnReady = true;
break;
}
}
if (!turnExists) {
console.log('Getting TURN server from ', turnURL);
// No TURN server. Get one from computeengineondemand.appspot.com:
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
let turnServer = JSON.parse(xhr.responseText);
console.log('Got TURN server: ', turnServer);
pcConfig.iceServers.push({
'url': 'turn:192.158.29.39:3478?transport=tcp', //+ turnServer.username + '#' + turnServer.turn,
'username':'28224511:1379330808',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA='
});
turnReady = true;
}
};
//xhr.open('GET', turnURL, true);
//xhr.send();
}
}
// function handleRemoteStreamAdded(event) {
// console.log('Remote stream added.');
// remoteVideo.src = window.URL.createObjectURL(event.stream);
// remoteStream = event.stream;
// }
function handleRemoteStreamRemoved(event) {
console.log('Remote stream removed. Event: ', event);
}
function hangup() {
console.log('Hanging up.');
stop();
sendMessage('bye');
}
function handleRemoteHangup() {
console.log('Session terminated.');
stop();
isInitiator = false;
}
function stop() {
isStarted = false;
// isAudioMuted = false;
// isVideoMuted = false;
pc.close();
pc = null;
}
///////////////////////////////////////////
// Set Opus as the default audio codec if it's present.
function preferOpus(sdp) {
let sdpLines = sdp.split('\r\n');
let mLineIndex;
// Search for m line.
for (let i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('m=audio') !== -1) {
mLineIndex = i;
break;
}
}
if (mLineIndex === null) {
return sdp;
}
// If Opus is available, set it as the default in m line.
for (let i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('opus/48000') !== -1) {
let opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i);
if (opusPayload) {
sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex],
opusPayload);
}
break;
}
}
// Remove CN in m line and sdp.
sdpLines = removeCN(sdpLines, mLineIndex);
sdp = sdpLines.join('\r\n');
return sdp;
}
function extractSdp(sdpLine, pattern) {
let result = sdpLine.match(pattern);
return result && result.length === 2 ? result[1] : null;
}
// Set the selected codec to the first in m line.
function setDefaultCodec(mLine, payload) {
let elements = mLine.split(' ');
let newLine = [];
let index = 0;
for (let i = 0; i < elements.length; i++) {
if (index === 3) { // Format of media starts from the fourth.
newLine[index++] = payload; // Put target payload to the first.
}
if (elements[i] !== payload) {
newLine[index++] = elements[i];
}
}
return newLine.join(' ');
}
// Strip CN from sdp before CN constraints is ready.
function removeCN(sdpLines, mLineIndex) {
let mLineElements = sdpLines[mLineIndex].split(' ');
// Scan from end for the convenience of removing an item.
for (let i = sdpLines.length - 1; i >= 0; i--) {
let payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i);
if (payload) {
let cnPos = mLineElements.indexOf(payload);
if (cnPos !== -1) {
// Remove CN payload from m line.
mLineElements.splice(cnPos, 1);
}
// Remove CN line in sdp
sdpLines.splice(i, 1);
}
}
sdpLines[mLineIndex] = mLineElements.join(' ');
return sdpLines;
}
Backend Code:
const path = require(`path`);
const http = require(`http`);
const express = require(`express`);
const socketIO = require(`socket.io`);
const {generateMessage} = require(`./utils/message`);
const {isRealString} = require(`./utils/validation`);
const publicPath = path.join(__dirname,`../public`);
let app = express();
let server = http.createServer(app);
let io = socketIO(server);
app.use(express.static(publicPath));
app.get(`/video`,(req,res)=>{
res.sendFile(path.join(__dirname,`../public/videochat.html`));
});
io.on(`connection`,(socket)=>{
console.log(`New User Connected`);
socket.emit(`newMessage`,generateMessage(`Admin`, `Welcome to Chat App`));
socket.broadcast.emit(`newMessage`,generateMessage(`Admin`,`New User Joined`));
socket.on(`join`,(params,callback)=>{
if(!isRealString(params.name) || !isRealString(params.room)){
callback(`Name and Room name is required`);
}
callback();
});
socket.on('createMessage',(message,callback)=>{
console.log(`create Message`,message);
io.emit(`newMessage`,generateMessage(message.from,message.text));
callback();
});
socket.on(`offer`,(callback)=>{
console.log(`Call is Starting`);
callback();
});
/////////////////////////////////////////
function log() {
let array = ['Message from server:'];
array.push.apply(array, arguments);
socket.emit('log', array);
}
socket.on('message', function (message) {
log('Client said: ', message);
// for a real app, would be room-only (not broadcast)
socket.emit('message', message);
});
socket.on(`sdp`,(data)=>{
console.log('Received SDP from ' + socket.id);
socket.emit('sdp received', data.sdp);
});
socket.on('create or join', function (room) {
log('Received request to create or join room ' + room);
let numClients = io.sockets.sockets.length;
log('Room ' + room + ' now has ' + numClients + ' client(s)');
if (numClients === 1) {
socket.join(room);
log('Client ID ' + socket.id + ' created room ' + room);
socket.emit('created', room, socket.id);
} else if (numClients === 2) {
log('Client ID ' + socket.id + ' joined room ' + room);
io.sockets.in(room).emit('join', room);
socket.join(room);
socket.emit('joined', room, socket.id);
io.sockets.in(room).emit('ready');
} else { // max two clients
socket.emit('full', room);
}
});
socket.on('ipaddr', function () {
let ifaces = os.networkInterfaces();
for (let dev in ifaces) {
ifaces[dev].forEach(function (details) {
if (details.family === 'IPv4' && details.address !== '127.0.0.1') {
socket.emit('ipaddr', details.address);
}
});
}
});
socket.on('bye', function () {
console.log('received bye');
});
});
server.listen(3000,`192.168.0.105`,()=>{
console.log(`Server is Up`)
});
I'm getting this Error:- Failed to create PeerConnection, exception: Failed to construct 'RTCSessionDescription': parameter 1 ('descriptionInitDict') is not an object.
Also getting
Uncaught (in promise) DOMException: Failed to set remote offer sdp: Called in wrong state: kHaveLocalOffer
This line:
function doCall() {
console.log('Sending offer to peer');
pc.createOffer(setLocalAndSendMessage, handleCreateOfferError);
}
Change to:
pc.createOffer().then(setDescription).catch(errorHandler);
function setDescription(description) {
console.log('Got description', description);
pc.setLocalDescription(description).then(function() {
console.log("Sending SDP");
socket.emit('signal', {'sdp': description});
}).catch(errorHandler);
}
You should than handle the emitted SDP:
function gotMessageFromServer(signal) {
console.log('Got message', signal);
if(signal.sdp) {
console.log("Set remote description: ", signal);
pc.setRemoteDescription(new RTCSessionDescription(signal.sdp)).then(function() {
// Only create answers in response to offers
if(signal.sdp.type === 'offer') {
console.log("Sending answer");
pc.createAnswer().then(setDescription).catch(errorHandler);
}
}).catch(errorHandler);
} else if(signal.ice) {
console.log('Got remote ice candidate: ', signal);
pc.addIceCandidate(new RTCIceCandidate(signal.ice)).catch(errorHandler);
}
}

client.postMessage() in service worker does not call onmessage handler inside angularjs controller

Service Worker Message Handler:
let angularClient;
self.addEventListener('message', function(event) {
// store the client which sent the message into angularClient variable
angularClient = event.ports[0];
});
Service Worker Notification Click Handler, Which sends data to angularClient
self.addEventListener('notificationclick', function(event) {
event.notification.close();
var url = /localhost:8080|example.com|https:\/\/www.example.com/;
var newurl = "/" + event.notification.data.url;
if (event.notification.data.url) {
newurl = event.notification.data.url;
}
function endsWith(str, suffix) {
console.log(str);
console.log(suffix);
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
event.waitUntil(
clients.matchAll({
type: 'window'
})
.then(function(windowClients) {
for (var i = 0; i < windowClients.length; i++) {
var client = windowClients[i];
if (url.test(client.url) && 'focus' in client) {
if (endsWith(client.url, newurl)) {
console.log("URL matched");
console.log("sending 1");
angularClient.postMessage(sendToAngularPayload);
return client.focus();
}
return client.navigate(newurl)
.then(client => client.focus());
}
}
if (clients.openWindow) {
console.log("sending 2");
angularClient.postMessage(sendToAngularPayload); //sendToAngularPayload is defined when notification is received in firebase's messaging.setBackgroundMessageHandler.
return clients.openWindow('https://www.example.com/#/' +
event.notification.data.url);
}
})
);
},true);
AngularJs Controller with functions
Function to send message to service worker so that it stores this client
$scope.checkServiceWorker = function() {
if ('serviceWorker' in navigator) {
// ensure service worker is ready
navigator.serviceWorker.ready.then(function(reg) {
console.log("Send message");
// PING to service worker, later we will use this ping to
//identify our client.
sendMessage().then(function(event) {
console.log(event);
}).catch(function(error) {
console.log("error", error);
location.reload();
});
}).catch(function() {
console.log('SW not ready');
$scope.checkServiceWorker();
});
}
}
sendMessage function with onMessage handler
function sendMessage() {
return new Promise(function(resolve, reject) {
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function(event) {
console.log("on message handler", event);
if (event.data.error) {
reject(event.data.error);
} else {
console.log('inside resolve', event.data);
console.log("Ping received from SW");
console.log(event);
resolve(event.data);
}
};
console.log("Sending");
navigator.serviceWorker.controller.postMessage("ping",
[messageChannel.port2]);
console.log("sent");
});
}
The problem is that onMessage Handler inside angularjs controller gets fired 90% of the times, but sometimes it does not. As I can see in the developer console, the execution stops in serviceworker.js after I print "sending 1" in the notification click handler, and does not show rest of the logs inside the controller's onMessage handler.
worker.ts
self.addEventListener("push", e => {
const data = e.data.json();
console.log("Push received");
console.log("data ", data);
self.registration.showNotification(data.title, {
body: "Notified",
})
// Broadcasting from a ServiceWorker to every client
self.clients.matchAll().then(all => all.map(client => client.postMessage(data)));
})
The listener is added on navigator.serviceWorker and not on a specific
worker
AngularJs controller:
constructor() {
navigator.serviceWorker.addEventListener('message', e => console.log(e.data));
}

Node js, Call WebSocket server from oracle apex

I am trying to create web-sockets in APEX for automatic refresh with node
but I am getting error This is not valid JSON:
java script code
$(function(){
window.WebSocket = window.WebSocket || window.MozWebSocket;
if (!window.WebSocket) {
console.log('Sorry websockets');
}
else {
var connection = new WebSocket('ws://127.0.0.1:1337');
connection.onerror = function (error) {
console.log( 'Sorry, but there is some problem with your connection or the server is down.');
};
connection.onmessage = function (message) {
console.log(message.data);
try {
var json = JSON.parse(message.data);
if (json.message=='REFRESH') {
gReport.pull();
}
else {
console.log(json.message);
}
}
catch (e) {
console.log('Thisnot valid JSON: ' + message.data);
}
};
}
});

WebRTC works locally, but not across different IP addresses

My code is on Github at: https://github.com/rashadrussell/webrtc_experiment/blob/master/public/script.js
I am trying to write a 1-to-1 video video conferencing script with WebRTC. And is being stored on AppFog, a cloud hosting website. It works on my localhost when I test with two different Chrome windows on a single computer. It also works on AppFog when I test it on two different computers at home.
The problem occurs when I test my app with a friend living at a different house. The remote streams are not being set. My only guess is that there is some error with IP addresses, which means something is wrong my the setup of Ice Candidates. All that pops up is a black box where the remote stream is supposed to be.
Here is some of my code:
Client-Side
var isInitiator = false;
socket.on('initiatorFound', function(data) {
isInitiator = data.setInitiator;
console.log("Is Initiator? " + isInitiator);
});
navigator.getMedia = (
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia
);
navigator.getMedia(
{video: true, audio: false},
(stream) => {
var video = document.getElementById("localView");
video.src = window.URL.createObjectURL(stream);
console.log("Add Stream");
sendMessage('streamAdd', {streamAdded: 'stream-added'});
createPeerConnection();
pc.addStream(stream);
if(isInitiator)
{
callPeer();
}
},
function(err) {
console.log("The following error occured: ");
console.dir(err);
}
);
function sendMessage(type, message)
{
console.log("Sending Message");
socket.emit('message',{
"type": type,
"message": message
});
}
function createPeerConnection() {
pc = new rtcPeerConnection(servers, options);
console.dir(pc);
pc.onicecandidate = function(evt) {
if(evt.candidate == null) return;
pc.onicecandidate = null;
console.log("Send Ice Candidate");
sendMessage("iceCandidate", JSON.stringify(evt.candidate));
};
pc.onaddstream = function(evt) {
document.body.append("<video id='remoteVideo' autoplay></video>");
var remoteVid = document.getElementById("remoteVideo");
remoteVid.src = window.URL.createObjectURL(evt.stream);
};
}
function callPeer() {
pc.createOffer(function (offer) {
pc.setLocalDescription(offer, function() {
sendMessage("offer", JSON.stringify(offer));
});
console.log("Send Offer");
}, function(err) { console.log("Offer Error: " + err) },
videoConstraints
);
}
function answerPeer() {
pc.createAnswer(function(answer) {
pc.setLocalDescription(answer);
sendMessage("answer", JSON.stringify(answer))
}, function(err) { console.log("Sending Answer Error: " + err) },
videoConstraints
);
}
socket.on('message', function(message) {
console.log("CONSOLE MESSAGE:");
console.dir(message);
if(message.type == 'streamAdd') {
console.log('Stream was added');
createPeerConnection();
if(isInitiator) {
callPeer();
}
} else if(message.type == 'offer') {
pc.setRemoteDescription( new rtcSessionDescription(JSON.parse(message.message)));
if(!isInitiator)
{
console.log("Sending Answer");
answerPeer();
}
} else if(message.type == 'answer') {
pc.setRemoteDescription( new rtcSessionDescription(JSON.parse(message.message)));
} else if(message.type == 'iceCandidate') {
console.log("Get Ice Candidate");
pc.addIceCandidate(new rtcIceCandidate(JSON.parse(message.message)) );
}
});
Server-Side
var isInitiator = false;
io.sockets.on('connection', function(socket) {
if (!isInitiator) {
isInitiator = true;
socket.emit('initiatorFound', {setInitiator: isInitiator});
} else {
socket.emit('initiatorFound', {setInitiator: !isInitiator});
}
// Signaling Channel
socket.on('message', function(message) {
if (message.type == 'streamAdd') {
console.log('Got message: ' + message);
}
//socket.emit('message' ,message);
// Should be:
socket.broadcast.emit('message', message);
});
});
In the line
pc = new rtcPeerConnection(servers, options);
While sending the server info through the server variable, you need to mention the addr of TURN servers as well along withthe STUN server. Typically the data gets blocked due to NAT or firewall and TURN should help in that case.
For more server details, you can check out https://gist.github.com/yetithefoot/7592580

Categories