ericz 12 жил өмнө
parent
commit
3cac542df7

+ 1 - 0
bin/build.js

@@ -46,6 +46,7 @@ var base = [
   , 'adapter.js' 
   , 'peer.js'
   , 'dataconnection.js'
+  , 'mediaconnection.js'
   , 'connectionmanager.js'
   , 'socket.js'
 

+ 174 - 18
dist/peer.js

@@ -1316,7 +1316,7 @@ Peer.prototype._handleServerJSONMessage = function(message) {
         this.connections[peer] = manager.connections;
       }
       manager.update(options.labels);
-      manager.handleSDP(payload.sdp, message.type);
+      manager.handleSDP(payload.sdp, message.type, payload.call);
       break;
     case 'EXPIRE':
       if (manager) {
@@ -1363,6 +1363,10 @@ Peer.prototype._attachManagerListeners = function(manager) {
   manager.on('connection', function(connection) {
     self.emit('connection', connection);
   });
+  // Handle receiving a call
+  manager.on('call', function(call) {
+    self.emit('call', call);
+  });
   // Handle a connection closing.
   manager.on('close', function() {
     if (!!self.managers[manager.peer]) {
@@ -1401,7 +1405,7 @@ Peer.prototype._cleanup = function() {
 
 /** Exposed connect function for users. Will try to connect later if user
  * is waiting for an ID. */
-Peer.prototype.connect = function(peer, options) {
+Peer.prototype._getManager = function(peer, options) {
   if (this.disconnected) {
     var err = new Error('This Peer has been disconnected from the server and can no longer make connections.');
     err.type = 'server-disconnected';
@@ -1417,7 +1421,7 @@ Peer.prototype.connect = function(peer, options) {
 
   // Firefox currently does not support multiplexing once an offer is made.
   if (util.browserisms === 'Firefox' && !!manager && manager.firefoxSingular) {
-    var err = new Error('Firefox currently does not support multiplexing after a DataChannel has already been established');
+    var err = new Error('Firefox currently does not support renegotiating connections');
     err.type = 'firefoxism';
     this.emit('error', err);
     return;
@@ -1430,13 +1434,30 @@ Peer.prototype.connect = function(peer, options) {
     this.connections[peer] = manager.connections;
   }
 
-  var connection = manager.connect(options);
+  return manager;
+};
 
-  if (!this.id) {
-    this._queued.push(manager);
+Peer.prototype.connect = function(peer, options) {
+  var manager = this._getManager(peer, options);
+  if (manager) {
+    var connection = manager.connect(options);
+    if (!this.id) {
+      this._queued.push(manager);
+    }
+    return connection;
   }
-  return connection;
-};
+}
+
+Peer.prototype.call = function(peer, stream, options) {
+  var manager = this._getManager(peer, options);
+  if (manager) {
+    var connection = manager.call(stream, options);
+    if (!this.id) {
+      this._queued.push(manager);
+    }
+    return connection;
+  }
+}
 
 /**
  * Return the peer id or null, if there's no id at the moment.
@@ -1668,6 +1689,63 @@ DataConnection.prototype.getLabel = function() {
 DataConnection.prototype.getPeer = function() {
   return this.peer;
 };
+/**
+ * Wraps the streaming interface between two Peers.
+ */
+function MediaConnection(peer, localStream, options) {
+  if (!(this instanceof MediaConnection)) return new MediaConnection(peer, localStream, options);
+  EventEmitter.call(this);
+
+  options = util.extend({
+   
+  }, options);
+
+  this.localStream = localStream;
+  this.peer = peer;
+  
+};
+
+util.inherits(MediaConnection, EventEmitter);
+
+MediaConnection.prototype.receiveStream = function(stream) {
+  console.log('receiving stream', stream);
+  this.remoteStream = stream;
+  this.emit('stream', stream);
+  //this._cleanup();
+};
+
+MediaConnection.prototype.answer = function(stream) {
+  this.localStream = stream;
+  this.emit('answer', stream);
+  //this._cleanup();
+};
+
+MediaConnection.prototype.answered = function(stream) {
+  this.emit('stream', this.remoteStream);
+  //this._cleanup();
+};
+
+
+/**
+ * Exposed functionality for users.
+ */
+
+/** Allows user to close connection. */
+MediaConnection.prototype.close = function() {
+  //this._cleanup();
+};
+
+
+
+/**
+ * Gets the brokering ID of the peer that you are connected with.
+ * Note that this ID may be out of date if the peer has disconnected from the
+ *  server, so it's not recommended that you use this ID to identify this
+ *  connection.
+ */
+MediaConnection.prototype.getPeer = function() {
+  return this.peer;
+};
 /**
  * Manages DataConnections between its peer and one other peer.
  * Internally, manages PeerConnection.
@@ -1730,6 +1808,9 @@ ConnectionManager.prototype.initialize = function(id, socket) {
 
   // Listen for data channel.
   this._setupDataChannel();
+  
+  // Listen for remote streams.
+  this._setupStreamListener();
 
   this.initialize = function() { };
 };
@@ -1742,11 +1823,21 @@ ConnectionManager.prototype._startPeerConnection = function() {
 
 /** Add DataChannels to all queued DataConnections. */
 ConnectionManager.prototype._processQueue = function() {
-  var conn = this._queued.pop();
-  if (!!conn) {
-    var reliable = util.browserisms === 'Firefox' ? conn.reliable : false;
-    conn.addDC(this.pc.createDataChannel(conn.label, { reliable: reliable }));
+console.log(this._queued);
+  for (var i = 0; i < this._queued.length; i++) {
+    var conn = this._queued[i];
+    if (conn.constructor == MediaConnection) {
+      console.log('adding', conn.localStream);
+      this.pc.addStream(conn.localStream);
+    } else if (conn.constructor = DataConnection) {
+      var reliable = util.browserisms === 'Firefox' ? conn.reliable : false;
+      conn.addDC(this.pc.createDataChannel(conn.label, { reliable: reliable }));
+    }
+  }
+  if (util.browserisms === 'Firefox' && this._queued.length > 0) {
+    this._makeOffer();
   }
+  this._queued = [];
 };
 
 /** Set up ICE candidate handlers. */
@@ -1807,6 +1898,21 @@ ConnectionManager.prototype._setupDataChannel = function() {
   };
 };
 
+/** Set up remote stream listener. */
+ConnectionManager.prototype._setupStreamListener = function() {
+  var self = this;
+  util.log('Listening for remote stream');
+  this.pc.onaddstream = function(evt) {
+    util.log('Received remote stream');
+    var stream = evt.stream;
+    if (!!self._call) {
+      self._call.receiveStream(stream);
+      
+    }
+  };
+};
+
+
 /** Send an offer. */
 ConnectionManager.prototype._makeOffer = function() {
   var self = this;
@@ -1816,7 +1922,7 @@ ConnectionManager.prototype._makeOffer = function() {
     self.firefoxSingular = true;
 
     if (util.browserisms === 'Webkit') {
-      offer.sdp = Reliable.higherBandwidthSDP(offer.sdp);
+      //offer.sdp = Reliable.higherBandwidthSDP(offer.sdp);
     }
 
     self.pc.setLocalDescription(offer, function() {
@@ -1826,7 +1932,8 @@ ConnectionManager.prototype._makeOffer = function() {
         payload: {
           sdp: offer,
           config: self._options.config,
-          labels: self.labels
+          labels: self.labels,
+          call: !!self._call
         },
         dst: self.peer
       });
@@ -1846,7 +1953,7 @@ ConnectionManager.prototype._makeAnswer = function() {
     util.log('Created answer.');
 
     if (util.browserisms === 'Webkit') {
-      answer.sdp = Reliable.higherBandwidthSDP(answer.sdp);
+      //answer.sdp = Reliable.higherBandwidthSDP(answer.sdp);
     }
 
     self.pc.setLocalDescription(answer, function() {
@@ -1905,14 +2012,33 @@ ConnectionManager.prototype._attachConnectionListeners = function(connection) {
 };
 
 /** Handle an SDP. */
-ConnectionManager.prototype.handleSDP = function(sdp, type) {
+ConnectionManager.prototype.handleSDP = function(sdp, type, call) {
   sdp = new RTCSessionDescription(sdp);
 
   var self = this;
   this.pc.setRemoteDescription(sdp, function() {
     util.log('Set remoteDescription: ' + type);
     if (type === 'OFFER') {
-      self._makeAnswer();
+      if (call && !self._call) {
+        window.g = self.pc;
+        self._call = new MediaConnection(self.peer);
+        self._call.on('answer', function(stream){
+          if (stream) {
+            self.pc.addStream(stream);
+          }
+          self._makeAnswer();
+          util.setZeroTimeout(function(){
+            // Add remote streams
+            self._call.receiveStream(self.pc.getRemoteStreams()[0]);
+          });
+        });
+        self.emit('call', self._call);
+      } else {
+        self._makeAnswer();
+      }
+    } else {
+      // Got answer from remote
+      self._lock = false;
     }
   }, function(err) {
     self.emit('error', err);
@@ -1955,7 +2081,7 @@ ConnectionManager.prototype.connect = function(options) {
   if (!this.open) {
     return;
   }
-
+console.log('trying to connect');
   options = util.extend({
     label: 'peerjs',
     reliable: (util.browserisms === 'Firefox')
@@ -1982,6 +2108,7 @@ ConnectionManager.prototype.connect = function(options) {
   this.connections[options.label] = connection;
 
   if (!this.pc || this._lock) {
+    console.log('qing', this._lock);
     this._queued.push(connection);
   }
 
@@ -1989,6 +2116,35 @@ ConnectionManager.prototype.connect = function(options) {
   return connection;
 };
 
+ConnectionManager.prototype.call = function(stream, options) {
+  if (!this.open) {
+    return;
+  }
+
+  options = util.extend({
+    
+  }, options);
+
+  if (!!this.pc && !this._lock) {
+    this.pc.addStream(stream);
+    if (util.browserisms === 'Firefox') {
+      this._makeOffer();
+    }
+  }
+  
+  var connection = new MediaConnection(this.peer, stream, options);
+  this._call = connection;
+  
+  if (!this.pc || this._lock) {
+    this._queued.push(connection);
+  }
+
+  this._lock = true;
+  
+  
+  return connection;
+};
+
 /** Updates label:[serialization, reliable, metadata] pairs from offer. */
 ConnectionManager.prototype.update = function(updates) {
   var labels = Object.keys(updates);

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/peer.min.js


+ 88 - 10
lib/connectionmanager.js

@@ -60,6 +60,9 @@ ConnectionManager.prototype.initialize = function(id, socket) {
 
   // Listen for data channel.
   this._setupDataChannel();
+  
+  // Listen for remote streams.
+  this._setupStreamListener();
 
   this.initialize = function() { };
 };
@@ -72,11 +75,21 @@ ConnectionManager.prototype._startPeerConnection = function() {
 
 /** Add DataChannels to all queued DataConnections. */
 ConnectionManager.prototype._processQueue = function() {
-  var conn = this._queued.pop();
-  if (!!conn) {
-    var reliable = util.browserisms === 'Firefox' ? conn.reliable : false;
-    conn.addDC(this.pc.createDataChannel(conn.label, { reliable: reliable }));
+console.log(this._queued);
+  for (var i = 0; i < this._queued.length; i++) {
+    var conn = this._queued[i];
+    if (conn.constructor == MediaConnection) {
+      console.log('adding', conn.localStream);
+      this.pc.addStream(conn.localStream);
+    } else if (conn.constructor = DataConnection) {
+      var reliable = util.browserisms === 'Firefox' ? conn.reliable : false;
+      conn.addDC(this.pc.createDataChannel(conn.label, { reliable: reliable }));
+    }
+  }
+  if (util.browserisms === 'Firefox' && this._queued.length > 0) {
+    this._makeOffer();
   }
+  this._queued = [];
 };
 
 /** Set up ICE candidate handlers. */
@@ -137,6 +150,21 @@ ConnectionManager.prototype._setupDataChannel = function() {
   };
 };
 
+/** Set up remote stream listener. */
+ConnectionManager.prototype._setupStreamListener = function() {
+  var self = this;
+  util.log('Listening for remote stream');
+  this.pc.onaddstream = function(evt) {
+    util.log('Received remote stream');
+    var stream = evt.stream;
+    if (!!self._call) {
+      self._call.receiveStream(stream);
+      
+    }
+  };
+};
+
+
 /** Send an offer. */
 ConnectionManager.prototype._makeOffer = function() {
   var self = this;
@@ -146,7 +174,7 @@ ConnectionManager.prototype._makeOffer = function() {
     self.firefoxSingular = true;
 
     if (util.browserisms === 'Webkit') {
-      offer.sdp = Reliable.higherBandwidthSDP(offer.sdp);
+      //offer.sdp = Reliable.higherBandwidthSDP(offer.sdp);
     }
 
     self.pc.setLocalDescription(offer, function() {
@@ -156,7 +184,8 @@ ConnectionManager.prototype._makeOffer = function() {
         payload: {
           sdp: offer,
           config: self._options.config,
-          labels: self.labels
+          labels: self.labels,
+          call: !!self._call
         },
         dst: self.peer
       });
@@ -176,7 +205,7 @@ ConnectionManager.prototype._makeAnswer = function() {
     util.log('Created answer.');
 
     if (util.browserisms === 'Webkit') {
-      answer.sdp = Reliable.higherBandwidthSDP(answer.sdp);
+      //answer.sdp = Reliable.higherBandwidthSDP(answer.sdp);
     }
 
     self.pc.setLocalDescription(answer, function() {
@@ -235,14 +264,33 @@ ConnectionManager.prototype._attachConnectionListeners = function(connection) {
 };
 
 /** Handle an SDP. */
-ConnectionManager.prototype.handleSDP = function(sdp, type) {
+ConnectionManager.prototype.handleSDP = function(sdp, type, call) {
   sdp = new RTCSessionDescription(sdp);
 
   var self = this;
   this.pc.setRemoteDescription(sdp, function() {
     util.log('Set remoteDescription: ' + type);
     if (type === 'OFFER') {
-      self._makeAnswer();
+      if (call && !self._call) {
+        window.g = self.pc;
+        self._call = new MediaConnection(self.peer);
+        self._call.on('answer', function(stream){
+          if (stream) {
+            self.pc.addStream(stream);
+          }
+          self._makeAnswer();
+          util.setZeroTimeout(function(){
+            // Add remote streams
+            self._call.receiveStream(self.pc.getRemoteStreams()[0]);
+          });
+        });
+        self.emit('call', self._call);
+      } else {
+        self._makeAnswer();
+      }
+    } else {
+      // Got answer from remote
+      self._lock = false;
     }
   }, function(err) {
     self.emit('error', err);
@@ -285,7 +333,7 @@ ConnectionManager.prototype.connect = function(options) {
   if (!this.open) {
     return;
   }
-
+console.log('trying to connect');
   options = util.extend({
     label: 'peerjs',
     reliable: (util.browserisms === 'Firefox')
@@ -312,6 +360,7 @@ ConnectionManager.prototype.connect = function(options) {
   this.connections[options.label] = connection;
 
   if (!this.pc || this._lock) {
+    console.log('qing', this._lock);
     this._queued.push(connection);
   }
 
@@ -319,6 +368,35 @@ ConnectionManager.prototype.connect = function(options) {
   return connection;
 };
 
+ConnectionManager.prototype.call = function(stream, options) {
+  if (!this.open) {
+    return;
+  }
+
+  options = util.extend({
+    
+  }, options);
+
+  if (!!this.pc && !this._lock) {
+    this.pc.addStream(stream);
+    if (util.browserisms === 'Firefox') {
+      this._makeOffer();
+    }
+  }
+  
+  var connection = new MediaConnection(this.peer, stream, options);
+  this._call = connection;
+  
+  if (!this.pc || this._lock) {
+    this._queued.push(connection);
+  }
+
+  this._lock = true;
+  
+  
+  return connection;
+};
+
 /** Updates label:[serialization, reliable, metadata] pairs from offer. */
 ConnectionManager.prototype.update = function(updates) {
   var labels = Object.keys(updates);

+ 57 - 0
lib/mediaconnection.js

@@ -0,0 +1,57 @@
+/**
+ * Wraps the streaming interface between two Peers.
+ */
+function MediaConnection(peer, localStream, options) {
+  if (!(this instanceof MediaConnection)) return new MediaConnection(peer, localStream, options);
+  EventEmitter.call(this);
+
+  options = util.extend({
+   
+  }, options);
+
+  this.localStream = localStream;
+  this.peer = peer;
+  
+};
+
+util.inherits(MediaConnection, EventEmitter);
+
+MediaConnection.prototype.receiveStream = function(stream) {
+  console.log('receiving stream', stream);
+  this.remoteStream = stream;
+  this.emit('stream', stream);
+  //this._cleanup();
+};
+
+MediaConnection.prototype.answer = function(stream) {
+  this.localStream = stream;
+  this.emit('answer', stream);
+  //this._cleanup();
+};
+
+MediaConnection.prototype.answered = function(stream) {
+  this.emit('stream', this.remoteStream);
+  //this._cleanup();
+};
+
+
+/**
+ * Exposed functionality for users.
+ */
+
+/** Allows user to close connection. */
+MediaConnection.prototype.close = function() {
+  //this._cleanup();
+};
+
+
+
+/**
+ * Gets the brokering ID of the peer that you are connected with.
+ * Note that this ID may be out of date if the peer has disconnected from the
+ *  server, so it's not recommended that you use this ID to identify this
+ *  connection.
+ */
+MediaConnection.prototype.getPeer = function() {
+  return this.peer;
+};

+ 29 - 8
lib/peer.js

@@ -160,7 +160,7 @@ Peer.prototype._handleServerJSONMessage = function(message) {
         this.connections[peer] = manager.connections;
       }
       manager.update(options.labels);
-      manager.handleSDP(payload.sdp, message.type);
+      manager.handleSDP(payload.sdp, message.type, payload.call);
       break;
     case 'EXPIRE':
       if (manager) {
@@ -207,6 +207,10 @@ Peer.prototype._attachManagerListeners = function(manager) {
   manager.on('connection', function(connection) {
     self.emit('connection', connection);
   });
+  // Handle receiving a call
+  manager.on('call', function(call) {
+    self.emit('call', call);
+  });
   // Handle a connection closing.
   manager.on('close', function() {
     if (!!self.managers[manager.peer]) {
@@ -245,7 +249,7 @@ Peer.prototype._cleanup = function() {
 
 /** Exposed connect function for users. Will try to connect later if user
  * is waiting for an ID. */
-Peer.prototype.connect = function(peer, options) {
+Peer.prototype._getManager = function(peer, options) {
   if (this.disconnected) {
     var err = new Error('This Peer has been disconnected from the server and can no longer make connections.');
     err.type = 'server-disconnected';
@@ -261,7 +265,7 @@ Peer.prototype.connect = function(peer, options) {
 
   // Firefox currently does not support multiplexing once an offer is made.
   if (util.browserisms === 'Firefox' && !!manager && manager.firefoxSingular) {
-    var err = new Error('Firefox currently does not support multiplexing after a DataChannel has already been established');
+    var err = new Error('Firefox currently does not support renegotiating connections');
     err.type = 'firefoxism';
     this.emit('error', err);
     return;
@@ -274,13 +278,30 @@ Peer.prototype.connect = function(peer, options) {
     this.connections[peer] = manager.connections;
   }
 
-  var connection = manager.connect(options);
+  return manager;
+};
 
-  if (!this.id) {
-    this._queued.push(manager);
+Peer.prototype.connect = function(peer, options) {
+  var manager = this._getManager(peer, options);
+  if (manager) {
+    var connection = manager.connect(options);
+    if (!this.id) {
+      this._queued.push(manager);
+    }
+    return connection;
   }
-  return connection;
-};
+}
+
+Peer.prototype.call = function(peer, stream, options) {
+  var manager = this._getManager(peer, options);
+  if (manager) {
+    var connection = manager.call(stream, options);
+    if (!this.id) {
+      this._queued.push(manager);
+    }
+    return connection;
+  }
+}
 
 /**
  * Return the peer id or null, if there's no id at the moment.

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно