Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to start a basic WebRTC data channel?

How to start a basic WebRTC data channel?

This is what I have so far, but it doesn't even seem to try and connect. Im sure I am just missing something basic.

var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.msRTCPeerConnection;

var peerConnection = new RTCPeerConnection({
    iceServers: [
        {url: 'stun:stun1.l.google.com:19302'},
        {url: 'stun:stun2.l.google.com:19302'},
        {url: 'stun:stun3.l.google.com:19302'},
        {url: 'stun:stun4.l.google.com:19302'},
    ]
});
peerConnection.ondatachannel  = function () {
    console.log('peerConnection.ondatachannel');
};
peerConnection.onicecandidate = function () {
    console.log('peerConnection.onicecandidate');
};

var dataChannel = peerConnection.createDataChannel('myLabel', {
});

dataChannel.onerror = function (error) {
    console.log('dataChannel.onerror');
};

dataChannel.onmessage = function (event) {
    console.log('dataChannel.onmessage');
};

dataChannel.onopen = function () {
    console.log('dataChannel.onopen');
    dataChannel.send('Hello World!');
};

dataChannel.onclose = function () {
    console.log('dataChannel.onclose');
};
console.log(peerConnection, dataChannel);
like image 738
Petah Avatar asked Jul 30 '15 08:07

Petah


1 Answers

WebRTC assumes you have a way to signal (send an offer-string to, and receive an answer-string from) whomever you wish to contact. Without some server, how will you do that?

To illustrate, here's some code that does everything but that (works in Firefox and Chrome 45):

var config = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }]};
var dc, pc = new RTCPeerConnection(config);
pc.ondatachannel = e => {
  dc = e.channel;
  dc.onopen = e => (log("Chat!"), chat.select());
  dc.onmessage = e => log(e.data);
}

function createOffer() {
  button.disabled = true;
  pc.ondatachannel({ channel: pc.createDataChannel("chat") });
  pc.createOffer().then(d => pc.setLocalDescription(d)).catch(failed);
  pc.onicecandidate = e => {
    if (e.candidate) return;
    offer.value = pc.localDescription.sdp;
    offer.select();
    answer.placeholder = "Paste answer here";
  };
};

offer.onkeypress = e => {
  if (e.keyCode != 13 || pc.signalingState != "stable") return;
  button.disabled = offer.disabled = true;
  var obj = { type:"offer", sdp:offer.value };
  pc.setRemoteDescription(new RTCSessionDescription(obj))
  .then(() => pc.createAnswer()).then(d => pc.setLocalDescription(d))
  .catch(failed);
  pc.onicecandidate = e => {
    if (e.candidate) return;
    answer.focus();
    answer.value = pc.localDescription.sdp;
    answer.select();
  };
};

answer.onkeypress = e => {
  if (e.keyCode != 13 || pc.signalingState != "have-local-offer") return;
  answer.disabled = true;
  var obj = { type:"answer", sdp:answer.value };
  pc.setRemoteDescription(new RTCSessionDescription(obj)).catch(failed);
};

chat.onkeypress = e => {
  if (e.keyCode != 13) return;
  dc.send(chat.value);
  log(chat.value);
  chat.value = "";
};

var log = msg => div.innerHTML += "<p>" + msg + "</p>";
var failed = e => log(e + ", line " + e.lineNumber);
<script src="https://rawgit.com/webrtc/adapter/master/adapter.js"></script>
<button id="button" onclick="createOffer()">Offer:</button>
<textarea id="offer" placeholder="Paste offer here"></textarea><br>
Answer: <textarea id="answer"></textarea><br><div id="div"></div>
Chat: <input id="chat"></input><br>

Open this page in a second tab, and you can chat from one tab to the other (or to a different machine around the world). What stinks is that you must get the offer there yourself:

  • Press the Offer button in Tab A (only) and wait 1-20 seconds till you see the offer-text,
  • copy-paste the offer-text from Tab A to Tab B, and hit Enter
  • copy-paste the answer-text that appears from Tab B to Tab A, and hit Enter.

You should now be able to chat between tabs, without a server.

As you can see, this is a sub-par experience, which is why you need some basic websocket server to pass offer/answer (as well as trickle ice candidates if you want connecting to happen fast) between A and B, to get things started. Once you have a connection, you can use data-channels for this, with a little extra work.

like image 152
jib Avatar answered Nov 13 '22 00:11

jib