Browse Source

Add message pool to avoid XHR race condition

Michelle Bu 12 years ago
parent
commit
beef057f21
3 changed files with 60 additions and 14 deletions
  1. 30 7
      dist/peer.js
  2. 0 0
      dist/peer.min.js
  3. 30 7
      lib/peer.js

+ 30 - 7
dist/peer.js

@@ -1309,6 +1309,7 @@ function Peer(id, options) {
 
 
   // References
   // References
   this.connections = {}; // DataConnections for this peer.
   this.connections = {}; // DataConnections for this peer.
+  this._lostMessages = {}; // src => [list of messages]
   //
   //
 
 
   // Initialize the 'socket' (which is actually a mix of XHR streaming and
   // Initialize the 'socket' (which is actually a mix of XHR streaming and
@@ -1415,15 +1416,15 @@ Peer.prototype._handleMessage = function(message) {
       } else {
       } else {
         // Create a new connection.
         // Create a new connection.
         if (payload.type === 'call') {
         if (payload.type === 'call') {
-          var call = new MediaConnection(peer, this, {
+          var connection = new MediaConnection(peer, this, {
             connectionId: connectionId,
             connectionId: connectionId,
-            _payload: payload, // A regular *Connection would have no payload.
+            _payload: payload,
             metadata: payload.metadata,
             metadata: payload.metadata,
           });
           });
-          this._addConnection(peer, call);
-          this.emit('call', call);
+          this._addConnection(peer, connection);
+          this.emit('call', connection);
         } else if (payload.type === 'data') {
         } else if (payload.type === 'data') {
-          var connection = new DataConnection(peer, this, {
+          connection = new DataConnection(peer, this, {
             connectionId: connectionId,
             connectionId: connectionId,
             _payload: payload,
             _payload: payload,
             metadata: payload.metadata,
             metadata: payload.metadata,
@@ -1435,13 +1436,22 @@ Peer.prototype._handleMessage = function(message) {
           this.emit('connection', connection);
           this.emit('connection', connection);
         } else {
         } else {
           util.warn('Received malformed connection type:', payload.type);
           util.warn('Received malformed connection type:', payload.type);
+          return;
+        }
+        // Find messages.
+        var messages = this._lostMessages[connection.id];
+        if (messages) {
+          for (var i = 0, ii = messages.length; i < ii; i += 1) {
+            connection.handleMessage(messages[i]);
+          }
+          delete this._lostMessages[connection.id];
         }
         }
       }
       }
       break;
       break;
     default:
     default:
       // TODO: if out of order, must queue.
       // TODO: if out of order, must queue.
       if (!payload) {
       if (!payload) {
-        util.warn('You received a malformed message from ' + peer);
+        util.warn('You received a malformed message from ' + peer + ' of type ' + type);
         return;
         return;
       }
       }
 
 
@@ -1452,12 +1462,25 @@ Peer.prototype._handleMessage = function(message) {
         // Pass it on.
         // Pass it on.
         connection.handleMessage(message);
         connection.handleMessage(message);
       } else {
       } else {
-        util.warn('You aborted your connection to ' + peer + ' before it opened.');
+        this._storeMessage(message);
       }
       }
       break;
       break;
   }
   }
 }
 }
 
 
+/** Stores messages without a connection, to be claimed later. */
+Peer.prototype._storeMessage = function(message) {
+  var connectionId = message.payload.connectionId;
+  if (!connectionId) {
+    util.warn('You received an unrecognized message:', message);
+  }
+
+  if (!this._lostMessages[connectionId]) {
+    this._lostMessages[connectionId] = [];
+  }
+  this._lostMessages[connectionId].push(message);
+}
+
 /**
 /**
  * Returns a DataConnection to the specified peer. See documentation for a
  * Returns a DataConnection to the specified peer. See documentation for a
  * complete list of options.
  * complete list of options.

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


+ 30 - 7
lib/peer.js

@@ -72,6 +72,7 @@ function Peer(id, options) {
 
 
   // References
   // References
   this.connections = {}; // DataConnections for this peer.
   this.connections = {}; // DataConnections for this peer.
+  this._lostMessages = {}; // src => [list of messages]
   //
   //
 
 
   // Initialize the 'socket' (which is actually a mix of XHR streaming and
   // Initialize the 'socket' (which is actually a mix of XHR streaming and
@@ -178,15 +179,15 @@ Peer.prototype._handleMessage = function(message) {
       } else {
       } else {
         // Create a new connection.
         // Create a new connection.
         if (payload.type === 'call') {
         if (payload.type === 'call') {
-          var call = new MediaConnection(peer, this, {
+          var connection = new MediaConnection(peer, this, {
             connectionId: connectionId,
             connectionId: connectionId,
-            _payload: payload, // A regular *Connection would have no payload.
+            _payload: payload,
             metadata: payload.metadata,
             metadata: payload.metadata,
           });
           });
-          this._addConnection(peer, call);
-          this.emit('call', call);
+          this._addConnection(peer, connection);
+          this.emit('call', connection);
         } else if (payload.type === 'data') {
         } else if (payload.type === 'data') {
-          var connection = new DataConnection(peer, this, {
+          connection = new DataConnection(peer, this, {
             connectionId: connectionId,
             connectionId: connectionId,
             _payload: payload,
             _payload: payload,
             metadata: payload.metadata,
             metadata: payload.metadata,
@@ -198,13 +199,22 @@ Peer.prototype._handleMessage = function(message) {
           this.emit('connection', connection);
           this.emit('connection', connection);
         } else {
         } else {
           util.warn('Received malformed connection type:', payload.type);
           util.warn('Received malformed connection type:', payload.type);
+          return;
+        }
+        // Find messages.
+        var messages = this._lostMessages[connection.id];
+        if (messages) {
+          for (var i = 0, ii = messages.length; i < ii; i += 1) {
+            connection.handleMessage(messages[i]);
+          }
+          delete this._lostMessages[connection.id];
         }
         }
       }
       }
       break;
       break;
     default:
     default:
       // TODO: if out of order, must queue.
       // TODO: if out of order, must queue.
       if (!payload) {
       if (!payload) {
-        util.warn('You received a malformed message from ' + peer);
+        util.warn('You received a malformed message from ' + peer + ' of type ' + type);
         return;
         return;
       }
       }
 
 
@@ -215,12 +225,25 @@ Peer.prototype._handleMessage = function(message) {
         // Pass it on.
         // Pass it on.
         connection.handleMessage(message);
         connection.handleMessage(message);
       } else {
       } else {
-        util.warn('You aborted your connection to ' + peer + ' before it opened.');
+        this._storeMessage(message);
       }
       }
       break;
       break;
   }
   }
 }
 }
 
 
+/** Stores messages without a connection, to be claimed later. */
+Peer.prototype._storeMessage = function(message) {
+  var connectionId = message.payload.connectionId;
+  if (!connectionId) {
+    util.warn('You received an unrecognized message:', message);
+  }
+
+  if (!this._lostMessages[connectionId]) {
+    this._lostMessages[connectionId] = [];
+  }
+  this._lostMessages[connectionId].push(message);
+}
+
 /**
 /**
  * Returns a DataConnection to the specified peer. See documentation for a
  * Returns a DataConnection to the specified peer. See documentation for a
  * complete list of options.
  * complete list of options.

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