Xirsys WebRTC can't find sdp object
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
javascript php webrtc xirsys
add a comment |
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
javascript php webrtc xirsys
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 '18 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 '18 at 3:02
1
No, that doesn't help. Figure out whatevt.target
is, ensure it's what you expect, figure out whyremoteDescription
is null, narrow this problem down.
– Brad
Nov 22 '18 at 3:04
add a comment |
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
javascript php webrtc xirsys
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
javascript php webrtc xirsys
javascript php webrtc xirsys
edited Nov 22 '18 at 2:28
Igor O
asked Nov 22 '18 at 1:54
Igor OIgor 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 '18 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 '18 at 3:02
1
No, that doesn't help. Figure out whatevt.target
is, ensure it's what you expect, figure out whyremoteDescription
is null, narrow this problem down.
– Brad
Nov 22 '18 at 3:04
add a comment |
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 '18 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 '18 at 3:02
1
No, that doesn't help. Figure out whatevt.target
is, ensure it's what you expect, figure out whyremoteDescription
is null, narrow this problem down.
– Brad
Nov 22 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 at 3:04
add a comment |
0
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',
autoActivateHeartbeat: false,
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 '18 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 '18 at 3:02
1
No, that doesn't help. Figure out what
evt.target
is, ensure it's what you expect, figure out whyremoteDescription
is null, narrow this problem down.– Brad
Nov 22 '18 at 3:04