ericz 11 жил өмнө
parent
commit
f1f4b23571

+ 3 - 3
changelog.md

@@ -1,17 +1,17 @@
 # PeerJS Changelog
 
-## Version 0.3.3 (2 Nov 2013)
+## Version 0.3.3 beta (2 Nov 2013)
 * Fix exceptions when peer emits errors upon creation
 * Remove extra commas
 
-## Version 0.3.2 (25 Oct 2013)
+## Version 0.3.2 beta (25 Oct 2013)
 * Use SCTP in Chrome 31+.
 * Work around Chrome 31+ tab crash. The crashes were due to Chrome's lack of support for the `maxRetransmits` parameter for modifying SDP.
 * Fix exceptions in Chrome 29 and below.
 * DataChannels are unreliable by default in Chrome 30 and below. In setting
   reliable to `true`, the reliable shim is used only in Chrome 30 and below.
 
-## Version 0.3.1 (19 Oct 2013)
+## Version 0.3.1 beta (19 Oct 2013)
 * Updated docs and examples for TURN server usage
 * Fixed global variable leak
 * DataConnections now have reliable: false by default. This will switch to on when reliable: true works in more browsers

+ 95 - 18
dist/peer.js

@@ -1043,11 +1043,14 @@ exports.RTCSessionDescription = window.mozRTCSessionDescription || window.RTCSes
 exports.RTCPeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.RTCPeerConnection;
 exports.RTCIceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate;
 var defaultConfig = {'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }]};
+var dataCount = 1;
+
 var util = {
   noop: function() {},
 
   CLOUD_HOST: '0.peerjs.com',
   CLOUD_PORT: 9000,
+  chunkedMTU: 120000, // 120KB
 
   // Logging logic
   logLevel: 0,
@@ -1126,8 +1129,8 @@ var util = {
     var data = true;
     var audioVideo = true;
 
-    var binary = false;
-    var reliable = false;
+    var binaryBlob = false;
+    var sctp = false;
     var onnegotiationneeded = !!window.webkitRTCPeerConnection;
 
     var pc, dc;
@@ -1150,7 +1153,7 @@ var util = {
       // Binary test
       try {
         dc.binaryType = 'blob';
-        binary = true;
+        binaryBlob = true;
       } catch (e) {
       }
 
@@ -1160,7 +1163,7 @@ var util = {
       var reliablePC = new RTCPeerConnection(defaultConfig, {});
       try {
         var reliableDC = reliablePC.createDataChannel('_PEERJSRELIABLETEST', {});
-        reliable = reliableDC.reliable;
+        sctp = reliableDC.reliable;
       } catch (e) {
       }
       reliablePC.close();
@@ -1197,8 +1200,10 @@ var util = {
     return {
       audioVideo: audioVideo,
       data: data,
-      binary: binary,
-      reliable: reliable,
+      binaryBlob: binaryBlob,
+      binary: sctp, // deprecated; sctp implies binary support.
+      reliable: sctp, // deprecated; sctp implies reliable data.
+      sctp: sctp,
       onnegotiationneeded: onnegotiationneeded
     };
   }()),
@@ -1286,6 +1291,33 @@ var util = {
   }(this)),
 
   // Binary stuff
+
+  // chunks a blob.
+  chunk: function(bl) {
+    var chunks = [];
+    var size = bl.size;
+    var start = index = 0;
+    var total = Math.ceil(size / util.chunkedMTU);
+    while (start < size) {
+      var end = Math.min(size, start + util.chunkedMTU);
+      var b = bl.slice(start, end);
+
+      var chunk = {
+        __peerData: dataCount,
+        n: index,
+        data: b,
+        total: total
+      };
+
+      chunks.push(chunk);
+
+      start = end;
+      index += 1;
+    }
+    dataCount += 1;
+    return chunks;
+  },
+
   blobToArrayBuffer: function(blob, cb){
     var fr = new FileReader();
     fr.onload = function(evt) {
@@ -1726,6 +1758,9 @@ function DataConnection(peer, provider, options) {
   this.serialization = this.options.serialization;
   this.reliable = this.options.reliable;
 
+  // For storing large data.
+  this._chunkedData = {};
+
   Negotiator.startConnection(
     this,
     this.options._payload || {
@@ -1746,8 +1781,7 @@ DataConnection.prototype.initialize = function(dc) {
 
 DataConnection.prototype._configureDataChannel = function() {
   var self = this;
-  if (util.supports.binary) {
-    // Webkit doesn't support binary yet
+  if (util.supports.sctp) {
     this._dc.binaryType = 'arraybuffer';
   }
   this._dc.onopen = function() {
@@ -1757,7 +1791,7 @@ DataConnection.prototype._configureDataChannel = function() {
   }
 
   // Use the Reliable shim for non Firefox browsers
-  if (!util.supports.reliable && this.reliable) {
+  if (!util.supports.sctp && this.reliable) {
     this._reliable = new Reliable(this._dc, util.debug);
   }
 
@@ -1799,6 +1833,29 @@ DataConnection.prototype._handleDataMessage = function(e) {
   } else if (this.serialization === 'json') {
     data = JSON.parse(data);
   }
+
+  // Check if we've chunked--if so, piece things back together.
+  // We're guaranteed that this isn't 0.
+  if (data.__peerData) {
+    var id = data.__peerData;
+    var chunkInfo = this._chunkedData[id] || {data: [], count: 0, total: data.total};
+
+    chunkInfo.data[data.n] = data.data;
+    chunkInfo.count += 1;
+
+    if (chunkInfo.total === chunkInfo.count) {
+      // We've received all the chunks--time to construct the complete data.
+      data = new Blob(chunkInfo.data);
+      this._handleDataMessage({data: data});
+
+      // We can also just delete the chunks now.
+      delete this._chunkedData[id];
+      return;
+    }
+
+    this._chunkedData[id] = chunkInfo;
+  }
+
   this.emit('data', data);
 }
 
@@ -1817,7 +1874,7 @@ DataConnection.prototype.close = function() {
 }
 
 /** Allows user to send data. */
-DataConnection.prototype.send = function(data) {
+DataConnection.prototype.send = function(data, chunked) {
   if (!this.open) {
     this.emit('error', new Error('Connection is not open. You should listen for the `open` event before sending messages.'));
     return;
@@ -1834,11 +1891,23 @@ DataConnection.prototype.send = function(data) {
   } else if ('binary-utf8'.indexOf(this.serialization) !== -1) {
     var utf8 = (this.serialization === 'binary-utf8');
     var blob = util.pack(data, utf8);
+
+    if (!chunked && blob.size > util.chunkedMTU) {
+      this._sendChunks(blob);
+      return;
+    }
+
     // DataChannel currently only supports strings.
-    if (!util.supports.binary) {
-      util.blobToBinaryString(blob, function(str){
+    if (!util.supports.sctp) {
+      util.blobToBinaryString(blob, function(str) {
         self._dc.send(str);
       });
+    } else if (!util.supports.binaryBlob) {
+      // We only do this if we really need to (e.g. blobs are not supported),
+      // because this conversion is costly.
+      util.blobToArrayBuffer(blob, function(ab) {
+        self._dc.send(ab);
+      });
     } else {
       this._dc.send(blob);
     }
@@ -1847,6 +1916,14 @@ DataConnection.prototype.send = function(data) {
   }
 }
 
+DataConnection.prototype._sendChunks = function(blob) {
+  var blobs = util.chunk(blob);
+  for (var i = 0, ii = blobs.length; i < ii; i += 1) {
+    var blob = blobs[i];
+    this.send(blob, true);
+  }
+}
+
 DataConnection.prototype.handleMessage = function(message) {
   var payload = message.payload;
 
@@ -1984,12 +2061,12 @@ Negotiator.startConnection = function(connection, options) {
       var config = {};
       // Dropping reliable:false support, since it seems to be crashing
       // Chrome.
-      /*if (util.supports.reliable && !options.reliable) {
+      /*if (util.supports.sctp && !options.reliable) {
         // If we have canonical reliable support...
         config = {maxRetransmits: 0};
       }*/
       // Fallback to ensure older browsers don't crash.
-      if (!util.supports.reliable) {
+      if (!util.supports.sctp) {
         config = {reliable: options.reliable};
       }
       var dc = pc.createDataChannel(connection.label, config);
@@ -2055,7 +2132,7 @@ Negotiator._startPeerConnection = function(connection) {
   var id = Negotiator._idPrefix + util.randomToken();
   var optional = {};
 
-  if (connection.type === 'data' && !util.supports.reliable) {
+  if (connection.type === 'data' && !util.supports.sctp) {
     optional = {optional: [{RtpDataChannels: true}]};
   } else if (connection.type === 'media') {
     // Interop req for chrome.
@@ -2156,7 +2233,7 @@ Negotiator._makeOffer = function(connection) {
   pc.createOffer(function(offer) {
     util.log('Created offer.');
 
-    if (!util.supports.reliable && connection.type === 'data' && connection.reliable) {
+    if (!util.supports.sctp && connection.type === 'data' && connection.reliable) {
       offer.sdp = Reliable.higherBandwidthSDP(offer.sdp);
     }
 
@@ -2172,7 +2249,7 @@ Negotiator._makeOffer = function(connection) {
           serialization: connection.serialization,
           metadata: connection.metadata,
           connectionId: connection.id,
-          sctp: util.supports.reliable
+          sctp: util.supports.sctp
         },
         dst: connection.peer
       });
@@ -2192,7 +2269,7 @@ Negotiator._makeAnswer = function(connection) {
   pc.createAnswer(function(answer) {
     util.log('Created answer.');
 
-    if (!util.supports.reliable && connection.type === 'data' && connection.reliable) {
+    if (!util.supports.sctp && connection.type === 'data' && connection.reliable) {
       answer.sdp = Reliable.higherBandwidthSDP(answer.sdp);
     }
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/peer.min.js


+ 1 - 1
examples/chat.html

@@ -7,7 +7,7 @@
 
 <link href="fancy.css" rel="stylesheet" type="text/css">
 
-<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script> 
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
 <script type="text/javascript" src="http://cdn.peerjs.com/0.3/peer.min.js"></script>
 <script>
 // Connect to PeerJS, have server assign an ID instead of providing one

+ 1 - 1
examples/videochat/index.html

@@ -3,7 +3,7 @@
   <title>PeerJS - Video chat example</title>
   <link rel="stylesheet" href="style.css">
   <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
-  <script type="text/javascript" src="http://cdn.peerjs.com/0.3/peer.min.js"></script>
+  <script type="text/javascript" src="/dist/peer.js"></script>
   <script>
 
     // Compatibility shim

+ 51 - 6
lib/dataconnection.js

@@ -24,6 +24,9 @@ function DataConnection(peer, provider, options) {
   this.serialization = this.options.serialization;
   this.reliable = this.options.reliable;
 
+  // For storing large data.
+  this._chunkedData = {};
+
   Negotiator.startConnection(
     this,
     this.options._payload || {
@@ -44,8 +47,7 @@ DataConnection.prototype.initialize = function(dc) {
 
 DataConnection.prototype._configureDataChannel = function() {
   var self = this;
-  if (util.supports.binary) {
-    // Webkit doesn't support binary yet
+  if (util.supports.sctp) {
     this._dc.binaryType = 'arraybuffer';
   }
   this._dc.onopen = function() {
@@ -55,7 +57,7 @@ DataConnection.prototype._configureDataChannel = function() {
   }
 
   // Use the Reliable shim for non Firefox browsers
-  if (!util.supports.reliable && this.reliable) {
+  if (!util.supports.sctp && this.reliable) {
     this._reliable = new Reliable(this._dc, util.debug);
   }
 
@@ -97,6 +99,29 @@ DataConnection.prototype._handleDataMessage = function(e) {
   } else if (this.serialization === 'json') {
     data = JSON.parse(data);
   }
+
+  // Check if we've chunked--if so, piece things back together.
+  // We're guaranteed that this isn't 0.
+  if (data.__peerData) {
+    var id = data.__peerData;
+    var chunkInfo = this._chunkedData[id] || {data: [], count: 0, total: data.total};
+
+    chunkInfo.data[data.n] = data.data;
+    chunkInfo.count += 1;
+
+    if (chunkInfo.total === chunkInfo.count) {
+      // We've received all the chunks--time to construct the complete data.
+      data = new Blob(chunkInfo.data);
+      this._handleDataMessage({data: data});
+
+      // We can also just delete the chunks now.
+      delete this._chunkedData[id];
+      return;
+    }
+
+    this._chunkedData[id] = chunkInfo;
+  }
+
   this.emit('data', data);
 }
 
@@ -115,7 +140,7 @@ DataConnection.prototype.close = function() {
 }
 
 /** Allows user to send data. */
-DataConnection.prototype.send = function(data) {
+DataConnection.prototype.send = function(data, chunked) {
   if (!this.open) {
     this.emit('error', new Error('Connection is not open. You should listen for the `open` event before sending messages.'));
     return;
@@ -132,11 +157,23 @@ DataConnection.prototype.send = function(data) {
   } else if ('binary-utf8'.indexOf(this.serialization) !== -1) {
     var utf8 = (this.serialization === 'binary-utf8');
     var blob = util.pack(data, utf8);
+
+    if (!chunked && blob.size > util.chunkedMTU) {
+      this._sendChunks(blob);
+      return;
+    }
+
     // DataChannel currently only supports strings.
-    if (!util.supports.binary) {
-      util.blobToBinaryString(blob, function(str){
+    if (!util.supports.sctp) {
+      util.blobToBinaryString(blob, function(str) {
         self._dc.send(str);
       });
+    } else if (!util.supports.binaryBlob) {
+      // We only do this if we really need to (e.g. blobs are not supported),
+      // because this conversion is costly.
+      util.blobToArrayBuffer(blob, function(ab) {
+        self._dc.send(ab);
+      });
     } else {
       this._dc.send(blob);
     }
@@ -145,6 +182,14 @@ DataConnection.prototype.send = function(data) {
   }
 }
 
+DataConnection.prototype._sendChunks = function(blob) {
+  var blobs = util.chunk(blob);
+  for (var i = 0, ii = blobs.length; i < ii; i += 1) {
+    var blob = blobs[i];
+    this.send(blob, true);
+  }
+}
+
 DataConnection.prototype.handleMessage = function(message) {
   var payload = message.payload;
 

+ 6 - 6
lib/negotiator.js

@@ -30,12 +30,12 @@ Negotiator.startConnection = function(connection, options) {
       var config = {};
       // Dropping reliable:false support, since it seems to be crashing
       // Chrome.
-      /*if (util.supports.reliable && !options.reliable) {
+      /*if (util.supports.sctp && !options.reliable) {
         // If we have canonical reliable support...
         config = {maxRetransmits: 0};
       }*/
       // Fallback to ensure older browsers don't crash.
-      if (!util.supports.reliable) {
+      if (!util.supports.sctp) {
         config = {reliable: options.reliable};
       }
       var dc = pc.createDataChannel(connection.label, config);
@@ -101,7 +101,7 @@ Negotiator._startPeerConnection = function(connection) {
   var id = Negotiator._idPrefix + util.randomToken();
   var optional = {};
 
-  if (connection.type === 'data' && !util.supports.reliable) {
+  if (connection.type === 'data' && !util.supports.sctp) {
     optional = {optional: [{RtpDataChannels: true}]};
   } else if (connection.type === 'media') {
     // Interop req for chrome.
@@ -202,7 +202,7 @@ Negotiator._makeOffer = function(connection) {
   pc.createOffer(function(offer) {
     util.log('Created offer.');
 
-    if (!util.supports.reliable && connection.type === 'data' && connection.reliable) {
+    if (!util.supports.sctp && connection.type === 'data' && connection.reliable) {
       offer.sdp = Reliable.higherBandwidthSDP(offer.sdp);
     }
 
@@ -218,7 +218,7 @@ Negotiator._makeOffer = function(connection) {
           serialization: connection.serialization,
           metadata: connection.metadata,
           connectionId: connection.id,
-          sctp: util.supports.reliable
+          sctp: util.supports.sctp
         },
         dst: connection.peer
       });
@@ -238,7 +238,7 @@ Negotiator._makeAnswer = function(connection) {
   pc.createAnswer(function(answer) {
     util.log('Created answer.');
 
-    if (!util.supports.reliable && connection.type === 'data' && connection.reliable) {
+    if (!util.supports.sctp && connection.type === 'data' && connection.reliable) {
       answer.sdp = Reliable.higherBandwidthSDP(answer.sdp);
     }
 

+ 38 - 6
lib/util.js

@@ -1,9 +1,12 @@
 var defaultConfig = {'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }]};
+var dataCount = 1;
+
 var util = {
   noop: function() {},
 
   CLOUD_HOST: '0.peerjs.com',
   CLOUD_PORT: 9000,
+  chunkedMTU: 120000, // 120KB
 
   // Logging logic
   logLevel: 0,
@@ -82,8 +85,8 @@ var util = {
     var data = true;
     var audioVideo = true;
 
-    var binary = false;
-    var reliable = false;
+    var binaryBlob = false;
+    var sctp = false;
     var onnegotiationneeded = !!window.webkitRTCPeerConnection;
 
     var pc, dc;
@@ -106,7 +109,7 @@ var util = {
       // Binary test
       try {
         dc.binaryType = 'blob';
-        binary = true;
+        binaryBlob = true;
       } catch (e) {
       }
 
@@ -116,7 +119,7 @@ var util = {
       var reliablePC = new RTCPeerConnection(defaultConfig, {});
       try {
         var reliableDC = reliablePC.createDataChannel('_PEERJSRELIABLETEST', {});
-        reliable = reliableDC.reliable;
+        sctp = reliableDC.reliable;
       } catch (e) {
       }
       reliablePC.close();
@@ -153,8 +156,10 @@ var util = {
     return {
       audioVideo: audioVideo,
       data: data,
-      binary: binary,
-      reliable: reliable,
+      binaryBlob: binaryBlob,
+      binary: sctp, // deprecated; sctp implies binary support.
+      reliable: sctp, // deprecated; sctp implies reliable data.
+      sctp: sctp,
       onnegotiationneeded: onnegotiationneeded
     };
   }()),
@@ -242,6 +247,33 @@ var util = {
   }(this)),
 
   // Binary stuff
+
+  // chunks a blob.
+  chunk: function(bl) {
+    var chunks = [];
+    var size = bl.size;
+    var start = index = 0;
+    var total = Math.ceil(size / util.chunkedMTU);
+    while (start < size) {
+      var end = Math.min(size, start + util.chunkedMTU);
+      var b = bl.slice(start, end);
+
+      var chunk = {
+        __peerData: dataCount,
+        n: index,
+        data: b,
+        total: total
+      };
+
+      chunks.push(chunk);
+
+      start = end;
+      index += 1;
+    }
+    dataCount += 1;
+    return chunks;
+  },
+
   blobToArrayBuffer: function(blob, cb){
     var fr = new FileReader();
     fr.onload = function(evt) {

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно