Created
March 19, 2015 05:15
-
-
Save potch/b2e8986a621827b05a0d to your computer and use it in GitHub Desktop.
datachannels test
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
| <!doctype html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width"> | |
| </head> | |
| <body> | |
| <script> | |
| var RTCPeerConnection = typeof window !== 'undefined' && | |
| (window.mozRTCPeerConnection | |
| || window.RTCPeerConnection | |
| || window.webkitRTCPeerConnection); | |
| var RTCSessionDescription = typeof window !== 'undefined' && | |
| (window.mozRTCSessionDescription | |
| || window.RTCSessionDescription | |
| || window.webkitRTCSessionDescription); | |
| var RTCIceCandidate = typeof window !== 'undefined' && | |
| (window.mozRTCIceCandidate | |
| || window.RTCIceCandidate | |
| || window.webkitRTCIceCandidate); | |
| </script> | |
| <script> | |
| function DataChannel(opts) { | |
| opts = opts || {}; | |
| var initiator = !!opts.initiator; | |
| var negotiationNeeded = true; | |
| var iceComplete = false; | |
| var pcReady = false; | |
| var dcReady = false; | |
| var readyForCandidates = false; | |
| var candidates = []; | |
| var pc = new RTCPeerConnection({ | |
| iceServers: [{ | |
| url: 'stun:23.21.150.121', | |
| urls: 'stun:23.21.150.121' | |
| }] | |
| }, {}); | |
| var dc = null; | |
| pc.ondatachannel = function (event) { | |
| console.log(event); | |
| dc = event.channel; | |
| dc.onopen = function () { | |
| dcReady = true; | |
| tryReady(); | |
| }; | |
| } | |
| pc.oniceconnectionstatechange = function (event) { | |
| console.log('ice', pc.iceGatheringState, pc.iceConnectionState); | |
| if (pc.iceConnectionState === 'connected' || pc.iceConnectionState === 'completed') { | |
| pcReady = true; | |
| tryReady(); | |
| } | |
| }; | |
| pc.onsignalingstatechange = function (event) { | |
| console.log('signaling', pc.signalingState); | |
| }; | |
| pc.onicecandidate = function(event) { | |
| if (!event) { | |
| return; | |
| } | |
| if (event.candidate) { | |
| api.onsignal({ candidate: event.candidate }); | |
| } else { | |
| iceComplete = true; | |
| } | |
| }; | |
| if (initiator) { | |
| dc = pc.createDataChannel("test"); | |
| dc.onopen = function () { | |
| dcReady = true; | |
| tryReady(); | |
| }; | |
| pc.onnegotiationneeded = function () { | |
| if (!negotiationNeeded) { | |
| return; | |
| } | |
| negotiationNeeded = false; | |
| pc.createOffer(function(offer) { | |
| speedHack(offer); | |
| pc.setLocalDescription(new RTCSessionDescription(offer), function() { | |
| setTimeout(function () { | |
| api.onsignal(pc.localDescription || offer); | |
| }, 0); | |
| }, error); | |
| }, error); | |
| }; | |
| setTimeout(pc.onnegotiationneeded, 0); | |
| } | |
| function signal(data) { | |
| console.log('[signal]', data); | |
| if (data.sdp) { | |
| pc.setRemoteDescription(new RTCSessionDescription(data), function() { | |
| readyForCandidates = true; | |
| // Flush any buffered candidates. | |
| while (candidates.length) { | |
| pc.addIceCandidate(candidates.pop(), noop, error); | |
| } | |
| if (data.type === 'offer') { | |
| pc.createAnswer(function (answer) { | |
| speedHack(answer); | |
| pc.setLocalDescription(answer, noop, error); | |
| setTimeout(function () { | |
| api.onsignal(pc.localDescription || answer); | |
| }, 0); | |
| }, error); | |
| } | |
| }, error); | |
| } | |
| if (data.candidate) { | |
| // I don't know why I need to buffer these, but if I don't Chrome breaks. | |
| if (readyForCandidates) { | |
| pc.addIceCandidate(new RTCIceCandidate(data.candidate), noop, error); | |
| } else { | |
| candidates.push(new RTCIceCandidate(data.candidate)); | |
| } | |
| } | |
| } | |
| function tryReady() { | |
| if (pcReady && dcReady) { | |
| ready(dc); | |
| } | |
| } | |
| function noop() {} | |
| var ready, error; | |
| var readyPromise = new Promise(function (resolve, reject) { | |
| ready = resolve; | |
| error = reject; | |
| }); | |
| var api = { | |
| pc: pc, | |
| signal: signal, | |
| onsignal: noop, | |
| ready: readyPromise | |
| }; | |
| return api; | |
| } | |
| function speedHack (obj) { | |
| var s = obj.sdp.split('b=AS:30') | |
| if (s.length > 1) obj.sdp = s[0] + 'b=AS:1638400' + s[1] | |
| } | |
| </script> | |
| <script> | |
| var peer1 = new DataChannel({initiator: true}); | |
| var peer2 = new DataChannel(); | |
| peer1.onsignal = peer2.signal; | |
| peer2.onsignal = peer1.signal; | |
| Promise.all([peer1.ready, peer2.ready]).then(function(dcs) { | |
| var dc1 = dcs[0]; | |
| var dc2 = dcs[1]; | |
| console.log('all ready'); | |
| dc1.onmessage = function (e) { | |
| console.log(e); | |
| }; | |
| dc2.onmessage = function (e) { | |
| console.log(e); | |
| }; | |
| dc1.onerror = console.error.bind(console, 'peer1:'); | |
| dc2.onerror = console.error.bind(console, 'peer2:'); | |
| dc1.send('hello'); | |
| dc2.send('hey'); | |
| }).catch(console.error.bind(console)); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment