Browse Source

Merge pull request #120 from peers/buffered-send

Buffered send implementation to get around Chrome buffer limits.
Michelle Bu 11 years ago
parent
commit
88e0caf1a9
3 changed files with 101 additions and 11 deletions
  1. 51 6
      dist/peer.js
  2. 0 0
      dist/peer.min.js
  3. 50 5
      lib/dataconnection.js

+ 51 - 6
dist/peer.js

@@ -1758,6 +1758,11 @@ function DataConnection(peer, provider, options) {
   this.serialization = this.options.serialization;
   this.reliable = this.options.reliable;
 
+  // Data channel buffering.
+  this._buffer = [];
+  this._buffering = false;
+  this.bufferSize = 0;
+
   // For storing large data.
   this._chunkedData = {};
 
@@ -1775,7 +1780,7 @@ DataConnection._idPrefix = 'dc_';
 
 /** Called by the Negotiator when the DataChannel is ready. */
 DataConnection.prototype.initialize = function(dc) {
-  this._dc = dc;
+  this._dc = this.dataChannel = dc;
   this._configureDataChannel();
 }
 
@@ -1887,7 +1892,7 @@ DataConnection.prototype.send = function(data, chunked) {
   }
   var self = this;
   if (this.serialization === 'json') {
-    this._dc.send(JSON.stringify(data));
+    this._bufferedSend(JSON.stringify(data));
   } else if ('binary-utf8'.indexOf(this.serialization) !== -1) {
     var utf8 = (this.serialization === 'binary-utf8');
     var blob = util.pack(data, utf8);
@@ -1900,19 +1905,59 @@ DataConnection.prototype.send = function(data, chunked) {
     // DataChannel currently only supports strings.
     if (!util.supports.sctp) {
       util.blobToBinaryString(blob, function(str) {
-        self._dc.send(str);
+        self._bufferedSend(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);
+        self._bufferedSend(ab);
       });
     } else {
-      this._dc.send(blob);
+      this._bufferedSend(blob);
     }
   } else {
-    this._dc.send(data);
+    this._bufferedSend(data);
+  }
+}
+
+DataConnection.prototype._bufferedSend = function(msg) {
+  if (this._buffering || !this._trySend(msg)) {
+    this._buffer.push(msg);
+    this.bufferSize = this._buffer.length;
+  }
+}
+
+// Returns true if the send succeeds.
+DataConnection.prototype._trySend = function(msg) {
+  try {
+    this._dc.send(msg);
+  } catch (e) {
+    this._buffering = true;
+
+    var self = this;
+    setTimeout(function() {
+      // Try again.
+      self._buffering = false;
+      self._tryBuffer();
+    }, 100);
+    return false;
+  }
+  return true;
+}
+
+// Try to send the first message in the buffer.
+DataConnection.prototype._tryBuffer = function() {
+  if (this._buffer.length === 0) {
+    return;
+  }
+
+  var msg = this._buffer[0];
+
+  if (this._trySend(msg)) {
+    this._buffer.shift();
+    this.bufferSize = this._buffer.length;
+    this._tryBuffer();
   }
 }
 

File diff suppressed because it is too large
+ 0 - 0
dist/peer.min.js


+ 50 - 5
lib/dataconnection.js

@@ -24,6 +24,11 @@ function DataConnection(peer, provider, options) {
   this.serialization = this.options.serialization;
   this.reliable = this.options.reliable;
 
+  // Data channel buffering.
+  this._buffer = [];
+  this._buffering = false;
+  this.bufferSize = 0;
+
   // For storing large data.
   this._chunkedData = {};
 
@@ -153,7 +158,7 @@ DataConnection.prototype.send = function(data, chunked) {
   }
   var self = this;
   if (this.serialization === 'json') {
-    this._dc.send(JSON.stringify(data));
+    this._bufferedSend(JSON.stringify(data));
   } else if ('binary-utf8'.indexOf(this.serialization) !== -1) {
     var utf8 = (this.serialization === 'binary-utf8');
     var blob = util.pack(data, utf8);
@@ -166,19 +171,59 @@ DataConnection.prototype.send = function(data, chunked) {
     // DataChannel currently only supports strings.
     if (!util.supports.sctp) {
       util.blobToBinaryString(blob, function(str) {
-        self._dc.send(str);
+        self._bufferedSend(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);
+        self._bufferedSend(ab);
       });
     } else {
-      this._dc.send(blob);
+      this._bufferedSend(blob);
     }
   } else {
-    this._dc.send(data);
+    this._bufferedSend(data);
+  }
+}
+
+DataConnection.prototype._bufferedSend = function(msg) {
+  if (this._buffering || !this._trySend(msg)) {
+    this._buffer.push(msg);
+    this.bufferSize = this._buffer.length;
+  }
+}
+
+// Returns true if the send succeeds.
+DataConnection.prototype._trySend = function(msg) {
+  try {
+    this._dc.send(msg);
+  } catch (e) {
+    this._buffering = true;
+
+    var self = this;
+    setTimeout(function() {
+      // Try again.
+      self._buffering = false;
+      self._tryBuffer();
+    }, 100);
+    return false;
+  }
+  return true;
+}
+
+// Try to send the first message in the buffer.
+DataConnection.prototype._tryBuffer = function() {
+  if (this._buffer.length === 0) {
+    return;
+  }
+
+  var msg = this._buffer[0];
+
+  if (this._trySend(msg)) {
+    this._buffer.shift();
+    this.bufferSize = this._buffer.length;
+    this._tryBuffer();
   }
 }
 

Some files were not shown because too many files changed in this diff