Jairo 7 жил өмнө
parent
commit
f05249137b
3 өөрчлөгдсөн 1030 нэмэгдсэн , 887 устгасан
  1. 839 761
      dist/peer.js
  2. 0 0
      dist/peer.min.js
  3. 191 126
      lib/peer.js

+ 839 - 761
dist/peer.js

@@ -408,13 +408,14 @@ Negotiator._idPrefix = 'pc_';
 Negotiator.startConnection = function(connection, options) {
   var pc = Negotiator._getPeerConnection(connection, options);
 
+  // Set the connection's PC.
+  connection.pc = connection.peerConnection = pc;
+
   if (connection.type === 'media' && options._stream) {
     // Add the stream.
     pc.addStream(options._stream);
   }
 
-  // Set the connection's PC.
-  connection.pc = connection.peerConnection = pc;
   // What do we need to do now?
   if (options.originator) {
     if (connection.type === 'data') {
@@ -595,7 +596,7 @@ Negotiator.cleanup = function(connection) {
 
   var pc = connection.pc;
 
-  if (!!pc && (pc.readyState !== 'closed' || pc.signalingState !== 'closed')) {
+  if (!!pc && ((pc.readyState && pc.readyState !== 'closed') || pc.signalingState !== 'closed')) {
     pc.close();
     connection.pc = null;
   }
@@ -700,11 +701,11 @@ Negotiator.handleCandidate = function(connection, ice) {
 module.exports = Negotiator;
 
 },{"./adapter":1,"./util":8}],6:[function(require,module,exports){
-var util = require('./util');
-var EventEmitter = require('eventemitter3');
-var Socket = require('./socket');
-var MediaConnection = require('./mediaconnection');
-var DataConnection = require('./dataconnection');
+var util = require("./util");
+var EventEmitter = require("eventemitter3");
+var Socket = require("./socket");
+var MediaConnection = require("./mediaconnection");
+var DataConnection = require("./dataconnection");
 
 /**
  * A peer who can initiate connections with other peers.
@@ -724,26 +725,29 @@ function Peer(id, options) {
   //
 
   // Configurize options
-  options = util.extend({
-    debug: 0, // 1: Errors, 2: Warnings, 3: All logs
-    host: util.CLOUD_HOST,
-    port: util.CLOUD_PORT,
-    key: 'peerjs',
-    path: '/',
-    token: util.randomToken(),
-    config: util.defaultConfig
-  }, options);
+  options = util.extend(
+    {
+      debug: 0, // 1: Errors, 2: Warnings, 3: All logs
+      host: util.CLOUD_HOST,
+      port: util.CLOUD_PORT,
+      key: "peerjs",
+      path: "/",
+      token: util.randomToken(),
+      config: util.defaultConfig
+    },
+    options
+  );
   this.options = options;
   // Detect relative URL host.
-  if (options.host === '/') {
+  if (options.host === "/") {
     options.host = window.location.hostname;
   }
   // Set path correctly.
-  if (options.path[0] !== '/') {
-    options.path = '/' + options.path;
+  if (options.path[0] !== "/") {
+    options.path = "/" + options.path;
   }
-  if (options.path[options.path.length - 1] !== '/') {
-    options.path += '/';
+  if (options.path[options.path.length - 1] !== "/") {
+    options.path += "/";
   }
 
   // Set whether we use SSL to same as current host
@@ -759,24 +763,32 @@ function Peer(id, options) {
 
   // Sanity checks
   // Ensure WebRTC supported
-  if (!util.supports.audioVideo && !util.supports.data ) {
-    this._delayedAbort('browser-incompatible', 'The current browser does not support WebRTC');
+  if (!util.supports.audioVideo && !util.supports.data) {
+    this._delayedAbort(
+      "browser-incompatible",
+      "The current browser does not support WebRTC"
+    );
     return;
   }
   // Ensure alphanumeric id
   if (!util.validateId(id)) {
-    this._delayedAbort('invalid-id', 'ID "' + id + '" is invalid');
+    this._delayedAbort("invalid-id", 'ID "' + id + '" is invalid');
     return;
   }
   // Ensure valid key
   if (!util.validateKey(options.key)) {
-    this._delayedAbort('invalid-key', 'API KEY "' + options.key + '" is invalid');
+    this._delayedAbort(
+      "invalid-key",
+      'API KEY "' + options.key + '" is invalid'
+    );
     return;
   }
   // Ensure not using unsecure cloud server on SSL page
-  if (options.secure && options.host === '0.peerjs.com') {
-    this._delayedAbort('ssl-unavailable',
-      'The cloud server currently does not support HTTPS. Please run your own PeerServer to use HTTPS.');
+  if (options.secure && options.host === "0.peerjs.com") {
+    this._delayedAbort(
+      "ssl-unavailable",
+      "The cloud server currently does not support HTTPS. Please run your own PeerServer to use HTTPS."
+    );
     return;
   }
   //
@@ -808,24 +820,31 @@ util.inherits(Peer, EventEmitter);
 // websockets.)
 Peer.prototype._initializeServerConnection = function() {
   var self = this;
-  this.socket = new Socket(this.options.secure, this.options.host, this.options.port, this.options.path, this.options.key);
-  this.socket.on('message', function(data) {
+  this.socket = new Socket(
+    this.options.secure,
+    this.options.host,
+    this.options.port,
+    this.options.path,
+    this.options.key,
+    this.options.wsport
+  );
+  this.socket.on("message", function(data) {
     self._handleMessage(data);
   });
-  this.socket.on('error', function(error) {
-    self._abort('socket-error', error);
+  this.socket.on("error", function(error) {
+    self._abort("socket-error", error);
   });
-  this.socket.on('disconnected', function() {
+  this.socket.on("disconnected", function() {
     // If we haven't explicitly disconnected, emit error and disconnect.
     if (!self.disconnected) {
-      self.emitError('network', 'Lost connection to server.');
+      self.emitError("network", "Lost connection to server.");
       self.disconnect();
     }
   });
-  this.socket.on('close', function() {
+  this.socket.on("close", function() {
     // If we haven't explicitly disconnected, emit error.
     if (!self.disconnected) {
-      self._abort('socket-closed', 'Underlying socket is already closed.');
+      self._abort("socket-closed", "Underlying socket is already closed.");
     }
   });
 };
@@ -834,23 +853,33 @@ Peer.prototype._initializeServerConnection = function() {
 Peer.prototype._retrieveId = function(cb) {
   var self = this;
   var http = new XMLHttpRequest();
-  var protocol = this.options.secure ? 'https://' : 'http://';
-  var url = protocol + this.options.host + ':' + this.options.port +
-    this.options.path + this.options.key + '/id';
-  var queryString = '?ts=' + new Date().getTime() + '' + Math.random();
+  var protocol = this.options.secure ? "https://" : "http://";
+  var url =
+    protocol +
+    this.options.host +
+    ":" +
+    this.options.port +
+    this.options.path +
+    this.options.key +
+    "/id";
+  var queryString = "?ts=" + new Date().getTime() + "" + Math.random();
   url += queryString;
 
   // If there's no ID we need to wait for one before trying to init socket.
-  http.open('get', url, true);
+  http.open("get", url, true);
   http.onerror = function(e) {
-    util.error('Error retrieving ID', e);
-    var pathError = '';
-    if (self.options.path === '/' && self.options.host !== util.CLOUD_HOST) {
-      pathError = ' If you passed in a `path` to your self-hosted PeerServer, ' +
-        'you\'ll also need to pass in that same path when creating a new ' +
-        'Peer.';
-    }
-    self._abort('server-error', 'Could not get an ID from the server.' + pathError);
+    util.error("Error retrieving ID", e);
+    var pathError = "";
+    if (self.options.path === "/" && self.options.host !== util.CLOUD_HOST) {
+      pathError =
+        " If you passed in a `path` to your self-hosted PeerServer, " +
+        "you'll also need to pass in that same path when creating a new " +
+        "Peer.";
+    }
+    self._abort(
+      "server-error",
+      "Could not get an ID from the server." + pathError
+    );
   };
   http.onreadystatechange = function() {
     if (http.readyState !== 4) {
@@ -879,71 +908,78 @@ Peer.prototype._handleMessage = function(message) {
   var connection;
 
   switch (type) {
-    case 'OPEN': // The connection to the server is open.
-      this.emit('open', this.id);
+    case "OPEN": // The connection to the server is open.
+      this.emit("open", this.id);
       this.open = true;
       break;
-    case 'ERROR': // Server error.
-      this._abort('server-error', payload.msg);
+    case "ERROR": // Server error.
+      this._abort("server-error", payload.msg);
       break;
-    case 'ID-TAKEN': // The selected ID is taken.
-      this._abort('unavailable-id', 'ID `' + this.id + '` is taken');
+    case "ID-TAKEN": // The selected ID is taken.
+      this._abort("unavailable-id", "ID `" + this.id + "` is taken");
       break;
-    case 'INVALID-KEY': // The given API key cannot be found.
-      this._abort('invalid-key', 'API KEY "' + this.options.key + '" is invalid');
+    case "INVALID-KEY": // The given API key cannot be found.
+      this._abort(
+        "invalid-key",
+        'API KEY "' + this.options.key + '" is invalid'
+      );
       break;
 
     //
-    case 'LEAVE': // Another peer has closed its connection to this peer.
-      util.log('Received leave message from', peer);
+    case "LEAVE": // Another peer has closed its connection to this peer.
+      util.log("Received leave message from", peer);
       this._cleanupPeer(peer);
       break;
 
-    case 'EXPIRE': // The offer sent to a peer has expired without response.
-      this.emitError('peer-unavailable', 'Could not connect to peer ' + peer);
+    case "EXPIRE": // The offer sent to a peer has expired without response.
+      this.emitError("peer-unavailable", "Could not connect to peer " + peer);
       break;
-    case 'OFFER': // we should consider switching this to CALL/CONNECT, but this is the least breaking option.
+    case "OFFER": // we should consider switching this to CALL/CONNECT, but this is the least breaking option.
       var connectionId = payload.connectionId;
       connection = this.getConnection(peer, connectionId);
 
       if (connection) {
-        util.warn('Offer received for existing Connection ID:', connectionId);
+        connection.close();
+        util.warn("Offer received for existing Connection ID:", connectionId);
         //connection.handleMessage(message);
+      }
+
+      // Create a new connection.
+      if (payload.type === "media") {
+        connection = new MediaConnection(peer, this, {
+          connectionId: connectionId,
+          _payload: payload,
+          metadata: payload.metadata
+        });
+        this._addConnection(peer, connection);
+        this.emit("call", connection);
+      } else if (payload.type === "data") {
+        connection = new DataConnection(peer, this, {
+          connectionId: connectionId,
+          _payload: payload,
+          metadata: payload.metadata,
+          label: payload.label,
+          serialization: payload.serialization,
+          reliable: payload.reliable
+        });
+        this._addConnection(peer, connection);
+        this.emit("connection", connection);
       } else {
-        // Create a new connection.
-        if (payload.type === 'media') {
-          connection = new MediaConnection(peer, this, {
-            connectionId: connectionId,
-            _payload: payload,
-            metadata: payload.metadata
-          });
-          this._addConnection(peer, connection);
-          this.emit('call', connection);
-        } else if (payload.type === 'data') {
-          connection = new DataConnection(peer, this, {
-            connectionId: connectionId,
-            _payload: payload,
-            metadata: payload.metadata,
-            label: payload.label,
-            serialization: payload.serialization,
-            reliable: payload.reliable
-          });
-          this._addConnection(peer, connection);
-          this.emit('connection', connection);
-        } else {
-          util.warn('Received malformed connection type:', payload.type);
-          return;
-        }
-        // Find messages.
-        var messages = this._getMessages(connectionId);
-        for (var i = 0, ii = messages.length; i < ii; i += 1) {
-          connection.handleMessage(messages[i]);
-        }
+        util.warn("Received malformed connection type:", payload.type);
+        return;
       }
+      // Find messages.
+      var messages = this._getMessages(connectionId);
+      for (var i = 0, ii = messages.length; i < ii; i += 1) {
+        connection.handleMessage(messages[i]);
+      }
+
       break;
     default:
       if (!payload) {
-        util.warn('You received a malformed message from ' + peer + ' of type ' + type);
+        util.warn(
+          "You received a malformed message from " + peer + " of type " + type
+        );
         return;
       }
 
@@ -957,7 +993,7 @@ Peer.prototype._handleMessage = function(message) {
         // Store for possible later use
         this._storeMessage(id, message);
       } else {
-        util.warn('You received an unrecognized message:', message);
+        util.warn("You received an unrecognized message:", message);
       }
       break;
   }
@@ -988,11 +1024,16 @@ Peer.prototype._getMessages = function(connectionId) {
  */
 Peer.prototype.connect = function(peer, options) {
   if (this.disconnected) {
-    util.warn('You cannot connect to a new Peer because you called ' +
-      '.disconnect() on this Peer and ended your connection with the ' +
-      'server. You can create a new Peer to reconnect, or call reconnect ' +
-      'on this peer if you believe its ID to still be available.');
-    this.emitError('disconnected', 'Cannot connect to new Peer after disconnecting from server.');
+    util.warn(
+      "You cannot connect to a new Peer because you called " +
+        ".disconnect() on this Peer and ended your connection with the " +
+        "server. You can create a new Peer to reconnect, or call reconnect " +
+        "on this peer if you believe its ID to still be available."
+    );
+    this.emitError(
+      "disconnected",
+      "Cannot connect to new Peer after disconnecting from server."
+    );
     return;
   }
   var connection = new DataConnection(peer, this, options);
@@ -1006,14 +1047,21 @@ Peer.prototype.connect = function(peer, options) {
  */
 Peer.prototype.call = function(peer, stream, options) {
   if (this.disconnected) {
-    util.warn('You cannot connect to a new Peer because you called ' +
-      '.disconnect() on this Peer and ended your connection with the ' +
-      'server. You can create a new Peer to reconnect.');
-    this.emitError('disconnected', 'Cannot connect to new Peer after disconnecting from server.');
+    util.warn(
+      "You cannot connect to a new Peer because you called " +
+        ".disconnect() on this Peer and ended your connection with the " +
+        "server. You can create a new Peer to reconnect."
+    );
+    this.emitError(
+      "disconnected",
+      "Cannot connect to new Peer after disconnecting from server."
+    );
     return;
   }
   if (!stream) {
-    util.error('To call a peer, you must provide a stream from your browser\'s `getUserMedia`.');
+    util.error(
+      "To call a peer, you must provide a stream from your browser's `getUserMedia`."
+    );
     return;
   }
   options = options || {};
@@ -1047,7 +1095,7 @@ Peer.prototype.getConnection = function(peer, id) {
 
 Peer.prototype._delayedAbort = function(type, message) {
   var self = this;
-  util.setZeroTimeout(function(){
+  util.setZeroTimeout(function() {
     self._abort(type, message);
   });
 };
@@ -1058,7 +1106,7 @@ Peer.prototype._delayedAbort = function(type, message) {
  * it retains its disconnected state and its existing connections.
  */
 Peer.prototype._abort = function(type, message) {
-  util.error('Aborting!');
+  util.error("Aborting!");
   if (!this._lastServerId) {
     this.destroy();
   } else {
@@ -1069,12 +1117,12 @@ Peer.prototype._abort = function(type, message) {
 
 /** Emits a typed error message. */
 Peer.prototype.emitError = function(type, err) {
-  util.error('Error:', err);
-  if (typeof err === 'string') {
+  util.error("Error:", err);
+  if (typeof err === "string") {
     err = new Error(err);
   }
   err.type = type;
-  this.emit('error', err);
+  this.emit("error", err);
 };
 
 /**
@@ -1091,7 +1139,6 @@ Peer.prototype.destroy = function() {
   }
 };
 
-
 /** Disconnects every connection on this peer. */
 Peer.prototype._cleanup = function() {
   if (this.connections) {
@@ -1100,7 +1147,7 @@ Peer.prototype._cleanup = function() {
       this._cleanupPeer(peers[i]);
     }
   }
-  this.emit('close');
+  this.emit("close");
 };
 
 /** Closes all connections to this peer. */
@@ -1119,14 +1166,14 @@ Peer.prototype._cleanupPeer = function(peer) {
  */
 Peer.prototype.disconnect = function() {
   var self = this;
-  util.setZeroTimeout(function(){
+  util.setZeroTimeout(function() {
     if (!self.disconnected) {
       self.disconnected = true;
       self.open = false;
       if (self.socket) {
         self.socket.close();
       }
-      self.emit('disconnected', self.id);
+      self.emit("disconnected", self.id);
       self._lastServerId = self.id;
       self.id = null;
     }
@@ -1136,17 +1183,25 @@ Peer.prototype.disconnect = function() {
 /** Attempts to reconnect with the same ID. */
 Peer.prototype.reconnect = function() {
   if (this.disconnected && !this.destroyed) {
-    util.log('Attempting reconnection to server with ID ' + this._lastServerId);
+    util.log("Attempting reconnection to server with ID " + this._lastServerId);
     this.disconnected = false;
     this._initializeServerConnection();
     this._initialize(this._lastServerId);
   } else if (this.destroyed) {
-    throw new Error('This peer cannot reconnect to the server. It has already been destroyed.');
+    throw new Error(
+      "This peer cannot reconnect to the server. It has already been destroyed."
+    );
   } else if (!this.disconnected && !this.open) {
     // Do nothing. We're still connecting the first time.
-    util.error('In a hurry? We\'re still trying to make the initial connection!');
+    util.error(
+      "In a hurry? We're still trying to make the initial connection!"
+    );
   } else {
-    throw new Error('Peer ' + this.id + ' cannot reconnect because it is not disconnected from the server!');
+    throw new Error(
+      "Peer " +
+        this.id +
+        " cannot reconnect because it is not disconnected from the server!"
+    );
   }
 };
 
@@ -1160,16 +1215,22 @@ Peer.prototype.listAllPeers = function(cb) {
   cb = cb || function() {};
   var self = this;
   var http = new XMLHttpRequest();
-  var protocol = this.options.secure ? 'https://' : 'http://';
-  var url = protocol + this.options.host + ':' + this.options.port +
-    this.options.path + this.options.key + '/peers';
-  var queryString = '?ts=' + new Date().getTime() + '' + Math.random();
+  var protocol = this.options.secure ? "https://" : "http://";
+  var url =
+    protocol +
+    this.options.host +
+    ":" +
+    this.options.port +
+    this.options.path +
+    this.options.key +
+    "/peers";
+  var queryString = "?ts=" + new Date().getTime() + "" + Math.random();
   url += queryString;
 
   // If there's no ID we need to wait for one before trying to init socket.
-  http.open('get', url, true);
+  http.open("get", url, true);
   http.onerror = function(e) {
-    self._abort('server-error', 'Could not get peers from the server.');
+    self._abort("server-error", "Could not get peers from the server.");
     cb([]);
   };
   http.onreadystatechange = function() {
@@ -1177,16 +1238,21 @@ Peer.prototype.listAllPeers = function(cb) {
       return;
     }
     if (http.status === 401) {
-      var helpfulError = '';
+      var helpfulError = "";
       if (self.options.host !== util.CLOUD_HOST) {
-        helpfulError = 'It looks like you\'re using the cloud server. You can email ' +
-          'team@peerjs.com to enable peer listing for your API key.';
+        helpfulError =
+          "It looks like you're using the cloud server. You can email " +
+          "team@peerjs.com to enable peer listing for your API key.";
       } else {
-        helpfulError = 'You need to enable `allow_discovery` on your self-hosted ' +
-          'PeerServer to use this feature.';
+        helpfulError =
+          "You need to enable `allow_discovery` on your self-hosted " +
+          "PeerServer to use this feature.";
       }
       cb([]);
-      throw new Error('It doesn\'t look like you have permission to list peers IDs. ' + helpfulError);
+      throw new Error(
+        "It doesn't look like you have permission to list peers IDs. " +
+          helpfulError
+      );
     } else if (http.status !== 200) {
       cb([]);
     } else {
@@ -1206,8 +1272,10 @@ var EventEmitter = require('eventemitter3');
  * An abstraction on top of WebSockets and XHR streaming to provide fastest
  * possible connection for peers.
  */
-function Socket(secure, host, port, path, key) {
-  if (!(this instanceof Socket)) return new Socket(secure, host, port, path, key);
+function Socket(secure, host, port, path, key, wsport) {
+  if (!(this instanceof Socket)) return new Socket(secure, host, port, path, key, wsport);
+
+  wsport = wsport || port;
 
   EventEmitter.call(this);
 
@@ -1218,7 +1286,7 @@ function Socket(secure, host, port, path, key) {
   var httpProtocol = secure ? 'https://' : 'http://';
   var wsProtocol = secure ? 'wss://' : 'ws://';
   this._httpUrl = httpProtocol + host + ':' + port + path + key;
-  this._wsUrl = wsProtocol + host + ':' + port + path + 'peerjs?key=' + key;
+  this._wsUrl = wsProtocol + host + ':' + wsport + path + 'peerjs?key=' + key;
 }
 
 util.inherits(Socket, EventEmitter);
@@ -1415,20 +1483,20 @@ Socket.prototype.close = function() {
 module.exports = Socket;
 
 },{"./util":8,"eventemitter3":9}],8:[function(require,module,exports){
-var defaultConfig = {'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }]};
+var defaultConfig = { iceServers: [{ url: "stun:stun.l.google.com:19302" }] };
 var dataCount = 1;
 
-var BinaryPack = require('js-binarypack');
-var RTCPeerConnection = require('./adapter').RTCPeerConnection;
+var BinaryPack = require("js-binarypack");
+var RTCPeerConnection = require("./adapter").RTCPeerConnection;
 
 var util = {
   noop: function() {},
 
-  CLOUD_HOST: '0.peerjs.com',
+  CLOUD_HOST: "0.peerjs.com",
   CLOUD_PORT: 9000,
 
   // Browsers that need chunking:
-  chunkedBrowsers: {'Chrome': 1},
+  chunkedBrowsers: { Chrome: 1 },
   chunkedMTU: 16300, // The original 60000 bytes setting does not work when sending data from Firefox to Chrome, which is "cut off" after 16384 bytes and delivered individually.
 
   // Logging logic
@@ -1443,10 +1511,10 @@ var util = {
     }
     util.log = util.warn = util.error = util.noop;
     if (util.logLevel > 0) {
-      util.error = util._printWith('ERROR');
+      util.error = util._printWith("ERROR");
     }
     if (util.logLevel > 1) {
-      util.warn = util._printWith('WARNING');
+      util.warn = util._printWith("WARNING");
     }
     if (util.logLevel > 2) {
       util.log = util._print;
@@ -1454,7 +1522,9 @@ var util = {
   },
   setLogFunction: function(fn) {
     if (fn.constructor !== Function) {
-      util.warn('The log function you passed in is not a function. Defaulting to regular logs.');
+      util.warn(
+        "The log function you passed in is not a function. Defaulting to regular logs."
+      );
     } else {
       util._print = fn;
     }
@@ -1467,13 +1537,13 @@ var util = {
       util._print.apply(util, copy);
     };
   },
-  _print: function () {
+  _print: function() {
     var err = false;
     var copy = Array.prototype.slice.call(arguments);
-    copy.unshift('PeerJS: ');
-    for (var i = 0, l = copy.length; i < l; i++){
+    copy.unshift("PeerJS: ");
+    for (var i = 0, l = copy.length; i < l; i++) {
       if (copy[i] instanceof Error) {
-        copy[i] = '(' + copy[i].name + ') ' + copy[i].message;
+        copy[i] = "(" + copy[i].name + ") " + copy[i].message;
         err = true;
       }
     }
@@ -1488,20 +1558,20 @@ var util = {
   // Returns the current browser.
   browser: (function() {
     if (window.mozRTCPeerConnection) {
-      return 'Firefox';
+      return "Firefox";
     } else if (window.webkitRTCPeerConnection) {
-      return 'Chrome';
+      return "Chrome";
     } else if (window.RTCPeerConnection) {
-      return 'Supported';
+      return "Supported";
     } else {
-      return 'Unsupported';
+      return "Unsupported";
     }
   })(),
   //
 
   // Lists which features are supported
   supports: (function() {
-    if (typeof RTCPeerConnection === 'undefined') {
+    if (typeof RTCPeerConnection === "undefined") {
       return {};
     }
 
@@ -1514,7 +1584,9 @@ var util = {
 
     var pc, dc;
     try {
-      pc = new RTCPeerConnection(defaultConfig, {optional: [{RtpDataChannels: true}]});
+      pc = new RTCPeerConnection(defaultConfig, {
+        optional: [{ RtpDataChannels: true }]
+      });
     } catch (e) {
       data = false;
       audioVideo = false;
@@ -1522,7 +1594,7 @@ var util = {
 
     if (data) {
       try {
-        dc = pc.createDataChannel('_PEERJSTEST');
+        dc = pc.createDataChannel("_PEERJSTEST");
       } catch (e) {
         data = false;
       }
@@ -1531,20 +1603,21 @@ var util = {
     if (data) {
       // Binary test
       try {
-        dc.binaryType = 'blob';
+        dc.binaryType = "blob";
         binaryBlob = true;
-      } catch (e) {
-      }
+      } catch (e) {}
 
       // Reliable test.
       // Unfortunately Chrome is a bit unreliable about whether or not they
       // support reliable.
       var reliablePC = new RTCPeerConnection(defaultConfig, {});
       try {
-        var reliableDC = reliablePC.createDataChannel('_PEERJSRELIABLETEST', {});
+        var reliableDC = reliablePC.createDataChannel(
+          "_PEERJSRELIABLETEST",
+          {}
+        );
         sctp = reliableDC.reliable;
-      } catch (e) {
-      }
+      } catch (e) {}
       reliablePC.close();
     }
 
@@ -1555,6 +1628,7 @@ var util = {
 
     // FIXME: this is not great because in theory it doesn't work for
     // av-only browsers (?).
+    /*
     if (!onnegotiationneeded && data) {
       // sync default check.
       var negotiationPC = new RTCPeerConnection(defaultConfig, {optional: [{RtpDataChannels: true}]});
@@ -1571,6 +1645,7 @@ var util = {
         negotiationPC.close();
       }, 1000);
     }
+    */
 
     if (pc) {
       pc.close();
@@ -1585,7 +1660,7 @@ var util = {
       sctp: sctp,
       onnegotiationneeded: onnegotiationneeded
     };
-  }()),
+  })(),
   //
 
   // Ensure alphanumeric ids
@@ -1599,7 +1674,6 @@ var util = {
     return !key || /^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.exec(key);
   },
 
-
   debug: false,
 
   inherits: function(ctor, superCtor) {
@@ -1614,8 +1688,8 @@ var util = {
     });
   },
   extend: function(dest, source) {
-    for(var key in source) {
-      if(source.hasOwnProperty(key)) {
+    for (var key in source) {
+      if (source.hasOwnProperty(key)) {
         dest[key] = source[key];
       }
     }
@@ -1624,31 +1698,33 @@ var util = {
   pack: BinaryPack.pack,
   unpack: BinaryPack.unpack,
 
-  log: function () {
+  log: function() {
     if (util.debug) {
       var err = false;
       var copy = Array.prototype.slice.call(arguments);
-      copy.unshift('PeerJS: ');
-      for (var i = 0, l = copy.length; i < l; i++){
+      copy.unshift("PeerJS: ");
+      for (var i = 0, l = copy.length; i < l; i++) {
         if (copy[i] instanceof Error) {
-          copy[i] = '(' + copy[i].name + ') ' + copy[i].message;
+          copy[i] = "(" + copy[i].name + ") " + copy[i].message;
           err = true;
         }
       }
-      err ? console.error.apply(console, copy) : console.log.apply(console, copy);
+      err
+        ? console.error.apply(console, copy)
+        : console.log.apply(console, copy);
     }
   },
 
   setZeroTimeout: (function(global) {
     var timeouts = [];
-    var messageName = 'zero-timeout-message';
+    var messageName = "zero-timeout-message";
 
     // Like setTimeout, but only takes a function argument.	 There's
     // no time argument (always zero) and no arguments (you have to
     // use a closure).
     function setZeroTimeoutPostMessage(fn) {
       timeouts.push(fn);
-      global.postMessage(messageName, '*');
+      global.postMessage(messageName, "*");
     }
 
     function handleMessage(event) {
@@ -1662,12 +1738,12 @@ var util = {
       }
     }
     if (global.addEventListener) {
-      global.addEventListener('message', handleMessage, true);
+      global.addEventListener("message", handleMessage, true);
     } else if (global.attachEvent) {
-      global.attachEvent('onmessage', handleMessage);
+      global.attachEvent("onmessage", handleMessage);
     }
     return setZeroTimeoutPostMessage;
-  }(window)),
+  })(window),
 
   // Binary stuff
 
@@ -1675,7 +1751,7 @@ var util = {
   chunk: function(bl) {
     var chunks = [];
     var size = bl.size;
-    var start = index = 0;
+    var start = (index = 0);
     var total = Math.ceil(size / util.chunkedMTU);
     while (start < size) {
       var end = Math.min(size, start + util.chunkedMTU);
@@ -1697,14 +1773,14 @@ var util = {
     return chunks;
   },
 
-  blobToArrayBuffer: function(blob, cb){
+  blobToArrayBuffer: function(blob, cb) {
     var fr = new FileReader();
     fr.onload = function(evt) {
       cb(evt.target.result);
     };
     fr.readAsArrayBuffer(blob);
   },
-  blobToBinaryString: function(blob, cb){
+  blobToBinaryString: function(blob, cb) {
     var fr = new FileReader();
     fr.onload = function(evt) {
       cb(evt.target.result);
@@ -1718,13 +1794,15 @@ var util = {
     }
     return byteArray.buffer;
   },
-  randomToken: function () {
-    return Math.random().toString(36).substr(2);
+  randomToken: function() {
+    return Math.random()
+      .toString(36)
+      .substr(2);
   },
   //
 
   isSecure: function() {
-    return location.protocol === 'https:';
+    return location.protocol === "https:";
   }
 };
 
@@ -1962,591 +2040,591 @@ EventEmitter.EventEmitter3 = EventEmitter;
 module.exports = EventEmitter;
 
 },{}],10:[function(require,module,exports){
-var BufferBuilder = require('./bufferbuilder').BufferBuilder;
-var binaryFeatures = require('./bufferbuilder').binaryFeatures;
-
-var BinaryPack = {
-  unpack: function(data){
-    var unpacker = new Unpacker(data);
-    return unpacker.unpack();
-  },
-  pack: function(data){
-    var packer = new Packer();
-    packer.pack(data);
-    var buffer = packer.getBuffer();
-    return buffer;
-  }
-};
-
-module.exports = BinaryPack;
-
-function Unpacker (data){
-  // Data is ArrayBuffer
-  this.index = 0;
-  this.dataBuffer = data;
-  this.dataView = new Uint8Array(this.dataBuffer);
-  this.length = this.dataBuffer.byteLength;
-}
-
-Unpacker.prototype.unpack = function(){
-  var type = this.unpack_uint8();
-  if (type < 0x80){
-    var positive_fixnum = type;
-    return positive_fixnum;
-  } else if ((type ^ 0xe0) < 0x20){
-    var negative_fixnum = (type ^ 0xe0) - 0x20;
-    return negative_fixnum;
-  }
-  var size;
-  if ((size = type ^ 0xa0) <= 0x0f){
-    return this.unpack_raw(size);
-  } else if ((size = type ^ 0xb0) <= 0x0f){
-    return this.unpack_string(size);
-  } else if ((size = type ^ 0x90) <= 0x0f){
-    return this.unpack_array(size);
-  } else if ((size = type ^ 0x80) <= 0x0f){
-    return this.unpack_map(size);
-  }
-  switch(type){
-    case 0xc0:
-      return null;
-    case 0xc1:
-      return undefined;
-    case 0xc2:
-      return false;
-    case 0xc3:
-      return true;
-    case 0xca:
-      return this.unpack_float();
-    case 0xcb:
-      return this.unpack_double();
-    case 0xcc:
-      return this.unpack_uint8();
-    case 0xcd:
-      return this.unpack_uint16();
-    case 0xce:
-      return this.unpack_uint32();
-    case 0xcf:
-      return this.unpack_uint64();
-    case 0xd0:
-      return this.unpack_int8();
-    case 0xd1:
-      return this.unpack_int16();
-    case 0xd2:
-      return this.unpack_int32();
-    case 0xd3:
-      return this.unpack_int64();
-    case 0xd4:
-      return undefined;
-    case 0xd5:
-      return undefined;
-    case 0xd6:
-      return undefined;
-    case 0xd7:
-      return undefined;
-    case 0xd8:
-      size = this.unpack_uint16();
-      return this.unpack_string(size);
-    case 0xd9:
-      size = this.unpack_uint32();
-      return this.unpack_string(size);
-    case 0xda:
-      size = this.unpack_uint16();
-      return this.unpack_raw(size);
-    case 0xdb:
-      size = this.unpack_uint32();
-      return this.unpack_raw(size);
-    case 0xdc:
-      size = this.unpack_uint16();
-      return this.unpack_array(size);
-    case 0xdd:
-      size = this.unpack_uint32();
-      return this.unpack_array(size);
-    case 0xde:
-      size = this.unpack_uint16();
-      return this.unpack_map(size);
-    case 0xdf:
-      size = this.unpack_uint32();
-      return this.unpack_map(size);
-  }
-}
-
-Unpacker.prototype.unpack_uint8 = function(){
-  var byte = this.dataView[this.index] & 0xff;
-  this.index++;
-  return byte;
-};
-
-Unpacker.prototype.unpack_uint16 = function(){
-  var bytes = this.read(2);
-  var uint16 =
-    ((bytes[0] & 0xff) * 256) + (bytes[1] & 0xff);
-  this.index += 2;
-  return uint16;
-}
-
-Unpacker.prototype.unpack_uint32 = function(){
-  var bytes = this.read(4);
-  var uint32 =
-     ((bytes[0]  * 256 +
-       bytes[1]) * 256 +
-       bytes[2]) * 256 +
-       bytes[3];
-  this.index += 4;
-  return uint32;
-}
-
-Unpacker.prototype.unpack_uint64 = function(){
-  var bytes = this.read(8);
-  var uint64 =
-   ((((((bytes[0]  * 256 +
-       bytes[1]) * 256 +
-       bytes[2]) * 256 +
-       bytes[3]) * 256 +
-       bytes[4]) * 256 +
-       bytes[5]) * 256 +
-       bytes[6]) * 256 +
-       bytes[7];
-  this.index += 8;
-  return uint64;
-}
-
-
-Unpacker.prototype.unpack_int8 = function(){
-  var uint8 = this.unpack_uint8();
-  return (uint8 < 0x80 ) ? uint8 : uint8 - (1 << 8);
-};
-
-Unpacker.prototype.unpack_int16 = function(){
-  var uint16 = this.unpack_uint16();
-  return (uint16 < 0x8000 ) ? uint16 : uint16 - (1 << 16);
-}
-
-Unpacker.prototype.unpack_int32 = function(){
-  var uint32 = this.unpack_uint32();
-  return (uint32 < Math.pow(2, 31) ) ? uint32 :
-    uint32 - Math.pow(2, 32);
-}
-
-Unpacker.prototype.unpack_int64 = function(){
-  var uint64 = this.unpack_uint64();
-  return (uint64 < Math.pow(2, 63) ) ? uint64 :
-    uint64 - Math.pow(2, 64);
-}
-
-Unpacker.prototype.unpack_raw = function(size){
-  if ( this.length < this.index + size){
-    throw new Error('BinaryPackFailure: index is out of range'
-      + ' ' + this.index + ' ' + size + ' ' + this.length);
-  }
-  var buf = this.dataBuffer.slice(this.index, this.index + size);
-  this.index += size;
-
-    //buf = util.bufferToString(buf);
-
-  return buf;
-}
-
-Unpacker.prototype.unpack_string = function(size){
-  var bytes = this.read(size);
-  var i = 0, str = '', c, code;
-  while(i < size){
-    c = bytes[i];
-    if ( c < 128){
-      str += String.fromCharCode(c);
-      i++;
-    } else if ((c ^ 0xc0) < 32){
-      code = ((c ^ 0xc0) << 6) | (bytes[i+1] & 63);
-      str += String.fromCharCode(code);
-      i += 2;
-    } else {
-      code = ((c & 15) << 12) | ((bytes[i+1] & 63) << 6) |
-        (bytes[i+2] & 63);
-      str += String.fromCharCode(code);
-      i += 3;
-    }
-  }
-  this.index += size;
-  return str;
-}
-
-Unpacker.prototype.unpack_array = function(size){
-  var objects = new Array(size);
-  for(var i = 0; i < size ; i++){
-    objects[i] = this.unpack();
-  }
-  return objects;
-}
-
-Unpacker.prototype.unpack_map = function(size){
-  var map = {};
-  for(var i = 0; i < size ; i++){
-    var key  = this.unpack();
-    var value = this.unpack();
-    map[key] = value;
-  }
-  return map;
-}
-
-Unpacker.prototype.unpack_float = function(){
-  var uint32 = this.unpack_uint32();
-  var sign = uint32 >> 31;
-  var exp  = ((uint32 >> 23) & 0xff) - 127;
-  var fraction = ( uint32 & 0x7fffff ) | 0x800000;
-  return (sign == 0 ? 1 : -1) *
-    fraction * Math.pow(2, exp - 23);
-}
-
-Unpacker.prototype.unpack_double = function(){
-  var h32 = this.unpack_uint32();
-  var l32 = this.unpack_uint32();
-  var sign = h32 >> 31;
-  var exp  = ((h32 >> 20) & 0x7ff) - 1023;
-  var hfrac = ( h32 & 0xfffff ) | 0x100000;
-  var frac = hfrac * Math.pow(2, exp - 20) +
-    l32   * Math.pow(2, exp - 52);
-  return (sign == 0 ? 1 : -1) * frac;
-}
-
-Unpacker.prototype.read = function(length){
-  var j = this.index;
-  if (j + length <= this.length) {
-    return this.dataView.subarray(j, j + length);
-  } else {
-    throw new Error('BinaryPackFailure: read index out of range');
-  }
-}
-
-function Packer(){
-  this.bufferBuilder = new BufferBuilder();
-}
-
-Packer.prototype.getBuffer = function(){
-  return this.bufferBuilder.getBuffer();
-}
-
-Packer.prototype.pack = function(value){
-  var type = typeof(value);
-  if (type == 'string'){
-    this.pack_string(value);
-  } else if (type == 'number'){
-    if (Math.floor(value) === value){
-      this.pack_integer(value);
-    } else{
-      this.pack_double(value);
-    }
-  } else if (type == 'boolean'){
-    if (value === true){
-      this.bufferBuilder.append(0xc3);
-    } else if (value === false){
-      this.bufferBuilder.append(0xc2);
-    }
-  } else if (type == 'undefined'){
-    this.bufferBuilder.append(0xc0);
-  } else if (type == 'object'){
-    if (value === null){
-      this.bufferBuilder.append(0xc0);
-    } else {
-      var constructor = value.constructor;
-      if (constructor == Array){
-        this.pack_array(value);
-      } else if (constructor == Blob || constructor == File) {
-        this.pack_bin(value);
-      } else if (constructor == ArrayBuffer) {
-        if(binaryFeatures.useArrayBufferView) {
-          this.pack_bin(new Uint8Array(value));
-        } else {
-          this.pack_bin(value);
-        }
-      } else if ('BYTES_PER_ELEMENT' in value){
-        if(binaryFeatures.useArrayBufferView) {
-          this.pack_bin(new Uint8Array(value.buffer));
-        } else {
-          this.pack_bin(value.buffer);
-        }
-      } else if (constructor == Object){
-        this.pack_object(value);
-      } else if (constructor == Date){
-        this.pack_string(value.toString());
-      } else if (typeof value.toBinaryPack == 'function'){
-        this.bufferBuilder.append(value.toBinaryPack());
-      } else {
-        throw new Error('Type "' + constructor.toString() + '" not yet supported');
-      }
-    }
-  } else {
-    throw new Error('Type "' + type + '" not yet supported');
-  }
-  this.bufferBuilder.flush();
-}
-
-
-Packer.prototype.pack_bin = function(blob){
-  var length = blob.length || blob.byteLength || blob.size;
-  if (length <= 0x0f){
-    this.pack_uint8(0xa0 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xda) ;
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xdb);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-  }
-  this.bufferBuilder.append(blob);
-}
-
-Packer.prototype.pack_string = function(str){
-  var length = utf8Length(str);
-
-  if (length <= 0x0f){
-    this.pack_uint8(0xb0 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xd8) ;
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xd9);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-  }
-  this.bufferBuilder.append(str);
-}
-
-Packer.prototype.pack_array = function(ary){
-  var length = ary.length;
-  if (length <= 0x0f){
-    this.pack_uint8(0x90 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xdc)
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xdd);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-  }
-  for(var i = 0; i < length ; i++){
-    this.pack(ary[i]);
-  }
-}
-
-Packer.prototype.pack_integer = function(num){
-  if ( -0x20 <= num && num <= 0x7f){
-    this.bufferBuilder.append(num & 0xff);
-  } else if (0x00 <= num && num <= 0xff){
-    this.bufferBuilder.append(0xcc);
-    this.pack_uint8(num);
-  } else if (-0x80 <= num && num <= 0x7f){
-    this.bufferBuilder.append(0xd0);
-    this.pack_int8(num);
-  } else if ( 0x0000 <= num && num <= 0xffff){
-    this.bufferBuilder.append(0xcd);
-    this.pack_uint16(num);
-  } else if (-0x8000 <= num && num <= 0x7fff){
-    this.bufferBuilder.append(0xd1);
-    this.pack_int16(num);
-  } else if ( 0x00000000 <= num && num <= 0xffffffff){
-    this.bufferBuilder.append(0xce);
-    this.pack_uint32(num);
-  } else if (-0x80000000 <= num && num <= 0x7fffffff){
-    this.bufferBuilder.append(0xd2);
-    this.pack_int32(num);
-  } else if (-0x8000000000000000 <= num && num <= 0x7FFFFFFFFFFFFFFF){
-    this.bufferBuilder.append(0xd3);
-    this.pack_int64(num);
-  } else if (0x0000000000000000 <= num && num <= 0xFFFFFFFFFFFFFFFF){
-    this.bufferBuilder.append(0xcf);
-    this.pack_uint64(num);
-  } else{
-    throw new Error('Invalid integer');
-  }
-}
-
-Packer.prototype.pack_double = function(num){
-  var sign = 0;
-  if (num < 0){
-    sign = 1;
-    num = -num;
-  }
-  var exp  = Math.floor(Math.log(num) / Math.LN2);
-  var frac0 = num / Math.pow(2, exp) - 1;
-  var frac1 = Math.floor(frac0 * Math.pow(2, 52));
-  var b32   = Math.pow(2, 32);
-  var h32 = (sign << 31) | ((exp+1023) << 20) |
-      (frac1 / b32) & 0x0fffff;
-  var l32 = frac1 % b32;
-  this.bufferBuilder.append(0xcb);
-  this.pack_int32(h32);
-  this.pack_int32(l32);
-}
-
-Packer.prototype.pack_object = function(obj){
-  var keys = Object.keys(obj);
-  var length = keys.length;
-  if (length <= 0x0f){
-    this.pack_uint8(0x80 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xde);
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xdf);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-  }
-  for(var prop in obj){
-    if (obj.hasOwnProperty(prop)){
-      this.pack(prop);
-      this.pack(obj[prop]);
-    }
-  }
-}
-
-Packer.prototype.pack_uint8 = function(num){
-  this.bufferBuilder.append(num);
-}
-
-Packer.prototype.pack_uint16 = function(num){
-  this.bufferBuilder.append(num >> 8);
-  this.bufferBuilder.append(num & 0xff);
-}
-
-Packer.prototype.pack_uint32 = function(num){
-  var n = num & 0xffffffff;
-  this.bufferBuilder.append((n & 0xff000000) >>> 24);
-  this.bufferBuilder.append((n & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((n & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((n & 0x000000ff));
-}
-
-Packer.prototype.pack_uint64 = function(num){
-  var high = num / Math.pow(2, 32);
-  var low  = num % Math.pow(2, 32);
-  this.bufferBuilder.append((high & 0xff000000) >>> 24);
-  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((high & 0x000000ff));
-  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
-  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((low  & 0x000000ff));
-}
-
-Packer.prototype.pack_int8 = function(num){
-  this.bufferBuilder.append(num & 0xff);
-}
-
-Packer.prototype.pack_int16 = function(num){
-  this.bufferBuilder.append((num & 0xff00) >> 8);
-  this.bufferBuilder.append(num & 0xff);
-}
-
-Packer.prototype.pack_int32 = function(num){
-  this.bufferBuilder.append((num >>> 24) & 0xff);
-  this.bufferBuilder.append((num & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((num & 0x0000ff00) >>> 8);
-  this.bufferBuilder.append((num & 0x000000ff));
-}
-
-Packer.prototype.pack_int64 = function(num){
-  var high = Math.floor(num / Math.pow(2, 32));
-  var low  = num % Math.pow(2, 32);
-  this.bufferBuilder.append((high & 0xff000000) >>> 24);
-  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((high & 0x000000ff));
-  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
-  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((low  & 0x000000ff));
-}
-
-function _utf8Replace(m){
-  var code = m.charCodeAt(0);
-
-  if(code <= 0x7ff) return '00';
-  if(code <= 0xffff) return '000';
-  if(code <= 0x1fffff) return '0000';
-  if(code <= 0x3ffffff) return '00000';
-  return '000000';
-}
-
-function utf8Length(str){
-  if (str.length > 600) {
-    // Blob method faster for large strings
-    return (new Blob([str])).size;
-  } else {
-    return str.replace(/[^\u0000-\u007F]/g, _utf8Replace).length;
-  }
-}
+var BufferBuilder = require('./bufferbuilder').BufferBuilder;
+var binaryFeatures = require('./bufferbuilder').binaryFeatures;
+
+var BinaryPack = {
+  unpack: function(data){
+    var unpacker = new Unpacker(data);
+    return unpacker.unpack();
+  },
+  pack: function(data){
+    var packer = new Packer();
+    packer.pack(data);
+    var buffer = packer.getBuffer();
+    return buffer;
+  }
+};
+
+module.exports = BinaryPack;
+
+function Unpacker (data){
+  // Data is ArrayBuffer
+  this.index = 0;
+  this.dataBuffer = data;
+  this.dataView = new Uint8Array(this.dataBuffer);
+  this.length = this.dataBuffer.byteLength;
+}
+
+Unpacker.prototype.unpack = function(){
+  var type = this.unpack_uint8();
+  if (type < 0x80){
+    var positive_fixnum = type;
+    return positive_fixnum;
+  } else if ((type ^ 0xe0) < 0x20){
+    var negative_fixnum = (type ^ 0xe0) - 0x20;
+    return negative_fixnum;
+  }
+  var size;
+  if ((size = type ^ 0xa0) <= 0x0f){
+    return this.unpack_raw(size);
+  } else if ((size = type ^ 0xb0) <= 0x0f){
+    return this.unpack_string(size);
+  } else if ((size = type ^ 0x90) <= 0x0f){
+    return this.unpack_array(size);
+  } else if ((size = type ^ 0x80) <= 0x0f){
+    return this.unpack_map(size);
+  }
+  switch(type){
+    case 0xc0:
+      return null;
+    case 0xc1:
+      return undefined;
+    case 0xc2:
+      return false;
+    case 0xc3:
+      return true;
+    case 0xca:
+      return this.unpack_float();
+    case 0xcb:
+      return this.unpack_double();
+    case 0xcc:
+      return this.unpack_uint8();
+    case 0xcd:
+      return this.unpack_uint16();
+    case 0xce:
+      return this.unpack_uint32();
+    case 0xcf:
+      return this.unpack_uint64();
+    case 0xd0:
+      return this.unpack_int8();
+    case 0xd1:
+      return this.unpack_int16();
+    case 0xd2:
+      return this.unpack_int32();
+    case 0xd3:
+      return this.unpack_int64();
+    case 0xd4:
+      return undefined;
+    case 0xd5:
+      return undefined;
+    case 0xd6:
+      return undefined;
+    case 0xd7:
+      return undefined;
+    case 0xd8:
+      size = this.unpack_uint16();
+      return this.unpack_string(size);
+    case 0xd9:
+      size = this.unpack_uint32();
+      return this.unpack_string(size);
+    case 0xda:
+      size = this.unpack_uint16();
+      return this.unpack_raw(size);
+    case 0xdb:
+      size = this.unpack_uint32();
+      return this.unpack_raw(size);
+    case 0xdc:
+      size = this.unpack_uint16();
+      return this.unpack_array(size);
+    case 0xdd:
+      size = this.unpack_uint32();
+      return this.unpack_array(size);
+    case 0xde:
+      size = this.unpack_uint16();
+      return this.unpack_map(size);
+    case 0xdf:
+      size = this.unpack_uint32();
+      return this.unpack_map(size);
+  }
+}
+
+Unpacker.prototype.unpack_uint8 = function(){
+  var byte = this.dataView[this.index] & 0xff;
+  this.index++;
+  return byte;
+};
+
+Unpacker.prototype.unpack_uint16 = function(){
+  var bytes = this.read(2);
+  var uint16 =
+    ((bytes[0] & 0xff) * 256) + (bytes[1] & 0xff);
+  this.index += 2;
+  return uint16;
+}
+
+Unpacker.prototype.unpack_uint32 = function(){
+  var bytes = this.read(4);
+  var uint32 =
+     ((bytes[0]  * 256 +
+       bytes[1]) * 256 +
+       bytes[2]) * 256 +
+       bytes[3];
+  this.index += 4;
+  return uint32;
+}
+
+Unpacker.prototype.unpack_uint64 = function(){
+  var bytes = this.read(8);
+  var uint64 =
+   ((((((bytes[0]  * 256 +
+       bytes[1]) * 256 +
+       bytes[2]) * 256 +
+       bytes[3]) * 256 +
+       bytes[4]) * 256 +
+       bytes[5]) * 256 +
+       bytes[6]) * 256 +
+       bytes[7];
+  this.index += 8;
+  return uint64;
+}
+
+
+Unpacker.prototype.unpack_int8 = function(){
+  var uint8 = this.unpack_uint8();
+  return (uint8 < 0x80 ) ? uint8 : uint8 - (1 << 8);
+};
+
+Unpacker.prototype.unpack_int16 = function(){
+  var uint16 = this.unpack_uint16();
+  return (uint16 < 0x8000 ) ? uint16 : uint16 - (1 << 16);
+}
+
+Unpacker.prototype.unpack_int32 = function(){
+  var uint32 = this.unpack_uint32();
+  return (uint32 < Math.pow(2, 31) ) ? uint32 :
+    uint32 - Math.pow(2, 32);
+}
+
+Unpacker.prototype.unpack_int64 = function(){
+  var uint64 = this.unpack_uint64();
+  return (uint64 < Math.pow(2, 63) ) ? uint64 :
+    uint64 - Math.pow(2, 64);
+}
+
+Unpacker.prototype.unpack_raw = function(size){
+  if ( this.length < this.index + size){
+    throw new Error('BinaryPackFailure: index is out of range'
+      + ' ' + this.index + ' ' + size + ' ' + this.length);
+  }
+  var buf = this.dataBuffer.slice(this.index, this.index + size);
+  this.index += size;
+
+    //buf = util.bufferToString(buf);
+
+  return buf;
+}
+
+Unpacker.prototype.unpack_string = function(size){
+  var bytes = this.read(size);
+  var i = 0, str = '', c, code;
+  while(i < size){
+    c = bytes[i];
+    if ( c < 128){
+      str += String.fromCharCode(c);
+      i++;
+    } else if ((c ^ 0xc0) < 32){
+      code = ((c ^ 0xc0) << 6) | (bytes[i+1] & 63);
+      str += String.fromCharCode(code);
+      i += 2;
+    } else {
+      code = ((c & 15) << 12) | ((bytes[i+1] & 63) << 6) |
+        (bytes[i+2] & 63);
+      str += String.fromCharCode(code);
+      i += 3;
+    }
+  }
+  this.index += size;
+  return str;
+}
+
+Unpacker.prototype.unpack_array = function(size){
+  var objects = new Array(size);
+  for(var i = 0; i < size ; i++){
+    objects[i] = this.unpack();
+  }
+  return objects;
+}
+
+Unpacker.prototype.unpack_map = function(size){
+  var map = {};
+  for(var i = 0; i < size ; i++){
+    var key  = this.unpack();
+    var value = this.unpack();
+    map[key] = value;
+  }
+  return map;
+}
+
+Unpacker.prototype.unpack_float = function(){
+  var uint32 = this.unpack_uint32();
+  var sign = uint32 >> 31;
+  var exp  = ((uint32 >> 23) & 0xff) - 127;
+  var fraction = ( uint32 & 0x7fffff ) | 0x800000;
+  return (sign == 0 ? 1 : -1) *
+    fraction * Math.pow(2, exp - 23);
+}
+
+Unpacker.prototype.unpack_double = function(){
+  var h32 = this.unpack_uint32();
+  var l32 = this.unpack_uint32();
+  var sign = h32 >> 31;
+  var exp  = ((h32 >> 20) & 0x7ff) - 1023;
+  var hfrac = ( h32 & 0xfffff ) | 0x100000;
+  var frac = hfrac * Math.pow(2, exp - 20) +
+    l32   * Math.pow(2, exp - 52);
+  return (sign == 0 ? 1 : -1) * frac;
+}
+
+Unpacker.prototype.read = function(length){
+  var j = this.index;
+  if (j + length <= this.length) {
+    return this.dataView.subarray(j, j + length);
+  } else {
+    throw new Error('BinaryPackFailure: read index out of range');
+  }
+}
+
+function Packer(){
+  this.bufferBuilder = new BufferBuilder();
+}
+
+Packer.prototype.getBuffer = function(){
+  return this.bufferBuilder.getBuffer();
+}
+
+Packer.prototype.pack = function(value){
+  var type = typeof(value);
+  if (type == 'string'){
+    this.pack_string(value);
+  } else if (type == 'number'){
+    if (Math.floor(value) === value){
+      this.pack_integer(value);
+    } else{
+      this.pack_double(value);
+    }
+  } else if (type == 'boolean'){
+    if (value === true){
+      this.bufferBuilder.append(0xc3);
+    } else if (value === false){
+      this.bufferBuilder.append(0xc2);
+    }
+  } else if (type == 'undefined'){
+    this.bufferBuilder.append(0xc0);
+  } else if (type == 'object'){
+    if (value === null){
+      this.bufferBuilder.append(0xc0);
+    } else {
+      var constructor = value.constructor;
+      if (constructor == Array){
+        this.pack_array(value);
+      } else if (constructor == Blob || constructor == File) {
+        this.pack_bin(value);
+      } else if (constructor == ArrayBuffer) {
+        if(binaryFeatures.useArrayBufferView) {
+          this.pack_bin(new Uint8Array(value));
+        } else {
+          this.pack_bin(value);
+        }
+      } else if ('BYTES_PER_ELEMENT' in value){
+        if(binaryFeatures.useArrayBufferView) {
+          this.pack_bin(new Uint8Array(value.buffer));
+        } else {
+          this.pack_bin(value.buffer);
+        }
+      } else if (constructor == Object){
+        this.pack_object(value);
+      } else if (constructor == Date){
+        this.pack_string(value.toString());
+      } else if (typeof value.toBinaryPack == 'function'){
+        this.bufferBuilder.append(value.toBinaryPack());
+      } else {
+        throw new Error('Type "' + constructor.toString() + '" not yet supported');
+      }
+    }
+  } else {
+    throw new Error('Type "' + type + '" not yet supported');
+  }
+  this.bufferBuilder.flush();
+}
+
+
+Packer.prototype.pack_bin = function(blob){
+  var length = blob.length || blob.byteLength || blob.size;
+  if (length <= 0x0f){
+    this.pack_uint8(0xa0 + length);
+  } else if (length <= 0xffff){
+    this.bufferBuilder.append(0xda) ;
+    this.pack_uint16(length);
+  } else if (length <= 0xffffffff){
+    this.bufferBuilder.append(0xdb);
+    this.pack_uint32(length);
+  } else{
+    throw new Error('Invalid length');
+  }
+  this.bufferBuilder.append(blob);
+}
+
+Packer.prototype.pack_string = function(str){
+  var length = utf8Length(str);
+
+  if (length <= 0x0f){
+    this.pack_uint8(0xb0 + length);
+  } else if (length <= 0xffff){
+    this.bufferBuilder.append(0xd8) ;
+    this.pack_uint16(length);
+  } else if (length <= 0xffffffff){
+    this.bufferBuilder.append(0xd9);
+    this.pack_uint32(length);
+  } else{
+    throw new Error('Invalid length');
+  }
+  this.bufferBuilder.append(str);
+}
+
+Packer.prototype.pack_array = function(ary){
+  var length = ary.length;
+  if (length <= 0x0f){
+    this.pack_uint8(0x90 + length);
+  } else if (length <= 0xffff){
+    this.bufferBuilder.append(0xdc)
+    this.pack_uint16(length);
+  } else if (length <= 0xffffffff){
+    this.bufferBuilder.append(0xdd);
+    this.pack_uint32(length);
+  } else{
+    throw new Error('Invalid length');
+  }
+  for(var i = 0; i < length ; i++){
+    this.pack(ary[i]);
+  }
+}
+
+Packer.prototype.pack_integer = function(num){
+  if ( -0x20 <= num && num <= 0x7f){
+    this.bufferBuilder.append(num & 0xff);
+  } else if (0x00 <= num && num <= 0xff){
+    this.bufferBuilder.append(0xcc);
+    this.pack_uint8(num);
+  } else if (-0x80 <= num && num <= 0x7f){
+    this.bufferBuilder.append(0xd0);
+    this.pack_int8(num);
+  } else if ( 0x0000 <= num && num <= 0xffff){
+    this.bufferBuilder.append(0xcd);
+    this.pack_uint16(num);
+  } else if (-0x8000 <= num && num <= 0x7fff){
+    this.bufferBuilder.append(0xd1);
+    this.pack_int16(num);
+  } else if ( 0x00000000 <= num && num <= 0xffffffff){
+    this.bufferBuilder.append(0xce);
+    this.pack_uint32(num);
+  } else if (-0x80000000 <= num && num <= 0x7fffffff){
+    this.bufferBuilder.append(0xd2);
+    this.pack_int32(num);
+  } else if (-0x8000000000000000 <= num && num <= 0x7FFFFFFFFFFFFFFF){
+    this.bufferBuilder.append(0xd3);
+    this.pack_int64(num);
+  } else if (0x0000000000000000 <= num && num <= 0xFFFFFFFFFFFFFFFF){
+    this.bufferBuilder.append(0xcf);
+    this.pack_uint64(num);
+  } else{
+    throw new Error('Invalid integer');
+  }
+}
+
+Packer.prototype.pack_double = function(num){
+  var sign = 0;
+  if (num < 0){
+    sign = 1;
+    num = -num;
+  }
+  var exp  = Math.floor(Math.log(num) / Math.LN2);
+  var frac0 = num / Math.pow(2, exp) - 1;
+  var frac1 = Math.floor(frac0 * Math.pow(2, 52));
+  var b32   = Math.pow(2, 32);
+  var h32 = (sign << 31) | ((exp+1023) << 20) |
+      (frac1 / b32) & 0x0fffff;
+  var l32 = frac1 % b32;
+  this.bufferBuilder.append(0xcb);
+  this.pack_int32(h32);
+  this.pack_int32(l32);
+}
+
+Packer.prototype.pack_object = function(obj){
+  var keys = Object.keys(obj);
+  var length = keys.length;
+  if (length <= 0x0f){
+    this.pack_uint8(0x80 + length);
+  } else if (length <= 0xffff){
+    this.bufferBuilder.append(0xde);
+    this.pack_uint16(length);
+  } else if (length <= 0xffffffff){
+    this.bufferBuilder.append(0xdf);
+    this.pack_uint32(length);
+  } else{
+    throw new Error('Invalid length');
+  }
+  for(var prop in obj){
+    if (obj.hasOwnProperty(prop)){
+      this.pack(prop);
+      this.pack(obj[prop]);
+    }
+  }
+}
+
+Packer.prototype.pack_uint8 = function(num){
+  this.bufferBuilder.append(num);
+}
+
+Packer.prototype.pack_uint16 = function(num){
+  this.bufferBuilder.append(num >> 8);
+  this.bufferBuilder.append(num & 0xff);
+}
+
+Packer.prototype.pack_uint32 = function(num){
+  var n = num & 0xffffffff;
+  this.bufferBuilder.append((n & 0xff000000) >>> 24);
+  this.bufferBuilder.append((n & 0x00ff0000) >>> 16);
+  this.bufferBuilder.append((n & 0x0000ff00) >>>  8);
+  this.bufferBuilder.append((n & 0x000000ff));
+}
+
+Packer.prototype.pack_uint64 = function(num){
+  var high = num / Math.pow(2, 32);
+  var low  = num % Math.pow(2, 32);
+  this.bufferBuilder.append((high & 0xff000000) >>> 24);
+  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
+  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
+  this.bufferBuilder.append((high & 0x000000ff));
+  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
+  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
+  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
+  this.bufferBuilder.append((low  & 0x000000ff));
+}
+
+Packer.prototype.pack_int8 = function(num){
+  this.bufferBuilder.append(num & 0xff);
+}
+
+Packer.prototype.pack_int16 = function(num){
+  this.bufferBuilder.append((num & 0xff00) >> 8);
+  this.bufferBuilder.append(num & 0xff);
+}
+
+Packer.prototype.pack_int32 = function(num){
+  this.bufferBuilder.append((num >>> 24) & 0xff);
+  this.bufferBuilder.append((num & 0x00ff0000) >>> 16);
+  this.bufferBuilder.append((num & 0x0000ff00) >>> 8);
+  this.bufferBuilder.append((num & 0x000000ff));
+}
+
+Packer.prototype.pack_int64 = function(num){
+  var high = Math.floor(num / Math.pow(2, 32));
+  var low  = num % Math.pow(2, 32);
+  this.bufferBuilder.append((high & 0xff000000) >>> 24);
+  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
+  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
+  this.bufferBuilder.append((high & 0x000000ff));
+  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
+  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
+  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
+  this.bufferBuilder.append((low  & 0x000000ff));
+}
+
+function _utf8Replace(m){
+  var code = m.charCodeAt(0);
+
+  if(code <= 0x7ff) return '00';
+  if(code <= 0xffff) return '000';
+  if(code <= 0x1fffff) return '0000';
+  if(code <= 0x3ffffff) return '00000';
+  return '000000';
+}
+
+function utf8Length(str){
+  if (str.length > 600) {
+    // Blob method faster for large strings
+    return (new Blob([str])).size;
+  } else {
+    return str.replace(/[^\u0000-\u007F]/g, _utf8Replace).length;
+  }
+}
 
 },{"./bufferbuilder":11}],11:[function(require,module,exports){
-var binaryFeatures = {};
-binaryFeatures.useBlobBuilder = (function(){
-  try {
-    new Blob([]);
-    return false;
-  } catch (e) {
-    return true;
-  }
-})();
-
-binaryFeatures.useArrayBufferView = !binaryFeatures.useBlobBuilder && (function(){
-  try {
-    return (new Blob([new Uint8Array([])])).size === 0;
-  } catch (e) {
-    return true;
-  }
-})();
-
-module.exports.binaryFeatures = binaryFeatures;
-var BlobBuilder = module.exports.BlobBuilder;
-if (typeof window != 'undefined') {
-  BlobBuilder = module.exports.BlobBuilder = window.WebKitBlobBuilder ||
-    window.MozBlobBuilder || window.MSBlobBuilder || window.BlobBuilder;
-}
-
-function BufferBuilder(){
-  this._pieces = [];
-  this._parts = [];
-}
-
-BufferBuilder.prototype.append = function(data) {
-  if(typeof data === 'number') {
-    this._pieces.push(data);
-  } else {
-    this.flush();
-    this._parts.push(data);
-  }
-};
-
-BufferBuilder.prototype.flush = function() {
-  if (this._pieces.length > 0) {
-    var buf = new Uint8Array(this._pieces);
-    if(!binaryFeatures.useArrayBufferView) {
-      buf = buf.buffer;
-    }
-    this._parts.push(buf);
-    this._pieces = [];
-  }
-};
-
-BufferBuilder.prototype.getBuffer = function() {
-  this.flush();
-  if(binaryFeatures.useBlobBuilder) {
-    var builder = new BlobBuilder();
-    for(var i = 0, ii = this._parts.length; i < ii; i++) {
-      builder.append(this._parts[i]);
-    }
-    return builder.getBlob();
-  } else {
-    return new Blob(this._parts);
-  }
-};
-
-module.exports.BufferBuilder = BufferBuilder;
+var binaryFeatures = {};
+binaryFeatures.useBlobBuilder = (function(){
+  try {
+    new Blob([]);
+    return false;
+  } catch (e) {
+    return true;
+  }
+})();
+
+binaryFeatures.useArrayBufferView = !binaryFeatures.useBlobBuilder && (function(){
+  try {
+    return (new Blob([new Uint8Array([])])).size === 0;
+  } catch (e) {
+    return true;
+  }
+})();
+
+module.exports.binaryFeatures = binaryFeatures;
+var BlobBuilder = module.exports.BlobBuilder;
+if (typeof window != 'undefined') {
+  BlobBuilder = module.exports.BlobBuilder = window.WebKitBlobBuilder ||
+    window.MozBlobBuilder || window.MSBlobBuilder || window.BlobBuilder;
+}
+
+function BufferBuilder(){
+  this._pieces = [];
+  this._parts = [];
+}
+
+BufferBuilder.prototype.append = function(data) {
+  if(typeof data === 'number') {
+    this._pieces.push(data);
+  } else {
+    this.flush();
+    this._parts.push(data);
+  }
+};
+
+BufferBuilder.prototype.flush = function() {
+  if (this._pieces.length > 0) {
+    var buf = new Uint8Array(this._pieces);
+    if(!binaryFeatures.useArrayBufferView) {
+      buf = buf.buffer;
+    }
+    this._parts.push(buf);
+    this._pieces = [];
+  }
+};
+
+BufferBuilder.prototype.getBuffer = function() {
+  this.flush();
+  if(binaryFeatures.useBlobBuilder) {
+    var builder = new BlobBuilder();
+    for(var i = 0, ii = this._parts.length; i < ii; i++) {
+      builder.append(this._parts[i]);
+    }
+    return builder.getBlob();
+  } else {
+    return new Blob(this._parts);
+  }
+};
+
+module.exports.BufferBuilder = BufferBuilder;
 
 },{}],12:[function(require,module,exports){
 var util = require('./util');

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


+ 191 - 126
lib/peer.js

@@ -1,8 +1,8 @@
-var util = require('./util');
-var EventEmitter = require('eventemitter3');
-var Socket = require('./socket');
-var MediaConnection = require('./mediaconnection');
-var DataConnection = require('./dataconnection');
+var util = require("./util");
+var EventEmitter = require("eventemitter3");
+var Socket = require("./socket");
+var MediaConnection = require("./mediaconnection");
+var DataConnection = require("./dataconnection");
 
 /**
  * A peer who can initiate connections with other peers.
@@ -22,26 +22,29 @@ function Peer(id, options) {
   //
 
   // Configurize options
-  options = util.extend({
-    debug: 0, // 1: Errors, 2: Warnings, 3: All logs
-    host: util.CLOUD_HOST,
-    port: util.CLOUD_PORT,
-    key: 'peerjs',
-    path: '/',
-    token: util.randomToken(),
-    config: util.defaultConfig
-  }, options);
+  options = util.extend(
+    {
+      debug: 0, // 1: Errors, 2: Warnings, 3: All logs
+      host: util.CLOUD_HOST,
+      port: util.CLOUD_PORT,
+      key: "peerjs",
+      path: "/",
+      token: util.randomToken(),
+      config: util.defaultConfig
+    },
+    options
+  );
   this.options = options;
   // Detect relative URL host.
-  if (options.host === '/') {
+  if (options.host === "/") {
     options.host = window.location.hostname;
   }
   // Set path correctly.
-  if (options.path[0] !== '/') {
-    options.path = '/' + options.path;
+  if (options.path[0] !== "/") {
+    options.path = "/" + options.path;
   }
-  if (options.path[options.path.length - 1] !== '/') {
-    options.path += '/';
+  if (options.path[options.path.length - 1] !== "/") {
+    options.path += "/";
   }
 
   // Set whether we use SSL to same as current host
@@ -57,24 +60,32 @@ function Peer(id, options) {
 
   // Sanity checks
   // Ensure WebRTC supported
-  if (!util.supports.audioVideo && !util.supports.data ) {
-    this._delayedAbort('browser-incompatible', 'The current browser does not support WebRTC');
+  if (!util.supports.audioVideo && !util.supports.data) {
+    this._delayedAbort(
+      "browser-incompatible",
+      "The current browser does not support WebRTC"
+    );
     return;
   }
   // Ensure alphanumeric id
   if (!util.validateId(id)) {
-    this._delayedAbort('invalid-id', 'ID "' + id + '" is invalid');
+    this._delayedAbort("invalid-id", 'ID "' + id + '" is invalid');
     return;
   }
   // Ensure valid key
   if (!util.validateKey(options.key)) {
-    this._delayedAbort('invalid-key', 'API KEY "' + options.key + '" is invalid');
+    this._delayedAbort(
+      "invalid-key",
+      'API KEY "' + options.key + '" is invalid'
+    );
     return;
   }
   // Ensure not using unsecure cloud server on SSL page
-  if (options.secure && options.host === '0.peerjs.com') {
-    this._delayedAbort('ssl-unavailable',
-      'The cloud server currently does not support HTTPS. Please run your own PeerServer to use HTTPS.');
+  if (options.secure && options.host === "0.peerjs.com") {
+    this._delayedAbort(
+      "ssl-unavailable",
+      "The cloud server currently does not support HTTPS. Please run your own PeerServer to use HTTPS."
+    );
     return;
   }
   //
@@ -106,24 +117,31 @@ util.inherits(Peer, EventEmitter);
 // websockets.)
 Peer.prototype._initializeServerConnection = function() {
   var self = this;
-  this.socket = new Socket(this.options.secure, this.options.host, this.options.port, this.options.path, this.options.key, this.options.wsport);
-  this.socket.on('message', function(data) {
+  this.socket = new Socket(
+    this.options.secure,
+    this.options.host,
+    this.options.port,
+    this.options.path,
+    this.options.key,
+    this.options.wsport
+  );
+  this.socket.on("message", function(data) {
     self._handleMessage(data);
   });
-  this.socket.on('error', function(error) {
-    self._abort('socket-error', error);
+  this.socket.on("error", function(error) {
+    self._abort("socket-error", error);
   });
-  this.socket.on('disconnected', function() {
+  this.socket.on("disconnected", function() {
     // If we haven't explicitly disconnected, emit error and disconnect.
     if (!self.disconnected) {
-      self.emitError('network', 'Lost connection to server.');
+      self.emitError("network", "Lost connection to server.");
       self.disconnect();
     }
   });
-  this.socket.on('close', function() {
+  this.socket.on("close", function() {
     // If we haven't explicitly disconnected, emit error.
     if (!self.disconnected) {
-      self._abort('socket-closed', 'Underlying socket is already closed.');
+      self._abort("socket-closed", "Underlying socket is already closed.");
     }
   });
 };
@@ -132,23 +150,33 @@ Peer.prototype._initializeServerConnection = function() {
 Peer.prototype._retrieveId = function(cb) {
   var self = this;
   var http = new XMLHttpRequest();
-  var protocol = this.options.secure ? 'https://' : 'http://';
-  var url = protocol + this.options.host + ':' + this.options.port +
-    this.options.path + this.options.key + '/id';
-  var queryString = '?ts=' + new Date().getTime() + '' + Math.random();
+  var protocol = this.options.secure ? "https://" : "http://";
+  var url =
+    protocol +
+    this.options.host +
+    ":" +
+    this.options.port +
+    this.options.path +
+    this.options.key +
+    "/id";
+  var queryString = "?ts=" + new Date().getTime() + "" + Math.random();
   url += queryString;
 
   // If there's no ID we need to wait for one before trying to init socket.
-  http.open('get', url, true);
+  http.open("get", url, true);
   http.onerror = function(e) {
-    util.error('Error retrieving ID', e);
-    var pathError = '';
-    if (self.options.path === '/' && self.options.host !== util.CLOUD_HOST) {
-      pathError = ' If you passed in a `path` to your self-hosted PeerServer, ' +
-        'you\'ll also need to pass in that same path when creating a new ' +
-        'Peer.';
+    util.error("Error retrieving ID", e);
+    var pathError = "";
+    if (self.options.path === "/" && self.options.host !== util.CLOUD_HOST) {
+      pathError =
+        " If you passed in a `path` to your self-hosted PeerServer, " +
+        "you'll also need to pass in that same path when creating a new " +
+        "Peer.";
     }
-    self._abort('server-error', 'Could not get an ID from the server.' + pathError);
+    self._abort(
+      "server-error",
+      "Could not get an ID from the server." + pathError
+    );
   };
   http.onreadystatechange = function() {
     if (http.readyState !== 4) {
@@ -177,71 +205,78 @@ Peer.prototype._handleMessage = function(message) {
   var connection;
 
   switch (type) {
-    case 'OPEN': // The connection to the server is open.
-      this.emit('open', this.id);
+    case "OPEN": // The connection to the server is open.
+      this.emit("open", this.id);
       this.open = true;
       break;
-    case 'ERROR': // Server error.
-      this._abort('server-error', payload.msg);
+    case "ERROR": // Server error.
+      this._abort("server-error", payload.msg);
       break;
-    case 'ID-TAKEN': // The selected ID is taken.
-      this._abort('unavailable-id', 'ID `' + this.id + '` is taken');
+    case "ID-TAKEN": // The selected ID is taken.
+      this._abort("unavailable-id", "ID `" + this.id + "` is taken");
       break;
-    case 'INVALID-KEY': // The given API key cannot be found.
-      this._abort('invalid-key', 'API KEY "' + this.options.key + '" is invalid');
+    case "INVALID-KEY": // The given API key cannot be found.
+      this._abort(
+        "invalid-key",
+        'API KEY "' + this.options.key + '" is invalid'
+      );
       break;
 
     //
-    case 'LEAVE': // Another peer has closed its connection to this peer.
-      util.log('Received leave message from', peer);
+    case "LEAVE": // Another peer has closed its connection to this peer.
+      util.log("Received leave message from", peer);
       this._cleanupPeer(peer);
       break;
 
-    case 'EXPIRE': // The offer sent to a peer has expired without response.
-      this.emitError('peer-unavailable', 'Could not connect to peer ' + peer);
+    case "EXPIRE": // The offer sent to a peer has expired without response.
+      this.emitError("peer-unavailable", "Could not connect to peer " + peer);
       break;
-    case 'OFFER': // we should consider switching this to CALL/CONNECT, but this is the least breaking option.
+    case "OFFER": // we should consider switching this to CALL/CONNECT, but this is the least breaking option.
       var connectionId = payload.connectionId;
       connection = this.getConnection(peer, connectionId);
 
       if (connection) {
-        util.warn('Offer received for existing Connection ID:', connectionId);
+        connection.close();
+        util.warn("Offer received for existing Connection ID:", connectionId);
         //connection.handleMessage(message);
+      }
+
+      // Create a new connection.
+      if (payload.type === "media") {
+        connection = new MediaConnection(peer, this, {
+          connectionId: connectionId,
+          _payload: payload,
+          metadata: payload.metadata
+        });
+        this._addConnection(peer, connection);
+        this.emit("call", connection);
+      } else if (payload.type === "data") {
+        connection = new DataConnection(peer, this, {
+          connectionId: connectionId,
+          _payload: payload,
+          metadata: payload.metadata,
+          label: payload.label,
+          serialization: payload.serialization,
+          reliable: payload.reliable
+        });
+        this._addConnection(peer, connection);
+        this.emit("connection", connection);
       } else {
-        // Create a new connection.
-        if (payload.type === 'media') {
-          connection = new MediaConnection(peer, this, {
-            connectionId: connectionId,
-            _payload: payload,
-            metadata: payload.metadata
-          });
-          this._addConnection(peer, connection);
-          this.emit('call', connection);
-        } else if (payload.type === 'data') {
-          connection = new DataConnection(peer, this, {
-            connectionId: connectionId,
-            _payload: payload,
-            metadata: payload.metadata,
-            label: payload.label,
-            serialization: payload.serialization,
-            reliable: payload.reliable
-          });
-          this._addConnection(peer, connection);
-          this.emit('connection', connection);
-        } else {
-          util.warn('Received malformed connection type:', payload.type);
-          return;
-        }
-        // Find messages.
-        var messages = this._getMessages(connectionId);
-        for (var i = 0, ii = messages.length; i < ii; i += 1) {
-          connection.handleMessage(messages[i]);
-        }
+        util.warn("Received malformed connection type:", payload.type);
+        return;
       }
+      // Find messages.
+      var messages = this._getMessages(connectionId);
+      for (var i = 0, ii = messages.length; i < ii; i += 1) {
+        connection.handleMessage(messages[i]);
+      }
+
       break;
     default:
       if (!payload) {
-        util.warn('You received a malformed message from ' + peer + ' of type ' + type);
+        util.warn(
+          "You received a malformed message from " + peer + " of type " + type
+        );
         return;
       }
 
@@ -255,7 +290,7 @@ Peer.prototype._handleMessage = function(message) {
         // Store for possible later use
         this._storeMessage(id, message);
       } else {
-        util.warn('You received an unrecognized message:', message);
+        util.warn("You received an unrecognized message:", message);
       }
       break;
   }
@@ -286,11 +321,16 @@ Peer.prototype._getMessages = function(connectionId) {
  */
 Peer.prototype.connect = function(peer, options) {
   if (this.disconnected) {
-    util.warn('You cannot connect to a new Peer because you called ' +
-      '.disconnect() on this Peer and ended your connection with the ' +
-      'server. You can create a new Peer to reconnect, or call reconnect ' +
-      'on this peer if you believe its ID to still be available.');
-    this.emitError('disconnected', 'Cannot connect to new Peer after disconnecting from server.');
+    util.warn(
+      "You cannot connect to a new Peer because you called " +
+        ".disconnect() on this Peer and ended your connection with the " +
+        "server. You can create a new Peer to reconnect, or call reconnect " +
+        "on this peer if you believe its ID to still be available."
+    );
+    this.emitError(
+      "disconnected",
+      "Cannot connect to new Peer after disconnecting from server."
+    );
     return;
   }
   var connection = new DataConnection(peer, this, options);
@@ -304,14 +344,21 @@ Peer.prototype.connect = function(peer, options) {
  */
 Peer.prototype.call = function(peer, stream, options) {
   if (this.disconnected) {
-    util.warn('You cannot connect to a new Peer because you called ' +
-      '.disconnect() on this Peer and ended your connection with the ' +
-      'server. You can create a new Peer to reconnect.');
-    this.emitError('disconnected', 'Cannot connect to new Peer after disconnecting from server.');
+    util.warn(
+      "You cannot connect to a new Peer because you called " +
+        ".disconnect() on this Peer and ended your connection with the " +
+        "server. You can create a new Peer to reconnect."
+    );
+    this.emitError(
+      "disconnected",
+      "Cannot connect to new Peer after disconnecting from server."
+    );
     return;
   }
   if (!stream) {
-    util.error('To call a peer, you must provide a stream from your browser\'s `getUserMedia`.');
+    util.error(
+      "To call a peer, you must provide a stream from your browser's `getUserMedia`."
+    );
     return;
   }
   options = options || {};
@@ -345,7 +392,7 @@ Peer.prototype.getConnection = function(peer, id) {
 
 Peer.prototype._delayedAbort = function(type, message) {
   var self = this;
-  util.setZeroTimeout(function(){
+  util.setZeroTimeout(function() {
     self._abort(type, message);
   });
 };
@@ -356,7 +403,7 @@ Peer.prototype._delayedAbort = function(type, message) {
  * it retains its disconnected state and its existing connections.
  */
 Peer.prototype._abort = function(type, message) {
-  util.error('Aborting!');
+  util.error("Aborting!");
   if (!this._lastServerId) {
     this.destroy();
   } else {
@@ -367,12 +414,12 @@ Peer.prototype._abort = function(type, message) {
 
 /** Emits a typed error message. */
 Peer.prototype.emitError = function(type, err) {
-  util.error('Error:', err);
-  if (typeof err === 'string') {
+  util.error("Error:", err);
+  if (typeof err === "string") {
     err = new Error(err);
   }
   err.type = type;
-  this.emit('error', err);
+  this.emit("error", err);
 };
 
 /**
@@ -389,7 +436,6 @@ Peer.prototype.destroy = function() {
   }
 };
 
-
 /** Disconnects every connection on this peer. */
 Peer.prototype._cleanup = function() {
   if (this.connections) {
@@ -398,7 +444,7 @@ Peer.prototype._cleanup = function() {
       this._cleanupPeer(peers[i]);
     }
   }
-  this.emit('close');
+  this.emit("close");
 };
 
 /** Closes all connections to this peer. */
@@ -417,14 +463,14 @@ Peer.prototype._cleanupPeer = function(peer) {
  */
 Peer.prototype.disconnect = function() {
   var self = this;
-  util.setZeroTimeout(function(){
+  util.setZeroTimeout(function() {
     if (!self.disconnected) {
       self.disconnected = true;
       self.open = false;
       if (self.socket) {
         self.socket.close();
       }
-      self.emit('disconnected', self.id);
+      self.emit("disconnected", self.id);
       self._lastServerId = self.id;
       self.id = null;
     }
@@ -434,17 +480,25 @@ Peer.prototype.disconnect = function() {
 /** Attempts to reconnect with the same ID. */
 Peer.prototype.reconnect = function() {
   if (this.disconnected && !this.destroyed) {
-    util.log('Attempting reconnection to server with ID ' + this._lastServerId);
+    util.log("Attempting reconnection to server with ID " + this._lastServerId);
     this.disconnected = false;
     this._initializeServerConnection();
     this._initialize(this._lastServerId);
   } else if (this.destroyed) {
-    throw new Error('This peer cannot reconnect to the server. It has already been destroyed.');
+    throw new Error(
+      "This peer cannot reconnect to the server. It has already been destroyed."
+    );
   } else if (!this.disconnected && !this.open) {
     // Do nothing. We're still connecting the first time.
-    util.error('In a hurry? We\'re still trying to make the initial connection!');
+    util.error(
+      "In a hurry? We're still trying to make the initial connection!"
+    );
   } else {
-    throw new Error('Peer ' + this.id + ' cannot reconnect because it is not disconnected from the server!');
+    throw new Error(
+      "Peer " +
+        this.id +
+        " cannot reconnect because it is not disconnected from the server!"
+    );
   }
 };
 
@@ -458,16 +512,22 @@ Peer.prototype.listAllPeers = function(cb) {
   cb = cb || function() {};
   var self = this;
   var http = new XMLHttpRequest();
-  var protocol = this.options.secure ? 'https://' : 'http://';
-  var url = protocol + this.options.host + ':' + this.options.port +
-    this.options.path + this.options.key + '/peers';
-  var queryString = '?ts=' + new Date().getTime() + '' + Math.random();
+  var protocol = this.options.secure ? "https://" : "http://";
+  var url =
+    protocol +
+    this.options.host +
+    ":" +
+    this.options.port +
+    this.options.path +
+    this.options.key +
+    "/peers";
+  var queryString = "?ts=" + new Date().getTime() + "" + Math.random();
   url += queryString;
 
   // If there's no ID we need to wait for one before trying to init socket.
-  http.open('get', url, true);
+  http.open("get", url, true);
   http.onerror = function(e) {
-    self._abort('server-error', 'Could not get peers from the server.');
+    self._abort("server-error", "Could not get peers from the server.");
     cb([]);
   };
   http.onreadystatechange = function() {
@@ -475,16 +535,21 @@ Peer.prototype.listAllPeers = function(cb) {
       return;
     }
     if (http.status === 401) {
-      var helpfulError = '';
+      var helpfulError = "";
       if (self.options.host !== util.CLOUD_HOST) {
-        helpfulError = 'It looks like you\'re using the cloud server. You can email ' +
-          'team@peerjs.com to enable peer listing for your API key.';
+        helpfulError =
+          "It looks like you're using the cloud server. You can email " +
+          "team@peerjs.com to enable peer listing for your API key.";
       } else {
-        helpfulError = 'You need to enable `allow_discovery` on your self-hosted ' +
-          'PeerServer to use this feature.';
+        helpfulError =
+          "You need to enable `allow_discovery` on your self-hosted " +
+          "PeerServer to use this feature.";
       }
       cb([]);
-      throw new Error('It doesn\'t look like you have permission to list peers IDs. ' + helpfulError);
+      throw new Error(
+        "It doesn't look like you have permission to list peers IDs. " +
+          helpfulError
+      );
     } else if (http.status !== 200) {
       cb([]);
     } else {

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