Created
October 27, 2012 15:17
-
-
Save luser/3965049 to your computer and use it in GitHub Desktop.
webrtc datachannel demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Simple WebRTC Data Channel Test</title> | |
</head> | |
<body> | |
<table width=100% height=100%> | |
<tr><td><h1>Simple WebRTC Data Channel Test</h1></td></tr> | |
<tr><td>(Note: this JS code is REALLY UGLY)</td></tr> | |
<tr><td><div><button id="thebutton" onClick="start();">Start!</button></div><br/></td></tr> | |
<tr><td><form id="pc1_form" action="javascript:sendit(1)"> | |
<div>pc1 says: <input id="pc1_input" type="text" value="type here" onKeyPress="return submitenter(this,event)"/> | |
<input type="submit"/></div></form></td> | |
<td><form id="pc1_blob" action="javascript:sendblob(1)"> | |
<div>pc1 sends a blob: <input id="pc1_browse" type="file"/> | |
<input type="submit"/></div></form></td></tr> | |
<tr><td><form id="pc2_form" action="javascript:sendit(2)"> | |
<div>pc2 says: <input id="pc2_input" type="text" value="type here" onKeyPress="return submitenter(this,event)"/> | |
<input type="submit"/></div></form></td> | |
<td><form id="pc2_blob" action="javascript:sendblob(2)"> | |
<div>pc2 sends a blob: <input id="pc2_browse" type="file"/> | |
<input type="submit"/></div></form></td></tr> | |
<tr><td><div id="datawindow" style=" | |
width: 100%; | |
height: 500px; | |
overflow: auto; | |
border: 1px solid red;"></div></td></tr> | |
</table> | |
<script type="application/javascript;version=1.8"> | |
let button = document.getElementById("thebutton"); | |
let text_pc1 = document.getElementById("pc1_input"); | |
let text_pc2 = document.getElementById("pc2_input"); | |
let blob_pc1 = document.getElementById("pc1_browse"); | |
let blob_pc2 = document.getElementById("pc2_browse"); | |
let datawindow = document.getElementById("datawindow"); | |
let pc1; | |
let pc2; | |
let dc1; | |
let dc2; | |
let channel1; | |
let channel2; | |
let num_channels; | |
num_channels = 0; | |
var datachannels = new Array(0); | |
let pc1_offer; | |
let pc2_answer; | |
let iter = 0; | |
let iter2 = 0; | |
function log(msg) { | |
console.log(msg); | |
let div = document.getElementById("datawindow"); | |
div.innerHTML = div.innerHTML + "<p>" + msg + "</p>"; | |
} | |
var fancy_log = function(msg,color) { | |
console.log(msg); | |
var pre = document.createElement("p"); | |
var message = '<span style="color: ' + color + ';">' + msg + '</span>'; | |
pre.style.wordWrap = "break-word"; | |
pre.innerHTML = message; | |
datawindow.appendChild(pre); // (window).* here doesn't work right | |
pre.scrollIntoView(false); | |
}; | |
function submitenter(myfield,e) | |
{ | |
var keycode; | |
if (window.event) keycode = window.event.keyCode; | |
else if (e) keycode = e.which; | |
else return true; | |
if (keycode == 13) | |
{ | |
myfield.form.submit(); | |
return false; | |
} | |
else | |
return true; | |
} | |
var sendit = function (which) { | |
iter = iter + 1; | |
//log("Sending message #" + iter + " this = " + this); | |
if (which == 1) { | |
dc1.send(text_pc1.value); | |
text_pc1.value = ""; | |
} else if (which == 2) { | |
dc2.send(text_pc2.value); | |
text_pc2.value = ""; | |
} | |
else log("Unknown send " + which); | |
}; | |
var sendblob = function (which) { | |
iter = iter + 1; | |
//log("Sending blob #" + iter + " this = " + this); | |
if (which == 1) { | |
dc1.send(blob_pc1.files[0]); | |
blob_pc1.value = ""; | |
} else if (which == 2) { | |
dc2.send(blob_pc2.files[0]); | |
blob_pc2.value = ""; | |
} | |
else log("Unknown sendblob " + which); | |
}; | |
function failed(code) { | |
log("Failure callback: " + code); | |
} | |
// pc1.createOffer finished, call pc1.setLocal | |
function step1(offer) { | |
log("pc1.createOffer success callback"); | |
pc1_offer = offer; | |
pc1.setLocalDescription(offer, step1_5, failed); | |
} | |
function step1_5() { | |
log("pc1 setLocalDescription callback"); | |
setTimeout(step2,0); | |
} | |
// pc1.setLocal finished, call pc2.setRemote | |
function step2() { | |
log("pc1 createOffer/setLocalDescription finished"); | |
pc2 = new mozRTCPeerConnection(); | |
log("pc2 created"); | |
pc2.ondatachannel = function(channel) { | |
log("pc2 onDataChannel [" +num_channels + "] = " + channel + | |
", label='" + channel.label + "'"); | |
dc2 = channel; | |
datachannels[num_channels] = channel; | |
num_channels++; | |
log("pc2 created channel " + dc2 + " binarytype = " + dc2.binaryType); | |
channel.binaryType = "blob"; | |
log("pc2 new binarytype = " + dc2.binaryType); | |
channel.onmessage = function(evt) { | |
iter2 = iter2 + 1; | |
if (evt.data instanceof Blob) { | |
fancy_log("*** pc1 sent Blob: " + evt.data + ", length=" + evt.data.size,"red"); | |
} else { | |
fancy_log("*** pc1 said: " + evt.data + ", length=" + evt.data.length,"red"); | |
} | |
}; | |
/* | |
channel.addEventListener("message",function(evt) { | |
fancy_log('*** pc1 said: ' + evt.data,"red"); | |
}, false); | |
*/ | |
channel.onopen = function() { | |
log("*** pc2 onopen fired, sending to " + channel); | |
channel.send("pc2 says Hi there!"); | |
}; | |
channel.onclose = function() { | |
log("*** pc2 onclose fired"); | |
}; | |
log("*** pc2 state:" + channel.readyState); | |
// There's a race condition with onopen; if the channel is already | |
// open it should fire after onDataChannel -- state should normally be 0 here | |
if (channel.readyState != 0) { | |
log("*** pc2 no onopen??! possible race"); | |
} | |
}; | |
log("set pc2.ondatachannel"); | |
pc2.onconnection = function() { | |
log("pc2 onconnection "); | |
//dc2 = pc2.createDataChannel(); | |
//log("pc2 created channel " + dc2); | |
}; | |
log("set pc2.onconnection"); | |
pc2.onclosedconnection = function() { | |
log("pc2 onClosedConnection "); | |
}; | |
log("set pc2.onclosedconnection"); | |
function gotMediaStream(stream) { | |
log("pc2 mozGetUserMedia callback"); | |
pc2.addStream(stream); | |
pc2.setRemoteDescription(pc1_offer, step3, failed); | |
log("pc2.setRemoteDescription finished"); | |
} | |
navigator.mozGetUserMedia({audio: true, fake: true}, | |
gotMediaStream, failed); | |
pc2.onaddstream = function(obj) { | |
log("pc2 got remote stream from pc1 " + obj.type); | |
} | |
}; | |
// pc2.setRemote finished, call pc2.createAnswer | |
function step3() { | |
log("pc2.setRemoteDescription success callback"); | |
pc2.createAnswer(step4, failed, {mandatory: {}, optional: []}, false); | |
log("pc2.createAnswer finished"); | |
} | |
// pc2.createAnswer finished, call pc2.setLocal | |
function step4(answer) { | |
log("pc2.createAnswer success callback"); | |
pc2_answer = answer; | |
pc2.setLocalDescription(answer, step5, failed); | |
log("pc2.setLocalDescription finished"); | |
} | |
// pc2.setLocal finished, call pc1.setRemote | |
function step5() { | |
log("pc2.setLocalDescription success callback"); | |
pc1.setRemoteDescription(pc2_answer, step6, failed); | |
log("pc1.setRemoteDescription finished"); | |
} | |
// pc1.setRemote finished, make a data channel | |
function step6() { | |
log("pc1.setRemoteDescription success callback"); | |
log("HIP HIP HOORAY"); | |
setTimeout(step7,2000); | |
} | |
function step7() { | |
log("about to connect data connections"); | |
pc1.connectDataConnection(5000,5001); | |
log("called pc1.connectDataConnection"); | |
pc2.connectDataConnection(5001,5000); | |
log("called pc2.connectDataConnection"); | |
} | |
function start() { | |
button.innerHTML = "Stop!"; | |
button.onclick = stop; | |
pc1 = new mozRTCPeerConnection(); | |
log("pc1 created"); | |
pc1.onaddstream = function(obj) { | |
log("pc1 got remote stream from pc2 " + obj.type); | |
} | |
log("set pc1.onaddstream"); | |
pc1.ondatachannel = function(channel) { | |
// In case pc2 opens a channel | |
log("pc1 ondatachannel [" +num_channels + "] = " + channel + | |
", label='" + channel.label + "'"); | |
datachannels[num_channels] = channel; | |
num_channels++; | |
channel.onmessage = function(evt) { | |
if (evt.data instanceof Blob) { | |
fancy_log("*** pc2 sent Blob: " + evt.data + ", length=" + evt.data.size,"blue"); | |
} else { | |
fancy_log('pc2 said: ' + evt.data + ", length=" + evt.data.length,"blue"); | |
} | |
} | |
/* | |
channel.addEventListener("message",function(evt) { | |
fancy_log('pc2 said: ' + evt.data,"blue"); | |
}, false); | |
*/ | |
channel.onopen = function() { | |
log("pc1 onopen fired for " + channel); | |
channel.send("pc1 says Hello out there..."); | |
log("pc1 state: " + channel.state); | |
} | |
channel.onclose = function() { | |
log("pc1 onclose fired"); | |
}; | |
log("pc1 state:" + channel.readyState); | |
// There's a race condition with onopen; if the channel is already | |
// open it should fire after ondatachannel -- state should normally be 0 here | |
if (channel.readyState != 0) { | |
log("*** pc1 no onopen??! possible race"); | |
} | |
}; | |
log("set pc1.ondatachannel"); | |
pc1.onconnection = function() { | |
log("pc1 onconnection "); | |
dc1 = pc1.createDataChannel("This is pc1",{}); // reliable (TCP-like) | |
// dc1 = pc1.createDataChannel("This is pc1",{outOfOrderAllowed: true, maxRetransmitNum: 0}); // unreliable (UDP-like) | |
log("pc1 created channel " + dc1 + " binarytype = " + dc1.binaryType); | |
channel = dc1; | |
channel.binaryType = "blob"; | |
log("pc1 new binarytype = " + dc1.binaryType); | |
// Since we create the datachannel, don't wait for ondatachannel! | |
channel.onmessage = function(evt) { | |
if (evt.data instanceof Blob) { | |
fancy_log("*** pc2 sent Blob: " + evt.data + ", length=" + evt.data.size,"blue"); | |
} else { | |
fancy_log('pc2 said: ' + evt.data,"blue"); | |
} | |
} | |
/* | |
// This is generally preferred to onxxx = | |
channel.addEventListener("message",function(evt) { | |
fancy_log('pc2 said: ' + evt.data,"blue"); | |
}, false); | |
*/ | |
channel.onopen = function() { | |
log("pc1 onopen fired for " + channel); | |
channel.send("pc1 says Hello..."); | |
log("pc1 state: " + channel.state); | |
} | |
channel.onclose = function() { | |
log("pc1 onclose fired"); | |
}; | |
log("pc1 state:" + channel.readyState); | |
}; | |
log("set pc1.onconnection"); | |
pc1.onclosedconnection = function() { | |
log("pc1 onclosedconnection "); | |
}; | |
log("set pc1.onclosedconnection"); | |
function gotMediaStream(stream) { | |
log("pc1 mozGetUserMedia callback"); | |
pc1.addStream(stream); | |
pc1.createOffer(step1, failed, {mandatory: {}, optional: []}); | |
log("pc1.createOffer"); | |
} | |
navigator.mozGetUserMedia({audio: true, fake: true}, | |
gotMediaStream, failed); | |
} | |
function stop() { | |
pc1.close(); | |
pc2.close(); | |
button.innerHTML = "Start!"; | |
button.onclick = start; | |
} | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment