Bladeren bron

getting id works over xhr stream

Michelle Bu 12 jaren geleden
bovenliggende
commit
29396400d9
6 gewijzigde bestanden met toevoegingen van 307 en 112 verwijderingen
  1. 1 2
      demo/static/peer.html
  2. 137 42
      demo/static/peer.js
  3. 1 1
      demo/static/peer1.html
  4. 137 42
      dist/peer.js
  5. 0 0
      dist/peer.min.js
  6. 31 25
      lib/peer.js

+ 1 - 2
demo/static/peer.html

@@ -12,8 +12,7 @@
 <script>
 $(document).ready(function() {
   connections = {};
-  var REMOTE = 'localhost:9000';
-  originator = new Peer({ server: REMOTE, debug: true });
+  originator = new Peer({ host: 'localhost', port: '9000', debug: true });
   originator.on('ready', function(id) {
     console.log(id);
   });

+ 137 - 42
demo/static/peer.js

@@ -729,6 +729,7 @@ EventEmitter.prototype.emit = function(type) {
 var util = {
   
   debug: false,
+  browserisms: '',
   
   inherits: function(ctor, superCtor) {
     ctor.super_ = superCtor;
@@ -757,9 +758,12 @@ var util = {
   
   log: function () {
     if (util.debug) {
+      var copy = [];
       for (var i = 0; i < arguments.length; i++) {
-        console.log('*', i, '-- ', arguments[i]);
+        copy[i] = arguments[i];
       }
+      copy.unshift('PeerJS: ');
+      console.log.apply(console, copy);
     }
   },
 
@@ -818,49 +822,48 @@ var util = {
 var RTCPeerConnection = null;
 var getUserMedia = null;
 var attachMediaStream = null;
-var browserisms = null;
 
 if (navigator.mozGetUserMedia) {
-  browserisms = 'Firefox'
+  util.browserisms = 'Firefox'
 
   RTCPeerConnection = mozRTCPeerConnection;
-
   getUserMedia = navigator.mozGetUserMedia.bind(navigator);
-  attachMediaStream = function(element, stream) {
-    console.log("Attaching media stream");
-    element.mozSrcObject = stream;
-    element.play();
-  };
 } else if (navigator.webkitGetUserMedia) {
-  browserisms = 'Webkit'
+  util.browserisms = 'Webkit'
 
   RTCPeerConnection = webkitRTCPeerConnection;
-
   getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
-  attachMediaStream = function(element, stream) {
-    element.src = webkitURL.createObjectURL(stream);
-  };
 }
 
 exports.RTCPeerConnection = RTCPeerConnection;
 exports.getUserMedia = getUserMedia;
-exports.attachMediaStream = attachMediaStream;
-exports.browserisms = browserisms;
 function Peer(options) {
   if (!(this instanceof Peer)) return new Peer(options);
   EventEmitter.call(this);
 
   options = util.extend({
     debug: false,
-    peer: 'ws://localhost'
+    host: 'localhost',
+    protocol: 'http',
+    port: 80
   }, options);
   this.options = options;
   util.debug = options.debug;
 
-  this._id = null;
+  this._server = options.host + ':' + options.port;
+  this._protocol = options.protocol;
+
+  // Ensure alphanumeric_-
+  if (options.id && !/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.exec(options.id))
+    throw new Error('Peer ID can only contain alphanumerics, "_", and "-".');
 
-  this._socket = new WebSocket(options.ws);
-  this._socketInit();
+  this._id = options.id;
+  // Not used unless using cloud server.
+  this._apikey = options.apikey;
+
+  // Check in with the server with ID or get an ID.
+//  this._startXhrStream();
+  this._checkIn();
 
   // Connections for this peer.
   this.connections = {};
@@ -874,8 +877,94 @@ function Peer(options) {
 
 util.inherits(Peer, EventEmitter);
 
+/** Check in with ID or get one from server. */
+Peer.prototype._checkIn = function() {
+  // If no ID provided, get a unique ID from server.
+  var self = this;
+  if (!this._id) {
+    try {
+      http = new XMLHttpRequest();
+      // If there's no ID we need to wait for one before trying to init socket.
+      http.open('get', this._protocol + '://' + this._server + '/id', true);
+      http.onreadystatechange = function() {
+        if (http.readyState > 2) {
+          if (!!http.responseText) {
+            try {
+              var response = JSON.parse(http.responseText.split('\n').shift());
+              if (!!response.id) {
+                self._id = response.id;
+                self.emit('ready', self._id);
+              }
+            } catch (e) {
+              // Ignore
+            }
+          }
+        }
+        self._socketInit();
+        self._handleStream(http, true);
+      };
+      http.send(null);
+    } catch(e) {
+      util.log('XMLHttpRequest not available; defaulting to WebSockets');
+      this._socketInit();
+    }
+  } else {
+    this._socketInit();
+    this._startXhrStream();
+  }
+  // TODO: may need to setInterval in case handleStream is not being called
+  // enough.
+};
+
+Peer.prototype._startXhrStream = function() {
+  try {
+    var http = new XMLHttpRequest();
+    var self = this;
+    http.open('post', this._protocol + '://' + this._server + '/id', true);
+    http.onreadystatechange = function() {
+      self._handleStream(http);
+    };
+    http.send('id=' + this._id);
+    // TODO: may need to setInterval in case handleStream is not being called
+    // enough.
+  } catch(e) {
+    util.log('XMLHttpRequest not available; defaulting to WebSockets');
+  }
+};
+
+/** Handles onreadystatechange response as a stream. */
+Peer.prototype._handleStream = function(http, pad) {
+  // 3 and 4 are loading/done state. All others are not relevant.
+  if (http.readyState < 3) {
+    return;
+  } else if (http.readyState == 3 && http.status != 200) {
+    return;
+  } else if (http.readyState == 4 && http.status != 200) {
+    // Clear setInterval here if using it.
+  }
+
+  if (this._index === undefined)
+    this._index = pad ? 2 : 1;
+
+  if (http.responseText === null)
+    return;
+
+  // TODO: handle
+  var message = http.responseText.split('\n')[this._index];
+  if (!!message)
+    this._index += 1;
+
+  if (http.readyState == 4 && !this._socketOpen)
+    this._startXhrStream();
+};
+
 /** Start up websocket communications. */
 Peer.prototype._socketInit = function() {
+  if (!!this._socket)
+    return;
+
+  this._socket = new WebSocket('ws://' + this._server + '/ws?id=' + this._id);
+
   var self = this;
   this._socket.onmessage = function(event) {
     var message = JSON.parse(event.data);
@@ -883,9 +972,12 @@ Peer.prototype._socketInit = function() {
     var connection = self.connections[peer];
     switch (message.type) {
       case 'ID':
-        self._id = message.id;
-        self._processQueue();
-        self.emit('ready', self._id);
+        if (!self._id) {
+          // If we're just now getting an ID then we may have a queue.
+          self._id = message.id;
+          self.emit('ready', self._id);
+          self._processQueue();
+        }
         break;
       case 'OFFER':
         var options = {
@@ -909,7 +1001,7 @@ Peer.prototype._socketInit = function() {
         if (connection) connection.handleLeave();
         break;
       case 'PORT':
-        if (browserisms == 'Firefox') {
+        if (util.browserisms === 'Firefox') {
           connection.handlePort(message);
           break;
         }
@@ -918,11 +1010,14 @@ Peer.prototype._socketInit = function() {
         break;
     }
   };
+
+  // Take care of the queue of connections if necessary and make sure Peer knows
+  // socket is open.
   this._socket.onopen = function() {
-    // Announce as a PEER to receive an ID.
-    self._socket.send(JSON.stringify({
-      type: 'PEER'
-    }));
+    util.log('Socket open');
+    self._socketOpen = true;
+    if (self._id)
+      self._processQueue();
   };
 };
 
@@ -977,7 +1072,7 @@ function DataConnection(id, peer, socket, cb, options) {
   
   this._id = id;
   this._peer = peer;
-  this._originator = (options.sdp == undefined);
+  this._originator = (options.sdp === undefined);
   this._cb = cb;
  
   this.metadata = options.metadata;
@@ -986,7 +1081,7 @@ function DataConnection(id, peer, socket, cb, options) {
   this._socket = socket;
 
   // Firefoxism: connectDataConnection ports.
-  if (browserisms == 'Firefox') {
+  if (util.browserisms === 'Firefox') {
     this._firefoxPortSetup();
   }
   //
@@ -999,7 +1094,7 @@ function DataConnection(id, peer, socket, cb, options) {
   
   // Listen for negotiation needed
   // ** Chrome only.
-  if (browserisms === 'Webkit') {
+  if (util.browserisms === 'Webkit') {
     this._setupOffer();
   }
   
@@ -1009,12 +1104,12 @@ function DataConnection(id, peer, socket, cb, options) {
   var self = this;
   if (options.sdp) {
     this.handleSDP({type: 'OFFER', sdp: options.sdp});
-    if (browserisms !== 'Firefox') { 
+    if (util.browserisms !== 'Firefox') { 
       this._makeAnswer();
     }
   }
   
-  if (browserisms === 'Firefox') {
+  if (util.browserisms === 'Firefox') {
     this._firefoxAdditional();
   }
 };
@@ -1048,14 +1143,14 @@ DataConnection.prototype._setupDataChannel = function() {
 
 DataConnection.prototype.handleSDP = function(message) {
   var sdp = message.sdp;
-  if (browserisms != 'Firefox') {
+  if (util.browserisms != 'Firefox') {
     sdp = new RTCSessionDescription(sdp);
   }
   var self = this;
   this._pc.setRemoteDescription(sdp, function() {
     util.log('Set remoteDescription: ' + message.type);
     // Firefoxism
-    if (message.type == 'ANSWER' && browserisms == 'Firefox') {
+    if (message.type === 'ANSWER' && util.browserisms === 'Firefox') {
       self._pc.connectDataConnection(self.localPort, self.remotePort);
       self._socket.send(JSON.stringify({
         type: 'PORT',
@@ -1124,7 +1219,7 @@ DataConnection.prototype._setupDataChannel = function() {
   var self = this;
   if (this._originator) {
     
-    if (browserisms == 'Webkit') {
+    if (util.browserisms === 'Webkit') {
 
       // TODO: figure out the right thing to do with this.
       this._pc.onstatechange = function() {
@@ -1162,7 +1257,7 @@ DataConnection.prototype._firefoxPortSetup = function() {
     this.localPort = util.randomPort();
   }
   this.remotePort = util.randomPort();
-  while (this.remotePort == this.localPort ||
+  while (this.remotePort === this.localPort ||
       DataConnection.usedPorts.indexOf(this.localPort) != -1) {
     this.remotePort = util.randomPort();
   }
@@ -1173,7 +1268,7 @@ DataConnection.prototype._firefoxPortSetup = function() {
 DataConnection.prototype._configureDataChannel = function() {
   var self = this;
   
-  if (browserisms === 'Firefox') {
+  if (util.browserisms === 'Firefox') {
     this._dc.binaryType = 'blob';
   }
   this._dc.onopen = function() {
@@ -1273,7 +1368,7 @@ DataConnection.prototype.close = function() {
 DataConnection.prototype.send = function(data) {
   var self = this;
   var blob = BinaryPack.pack(data);
-  if (browserisms == 'Webkit') {
+  if (util.browserisms === 'Webkit') {
     util.blobToBinaryString(blob, function(str){
       self._dc.send(str);
     });
@@ -1286,15 +1381,15 @@ DataConnection.prototype.send = function(data) {
 // Handles a DataChannel message.
 DataConnection.prototype._handleDataMessage = function(e) {
   var self = this;
-  if (e.data.constructor == Blob) {
+  if (e.data.constructor === Blob) {
     util.blobToArrayBuffer(e.data, function(ab) {
       var data = BinaryPack.unpack(ab);
       self.emit('data', data);
     });
-  } else if (e.data.constructor == ArrayBuffer) {
+  } else if (e.data.constructor === ArrayBuffer) {
       var data = BinaryPack.unpack(e.data);
       self.emit('data', data);
-  } else if (e.data.constructor == String) {
+  } else if (e.data.constructor === String) {
       var ab = util.binaryStringToArrayBuffer(e.data);
       var data = BinaryPack.unpack(ab);
       self.emit('data', data);

+ 1 - 1
demo/static/peer1.html

@@ -15,7 +15,7 @@ $(document).ready(function() {
   $('#connect').click(function() {
     var source = $('#source').val();
 
-    sink = new Peer({ server: 'localhost:9000', debug: true });
+    sink = new Peer({ host: 'localhost', port: '9000', debug: true });
       sink.connect(source, { username: 'michelle' }, function(err, connection) {
         x = connection;
         console.log('got connection');

+ 137 - 42
dist/peer.js

@@ -729,6 +729,7 @@ EventEmitter.prototype.emit = function(type) {
 var util = {
   
   debug: false,
+  browserisms: '',
   
   inherits: function(ctor, superCtor) {
     ctor.super_ = superCtor;
@@ -757,9 +758,12 @@ var util = {
   
   log: function () {
     if (util.debug) {
+      var copy = [];
       for (var i = 0; i < arguments.length; i++) {
-        console.log('*', i, '-- ', arguments[i]);
+        copy[i] = arguments[i];
       }
+      copy.unshift('PeerJS: ');
+      console.log.apply(console, copy);
     }
   },
 
@@ -818,49 +822,48 @@ var util = {
 var RTCPeerConnection = null;
 var getUserMedia = null;
 var attachMediaStream = null;
-var browserisms = null;
 
 if (navigator.mozGetUserMedia) {
-  browserisms = 'Firefox'
+  util.browserisms = 'Firefox'
 
   RTCPeerConnection = mozRTCPeerConnection;
-
   getUserMedia = navigator.mozGetUserMedia.bind(navigator);
-  attachMediaStream = function(element, stream) {
-    console.log("Attaching media stream");
-    element.mozSrcObject = stream;
-    element.play();
-  };
 } else if (navigator.webkitGetUserMedia) {
-  browserisms = 'Webkit'
+  util.browserisms = 'Webkit'
 
   RTCPeerConnection = webkitRTCPeerConnection;
-
   getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
-  attachMediaStream = function(element, stream) {
-    element.src = webkitURL.createObjectURL(stream);
-  };
 }
 
 exports.RTCPeerConnection = RTCPeerConnection;
 exports.getUserMedia = getUserMedia;
-exports.attachMediaStream = attachMediaStream;
-exports.browserisms = browserisms;
 function Peer(options) {
   if (!(this instanceof Peer)) return new Peer(options);
   EventEmitter.call(this);
 
   options = util.extend({
     debug: false,
-    peer: 'ws://localhost'
+    host: 'localhost',
+    protocol: 'http',
+    port: 80
   }, options);
   this.options = options;
   util.debug = options.debug;
 
-  this._id = null;
+  this._server = options.host + ':' + options.port;
+  this._protocol = options.protocol;
+
+  // Ensure alphanumeric_-
+  if (options.id && !/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.exec(options.id))
+    throw new Error('Peer ID can only contain alphanumerics, "_", and "-".');
 
-  this._socket = new WebSocket(options.ws);
-  this._socketInit();
+  this._id = options.id;
+  // Not used unless using cloud server.
+  this._apikey = options.apikey;
+
+  // Check in with the server with ID or get an ID.
+//  this._startXhrStream();
+  this._checkIn();
 
   // Connections for this peer.
   this.connections = {};
@@ -874,8 +877,94 @@ function Peer(options) {
 
 util.inherits(Peer, EventEmitter);
 
+/** Check in with ID or get one from server. */
+Peer.prototype._checkIn = function() {
+  // If no ID provided, get a unique ID from server.
+  var self = this;
+  if (!this._id) {
+    try {
+      http = new XMLHttpRequest();
+      // If there's no ID we need to wait for one before trying to init socket.
+      http.open('get', this._protocol + '://' + this._server + '/id', true);
+      http.onreadystatechange = function() {
+        if (http.readyState > 2) {
+          if (!!http.responseText) {
+            try {
+              var response = JSON.parse(http.responseText.split('\n').shift());
+              if (!!response.id) {
+                self._id = response.id;
+                self.emit('ready', self._id);
+              }
+            } catch (e) {
+              // Ignore
+            }
+          }
+        }
+        self._socketInit();
+        self._handleStream(http, true);
+      };
+      http.send(null);
+    } catch(e) {
+      util.log('XMLHttpRequest not available; defaulting to WebSockets');
+      this._socketInit();
+    }
+  } else {
+    this._socketInit();
+    this._startXhrStream();
+  }
+  // TODO: may need to setInterval in case handleStream is not being called
+  // enough.
+};
+
+Peer.prototype._startXhrStream = function() {
+  try {
+    var http = new XMLHttpRequest();
+    var self = this;
+    http.open('post', this._protocol + '://' + this._server + '/id', true);
+    http.onreadystatechange = function() {
+      self._handleStream(http);
+    };
+    http.send('id=' + this._id);
+    // TODO: may need to setInterval in case handleStream is not being called
+    // enough.
+  } catch(e) {
+    util.log('XMLHttpRequest not available; defaulting to WebSockets');
+  }
+};
+
+/** Handles onreadystatechange response as a stream. */
+Peer.prototype._handleStream = function(http, pad) {
+  // 3 and 4 are loading/done state. All others are not relevant.
+  if (http.readyState < 3) {
+    return;
+  } else if (http.readyState == 3 && http.status != 200) {
+    return;
+  } else if (http.readyState == 4 && http.status != 200) {
+    // Clear setInterval here if using it.
+  }
+
+  if (this._index === undefined)
+    this._index = pad ? 2 : 1;
+
+  if (http.responseText === null)
+    return;
+
+  // TODO: handle
+  var message = http.responseText.split('\n')[this._index];
+  if (!!message)
+    this._index += 1;
+
+  if (http.readyState == 4 && !this._socketOpen)
+    this._startXhrStream();
+};
+
 /** Start up websocket communications. */
 Peer.prototype._socketInit = function() {
+  if (!!this._socket)
+    return;
+
+  this._socket = new WebSocket('ws://' + this._server + '/ws?id=' + this._id);
+
   var self = this;
   this._socket.onmessage = function(event) {
     var message = JSON.parse(event.data);
@@ -883,9 +972,12 @@ Peer.prototype._socketInit = function() {
     var connection = self.connections[peer];
     switch (message.type) {
       case 'ID':
-        self._id = message.id;
-        self._processQueue();
-        self.emit('ready', self._id);
+        if (!self._id) {
+          // If we're just now getting an ID then we may have a queue.
+          self._id = message.id;
+          self.emit('ready', self._id);
+          self._processQueue();
+        }
         break;
       case 'OFFER':
         var options = {
@@ -909,7 +1001,7 @@ Peer.prototype._socketInit = function() {
         if (connection) connection.handleLeave();
         break;
       case 'PORT':
-        if (browserisms == 'Firefox') {
+        if (util.browserisms === 'Firefox') {
           connection.handlePort(message);
           break;
         }
@@ -918,11 +1010,14 @@ Peer.prototype._socketInit = function() {
         break;
     }
   };
+
+  // Take care of the queue of connections if necessary and make sure Peer knows
+  // socket is open.
   this._socket.onopen = function() {
-    // Announce as a PEER to receive an ID.
-    self._socket.send(JSON.stringify({
-      type: 'PEER'
-    }));
+    util.log('Socket open');
+    self._socketOpen = true;
+    if (self._id)
+      self._processQueue();
   };
 };
 
@@ -977,7 +1072,7 @@ function DataConnection(id, peer, socket, cb, options) {
   
   this._id = id;
   this._peer = peer;
-  this._originator = (options.sdp == undefined);
+  this._originator = (options.sdp === undefined);
   this._cb = cb;
  
   this.metadata = options.metadata;
@@ -986,7 +1081,7 @@ function DataConnection(id, peer, socket, cb, options) {
   this._socket = socket;
 
   // Firefoxism: connectDataConnection ports.
-  if (browserisms == 'Firefox') {
+  if (util.browserisms === 'Firefox') {
     this._firefoxPortSetup();
   }
   //
@@ -999,7 +1094,7 @@ function DataConnection(id, peer, socket, cb, options) {
   
   // Listen for negotiation needed
   // ** Chrome only.
-  if (browserisms === 'Webkit') {
+  if (util.browserisms === 'Webkit') {
     this._setupOffer();
   }
   
@@ -1009,12 +1104,12 @@ function DataConnection(id, peer, socket, cb, options) {
   var self = this;
   if (options.sdp) {
     this.handleSDP({type: 'OFFER', sdp: options.sdp});
-    if (browserisms !== 'Firefox') { 
+    if (util.browserisms !== 'Firefox') { 
       this._makeAnswer();
     }
   }
   
-  if (browserisms === 'Firefox') {
+  if (util.browserisms === 'Firefox') {
     this._firefoxAdditional();
   }
 };
@@ -1048,14 +1143,14 @@ DataConnection.prototype._setupDataChannel = function() {
 
 DataConnection.prototype.handleSDP = function(message) {
   var sdp = message.sdp;
-  if (browserisms != 'Firefox') {
+  if (util.browserisms != 'Firefox') {
     sdp = new RTCSessionDescription(sdp);
   }
   var self = this;
   this._pc.setRemoteDescription(sdp, function() {
     util.log('Set remoteDescription: ' + message.type);
     // Firefoxism
-    if (message.type == 'ANSWER' && browserisms == 'Firefox') {
+    if (message.type === 'ANSWER' && util.browserisms === 'Firefox') {
       self._pc.connectDataConnection(self.localPort, self.remotePort);
       self._socket.send(JSON.stringify({
         type: 'PORT',
@@ -1124,7 +1219,7 @@ DataConnection.prototype._setupDataChannel = function() {
   var self = this;
   if (this._originator) {
     
-    if (browserisms == 'Webkit') {
+    if (util.browserisms === 'Webkit') {
 
       // TODO: figure out the right thing to do with this.
       this._pc.onstatechange = function() {
@@ -1162,7 +1257,7 @@ DataConnection.prototype._firefoxPortSetup = function() {
     this.localPort = util.randomPort();
   }
   this.remotePort = util.randomPort();
-  while (this.remotePort == this.localPort ||
+  while (this.remotePort === this.localPort ||
       DataConnection.usedPorts.indexOf(this.localPort) != -1) {
     this.remotePort = util.randomPort();
   }
@@ -1173,7 +1268,7 @@ DataConnection.prototype._firefoxPortSetup = function() {
 DataConnection.prototype._configureDataChannel = function() {
   var self = this;
   
-  if (browserisms === 'Firefox') {
+  if (util.browserisms === 'Firefox') {
     this._dc.binaryType = 'blob';
   }
   this._dc.onopen = function() {
@@ -1273,7 +1368,7 @@ DataConnection.prototype.close = function() {
 DataConnection.prototype.send = function(data) {
   var self = this;
   var blob = BinaryPack.pack(data);
-  if (browserisms == 'Webkit') {
+  if (util.browserisms === 'Webkit') {
     util.blobToBinaryString(blob, function(str){
       self._dc.send(str);
     });
@@ -1286,15 +1381,15 @@ DataConnection.prototype.send = function(data) {
 // Handles a DataChannel message.
 DataConnection.prototype._handleDataMessage = function(e) {
   var self = this;
-  if (e.data.constructor == Blob) {
+  if (e.data.constructor === Blob) {
     util.blobToArrayBuffer(e.data, function(ab) {
       var data = BinaryPack.unpack(ab);
       self.emit('data', data);
     });
-  } else if (e.data.constructor == ArrayBuffer) {
+  } else if (e.data.constructor === ArrayBuffer) {
       var data = BinaryPack.unpack(e.data);
       self.emit('data', data);
-  } else if (e.data.constructor == String) {
+  } else if (e.data.constructor === String) {
       var ab = util.binaryStringToArrayBuffer(e.data);
       var data = BinaryPack.unpack(ab);
       self.emit('data', data);

File diff suppressed because it is too large
+ 0 - 0
dist/peer.min.js


+ 31 - 25
lib/peer.js

@@ -5,12 +5,14 @@ function Peer(options) {
   options = util.extend({
     debug: false,
     host: 'localhost',
+    protocol: 'http',
     port: 80
   }, options);
   this.options = options;
   util.debug = options.debug;
 
   this._server = options.host + ':' + options.port;
+  this._protocol = options.protocol;
 
   // Ensure alphanumeric_-
   if (options.id && !/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.exec(options.id))
@@ -38,20 +40,21 @@ util.inherits(Peer, EventEmitter);
 
 /** Check in with ID or get one from server. */
 Peer.prototype._checkIn = function() {
-  try {
-    var http = new XMLHttpRequest();
-    // If no ID provided, get a unique ID from server.
-    var self = this;
-    if (!this._id) {
+  // If no ID provided, get a unique ID from server.
+  var self = this;
+  if (!this._id) {
+    try {
+      http = new XMLHttpRequest();
       // If there's no ID we need to wait for one before trying to init socket.
-      http.open('get', this._server + '/id', true);
+      http.open('get', this._protocol + '://' + this._server + '/id', true);
       http.onreadystatechange = function() {
         if (http.readyState > 2) {
           if (!!http.responseText) {
             try {
-              var response = JSON.parse(http.responseText);
+              var response = JSON.parse(http.responseText.split('\n').shift());
               if (!!response.id) {
                 self._id = response.id;
+                self.emit('ready', self._id);
               }
             } catch (e) {
               // Ignore
@@ -59,46 +62,39 @@ Peer.prototype._checkIn = function() {
           }
         }
         self._socketInit();
-        self._handleStream(http);
+        self._handleStream(http, true);
       };
       http.send(null);
-    } else {
+    } catch(e) {
+      util.log('XMLHttpRequest not available; defaulting to WebSockets');
       this._socketInit();
-      http.open('post', this._server + '/id', true);
-      http.onreadystatechange = function() {
-        self._handleStream(http);
-      };
-      http.send('id=' + this._id);
     }
-    // TODO: may need to setInterval in case handleStream is not being called
-    // enough.
-  } catch(e) {
-    util.log('XMLHttpRequest not available; defaulting to WebSockets');
+  } else {
     this._socketInit();
+    this._startXhrStream();
   }
+  // TODO: may need to setInterval in case handleStream is not being called
+  // enough.
 };
 
-/** Taking care of this in /id now.
 Peer.prototype._startXhrStream = function() {
   try {
     var http = new XMLHttpRequest();
-    // If no ID provided, get a unique ID from server.
     var self = this;
-    http.open('get', this._server + '/stream', true);
+    http.open('post', this._protocol + '://' + this._server + '/id', true);
     http.onreadystatechange = function() {
       self._handleStream(http);
     };
-    http.send(null);
+    http.send('id=' + this._id);
     // TODO: may need to setInterval in case handleStream is not being called
     // enough.
   } catch(e) {
     util.log('XMLHttpRequest not available; defaulting to WebSockets');
   }
 };
-*/
 
 /** Handles onreadystatechange response as a stream. */
-Peer.prototype._handleStream = function(http) {
+Peer.prototype._handleStream = function(http, pad) {
   // 3 and 4 are loading/done state. All others are not relevant.
   if (http.readyState < 3) {
     return;
@@ -108,11 +104,16 @@ Peer.prototype._handleStream = function(http) {
     // Clear setInterval here if using it.
   }
 
+  if (this._index === undefined)
+    this._index = pad ? 2 : 1;
+
   if (http.responseText === null)
     return;
 
   // TODO: handle
-  console.log(http.responseText);
+  var message = http.responseText.split('\n')[this._index];
+  if (!!message)
+    this._index += 1;
 
   if (http.readyState == 4 && !this._socketOpen)
     this._startXhrStream();
@@ -120,6 +121,9 @@ Peer.prototype._handleStream = function(http) {
 
 /** Start up websocket communications. */
 Peer.prototype._socketInit = function() {
+  if (!!this._socket)
+    return;
+
   this._socket = new WebSocket('ws://' + this._server + '/ws?id=' + this._id);
 
   var self = this;
@@ -132,6 +136,7 @@ Peer.prototype._socketInit = function() {
         if (!self._id) {
           // If we're just now getting an ID then we may have a queue.
           self._id = message.id;
+          self.emit('ready', self._id);
           self._processQueue();
         }
         break;
@@ -170,6 +175,7 @@ Peer.prototype._socketInit = function() {
   // Take care of the queue of connections if necessary and make sure Peer knows
   // socket is open.
   this._socket.onopen = function() {
+    util.log('Socket open');
     self._socketOpen = true;
     if (self._id)
       self._processQueue();

Some files were not shown because too many files changed in this diff