Xirsys WebRTC can't find sdp object











up vote
0
down vote

favorite












I'm trying to test an example provided by Xirsys where I can proceed with signaling using only PHP. The ice servers / token and host seems to work perfectly, but when trying to connect it returns "uncaught: Typeerror: cannot read property 'sdp' of null. The object it doesn't seem null, not sure what is happening here.
Follow my code:



    <html>
<head>
<title>PHP Xirsys</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="panel" id="video-wrapper">
<style>
video {
background: #cccccc;
width: 200px;
}
</style>

<div class="col">
<div>
your message: <input type="text" id="newMessage" disabled />
<button id="sendButton" onclick="send()" disabled>send</button>
</div>

<div id="messages"></div>
</div>
<div id="videos">
<video autoplay="true" id="localVideo"></video>
</div>

<div>
username: <input type="text" id="username" />
<button id="connectButton" onclick="connect()">connect</button>
</div>

<script>
var token;
var socket;
var ice;
var pcs = {};
var localUsername;

function displayMessage(message) {
$('#messages')[0].innerHTML += message + "<br>";
}

window.onload = () => {
$.post("getice.php", null, r => onIce(r));
}

function onIce(r) {
ice = JSON.parse(r).v;
navigator.mediaDevices.getUserMedia({audio: true, video: true}).then(stream => onGetMedia(stream));
}

function connect() {
localUsername = $('#username')[0].value;
$.post("gettoken.php", {username: localUsername}, r => getHost(r));
}

function getHost(r) {
token = JSON.parse(r).v;
$.post("gethost.php", {username: localUsername}, r => openSocket(r));
}

function openSocket(r) {
var host = JSON.parse(r).v;
socket = new WebSocket(host + "/v2/" + token);
socket.addEventListener("message", onSocketMessage);
}

function onSocketMessage(evt) {
var data = JSON.parse(evt.data);
var option;
var pc;
switch (data.m.o) {
case "peers":
var users = data.p.users;
for(i = 0; i < users.length; i++) {
displayMessage("user in chat:" + users[i]);
}
break;
case "peer_connected":
var f = data.m.f.split("/");
var joining = f[f.length-1];
displayMessage("new user joined: " + joining)
callPeer(joining);
break;
case "message":
switch(data.p.msg.type) {
case "offer":
var desc = new RTCSessionDescription(data.p.msg);
var f = data.m.f.split("/");
var sender = f[f.length-1];
pc = createNewPeerConnection(sender);
pc.setRemoteDescription(desc);
pc.createAnswer().then(d => onCreateAnswer(d,sender));
break;
case "answer":
var desc = new RTCSessionDescription(data.p.msg);
var f = data.m.f.split("/");
var sender = f[f.length-1];
pcs[sender].pc.setRemoteDescription(desc);
break;
case "candidate":
var f = data.m.f.split("/");
var sender = f[f.length-1];
var candidate = new RTCIceCandidate(data.p.msg);
pcs[sender].pc.addIceCandidate(candidate);
break;
}
}
}

function callPeer(peer) {
var pc = createNewPeerConnection(peer);
var dataChannel = pc.createDataChannel("data");
pcs[peer].dc = dataChannel;
setDataChannelHandlers(dataChannel);
pc.createOffer().then(d => onCreateOffer(d, peer));
}

function onCreateOffer(d, peer) {
pcs[peer].pc.setLocalDescription(d);
var pkt = {t: "u", m: {f: "appchannel/" + localUsername, o: "message", t: peer}, p: {msg:d}};
socket.send(JSON.stringify(pkt));
}

function onCreateAnswer(d, peer) {
pcs[peer].pc.setLocalDescription(d);
var pkt = {t: "u", m: {f: "appchannel/" + localUsername, o: "message", t: peer}, p: {msg:d}};
socket.send(JSON.stringify(pkt));
}

function onIceCandidate(evt) {
var remoteUsername = getUsernameByRemoteDescription(evt.target.remoteDescription.sdp);
var candidate = evt.candidate;
if (candidate != null && remoteUsername != null) {
var cPkt = {type: "candidate",
candidate: candidate.candidate,
sdpMid: candidate.sdpMid,
sdpMLineIndex: candidate.sdpMLineIndex
};
var pkt = {
t: "u",
m: {
f: "appchannel/" + localUsername,
o: "message",
t: remoteUsername
},
p: {msg:cPkt}
}
socket.send(JSON.stringify(pkt));
}
}

function setDataChannelHandlers(dc) {
dc.onmessage = evt => onDataMessage(evt);
dc.onopen = evt => onDataChannelOpen(evt);
}

function onDataChannelOpen(evt) {
$("#newMessage")[0].disabled = false;
$("#sendButton")[0].disabled = false;
}

function onDataChannel(evt) {
var dataChannel = evt.channel;
var keys = Object.keys(pcs);
var comp;
var localDescription;
var remoteDescription;
for(var i = 0; i < keys.length; i++) {
comp = pcs[keys[i]];
if(evt.currentTarget.localDescription.sdp == comp.pc.localDescription.sdp) {
comp.dc = dataChannel;
}
}
setDataChannelHandlers(dataChannel);
}

function send() {
var messageElement = $('#newMessage')[0];
displayMessage("you said: " + messageElement.value);
var message = {f: localUsername, msg: messageElement.value};
messageElement.value = "";
var dataChannel;
var keys = Object.keys(pcs);
var comp;
for(var i = 0; i < keys.length; i++) {
comp = pcs[keys[i]];
dataChannel = comp.dc;
dataChannel.send(JSON.stringify(message));
}
}

function onDataMessage(evt) {
var messageObj = JSON.parse(evt.data);
displayMessage(messageObj.f + " said: " + messageObj.msg);
}

function createNewPeerConnection(username){
var pc = new RTCPeerConnection(ice);
pc.addStream(localStream);
pc.onaddstream = evt => onAddStream(evt);
pc.ondatachannel = evt => onDataChannel(evt);
pc.onicecandidate = candidate => onIceCandidate(candidate);
pcs[username] = {pc: pc, dc: null, s: null, v: null};
return pc;
}

function getUsernameByRemoteDescription(sdp) {
var keys = Object.keys(pcs);
var pc;
for(var i = 0; i < keys.length; i++) {
pc = pcs[keys[i]].pc;
if(pc.remoteDescription.sdp == sdp) {
return keys[i];
}
}
return null;
}

function onGetMedia(stream) {
var vid = $("#localVideo")[0];
vid.srcObject = stream;
localStream = stream;
}

function onAddStream(evt) {
var pc = evt.target;
var stream = evt.stream;
var peer = getUsernameByRemoteDescription(pc.remoteDescription.sdp);
pcs[peer].s = stream;
var v = addNewVideo(stream);
pcs[peer].v = v;
}

function addNewVideo(stream) {
var vid = document.createElement("video");
$("#videos")[0].appendChild(vid);
vid.srcObject = stream;
return vid;
}
</script>
</div>
</body>
</html>


getice.php



<?php
$curl = curl_init();
curl_setopt_array( $curl, array (
CURLOPT_URL =>
"https://global.xirsys.net/_turn/appchannel/",
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_RETURNTRANSFER => 1
));
$resp = curl_exec($curl);
print $resp;
curl_close($curl);
?>


gettoken.php



$data = array( 'k' => $_POST["username"], 'expire' => 45, 'depth' => 10 );
$qs = http_build_query($data);

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://global.xirsys.net/_token/appchannel?'.$qs,
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => 'PUT'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);


gethost.php



$data = array( 'k' => $_POST["username"], 'type' => 'signal' );
$qs = http_build_query($data);

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://global.xirsys.net/_host?'.$qs,
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => 'GET'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);


Edit: errors -> on Chrome / Firefox
on Chromeon Firefox










share|improve this question
























  • You're going to have to try to narrow this down a bit... we don't have any way of reproducing this issue.
    – Brad
    Nov 22 at 2:32










  • You are right @Brad, actually, I'm a bit lost, I'm not sure how to summarize this... With an account and keys, you will be able to run the code on your side. Is that helps?
    – Igor O
    Nov 22 at 3:02






  • 1




    No, that doesn't help. Figure out what evt.target is, ensure it's what you expect, figure out why remoteDescription is null, narrow this problem down.
    – Brad
    Nov 22 at 3:04















up vote
0
down vote

favorite












I'm trying to test an example provided by Xirsys where I can proceed with signaling using only PHP. The ice servers / token and host seems to work perfectly, but when trying to connect it returns "uncaught: Typeerror: cannot read property 'sdp' of null. The object it doesn't seem null, not sure what is happening here.
Follow my code:



    <html>
<head>
<title>PHP Xirsys</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="panel" id="video-wrapper">
<style>
video {
background: #cccccc;
width: 200px;
}
</style>

<div class="col">
<div>
your message: <input type="text" id="newMessage" disabled />
<button id="sendButton" onclick="send()" disabled>send</button>
</div>

<div id="messages"></div>
</div>
<div id="videos">
<video autoplay="true" id="localVideo"></video>
</div>

<div>
username: <input type="text" id="username" />
<button id="connectButton" onclick="connect()">connect</button>
</div>

<script>
var token;
var socket;
var ice;
var pcs = {};
var localUsername;

function displayMessage(message) {
$('#messages')[0].innerHTML += message + "<br>";
}

window.onload = () => {
$.post("getice.php", null, r => onIce(r));
}

function onIce(r) {
ice = JSON.parse(r).v;
navigator.mediaDevices.getUserMedia({audio: true, video: true}).then(stream => onGetMedia(stream));
}

function connect() {
localUsername = $('#username')[0].value;
$.post("gettoken.php", {username: localUsername}, r => getHost(r));
}

function getHost(r) {
token = JSON.parse(r).v;
$.post("gethost.php", {username: localUsername}, r => openSocket(r));
}

function openSocket(r) {
var host = JSON.parse(r).v;
socket = new WebSocket(host + "/v2/" + token);
socket.addEventListener("message", onSocketMessage);
}

function onSocketMessage(evt) {
var data = JSON.parse(evt.data);
var option;
var pc;
switch (data.m.o) {
case "peers":
var users = data.p.users;
for(i = 0; i < users.length; i++) {
displayMessage("user in chat:" + users[i]);
}
break;
case "peer_connected":
var f = data.m.f.split("/");
var joining = f[f.length-1];
displayMessage("new user joined: " + joining)
callPeer(joining);
break;
case "message":
switch(data.p.msg.type) {
case "offer":
var desc = new RTCSessionDescription(data.p.msg);
var f = data.m.f.split("/");
var sender = f[f.length-1];
pc = createNewPeerConnection(sender);
pc.setRemoteDescription(desc);
pc.createAnswer().then(d => onCreateAnswer(d,sender));
break;
case "answer":
var desc = new RTCSessionDescription(data.p.msg);
var f = data.m.f.split("/");
var sender = f[f.length-1];
pcs[sender].pc.setRemoteDescription(desc);
break;
case "candidate":
var f = data.m.f.split("/");
var sender = f[f.length-1];
var candidate = new RTCIceCandidate(data.p.msg);
pcs[sender].pc.addIceCandidate(candidate);
break;
}
}
}

function callPeer(peer) {
var pc = createNewPeerConnection(peer);
var dataChannel = pc.createDataChannel("data");
pcs[peer].dc = dataChannel;
setDataChannelHandlers(dataChannel);
pc.createOffer().then(d => onCreateOffer(d, peer));
}

function onCreateOffer(d, peer) {
pcs[peer].pc.setLocalDescription(d);
var pkt = {t: "u", m: {f: "appchannel/" + localUsername, o: "message", t: peer}, p: {msg:d}};
socket.send(JSON.stringify(pkt));
}

function onCreateAnswer(d, peer) {
pcs[peer].pc.setLocalDescription(d);
var pkt = {t: "u", m: {f: "appchannel/" + localUsername, o: "message", t: peer}, p: {msg:d}};
socket.send(JSON.stringify(pkt));
}

function onIceCandidate(evt) {
var remoteUsername = getUsernameByRemoteDescription(evt.target.remoteDescription.sdp);
var candidate = evt.candidate;
if (candidate != null && remoteUsername != null) {
var cPkt = {type: "candidate",
candidate: candidate.candidate,
sdpMid: candidate.sdpMid,
sdpMLineIndex: candidate.sdpMLineIndex
};
var pkt = {
t: "u",
m: {
f: "appchannel/" + localUsername,
o: "message",
t: remoteUsername
},
p: {msg:cPkt}
}
socket.send(JSON.stringify(pkt));
}
}

function setDataChannelHandlers(dc) {
dc.onmessage = evt => onDataMessage(evt);
dc.onopen = evt => onDataChannelOpen(evt);
}

function onDataChannelOpen(evt) {
$("#newMessage")[0].disabled = false;
$("#sendButton")[0].disabled = false;
}

function onDataChannel(evt) {
var dataChannel = evt.channel;
var keys = Object.keys(pcs);
var comp;
var localDescription;
var remoteDescription;
for(var i = 0; i < keys.length; i++) {
comp = pcs[keys[i]];
if(evt.currentTarget.localDescription.sdp == comp.pc.localDescription.sdp) {
comp.dc = dataChannel;
}
}
setDataChannelHandlers(dataChannel);
}

function send() {
var messageElement = $('#newMessage')[0];
displayMessage("you said: " + messageElement.value);
var message = {f: localUsername, msg: messageElement.value};
messageElement.value = "";
var dataChannel;
var keys = Object.keys(pcs);
var comp;
for(var i = 0; i < keys.length; i++) {
comp = pcs[keys[i]];
dataChannel = comp.dc;
dataChannel.send(JSON.stringify(message));
}
}

function onDataMessage(evt) {
var messageObj = JSON.parse(evt.data);
displayMessage(messageObj.f + " said: " + messageObj.msg);
}

function createNewPeerConnection(username){
var pc = new RTCPeerConnection(ice);
pc.addStream(localStream);
pc.onaddstream = evt => onAddStream(evt);
pc.ondatachannel = evt => onDataChannel(evt);
pc.onicecandidate = candidate => onIceCandidate(candidate);
pcs[username] = {pc: pc, dc: null, s: null, v: null};
return pc;
}

function getUsernameByRemoteDescription(sdp) {
var keys = Object.keys(pcs);
var pc;
for(var i = 0; i < keys.length; i++) {
pc = pcs[keys[i]].pc;
if(pc.remoteDescription.sdp == sdp) {
return keys[i];
}
}
return null;
}

function onGetMedia(stream) {
var vid = $("#localVideo")[0];
vid.srcObject = stream;
localStream = stream;
}

function onAddStream(evt) {
var pc = evt.target;
var stream = evt.stream;
var peer = getUsernameByRemoteDescription(pc.remoteDescription.sdp);
pcs[peer].s = stream;
var v = addNewVideo(stream);
pcs[peer].v = v;
}

function addNewVideo(stream) {
var vid = document.createElement("video");
$("#videos")[0].appendChild(vid);
vid.srcObject = stream;
return vid;
}
</script>
</div>
</body>
</html>


getice.php



<?php
$curl = curl_init();
curl_setopt_array( $curl, array (
CURLOPT_URL =>
"https://global.xirsys.net/_turn/appchannel/",
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_RETURNTRANSFER => 1
));
$resp = curl_exec($curl);
print $resp;
curl_close($curl);
?>


gettoken.php



$data = array( 'k' => $_POST["username"], 'expire' => 45, 'depth' => 10 );
$qs = http_build_query($data);

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://global.xirsys.net/_token/appchannel?'.$qs,
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => 'PUT'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);


gethost.php



$data = array( 'k' => $_POST["username"], 'type' => 'signal' );
$qs = http_build_query($data);

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://global.xirsys.net/_host?'.$qs,
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => 'GET'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);


Edit: errors -> on Chrome / Firefox
on Chromeon Firefox










share|improve this question
























  • You're going to have to try to narrow this down a bit... we don't have any way of reproducing this issue.
    – Brad
    Nov 22 at 2:32










  • You are right @Brad, actually, I'm a bit lost, I'm not sure how to summarize this... With an account and keys, you will be able to run the code on your side. Is that helps?
    – Igor O
    Nov 22 at 3:02






  • 1




    No, that doesn't help. Figure out what evt.target is, ensure it's what you expect, figure out why remoteDescription is null, narrow this problem down.
    – Brad
    Nov 22 at 3:04













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm trying to test an example provided by Xirsys where I can proceed with signaling using only PHP. The ice servers / token and host seems to work perfectly, but when trying to connect it returns "uncaught: Typeerror: cannot read property 'sdp' of null. The object it doesn't seem null, not sure what is happening here.
Follow my code:



    <html>
<head>
<title>PHP Xirsys</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="panel" id="video-wrapper">
<style>
video {
background: #cccccc;
width: 200px;
}
</style>

<div class="col">
<div>
your message: <input type="text" id="newMessage" disabled />
<button id="sendButton" onclick="send()" disabled>send</button>
</div>

<div id="messages"></div>
</div>
<div id="videos">
<video autoplay="true" id="localVideo"></video>
</div>

<div>
username: <input type="text" id="username" />
<button id="connectButton" onclick="connect()">connect</button>
</div>

<script>
var token;
var socket;
var ice;
var pcs = {};
var localUsername;

function displayMessage(message) {
$('#messages')[0].innerHTML += message + "<br>";
}

window.onload = () => {
$.post("getice.php", null, r => onIce(r));
}

function onIce(r) {
ice = JSON.parse(r).v;
navigator.mediaDevices.getUserMedia({audio: true, video: true}).then(stream => onGetMedia(stream));
}

function connect() {
localUsername = $('#username')[0].value;
$.post("gettoken.php", {username: localUsername}, r => getHost(r));
}

function getHost(r) {
token = JSON.parse(r).v;
$.post("gethost.php", {username: localUsername}, r => openSocket(r));
}

function openSocket(r) {
var host = JSON.parse(r).v;
socket = new WebSocket(host + "/v2/" + token);
socket.addEventListener("message", onSocketMessage);
}

function onSocketMessage(evt) {
var data = JSON.parse(evt.data);
var option;
var pc;
switch (data.m.o) {
case "peers":
var users = data.p.users;
for(i = 0; i < users.length; i++) {
displayMessage("user in chat:" + users[i]);
}
break;
case "peer_connected":
var f = data.m.f.split("/");
var joining = f[f.length-1];
displayMessage("new user joined: " + joining)
callPeer(joining);
break;
case "message":
switch(data.p.msg.type) {
case "offer":
var desc = new RTCSessionDescription(data.p.msg);
var f = data.m.f.split("/");
var sender = f[f.length-1];
pc = createNewPeerConnection(sender);
pc.setRemoteDescription(desc);
pc.createAnswer().then(d => onCreateAnswer(d,sender));
break;
case "answer":
var desc = new RTCSessionDescription(data.p.msg);
var f = data.m.f.split("/");
var sender = f[f.length-1];
pcs[sender].pc.setRemoteDescription(desc);
break;
case "candidate":
var f = data.m.f.split("/");
var sender = f[f.length-1];
var candidate = new RTCIceCandidate(data.p.msg);
pcs[sender].pc.addIceCandidate(candidate);
break;
}
}
}

function callPeer(peer) {
var pc = createNewPeerConnection(peer);
var dataChannel = pc.createDataChannel("data");
pcs[peer].dc = dataChannel;
setDataChannelHandlers(dataChannel);
pc.createOffer().then(d => onCreateOffer(d, peer));
}

function onCreateOffer(d, peer) {
pcs[peer].pc.setLocalDescription(d);
var pkt = {t: "u", m: {f: "appchannel/" + localUsername, o: "message", t: peer}, p: {msg:d}};
socket.send(JSON.stringify(pkt));
}

function onCreateAnswer(d, peer) {
pcs[peer].pc.setLocalDescription(d);
var pkt = {t: "u", m: {f: "appchannel/" + localUsername, o: "message", t: peer}, p: {msg:d}};
socket.send(JSON.stringify(pkt));
}

function onIceCandidate(evt) {
var remoteUsername = getUsernameByRemoteDescription(evt.target.remoteDescription.sdp);
var candidate = evt.candidate;
if (candidate != null && remoteUsername != null) {
var cPkt = {type: "candidate",
candidate: candidate.candidate,
sdpMid: candidate.sdpMid,
sdpMLineIndex: candidate.sdpMLineIndex
};
var pkt = {
t: "u",
m: {
f: "appchannel/" + localUsername,
o: "message",
t: remoteUsername
},
p: {msg:cPkt}
}
socket.send(JSON.stringify(pkt));
}
}

function setDataChannelHandlers(dc) {
dc.onmessage = evt => onDataMessage(evt);
dc.onopen = evt => onDataChannelOpen(evt);
}

function onDataChannelOpen(evt) {
$("#newMessage")[0].disabled = false;
$("#sendButton")[0].disabled = false;
}

function onDataChannel(evt) {
var dataChannel = evt.channel;
var keys = Object.keys(pcs);
var comp;
var localDescription;
var remoteDescription;
for(var i = 0; i < keys.length; i++) {
comp = pcs[keys[i]];
if(evt.currentTarget.localDescription.sdp == comp.pc.localDescription.sdp) {
comp.dc = dataChannel;
}
}
setDataChannelHandlers(dataChannel);
}

function send() {
var messageElement = $('#newMessage')[0];
displayMessage("you said: " + messageElement.value);
var message = {f: localUsername, msg: messageElement.value};
messageElement.value = "";
var dataChannel;
var keys = Object.keys(pcs);
var comp;
for(var i = 0; i < keys.length; i++) {
comp = pcs[keys[i]];
dataChannel = comp.dc;
dataChannel.send(JSON.stringify(message));
}
}

function onDataMessage(evt) {
var messageObj = JSON.parse(evt.data);
displayMessage(messageObj.f + " said: " + messageObj.msg);
}

function createNewPeerConnection(username){
var pc = new RTCPeerConnection(ice);
pc.addStream(localStream);
pc.onaddstream = evt => onAddStream(evt);
pc.ondatachannel = evt => onDataChannel(evt);
pc.onicecandidate = candidate => onIceCandidate(candidate);
pcs[username] = {pc: pc, dc: null, s: null, v: null};
return pc;
}

function getUsernameByRemoteDescription(sdp) {
var keys = Object.keys(pcs);
var pc;
for(var i = 0; i < keys.length; i++) {
pc = pcs[keys[i]].pc;
if(pc.remoteDescription.sdp == sdp) {
return keys[i];
}
}
return null;
}

function onGetMedia(stream) {
var vid = $("#localVideo")[0];
vid.srcObject = stream;
localStream = stream;
}

function onAddStream(evt) {
var pc = evt.target;
var stream = evt.stream;
var peer = getUsernameByRemoteDescription(pc.remoteDescription.sdp);
pcs[peer].s = stream;
var v = addNewVideo(stream);
pcs[peer].v = v;
}

function addNewVideo(stream) {
var vid = document.createElement("video");
$("#videos")[0].appendChild(vid);
vid.srcObject = stream;
return vid;
}
</script>
</div>
</body>
</html>


getice.php



<?php
$curl = curl_init();
curl_setopt_array( $curl, array (
CURLOPT_URL =>
"https://global.xirsys.net/_turn/appchannel/",
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_RETURNTRANSFER => 1
));
$resp = curl_exec($curl);
print $resp;
curl_close($curl);
?>


gettoken.php



$data = array( 'k' => $_POST["username"], 'expire' => 45, 'depth' => 10 );
$qs = http_build_query($data);

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://global.xirsys.net/_token/appchannel?'.$qs,
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => 'PUT'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);


gethost.php



$data = array( 'k' => $_POST["username"], 'type' => 'signal' );
$qs = http_build_query($data);

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://global.xirsys.net/_host?'.$qs,
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => 'GET'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);


Edit: errors -> on Chrome / Firefox
on Chromeon Firefox










share|improve this question















I'm trying to test an example provided by Xirsys where I can proceed with signaling using only PHP. The ice servers / token and host seems to work perfectly, but when trying to connect it returns "uncaught: Typeerror: cannot read property 'sdp' of null. The object it doesn't seem null, not sure what is happening here.
Follow my code:



    <html>
<head>
<title>PHP Xirsys</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="panel" id="video-wrapper">
<style>
video {
background: #cccccc;
width: 200px;
}
</style>

<div class="col">
<div>
your message: <input type="text" id="newMessage" disabled />
<button id="sendButton" onclick="send()" disabled>send</button>
</div>

<div id="messages"></div>
</div>
<div id="videos">
<video autoplay="true" id="localVideo"></video>
</div>

<div>
username: <input type="text" id="username" />
<button id="connectButton" onclick="connect()">connect</button>
</div>

<script>
var token;
var socket;
var ice;
var pcs = {};
var localUsername;

function displayMessage(message) {
$('#messages')[0].innerHTML += message + "<br>";
}

window.onload = () => {
$.post("getice.php", null, r => onIce(r));
}

function onIce(r) {
ice = JSON.parse(r).v;
navigator.mediaDevices.getUserMedia({audio: true, video: true}).then(stream => onGetMedia(stream));
}

function connect() {
localUsername = $('#username')[0].value;
$.post("gettoken.php", {username: localUsername}, r => getHost(r));
}

function getHost(r) {
token = JSON.parse(r).v;
$.post("gethost.php", {username: localUsername}, r => openSocket(r));
}

function openSocket(r) {
var host = JSON.parse(r).v;
socket = new WebSocket(host + "/v2/" + token);
socket.addEventListener("message", onSocketMessage);
}

function onSocketMessage(evt) {
var data = JSON.parse(evt.data);
var option;
var pc;
switch (data.m.o) {
case "peers":
var users = data.p.users;
for(i = 0; i < users.length; i++) {
displayMessage("user in chat:" + users[i]);
}
break;
case "peer_connected":
var f = data.m.f.split("/");
var joining = f[f.length-1];
displayMessage("new user joined: " + joining)
callPeer(joining);
break;
case "message":
switch(data.p.msg.type) {
case "offer":
var desc = new RTCSessionDescription(data.p.msg);
var f = data.m.f.split("/");
var sender = f[f.length-1];
pc = createNewPeerConnection(sender);
pc.setRemoteDescription(desc);
pc.createAnswer().then(d => onCreateAnswer(d,sender));
break;
case "answer":
var desc = new RTCSessionDescription(data.p.msg);
var f = data.m.f.split("/");
var sender = f[f.length-1];
pcs[sender].pc.setRemoteDescription(desc);
break;
case "candidate":
var f = data.m.f.split("/");
var sender = f[f.length-1];
var candidate = new RTCIceCandidate(data.p.msg);
pcs[sender].pc.addIceCandidate(candidate);
break;
}
}
}

function callPeer(peer) {
var pc = createNewPeerConnection(peer);
var dataChannel = pc.createDataChannel("data");
pcs[peer].dc = dataChannel;
setDataChannelHandlers(dataChannel);
pc.createOffer().then(d => onCreateOffer(d, peer));
}

function onCreateOffer(d, peer) {
pcs[peer].pc.setLocalDescription(d);
var pkt = {t: "u", m: {f: "appchannel/" + localUsername, o: "message", t: peer}, p: {msg:d}};
socket.send(JSON.stringify(pkt));
}

function onCreateAnswer(d, peer) {
pcs[peer].pc.setLocalDescription(d);
var pkt = {t: "u", m: {f: "appchannel/" + localUsername, o: "message", t: peer}, p: {msg:d}};
socket.send(JSON.stringify(pkt));
}

function onIceCandidate(evt) {
var remoteUsername = getUsernameByRemoteDescription(evt.target.remoteDescription.sdp);
var candidate = evt.candidate;
if (candidate != null && remoteUsername != null) {
var cPkt = {type: "candidate",
candidate: candidate.candidate,
sdpMid: candidate.sdpMid,
sdpMLineIndex: candidate.sdpMLineIndex
};
var pkt = {
t: "u",
m: {
f: "appchannel/" + localUsername,
o: "message",
t: remoteUsername
},
p: {msg:cPkt}
}
socket.send(JSON.stringify(pkt));
}
}

function setDataChannelHandlers(dc) {
dc.onmessage = evt => onDataMessage(evt);
dc.onopen = evt => onDataChannelOpen(evt);
}

function onDataChannelOpen(evt) {
$("#newMessage")[0].disabled = false;
$("#sendButton")[0].disabled = false;
}

function onDataChannel(evt) {
var dataChannel = evt.channel;
var keys = Object.keys(pcs);
var comp;
var localDescription;
var remoteDescription;
for(var i = 0; i < keys.length; i++) {
comp = pcs[keys[i]];
if(evt.currentTarget.localDescription.sdp == comp.pc.localDescription.sdp) {
comp.dc = dataChannel;
}
}
setDataChannelHandlers(dataChannel);
}

function send() {
var messageElement = $('#newMessage')[0];
displayMessage("you said: " + messageElement.value);
var message = {f: localUsername, msg: messageElement.value};
messageElement.value = "";
var dataChannel;
var keys = Object.keys(pcs);
var comp;
for(var i = 0; i < keys.length; i++) {
comp = pcs[keys[i]];
dataChannel = comp.dc;
dataChannel.send(JSON.stringify(message));
}
}

function onDataMessage(evt) {
var messageObj = JSON.parse(evt.data);
displayMessage(messageObj.f + " said: " + messageObj.msg);
}

function createNewPeerConnection(username){
var pc = new RTCPeerConnection(ice);
pc.addStream(localStream);
pc.onaddstream = evt => onAddStream(evt);
pc.ondatachannel = evt => onDataChannel(evt);
pc.onicecandidate = candidate => onIceCandidate(candidate);
pcs[username] = {pc: pc, dc: null, s: null, v: null};
return pc;
}

function getUsernameByRemoteDescription(sdp) {
var keys = Object.keys(pcs);
var pc;
for(var i = 0; i < keys.length; i++) {
pc = pcs[keys[i]].pc;
if(pc.remoteDescription.sdp == sdp) {
return keys[i];
}
}
return null;
}

function onGetMedia(stream) {
var vid = $("#localVideo")[0];
vid.srcObject = stream;
localStream = stream;
}

function onAddStream(evt) {
var pc = evt.target;
var stream = evt.stream;
var peer = getUsernameByRemoteDescription(pc.remoteDescription.sdp);
pcs[peer].s = stream;
var v = addNewVideo(stream);
pcs[peer].v = v;
}

function addNewVideo(stream) {
var vid = document.createElement("video");
$("#videos")[0].appendChild(vid);
vid.srcObject = stream;
return vid;
}
</script>
</div>
</body>
</html>


getice.php



<?php
$curl = curl_init();
curl_setopt_array( $curl, array (
CURLOPT_URL =>
"https://global.xirsys.net/_turn/appchannel/",
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_RETURNTRANSFER => 1
));
$resp = curl_exec($curl);
print $resp;
curl_close($curl);
?>


gettoken.php



$data = array( 'k' => $_POST["username"], 'expire' => 45, 'depth' => 10 );
$qs = http_build_query($data);

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://global.xirsys.net/_token/appchannel?'.$qs,
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => 'PUT'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);


gethost.php



$data = array( 'k' => $_POST["username"], 'type' => 'signal' );
$qs = http_build_query($data);

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://global.xirsys.net/_host?'.$qs,
CURLOPT_USERPWD => "account:key",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_CUSTOMREQUEST => 'GET'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);


Edit: errors -> on Chrome / Firefox
on Chromeon Firefox







javascript php webrtc xirsys






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 at 2:28

























asked Nov 22 at 1:54









Igor O

232415




232415












  • You're going to have to try to narrow this down a bit... we don't have any way of reproducing this issue.
    – Brad
    Nov 22 at 2:32










  • You are right @Brad, actually, I'm a bit lost, I'm not sure how to summarize this... With an account and keys, you will be able to run the code on your side. Is that helps?
    – Igor O
    Nov 22 at 3:02






  • 1




    No, that doesn't help. Figure out what evt.target is, ensure it's what you expect, figure out why remoteDescription is null, narrow this problem down.
    – Brad
    Nov 22 at 3:04


















  • You're going to have to try to narrow this down a bit... we don't have any way of reproducing this issue.
    – Brad
    Nov 22 at 2:32










  • You are right @Brad, actually, I'm a bit lost, I'm not sure how to summarize this... With an account and keys, you will be able to run the code on your side. Is that helps?
    – Igor O
    Nov 22 at 3:02






  • 1




    No, that doesn't help. Figure out what evt.target is, ensure it's what you expect, figure out why remoteDescription is null, narrow this problem down.
    – Brad
    Nov 22 at 3:04
















You're going to have to try to narrow this down a bit... we don't have any way of reproducing this issue.
– Brad
Nov 22 at 2:32




You're going to have to try to narrow this down a bit... we don't have any way of reproducing this issue.
– Brad
Nov 22 at 2:32












You are right @Brad, actually, I'm a bit lost, I'm not sure how to summarize this... With an account and keys, you will be able to run the code on your side. Is that helps?
– Igor O
Nov 22 at 3:02




You are right @Brad, actually, I'm a bit lost, I'm not sure how to summarize this... With an account and keys, you will be able to run the code on your side. Is that helps?
– Igor O
Nov 22 at 3:02




1




1




No, that doesn't help. Figure out what evt.target is, ensure it's what you expect, figure out why remoteDescription is null, narrow this problem down.
– Brad
Nov 22 at 3:04




No, that doesn't help. Figure out what evt.target is, ensure it's what you expect, figure out why remoteDescription is null, narrow this problem down.
– Brad
Nov 22 at 3:04

















active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53422849%2fxirsys-webrtc-cant-find-sdp-object%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53422849%2fxirsys-webrtc-cant-find-sdp-object%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

Calculate evaluation metrics using cross_val_predict sklearn

Insert data from modal to MySQL (multiple modal on website)