Parcourir la source

firefox basic connectivity working. #24

Michelle Bu il y a 12 ans
Parent
commit
f7314a30d5
6 fichiers modifiés avec 200 ajouts et 32 suppressions
  1. 125 19
      dist/peer.js
  2. 0 0
      dist/peer.min.js
  3. 66 7
      lib/connectionmanager.js
  4. 1 0
      lib/dataconnection.js
  5. 7 5
      lib/peer.js
  6. 1 1
      lib/util.js

+ 125 - 19
dist/peer.js

@@ -721,7 +721,7 @@ EventEmitter.prototype.emit = function(type) {
 var util = {
   
   chromeCompatible: true,
-  firefoxCompatible: false,
+  firefoxCompatible: true,
   chromeVersion: 26,
   firefoxVersion: 22,
 
@@ -1287,6 +1287,12 @@ Peer.prototype._handleServerJSONMessage = function(message) {
   var peer = message.src;
   var manager = this.managers[peer];
   var payload = message.payload;
+
+  // Check that browsers match.
+  if (!!payload && !!payload.browserisms && payload.browserisms !== util.browserisms) {
+    this._warn('incompatible-peer', 'Peer ' + self.peer + ' is on an incompatible browser. Please clean up this peer.');
+  }
+
   switch (message.type) {
     case 'OPEN':
       this._processQueue();
@@ -1341,10 +1347,11 @@ Peer.prototype._handleServerJSONMessage = function(message) {
       this._abort('invalid-key', 'API KEY "' + this._key + '" is invalid');
       break;
     case 'PORT':
-      //if (util.browserisms === 'Firefox') {
-      //  connection.handlePort(payload);
-      //  break;
-      //}
+      // Firefoxism: exchanging ports.
+      if (util.browserisms === 'Firefox' && manager) {
+        manager.handlePort(payload);
+        break;
+      }
     default:
       util.log('Unrecognized message type:', message.type);
       break;
@@ -1385,6 +1392,12 @@ Peer.prototype._abort = function(type, message) {
   this.destroy();
   this.emit('error', err);
 };
+/** Emits an error message that things may not work. */
+Peer.prototype._warn = function(type, message) {
+  var err = new Error(message);
+  err.type = type;
+  this.emit('error', err);
+};
 
 Peer.prototype._cleanup = function() {
   var self = this;
@@ -1406,15 +1419,14 @@ Peer.prototype._cleanup = function() {
  * is waiting for an ID. */
 Peer.prototype.connect = function(peer, options) {
   if (this.disconnected) {
-    var err = new Error('This Peer has been disconnected from the server and');
-    err.type = 'peer-disconnected';
-    this.emit('error', err);
+    this._warn('peer-disconnected', 'This Peer has been disconnected from the server and');
     return;
   }
 
   options = util.extend({
     config: this._options.config
   }, options);
+  options.originator = true;
 
   var manager = this.managers[peer];
   if (!manager) {
@@ -1493,6 +1505,7 @@ function DataConnection(peer, dc, options) {
 util.inherits(DataConnection, EventEmitter);
 
 DataConnection.prototype._configureDataChannel = function() {
+  util.log('Configuring DataChannel with peer ' + this.peer);
   var self = this;
   if (util.browserisms !== 'Webkit') {
     this._dc.binaryType = 'arraybuffer';
@@ -1651,25 +1664,80 @@ ConnectionManager.prototype.initialize = function(id, socket) {
     this._socket = socket;
   }
 
+  // Firefoxism where ports need to be generated.
+  if (util.browserisms === 'Firefox') {
+    this._firefoxPortSetup();
+  }
+
   // Set up PeerConnection.
   this._startPeerConnection();
 
   // Process queued DCs.
-  this._processQueue();
+  if (util.browserisms !== 'Firefox') {
+    this._processQueue();
+  }
 
   // Listen for ICE candidates.
   this._setupIce();
 
-  // Listen for negotiation needed.
-  // Chrome only **
-  this._setupNegotiationHandler();
-
   // Listen for data channel.
   this._setupDataChannel();
 
+  // Listen for negotiation needed.
+  // Chrome only--Firefox instead has to manually makeOffer.
+  if (util.browserisms !== 'Firefox') {
+    this._setupNegotiationHandler();
+  } else if (this._options.originator) {
+    this._firefoxHandlerSetup()
+    this._firefoxAdditional()
+  }
+
   this.initialize = function() { };
 };
 
+/** Firefoxism that requires a fake media stream. */
+ConnectionManager.prototype._firefoxAdditional = function() {
+  util.log('Additional media stream for Firefox.');
+  var self = this;
+  getUserMedia({ audio: true, fake: true }, function(s) {
+    self.pc.addStream(s);
+    if (self._options.originator) {
+      self._makeOffer();
+    } else {
+      self._makeAnswer();
+    }
+  }, function(err) { util.log('Could not getUserMedia'); });
+};
+
+/** Firefoxism that requires ports to be set up. */
+ConnectionManager.prototype._firefoxPortSetup = function() {
+  if (!ConnectionManager.usedPorts) {
+    ConnectionManager.usedPorts = [];
+  }
+  this._localPort = util.randomPort();
+  while (ConnectionManager.usedPorts.indexOf(this._localPort) != -1) {
+    this._localPort = util.randomPort();
+  }
+  this._remotePort = util.randomPort();
+  while (this._remotePort === this._localPort ||
+      ConnectionManager.usedPorts.indexOf(this._remotePort) != -1) {
+    this._remotePort = util.randomPort();
+  }
+  ConnectionManager.usedPorts.push(this._remotePort);
+  ConnectionManager.usedPorts.push(this._localPort);
+};
+
+/** Firefoxism that is `onconnection`. */
+ConnectionManager.prototype._firefoxHandlerSetup = function() {
+  util.log('Setup Firefox `onconnection`.');
+  var self = this;
+  this.pc.onconnection = function() {
+    util.log('FIREFOX: onconnection triggered');
+
+    self._processQueue();
+  }
+};
+
 /** Start a PC. */
 ConnectionManager.prototype._startPeerConnection = function() {
   util.log('Creating RTCPeerConnection');
@@ -1718,11 +1786,15 @@ ConnectionManager.prototype._setupDataChannel = function() {
   util.log('Listening for data channel');
   this.pc.ondatachannel = function(evt) {
     util.log('Received data channel');
-    var dc = evt.channel;
+    // Firefoxism: ondatachannel receives channel directly. NOT TO SPEC.
+    var dc = util.browserisms === 'Firefox' ? evt : evt.channel;
     var label = dc.label;
+
     // This should not be empty.
     var options = self.labels[label] || {};
     var connection  = new DataConnection(self.peer, dc, options);
+    delete self.labels[label];
+
     self._attachConnectionListeners(connection);
     self.connections[label] = connection;
     self.emit('connection', connection);
@@ -1739,6 +1811,7 @@ ConnectionManager.prototype._makeOffer = function() {
       self._socket.send({
         type: 'OFFER',
         payload: {
+          browserisms: util.browserisms,
           sdp: offer,
           config: self._options.config,
           labels: self.labels
@@ -1764,6 +1837,7 @@ ConnectionManager.prototype._makeAnswer = function() {
       self._socket.send({
         type: 'ANSWER',
         payload: {
+          browserisms: util.browserisms,
           sdp: answer
         },
         dst: self.peer
@@ -1810,19 +1884,51 @@ ConnectionManager.prototype._attachConnectionListeners = function(connection) {
   });
   connection.on('open', function() {
     self._lock = false;
-    self._processQueue();
+    if (util.browserisms !== 'Firefox') {
+      self._processQueue();
+    }
   });
 };
 
+/** Firefoxism: handle receiving a set of ports. */
+ConnectionManager.prototype.handlePort = function(ports) {
+  util.log('Received ports, calling connectDataConnection.');
+  if (!ConnectionManager.usedPorts) {
+    ConnectionManager.usedPorts = [];
+  }
+  ConnectionManager.usedPorts.push(ports.local);
+  ConnectionManager.usedPorts.push(ports.remote);
+  this.pc.connectDataConnection(ports.local, ports.remote);
+};
+
 /** Handle an SDP. */
 ConnectionManager.prototype.handleSDP = function(sdp, type) {
-  sdp = new RTCSessionDescription(sdp);
+  if (util.browserisms !== 'Firefox') {
+    // Doesn't need to happen for FF.
+    sdp = new RTCSessionDescription(sdp);
+  }
 
   var self = this;
   this.pc.setRemoteDescription(sdp, function() {
     util.log('Set remoteDescription: ' + type);
     if (type === 'OFFER') {
-      self._makeAnswer();
+      if (util.browserisms === 'Firefox') {
+        self._firefoxAdditional();
+      } else {
+        self._makeAnswer();
+      }
+    } else if (util.browserisms === 'Firefox') {
+      // Firefoxism.
+      util.log('Peer ANSWER received, connectDataConnection called.');
+      self.pc.connectDataConnection(self._localPort, self._remotePort);
+      self._socket.send({
+        type: 'PORT',
+        payload: {
+          remote: self._localPort,
+          local: self._remotePort
+        },
+        dst: self.peer
+      });
     }
   }, function(err) {
     self.emit('error', err);
@@ -1879,14 +1985,14 @@ ConnectionManager.prototype.connect = function(options) {
   this.labels[options.label] = options;
 
   var dc;
-  if (!!this.pc && !this._lock) {
+  if (!!this.pc && !this._lock && util.browserisms !== 'Firefox') {
     dc = this.pc.createDataChannel(options.label, { reliable: false });
   }
   var connection = new DataConnection(this.peer, dc, options);
   this._attachConnectionListeners(connection);
   this.connections[options.label] = connection;
 
-  if (!this.pc || this._lock) {
+  if (!this.pc || this._lock || util.browserisms === 'Firefox') {
     this._queued.push(connection);
   }
 

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
dist/peer.min.js


+ 66 - 7
lib/connectionmanager.js

@@ -45,11 +45,18 @@ ConnectionManager.prototype.initialize = function(id, socket) {
     this._socket = socket;
   }
 
+  // Firefoxism where ports need to be generated.
+  if (util.browserisms === 'Firefox') {
+    this._firefoxPortSetup();
+  }
+
   // Set up PeerConnection.
   this._startPeerConnection();
 
   // Process queued DCs.
-  this._processQueue();
+  if (util.browserisms !== 'Firefox') {
+    this._processQueue();
+  }
 
   // Listen for ICE candidates.
   this._setupIce();
@@ -62,6 +69,7 @@ ConnectionManager.prototype.initialize = function(id, socket) {
   if (util.browserisms !== 'Firefox') {
     this._setupNegotiationHandler();
   } else if (this._options.originator) {
+    this._firefoxHandlerSetup()
     this._firefoxAdditional()
   }
 
@@ -70,6 +78,7 @@ ConnectionManager.prototype.initialize = function(id, socket) {
 
 /** Firefoxism that requires a fake media stream. */
 ConnectionManager.prototype._firefoxAdditional = function() {
+  util.log('Additional media stream for Firefox.');
   var self = this;
   getUserMedia({ audio: true, fake: true }, function(s) {
     self.pc.addStream(s);
@@ -81,6 +90,35 @@ ConnectionManager.prototype._firefoxAdditional = function() {
   }, function(err) { util.log('Could not getUserMedia'); });
 };
 
+/** Firefoxism that requires ports to be set up. */
+ConnectionManager.prototype._firefoxPortSetup = function() {
+  if (!ConnectionManager.usedPorts) {
+    ConnectionManager.usedPorts = [];
+  }
+  this._localPort = util.randomPort();
+  while (ConnectionManager.usedPorts.indexOf(this._localPort) != -1) {
+    this._localPort = util.randomPort();
+  }
+  this._remotePort = util.randomPort();
+  while (this._remotePort === this._localPort ||
+      ConnectionManager.usedPorts.indexOf(this._remotePort) != -1) {
+    this._remotePort = util.randomPort();
+  }
+  ConnectionManager.usedPorts.push(this._remotePort);
+  ConnectionManager.usedPorts.push(this._localPort);
+};
+
+/** Firefoxism that is `onconnection`. */
+ConnectionManager.prototype._firefoxHandlerSetup = function() {
+  util.log('Setup Firefox `onconnection`.');
+  var self = this;
+  this.pc.onconnection = function() {
+    util.log('FIREFOX: onconnection triggered');
+
+    self._processQueue();
+  }
+};
+
 /** Start a PC. */
 ConnectionManager.prototype._startPeerConnection = function() {
   util.log('Creating RTCPeerConnection');
@@ -129,11 +167,15 @@ ConnectionManager.prototype._setupDataChannel = function() {
   util.log('Listening for data channel');
   this.pc.ondatachannel = function(evt) {
     util.log('Received data channel');
-    var dc = evt.channel;
+    // Firefoxism: ondatachannel receives channel directly. NOT TO SPEC.
+    var dc = util.browserisms === 'Firefox' ? evt : evt.channel;
     var label = dc.label;
+
     // This should not be empty.
     var options = self.labels[label] || {};
     var connection  = new DataConnection(self.peer, dc, options);
+    delete self.labels[label];
+
     self._attachConnectionListeners(connection);
     self.connections[label] = connection;
     self.emit('connection', connection);
@@ -150,6 +192,7 @@ ConnectionManager.prototype._makeOffer = function() {
       self._socket.send({
         type: 'OFFER',
         payload: {
+          browserisms: util.browserisms,
           sdp: offer,
           config: self._options.config,
           labels: self.labels
@@ -175,6 +218,7 @@ ConnectionManager.prototype._makeAnswer = function() {
       self._socket.send({
         type: 'ANSWER',
         payload: {
+          browserisms: util.browserisms,
           sdp: answer
         },
         dst: self.peer
@@ -221,10 +265,23 @@ ConnectionManager.prototype._attachConnectionListeners = function(connection) {
   });
   connection.on('open', function() {
     self._lock = false;
-    self._processQueue();
+    if (util.browserisms !== 'Firefox') {
+      self._processQueue();
+    }
   });
 };
 
+/** Firefoxism: handle receiving a set of ports. */
+ConnectionManager.prototype.handlePort = function(ports) {
+  util.log('Received ports, calling connectDataConnection.');
+  if (!ConnectionManager.usedPorts) {
+    ConnectionManager.usedPorts = [];
+  }
+  ConnectionManager.usedPorts.push(ports.local);
+  ConnectionManager.usedPorts.push(ports.remote);
+  this.pc.connectDataConnection(ports.local, ports.remote);
+};
+
 /** Handle an SDP. */
 ConnectionManager.prototype.handleSDP = function(sdp, type) {
   if (util.browserisms !== 'Firefox') {
@@ -243,13 +300,15 @@ ConnectionManager.prototype.handleSDP = function(sdp, type) {
       }
     } else if (util.browserisms === 'Firefox') {
       // Firefoxism.
-      self.pc.connectDataConnection(self.localPort, self.remotePort);
+      util.log('Peer ANSWER received, connectDataConnection called.');
+      self.pc.connectDataConnection(self._localPort, self._remotePort);
       self._socket.send({
         type: 'PORT',
         payload: {
           remote: self._localPort,
           local: self._remotePort
-        }
+        },
+        dst: self.peer
       });
     }
   }, function(err) {
@@ -307,14 +366,14 @@ ConnectionManager.prototype.connect = function(options) {
   this.labels[options.label] = options;
 
   var dc;
-  if (!!this.pc && !this._lock) {
+  if (!!this.pc && !this._lock && util.browserisms !== 'Firefox') {
     dc = this.pc.createDataChannel(options.label, { reliable: false });
   }
   var connection = new DataConnection(this.peer, dc, options);
   this._attachConnectionListeners(connection);
   this.connections[options.label] = connection;
 
-  if (!this.pc || this._lock) {
+  if (!this.pc || this._lock || util.browserisms === 'Firefox') {
     this._queued.push(connection);
   }
 

+ 1 - 0
lib/dataconnection.js

@@ -28,6 +28,7 @@ function DataConnection(peer, dc, options) {
 util.inherits(DataConnection, EventEmitter);
 
 DataConnection.prototype._configureDataChannel = function() {
+  util.log('Configuring DataChannel with peer ' + this.peer);
   var self = this;
   if (util.browserisms !== 'Webkit') {
     this._dc.binaryType = 'arraybuffer';

+ 7 - 5
lib/peer.js

@@ -115,6 +115,12 @@ Peer.prototype._handleServerJSONMessage = function(message) {
   var peer = message.src;
   var manager = this.managers[peer];
   var payload = message.payload;
+
+  // Check that browsers match.
+  if (!!payload && !!payload.browserisms && payload.browserisms !== util.browserisms) {
+    this._warn('incompatible-peer', 'Peer ' + self.peer + ' is on an incompatible browser. Please clean up this peer.');
+  }
+
   switch (message.type) {
     case 'OPEN':
       this._processQueue();
@@ -128,11 +134,6 @@ Peer.prototype._handleServerJSONMessage = function(message) {
       this._abort('unavailable-id', 'ID `'+this.id+'` is taken');
       break;
     case 'OFFER':
-      // Check that browsers match.
-      if (payload.browserisms !== util.browserisms) {
-        self._warn('incompatible-peer', 'Peer ' + self.peer + ' is on an incompatible browser.');
-        return;
-      }
       var options = {
         sdp: payload.sdp,
         labels: payload.labels,
@@ -253,6 +254,7 @@ Peer.prototype.connect = function(peer, options) {
   options = util.extend({
     config: this._options.config
   }, options);
+  options.originator = true;
 
   var manager = this.managers[peer];
   if (!manager) {

+ 1 - 1
lib/util.js

@@ -1,7 +1,7 @@
 var util = {
   
   chromeCompatible: true,
-  firefoxCompatible: false,
+  firefoxCompatible: true,
   chromeVersion: 26,
   firefoxVersion: 22,
 

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff