From 8c1c6a12f748b6a1f3227e45ececcc651f5c6ce9 Mon Sep 17 00:00:00 2001 From: jbenet Date: Sun, 27 Jan 2013 09:07:19 -0800 Subject: [PATCH] DataChannel support (with fallback) This commit adds support for the WebRTC DataChannel API. This is -- of course -- preliminary. The interface in the future should not automatically connect to all peers (neither data channel or video/audio streams). --- lib/webrtc.io.js | 121 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 2 deletions(-) diff --git a/lib/webrtc.io.js b/lib/webrtc.io.js index 2d75490..faf3e3d 100644 --- a/lib/webrtc.io.js +++ b/lib/webrtc.io.js @@ -56,6 +56,30 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav rtc.numStreams = 0; rtc.initializedStreams = 0; + + // Reference to the data channels + rtc.dataChannels = {}; + + // PeerConnection datachannel configuration + rtc.dataChannelConfig = {optional: [ {RtpDataChannels: true} ] }; + + + // check whether data channel is supported. + rtc.checkDataChannelSupport = function() { + try { + // raises exception if createDataChannel is not supported + var pc = new PeerConnection(rtc.SERVER, rtc.dataChannelConfig); + channel = pc.createDataChannel('supportCheck', {reliable: false}); + channel.close(); + return true; + } catch(e) { + return false; + } + } + + rtc.dataChannelSupport = rtc.checkDataChannelSupport(); + + /** * Connects to the websocket server. */ @@ -150,7 +174,11 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav }; rtc.createPeerConnection = function(id) { - var pc = rtc.peerConnections[id] = new PeerConnection(rtc.SERVER); + var config = undefined; + if (rtc.dataChannelSupport) + config = rtc.dataChannelConfig; + + var pc = rtc.peerConnections[id] = new PeerConnection(rtc.SERVER, config); pc.onicecandidate = function(event) { if (event.candidate) { rtc._socket.send(JSON.stringify({ @@ -174,6 +202,14 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav // TODO: Finalize this API rtc.fire('add remote stream', event.stream, id); }; + + if (rtc.dataChannelSupport) { + pc.ondatachannel = function (evt) { + console.log('data channel connecting ' + id); + rtc.addDataChannel(id, evt.channel); + }; + }; + return pc; }; @@ -261,14 +297,95 @@ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || nav } }; - rtc.attachStream = function(stream, domId) { document.getElementById(domId).src = URL.createObjectURL(stream); }; + + rtc.createDataChannel = function(pcOrId, label) { + if (!rtc.dataChannelSupport) { + alert('webRTC data channel is not yet supported in this browser,' + + ' or you must turn on experimental flags'); + return; + } + + if (typeof(pcOrId) === 'string') { + id = pcOrId; + pc = rtc.peerConnections[pcOrId]; + } else { + pc = pcOrId; + id = undefined; + for (var key in rtc.peerConnections) { + if (rtc.peerConnections[key] === pc) + id = key; + } + } + + if (!id) + throw new Error ('attempt to createDataChannel with unknown id'); + + if (!pc || !(pc instanceof PeerConnection)) + throw new Error ('attempt to createDataChannel without peerConnection'); + + // need a label + label = label || 'fileTransfer' || String(id); + + // chrome only supports reliable false atm. + options = {reliable: false}; + + try { + console.log('createDataChannel ' + id); + channel = pc.createDataChannel(label, options); + } catch (error) { + console.log('seems that DataChannel is NOT actually supported!'); + throw error; + } + + return rtc.addDataChannel(id, channel); + } + + rtc.addDataChannel = function(id, channel) { + + channel.onopen = function() { + console.log('data stream open ' + id) + rtc.fire('data stream open', channel); + } + + channel.onclose = function(event) { + delete rtc.dataChannels[id]; + console.log('data stream close ' + id) + rtc.fire('data stream close', channel); + } + + channel.onmessage = function(message) { + console.log('data stream message ' + id); + console.log(message); + rtc.fire('data stream data', channel, message.data); + } + + channel.onerror = function(err) { + console.log('data stream error ' + id + ': ' + err); + rtc.fire('data stream error', channel, err); + } + + // track dataChannel + rtc.dataChannels[id] = channel; + return channel; + }; + + rtc.addDataChannels = function() { + if (!rtc.dataChannelSupport) + return; + + for (var connection in rtc.peerConnections) + rtc.createDataChannel(connection); + }; + + rtc.on('ready', function() { rtc.createPeerConnections(); rtc.addStreams(); + rtc.addDataChannels(); rtc.sendOffers(); });