ソースを参照

connectionmanager fns

Michelle Bu 12 年 前
コミット
ac39e1f0d5
1 ファイル変更72 行追加18 行削除
  1. 72 18
      lib/connectionmanager.js

+ 72 - 18
lib/connectionmanager.js

@@ -4,7 +4,6 @@
  */
 function ConnectionManager(id, peer, socket, options) {
   if (!(this instanceof ConnectionManager)) return new ConnectionManager(id, peer, socket, options);
-  // TODO: need eventemitter?
   EventEmitter.call(this);
 
   options = util.extend({
@@ -22,9 +21,8 @@ function ConnectionManager(id, peer, socket, options) {
   this.pc = null;
 
   // Mapping labels to metadata and serialization.
-  this.metadatas = {};
-  this.serializations = {};
-  this.reliables = {};
+  // label => { metadata: ..., serialization: ..., reliable: ...}
+  this.labels = {}
 
   // DataConnections on this PC.
   this.connections = {};
@@ -62,13 +60,13 @@ ConnectionManager.prototype.initialize = function(id, socket) {
   this.initialize = function() { };
 };
 
-// Start a PC.
+/** Start a PC. */
 ConnectionManager.prototype._startPeerConnection = function() {
   util.log('Creating RTCPeerConnection');
   this.pc = new RTCPeerConnection(this._options.config, { optional: [ { rtpDataChannels: true } ]});
 };
 
-// Set up ICE candidate handlers.
+/** Set up ICE candidate handlers. */
 ConnectionManager.prototype._setupIce = function() {
   util.log('Listening for ICE candidates.');
   var self = this;
@@ -86,7 +84,7 @@ ConnectionManager.prototype._setupIce = function() {
   };
 };
 
-// Set up onnegotiationneeded.
+/** Set up onnegotiationneeded. */
 ConnectionManager.prototype._setupNegotiationHandler = function() {
   var self = this;
   util.log('Listening for `negotiationneeded`');
@@ -96,16 +94,22 @@ ConnectionManager.prototype._setupNegotiationHandler = function() {
   };
 };
 
-// Set up Data Channel listener.
+/** Set up Data Channel listener. */
 ConnectionManager.prototype._setupDataChannel = function() {
   var self = this;
-  this._pc.ondatachannel = function(evt) {
+  this.pc.ondatachannel = function(evt) {
     util.log('Received data channel');
     // TODO: Create DataConnection object.
+    var dc = evt.channel;
+    var label = dc.label;
+    var options = self.labels[label] || {};
+    var connection  = new DataConnection(dc, options);
+    self.connections[label] = connection;
+    self.emit('connection', connection);
   };
 };
 
-// Send an offer.
+/** Send an offer. */
 ConnectionManager.prototype._makeOffer = function() {
   var self = this;
   this.pc.createOffer(function(offer) {
@@ -116,12 +120,12 @@ ConnectionManager.prototype._makeOffer = function() {
         type: 'OFFER',
         payload: {
           sdp: offer,
-          serialization: self.serializations,
-          metadata: self.metadatas,
-          reliable: self.reliables
+          labels: self.labels
         },
         dst: self.peer
       });
+      // We can now reset labels because all info has been communicated.
+      self.labels = {};
     }, function(err) {
       self.emit('error', err);
       util.log('Failed to setLocalDescription, ', err);
@@ -129,7 +133,7 @@ ConnectionManager.prototype._makeOffer = function() {
   });
 };
 
-// Create an answer for PC.
+/** Create an answer for PC. */
 ConnectionManager.prototype._makeAnswer = function() {
   var self = this;
   this.pc.createAnswer(function(answer) {
@@ -153,13 +157,39 @@ ConnectionManager.prototype._makeAnswer = function() {
   });
 };
 
-// Clean up PC, close related DCs.
+/** Clean up PC, close related DCs. */
 ConnectionManager.prototype._cleanup = function() {
+  util.log('Cleanup ConnectionManager for ' + this.peer);
 
-}
+};
+
+/** Handle an SDP. */
+ConnectionManager.prototype.handleSDP = function(sdp, type) {
+  sdp = new RTCSessionDescription(sdp);
+
+  var self = this;
+  this.pc.setRemoteDescription(sdp, function() {
+    util.log('Set remoteDescription: ' + type);
+    if (type === 'OFFER') {
+      self._makeAnswer();
+    }
+  }, function(err) {
+    self.emit('error', err);
+    util.log('Failed to setRemoteDescription, ', err);
+  });
+};
 
-ConnectionManager.prototype.handleSDP = function(sdp) {
+/** Handle a candidate. */
+ConnectionManager.prototype.handleCandidate = function(message) {
+  var candidate = new RTCIceCandidate(message.candidate);
+  this.pc.addIceCandidate(candidate);
+  util.log('Added ICE candidate.');
+};
 
+/** Handle peer leaving. */
+ConnectionManager.prototype.handleLeave = function() {
+  util.log('Peer ' + this.peer + ' disconnected.');
+  this.close();
 };
 
 /** Closes manager and all related connections. */
@@ -177,6 +207,30 @@ ConnectionManager.prototype.close = function() {
 };
 
 /** Create and returns a DataConnection with the peer with the given label. */
-ConnectionManager.prototype.connect = function(label) {
+// TODO: queue in case no ID/PC.
+ConnectionManager.prototype.connect = function(label, options) {
+  options = util.extend({
+    reliable: false,
+    serialization: 'binary'
+  }, options);
 
+  this.labels[label] = {
+    reliable: options.reliable,
+    serialization: options.serialization,
+    metadata: options.metadata
+  };
+
+  var connection  = new DataConnection(this.pc.createDataChannel(this.peer, { reliable: false }), options);
+  this.connections[label] = connection;
+  return connection;
+};
+
+/** Updates label:[serialization, reliable, metadata] pairs from offer. */
+// TODO: queue in case no ID/PC.
+ConnectionManager.prototype.update = function(updates) {
+  var labels = Object.keys(updates);
+  for (var i = 0, ii = labels.length; i < ii; i += 1) {
+    var label = labels[i];
+    this.labels[label] = updates[label];
+  }
 };