|
@@ -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();
|
|
|
}
|
|
|
}
|
|
|
|