瀏覽代碼

Chunked large messages

Michelle Bu 11 年之前
父節點
當前提交
5041437ffb
共有 5 個文件被更改,包括 142 次插入4 次删除
  1. 70 1
      dist/peer.js
  2. 0 0
      dist/peer.min.js
  3. 2 2
      examples/chat.html
  4. 40 1
      lib/dataconnection.js
  5. 30 0
      lib/util.js

+ 70 - 1
dist/peer.js

@@ -1038,11 +1038,15 @@ 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 MTU = 120000; // 120KB
+var dataCount = 1;
+
 var util = {
   noop: function() {},
 
   CLOUD_HOST: '0.peerjs.com',
   CLOUD_PORT: 9000,
+  MTU: MTU,
 
   // Logging logic
   logLevel: 0,
@@ -1283,6 +1287,32 @@ var util = {
   }(this)),
 
   // Binary stuff
+
+  // chunks a blob.
+  chunk: function(bl) {
+    var chunks = [];
+    var size = bl.size;
+    var start = index = 0;
+    while (start < size) {
+      var end = Math.min(size, start + MTU);
+      var b = bl.slice(start, end);
+
+      var chunk = {
+        __peerData: dataCount,
+        n: index,
+        data: b,
+        end: size === end ? index + 1 : null
+      };
+
+      chunks.push(chunk);
+
+      start = end;
+      index += 1;
+    }
+    dataCount += 1;
+    return chunks;
+  },
+
   blobToArrayBuffer: function(blob, cb){
     var fr = new FileReader();
     fr.onload = function(evt) {
@@ -1722,6 +1752,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 || {
@@ -1794,6 +1827,28 @@ 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) {
+    // Since we're doing this over SCTP, we're guaranteed that the messages will
+    // arrive in order.
+    var id = data.__peerData;
+    var chunkInfo = this._chunkedData[id] || {data: [], count: 0};
+
+    chunkInfo['data'][data.n] = data.data;
+    chunkInfo['end'] = chunkInfo['end'] || data.end;
+    chunkInfo['count'] += 1;
+
+    if (chunkInfo['end'] === chunkInfo['count']) {
+      data = new Blob(chunkInfo['data']);
+      this._handleDataMessage({data: data});
+      return;
+    }
+
+    this._chunkedData[id] = chunkInfo;
+  }
+
   this.emit('data', data);
 }
 
@@ -1812,7 +1867,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;
@@ -1829,6 +1884,12 @@ 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.MTU) {
+      this._sendChunks(blob);
+      return;
+    }
+
     // DataChannel currently only supports strings.
     if (!util.supports.sctp) {
       util.blobToBinaryString(blob, function(str) {
@@ -1848,6 +1909,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;
 

文件差異過大導致無法顯示
+ 0 - 0
dist/peer.min.js


+ 2 - 2
examples/chat.html

@@ -7,8 +7,8 @@
 
 <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://cdn.peerjs.com/0.3/peer.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="../dist/peer.js"></script>
 <script>
 // Connect to PeerJS, have server assign an ID instead of providing one
 // Showing off some of the configs available with PeerJS :).

+ 40 - 1
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 || {
@@ -96,6 +99,28 @@ 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) {
+    // Since we're doing this over SCTP, we're guaranteed that the messages will
+    // arrive in order.
+    var id = data.__peerData;
+    var chunkInfo = this._chunkedData[id] || {data: [], count: 0};
+
+    chunkInfo['data'][data.n] = data.data;
+    chunkInfo['end'] = chunkInfo['end'] || data.end;
+    chunkInfo['count'] += 1;
+
+    if (chunkInfo['end'] === chunkInfo['count']) {
+      data = new Blob(chunkInfo['data']);
+      this._handleDataMessage({data: data});
+      return;
+    }
+
+    this._chunkedData[id] = chunkInfo;
+  }
+
   this.emit('data', data);
 }
 
@@ -114,7 +139,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;
@@ -131,6 +156,12 @@ 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.MTU) {
+      this._sendChunks(blob);
+      return;
+    }
+
     // DataChannel currently only supports strings.
     if (!util.supports.sctp) {
       util.blobToBinaryString(blob, function(str) {
@@ -150,6 +181,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;
 

+ 30 - 0
lib/util.js

@@ -1,9 +1,13 @@
 var defaultConfig = {'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }]};
+var MTU = 120000; // 120KB
+var dataCount = 1;
+
 var util = {
   noop: function() {},
 
   CLOUD_HOST: '0.peerjs.com',
   CLOUD_PORT: 9000,
+  MTU: MTU,
 
   // Logging logic
   logLevel: 0,
@@ -244,6 +248,32 @@ var util = {
   }(this)),
 
   // Binary stuff
+
+  // chunks a blob.
+  chunk: function(bl) {
+    var chunks = [];
+    var size = bl.size;
+    var start = index = 0;
+    while (start < size) {
+      var end = Math.min(size, start + MTU);
+      var b = bl.slice(start, end);
+
+      var chunk = {
+        __peerData: dataCount,
+        n: index,
+        data: b,
+        end: size === end ? index + 1 : null
+      };
+
+      chunks.push(chunk);
+
+      start = end;
+      index += 1;
+    }
+    dataCount += 1;
+    return chunks;
+  },
+
   blobToArrayBuffer: function(blob, cb){
     var fr = new FileReader();
     fr.onload = function(evt) {

部分文件因文件數量過多而無法顯示