Michelle Bu 12 éve
szülő
commit
5f65cbeda4
1 módosított fájl, 182 hozzáadás és 0 törlés
  1. 182 0
      lib/connectionmanager.js

+ 182 - 0
lib/connectionmanager.js

@@ -0,0 +1,182 @@
+/**
+ * Manages DataConnections between its peer and one other peer.
+ * Internally, manages PeerConnection.
+ */
+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({
+    config: { 'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }] },
+    reliable: false,
+    serialization: 'binary'
+  }, options);
+  this._options = options;
+
+  // PeerConnection is not yet open.
+  this.open = false;
+
+  this.id = id;
+  this.peer = peer;
+  this.pc = null;
+
+  // Mapping labels to metadata and serialization.
+  this.metadatas = {};
+  this.serializations = {};
+  this.reliables = {};
+
+  // DataConnections on this PC.
+  this.connections = {};
+
+  this._socket = socket;
+
+  if (!!this.id) {
+    this.initialize();
+  }
+};
+
+util.inherits(ConnectionManager, EventEmitter);
+
+ConnectionManager.prototype.initialize = function(id, socket) {
+  if (!!id) {
+    this.id = id;
+  }
+  if (!!socket) {
+    this._socket = socket;
+  }
+
+  // Set up PeerConnection.
+  this._startPeerConnection();
+
+  // Listen for ICE candidates.
+  this._setupIce();
+
+  // Listen for negotiation needed.
+  // Chrome only **
+  this._setupNegotiationHandler();
+
+  // Listen for data channel.
+  this._setupDataChannel();
+
+  this.initialize = function() { };
+};
+
+// 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.
+ConnectionManager.prototype._setupIce = function() {
+  util.log('Listening for ICE candidates.');
+  var self = this;
+  this.pc.onicecandidate = function(evt) {
+    if (evt.candidate) {
+      util.log('Received ICE candidates.');
+      self._socket.send({
+        type: 'CANDIDATE',
+        payload: {
+          candidate: evt.candidate
+        },
+        dst: self.peer
+      });
+    }
+  };
+};
+
+// Set up onnegotiationneeded.
+ConnectionManager.prototype._setupNegotiationHandler = function() {
+  var self = this;
+  util.log('Listening for `negotiationneeded`');
+  this.pc.onnegotiationneeded = function() {
+    util.log('`negotiationneeded` triggered');
+    self._makeOffer();
+  };
+};
+
+// Set up Data Channel listener.
+ConnectionManager.prototype._setupDataChannel = function() {
+  var self = this;
+  this._pc.ondatachannel = function(evt) {
+    util.log('Received data channel');
+    // TODO: Create DataConnection object.
+  };
+};
+
+// Send an offer.
+ConnectionManager.prototype._makeOffer = function() {
+  var self = this;
+  this.pc.createOffer(function(offer) {
+    util.log('Created offer.');
+    self.pc.setLocalDescription(offer, function() {
+      util.log('Set localDescription to offer');
+      self._socket.send({
+        type: 'OFFER',
+        payload: {
+          sdp: offer,
+          serialization: self.serializations,
+          metadata: self.metadatas,
+          reliable: self.reliables
+        },
+        dst: self.peer
+      });
+    }, function(err) {
+      self.emit('error', err);
+      util.log('Failed to setLocalDescription, ', err);
+    });
+  });
+};
+
+// Create an answer for PC.
+ConnectionManager.prototype._makeAnswer = function() {
+  var self = this;
+  this.pc.createAnswer(function(answer) {
+    util.log('Created answer.');
+    self.pc.setLocalDescription(answer, function() {
+      util.log('Set localDescription to answer.');
+      self._socket.send({
+        type: 'ANSWER',
+        payload: {
+          sdp: answer
+        },
+        dst: self.peer
+      });
+    }, function(err) {
+      self.emit('error', err);
+      util.log('Failed to setLocalDescription, ', err);
+    });
+  }, function(err) {
+    self.emit('error', err);
+    util.log('Failed to create answer, ', err);
+  });
+};
+
+// Clean up PC, close related DCs.
+ConnectionManager.prototype._cleanup = function() {
+
+}
+
+ConnectionManager.prototype.handleSDP = function(sdp) {
+
+};
+
+/** Closes manager and all related connections. */
+ConnectionManager.prototype.close = function() {
+  this._cleanup();
+  var self = this;
+  if (this.open) {
+    this._socket.send({
+      type: 'LEAVE',
+      dst: self.peer
+    });
+  }
+  this.open = false;
+  this.emit('close', this.peer);
+};
+
+/** Create and returns a DataConnection with the peer with the given label. */
+ConnectionManager.prototype.connect = function(label) {
+
+};