Răsfoiți Sursa

Dumb reconnection/disconnection

Michelle Bu 11 ani în urmă
părinte
comite
a035f0bb51
3 a modificat fișierele cu 62 adăugiri și 29 ștergeri
  1. 5 5
      lib/negotiator.js
  2. 42 18
      lib/peer.js
  3. 15 6
      lib/socket.js

+ 5 - 5
lib/negotiator.js

@@ -223,11 +223,11 @@ Negotiator._makeOffer = function(connection) {
         dst: connection.peer
       });
     }, function(err) {
-      connection.provider.emit('error', err);
+      connection.provider.emitError('webrtc', err);
       util.log('Failed to setLocalDescription, ', err);
     });
   }, function(err) {
-    connection.provider.emit('error', err);
+    connection.provider.emitError('webrtc', err);
     util.log('Failed to createOffer, ', err);
   }, connection.options.constraints);
 }
@@ -255,11 +255,11 @@ Negotiator._makeAnswer = function(connection) {
         dst: connection.peer
       });
     }, function(err) {
-      connection.provider.emit('error', err);
+      connection.provider.emitError('webrtc', err);
       util.log('Failed to setLocalDescription, ', err);
     });
   }, function(err) {
-    connection.provider.emit('error', err);
+    connection.provider.emitError('webrtc', err);
     util.log('Failed to create answer, ', err);
   });
 }
@@ -277,7 +277,7 @@ Negotiator.handleSDP = function(type, connection, sdp) {
       Negotiator._makeAnswer(connection);
     }
   }, function(err) {
-    connection.provider.emit('error', err);
+    connection.provider.emitError('webrtc', err);
     util.log('Failed to setRemoteDescription, ', err);
   });
 }

+ 42 - 18
lib/peer.js

@@ -75,7 +75,7 @@ function Peer(id, options) {
 
   // States.
   this.destroyed = false; // Connections have been killed
-  this.disconnected = false; // Connection to PeerServer killed manually but P2P connections still active
+  this.disconnected = false; // Connection to PeerServer killed but P2P connections still active
   this.open = false; // Sockets and such are not yet open.
   //
 
@@ -84,8 +84,21 @@ function Peer(id, options) {
   this._lostMessages = {}; // src => [list of messages]
   //
 
-  // Initialize the 'socket' (which is actually a mix of XHR streaming and
-  // websockets.)
+  // Start the server connection
+  this._initializeServerConnection();
+  if (id) {
+    this._initialize(id);
+  } else {
+    this._retrieveId();
+  }
+  //
+};
+
+util.inherits(Peer, EventEmitter);
+
+// Initialize the 'socket' (which is actually a mix of XHR streaming and
+// websockets.)
+Peer.prototype._initializeServerConnection = function() {
   var self = this;
   this.socket = new Socket(this.options.secure, this.options.host, this.options.port, this.options.path, this.options.key);
   this.socket.on('message', function(data) {
@@ -99,19 +112,22 @@ function Peer(id, options) {
       self._abort('socket-closed', 'Underlying socket is already closed.');
     }
   });
-  //
+};
 
-  // Start the connections
-  if (id) {
-    this._initialize(id);
+Peer.prototype.reconnect = function() {
+  if (this.disconnected && !this.destroyed) {
+    this._initializeServerConnection();
+    this._initialize(this._lastServerId);
+  } else if (this.destroyed) {
+    throw new Error('This peer cannot reconnect to the server. It has already been destroyed.');
+  } else if (!this.disconnected && !this.open) {
+    // Do nothing. We're still connecting the first time.
+    util.error('In a hurry? We\'re still trying to make the initial connection!');
   } else {
-    this._retrieveId();
+    throw new Error('Peer ' + this.id + ' cannot reconnect because it is not disconnected from the server!');
   }
-  //
 };
 
-util.inherits(Peer, EventEmitter);
-
 /** Get a unique ID from the server via XHR. */
 Peer.prototype._retrieveId = function(cb) {
   var self = this;
@@ -149,7 +165,6 @@ Peer.prototype._retrieveId = function(cb) {
 
 /** Initialize a connection with the server. */
 Peer.prototype._initialize = function(id) {
-  var self = this;
   this.id = id;
   this.socket.start(this.id, this.options.token);
 }
@@ -182,7 +197,7 @@ Peer.prototype._handleMessage = function(message) {
       break;
 
     case 'EXPIRE': // The offer sent to a peer has expired without response.
-      this.emit('error', new Error('Could not connect to peer ' + peer));
+      this.emitError('peer-unavailable', 'Could not connect to peer ' + peer);
       break;
     case 'OFFER': // we should consider switching this to CALL/CONNECT, but this is the least breaking option.
       var connectionId = payload.connectionId;
@@ -273,7 +288,7 @@ Peer.prototype.connect = function(peer, options) {
     util.warn('You cannot connect to a new Peer because you called '
         + '.disconnect() on this Peer and ended your connection with the'
         + ' server. You can create a new Peer to reconnect.');
-    this.emit('error', new Error('Cannot connect to new Peer after disconnecting from server.'));
+    this.emitError('disconnected', 'Cannot connect to new Peer after disconnecting from server.');
     return;
   }
   var connection = new DataConnection(peer, this, options);
@@ -290,7 +305,7 @@ Peer.prototype.call = function(peer, stream, options) {
     util.warn('You cannot connect to a new Peer because you called '
         + '.disconnect() on this Peer and ended your connection with the'
         + ' server. You can create a new Peer to reconnect.');
-    this.emit('error', new Error('Cannot connect to new Peer after disconnecting from server.'));
+    this.emitError('disconnected', 'Cannot connect to new Peer after disconnecting from server.');
     return;
   }
   if (!stream) {
@@ -335,10 +350,17 @@ Peer.prototype._delayedAbort = function(type, message) {
 
 /** Destroys the Peer and emits an error message. */
 Peer.prototype._abort = function(type, message) {
-  util.error('Aborting. Error:', message);
-  var err = new Error(message);
+  util.error('Aborting!');
+  this.emitError(type, message);
+};
+
+/** Emits a typed error message. */
+Peer.prototype.emitError = function(type, err) {
+  util.error('Error:', err);
+  if (typeof err === 'string') {
+    err = new Error(err);
+  }
   err.type = type;
-  this.destroy();
   this.emit('error', err);
 };
 
@@ -391,6 +413,8 @@ Peer.prototype.disconnect = function() {
       if (self.socket) {
         self.socket.close();
       }
+      self.emit('disconnected', self.id);
+      self._lastServerId = self.id;
       self.id = null;
     }
   });

+ 15 - 6
lib/socket.js

@@ -25,7 +25,7 @@ Socket.prototype.start = function(id, token) {
   this.id = id;
 
   this._httpUrl += '/' + id + '/' + token;
-  this._wsUrl += '&id='+id+'&token='+token;
+  this._wsUrl += '&id=' + id + '&token=' + token;
 
   this._startXhrStream();
   this._startWebSocket();
@@ -43,14 +43,18 @@ Socket.prototype._startWebSocket = function(id) {
   this._socket = new WebSocket(this._wsUrl);
 
   this._socket.onmessage = function(event) {
-    var data;
     try {
-      data = JSON.parse(event.data);
+      var data = JSON.parse(event.data);
+      self.emit('message', data);
     } catch(e) {
       util.log('Invalid server message', event.data);
       return;
     }
-    self.emit('message', data);
+  };
+
+  this._socket.onclose = function(event) {
+    util.log('Socket closed.');
+    self.disconnect();
   };
 
   // Take care of the queue of connections if necessary and make sure Peer knows
@@ -80,9 +84,14 @@ Socket.prototype._startXhrStream = function(n) {
       if (this.readyState == 2 && this.old) {
         this.old.abort();
         delete this.old;
-      }
-      if (this.readyState > 2 && this.status == 200 && this.responseText) {
+      } else if (this.readyState > 2 && this.status === 200 && this.responseText) {
         self._handleStream(this);
+      } else if (this.status !== 200) {
+        // If we get a different status code, likely something went wrong.
+        // Stop streaming.
+        clearTimeout(self._timeout);
+        self._error('network', 'Cannot connect to server.')
+        self.disconnect();
       }
     };
     this._http.send(null);