Browse Source

Merge branch 'michelle-express-rewrite'

Michelle Bu 10 years ago
parent
commit
1c7ba7f77f
7 changed files with 328 additions and 326 deletions
  1. 41 3
      README.md
  2. 31 14
      bin/peerjs
  3. 99 0
      lib/index.js
  4. 39 118
      lib/server.js
  5. 1 15
      lib/util.js
  6. 5 4
      package.json
  7. 112 172
      test/server.js

+ 41 - 3
README.md

@@ -30,7 +30,7 @@ Or, create a custom server:
 
 ```javascript
 var PeerServer = require('peer').PeerServer;
-var server = new PeerServer({port: 9000, path: '/myapp'});
+var server = PeerServer({port: 9000, path: '/myapp'});
 ```
 
 Connecting to the server from PeerJS:
@@ -48,15 +48,53 @@ Using HTTPS: Simply pass in PEM-encoded certificate and key.
 var fs = require('fs');
 var PeerServer = require('peer').PeerServer;
 
-var server = new PeerServer({
+var server = PeerServer({
   port: 9000,
   ssl: {
     key: fs.readFileSync('/path/to/your/ssl/key/here.key'),
-    certificate: fs.readFileSync('/path/to/your/ssl/certificate/here.crt')
+    cert: fs.readFileSync('/path/to/your/ssl/certificate/here.crt')
   }
 });
 ```
 
+#### Running PeerServer behind a reverse proxy
+
+Make sure to set the `proxied` option, otherwise IP based limiting will fail.
+The option is passed verbatim to the
+[expressjs `trust proxy` setting](http://expressjs.com/4x/api.html#app-settings)
+if it is truthy.
+
+```javascript
+var PeerServer = require('peer').PeerServer;
+var server = PeerServer({port: 9000, path: '/myapp', proxied: true});
+```
+
+### Combining with existing express app
+
+```javascript
+var express = require('express');
+var app = express();
+var ExpressPeerServer = require('peer').ExpressPeerServer;
+
+app.get('/', function (req, res, next) { res.send('Hello world!'); });
+
+var server = app.listen(9000);
+
+var options = {
+    debug: true
+}
+
+app.use('/api', ExpressPeerServer(server, options));
+
+// OR
+
+var server = require('http').createServer(app);
+
+app.use('/api', ExpressPeerServer(server, options));
+
+server.listen(9000);
+```
+
 ### Events
 
 The `'connection'` event is emitted when a peer connects to the server.

+ 31 - 14
bin/peerjs

@@ -4,7 +4,8 @@ var path = require('path')
   , pkg = require('../package.json')
   , fs = require('fs')
   , version = pkg.version
-  , PeerServer = require('../lib/server').PeerServer
+  , PeerServer = require('../lib').PeerServer
+  , util = require('../lib/util')
   , opts = require('optimist')
     .usage('Usage: $0')
     .options({
@@ -53,7 +54,8 @@ var path = require('path')
       },
       path: {
         demand: false,
-        description: 'custom path'
+        description: 'custom path',
+        default: '/'
       },
       allow_discovery: {
         demand: false,
@@ -63,19 +65,34 @@ var path = require('path')
     .boolean('allow_discovery')
     .argv;
 
-opts.version = version;
-
-if (opts.sslkey && opts.sslcert) {
-  opts['ssl'] = {};
-  opts.ssl['key'] = fs.readFileSync(path.resolve(opts.sslkey));
-  opts.ssl['certificate'] = fs.readFileSync(path.resolve(opts.sslcert));
-}
-
 process.on('uncaughtException', function(e) {
   console.error('Error: ' + e);
 });
 
-var server = new PeerServer(opts);
-console.log(
-  'Started PeerServer, port: ' + opts.port + ', path: ' + (opts.path || '/') + (" (v. %s)"), version
-);
+if (opts.sslkey || opts.sslcert) {
+  if (opts.sslkey && opts.sslcert) {
+    opts.ssl = {
+      key: fs.readFileSync(path.resolve(opts.sslkey)),
+      cert: fs.readFileSync(path.resolve(opts.sslcert))
+    }
+
+    delete opts.sslkey;
+    delete opts.sslcert;
+  } else {
+    util.prettyError('Warning: PeerServer will not run because either ' +
+      'the key or the certificate has not been provided.');
+    process.exit(1);
+  }
+}
+
+
+var userPath = opts.path;
+var server = PeerServer(opts, function(server) {
+  var host = server.address().address;
+  var port = server.address().port;
+
+  console.log(
+    'Started PeerServer on %s, port: %s, path: %s (v. %s)',
+    host, port, userPath || '/', version
+  );
+});

+ 99 - 0
lib/index.js

@@ -0,0 +1,99 @@
+var express = require('express');
+var proto = require('./server');
+var util = require('./util');
+var http = require('http');
+var https = require('https');
+
+function ExpressPeerServer(server, options) {
+  var app = express();
+
+  util.extend(app, proto);
+
+  options = app._options = util.extend({
+    debug: false,
+    timeout: 5000,
+    key: 'peerjs',
+    ip_limit: 5000,
+    concurrent_limit: 5000,
+    allow_discovery: false,
+    proxied: false
+  }, options);
+
+  // Connected clients
+  app._clients = {};
+
+  // Messages waiting for another peer.
+  app._outstanding = {};
+
+  // Mark concurrent users per ip
+  app._ips = {};
+
+  if (options.proxied) {
+    app.set('trust proxy', options.proxied);
+  }
+
+  app.on('mount', function() {
+    if (!server) {
+      throw new Error('Server is not passed to constructor - '+
+        'can\'t start PeerServer');
+    }
+
+    // Initialize HTTP routes. This is only used for the first few milliseconds
+    // before a socket is opened for a Peer.
+    app._initializeHTTP();
+    app._setCleanupIntervals();
+    app._initializeWSS(server);
+  });
+
+  return app;
+}
+
+function PeerServer(options, callback) {
+  var app = express();
+
+  options = options || {};
+  var path = options.path || '/';
+  var port = options.port || 80;
+
+  delete options.path;
+
+  if (path[0] !== '/') {
+    path = '/' + path;
+  }
+
+  if (path[path.length - 1] !== '/') {
+    path += '/';
+  }
+
+  var server;
+  if (options.ssl) {
+    if (options.ssl.certificate) {
+      // Preserve compatibility with 0.2.7 API
+      options.ssl.cert = options.ssl.certificate;
+      delete options.ssl.certificate;
+    }
+
+    server = https.createServer(options.ssl, app);
+    delete options.ssl;
+  } else {
+    server = http.createServer(app);
+  }
+
+  var peerjs = ExpressPeerServer(server, options);
+  app.use(path, peerjs);
+
+  if (callback) {
+    server.listen(port, function() {
+      callback(server);
+    });
+  } else {
+    server.listen(port);
+  }
+
+  return peerjs;
+}
+
+exports = module.exports = {
+  ExpressPeerServer: ExpressPeerServer,
+  PeerServer: PeerServer
+};

+ 39 - 118
lib/server.js

@@ -1,72 +1,23 @@
 var util = require('./util');
-var restify = require('restify');
-var EventEmitter = require('events').EventEmitter;
+var bodyParser = require('body-parser');
 var WebSocketServer = require('ws').Server;
 var url = require('url');
 
-function PeerServer(options) {
-  if (!(this instanceof PeerServer)) return new PeerServer(options);
-  EventEmitter.call(this);
-
-  this._options = util.extend({
-    port: 80,
-    debug: false,
-    timeout: 5000,
-    key: 'peerjs',
-    ip_limit: 5000,
-    concurrent_limit: 5000,
-    ssl: {},
-    path: '/',
-    allow_discovery: false
-  }, options);
-
-  util.debug = this._options.debug;
-
-  // Print warning if only one of the two is given.
-  if (Object.keys(this._options.ssl).length === 1) {
-    util.prettyError('Warning: PeerServer will not run on an HTTPS server'
-        + ' because either the key or the certificate has not been provided.');
-  }
+var app = exports = module.exports = {};
 
-  this._options.ssl['name'] = 'PeerServer';
+/** Initialize WebSocket server. */
+app._initializeWSS = function(server) {
+  var self = this;
 
-  if (this._options.path[0] !== '/') {
-    this._options.path = '/' + this._options.path;
-  }
-  if (this._options.path[this._options.path.length - 1] !== '/') {
-    this._options.path += '/';
+  if (this.mountpath instanceof Array) {
+    throw new Error("This app can only be mounted on a single path");
   }
 
-  this._app = restify.createServer(this._options.ssl);
-
-  // Connected clients
-  this._clients = {};
-
-  // Messages waiting for another peer.
-  this._outstanding = {};
-
-  // Initailize WebSocket server handlers.
-  this._initializeWSS();
-
-  // Initialize HTTP routes. This is only used for the first few milliseconds
-  // before a socket is opened for a Peer.
-  this._initializeHTTP();
-
-  // Mark concurrent users per ip
-  this._ips = {};
-
-  this._setCleanupIntervals();
-}
-
-util.inherits(PeerServer, EventEmitter);
-
-
-/** Initialize WebSocket server. */
-PeerServer.prototype._initializeWSS = function() {
-  var self = this;
+  var path = this.mountpath;
+  var path = path + (path[path.length - 1] != '/' ? '/' : '') + 'peerjs';
 
   // Create WebSocket server as well.
-  this._wss = new WebSocketServer({ path: this._options.path + 'peerjs', server: this._app});
+  this._wss = new WebSocketServer({ path: path, server: server});
 
   this._wss.on('connection', function(socket) {
     var query = url.parse(socket.upgradeReq.url, true).query;
@@ -100,7 +51,8 @@ PeerServer.prototype._initializeWSS = function() {
   });
 };
 
-PeerServer.prototype._configureWS = function(socket, key, id, token) {
+app._configureWS = function(socket, key, id, token) {
+
   var self = this;
   var client = this._clients[key][id];
 
@@ -122,7 +74,7 @@ PeerServer.prototype._configureWS = function(socket, key, id, token) {
 
   // Cleanup after a socket closes.
   socket.on('close', function() {
-    util.log('Socket closed:', id);
+    self._log('Socket closed:', id);
     if (client.socket == socket) {
       self._removePeer(key, id);
     }
@@ -144,7 +96,7 @@ PeerServer.prototype._configureWS = function(socket, key, id, token) {
         util.prettyError('Message unrecognized');
       }
     } catch(e) {
-      util.log('Invalid message', data);
+      self._log('Invalid message', data);
       throw e;
     }
   });
@@ -154,11 +106,11 @@ PeerServer.prototype._configureWS = function(socket, key, id, token) {
   this.emit('connection', id);
 };
 
-PeerServer.prototype._checkAllowsDiscovery = function(key, cb) {
+app._checkAllowsDiscovery = function(key, cb) {
   cb(this._options.allow_discovery);
 };
 
-PeerServer.prototype._checkKey = function(key, ip, cb) {
+app._checkKey = function(key, ip, cb) {
   if (key == this._options.key) {
     if (!this._clients[key]) {
       this._clients[key] = {};
@@ -185,46 +137,23 @@ PeerServer.prototype._checkKey = function(key, ip, cb) {
 };
 
 /** Initialize HTTP server routes. */
-PeerServer.prototype._initializeHTTP = function() {
+app._initializeHTTP = function() {
   var self = this;
 
-  this._app.use(restify.bodyParser({ mapParams: false }));
-  this._app.use(restify.queryParser());
-  this._app.use(util.allowCrossDomain);
-
-  /** Hack from https://github.com/mcavage/node-restify/issues/284, until we switch to express */
-  function unknownMethodHandler(req, res) {
-    if (req.method.toLowerCase() === 'options') {
-      var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version'];
-
-      if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');
-
-      res.header('Access-Control-Allow-Credentials', true);
-      res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
-      res.header('Access-Control-Allow-Methods', res.methods.join(', '));
-      res.header('Access-Control-Allow-Origin', req.headers.origin);
-
-      return res.send(204);
-    } else {
-      return res.send(new restify.MethodNotAllowedError());
-    }
-  }
-
-  this._app.on('MethodNotAllowed', unknownMethodHandler);
+  this.use(util.allowCrossDomain);
 
   this._app.get(this._options.path, function(req, res, next) {
     res.send(require('../app.json'));
   });
 
   // Retrieve guaranteed random ID.
-  this._app.get(this._options.path + ':key/id', function(req, res, next) {
+  this.get('/:key/id', function(req, res, next) {
     res.contentType = 'text/html';
     res.send(self._generateClientId(req.params.key));
-    return next();
   });
 
   // Server sets up HTTP streaming when you get post an ID.
-  this._app.post(this._options.path + ':key/:id/:token/id', function(req, res, next) {
+  this.post('/:key/:id/:token/id', function(req, res, next) {
     var id = req.params.id;
     var token = req.params.token;
     var key = req.params.key;
@@ -243,11 +172,10 @@ PeerServer.prototype._initializeHTTP = function() {
     } else {
       self._startStreaming(res, key, id, token);
     }
-    return next();
   });
 
   // Get a list of all peers for a key, enabled by the `allowDiscovery` flag.
-  this._app.get(this._options.path + ':key/peers', function(req, res, next) {
+  this.get('/:key/peers', function(req, res, next) {
     var key = req.params.key;
     if (self._clients[key]) {
       self._checkAllowsDiscovery(key, function(isAllowed) {
@@ -256,11 +184,9 @@ PeerServer.prototype._initializeHTTP = function() {
         } else {
           res.send(401);
         }
-        return next();
       });
     } else {
       res.send(404);
-      return next();
     }
   });
 
@@ -272,7 +198,6 @@ PeerServer.prototype._initializeHTTP = function() {
     if (!self._clients[key] || !(client = self._clients[key][id])) {
       if (req.params.retry) {
         res.send(401);
-        return next();
       } else {
         // Retry this request
         req.params.retry = true;
@@ -294,28 +219,21 @@ PeerServer.prototype._initializeHTTP = function() {
       });
       res.send(200);
     }
-    return next();
   };
 
-  this._app.post(this._options.path + ':key/:id/:token/offer', handle);
+  var jsonParser = bodyParser.json();
 
-  this._app.post(this._options.path + ':key/:id/:token/candidate', handle);
+  this.post('/:key/:id/:token/offer', jsonParser, handle);
 
-  this._app.post(this._options.path + ':key/:id/:token/answer', handle);
+  this.post('/:key/:id/:token/candidate', jsonParser, handle);
 
-  this._app.post(this._options.path + ':key/:id/:token/leave', handle);
-
-  // Listen on user-specified port and IP address.
-  if (this._options.ip) {
-    this._app.listen(this._options.port, this._options.ip);
-  } else {
-    this._app.listen(this._options.port);
-  }
+  this.post('/:key/:id/:token/answer', jsonParser, handle);
 
+  this.post('/:key/:id/:token/leave', jsonParser, handle);
 };
 
 /** Saves a streaming response and takes care of timeouts and headers. */
-PeerServer.prototype._startStreaming = function(res, key, id, token, open) {
+app._startStreaming = function(res, key, id, token, open) {
   var self = this;
 
   res.writeHead(200, {'Content-Type': 'application/octet-stream'});
@@ -352,7 +270,7 @@ PeerServer.prototype._startStreaming = function(res, key, id, token, open) {
   }
 };
 
-PeerServer.prototype._pruneOutstanding = function() {
+app._pruneOutstanding = function() {
   var keys = Object.keys(this._outstanding);
   for (var k = 0, kk = keys.length; k < kk; k += 1) {
     var key = keys[k];
@@ -373,7 +291,7 @@ PeerServer.prototype._pruneOutstanding = function() {
 };
 
 /** Cleanup */
-PeerServer.prototype._setCleanupIntervals = function() {
+app._setCleanupIntervals = function() {
   var self = this;
 
   // Clean up ips every 10 minutes
@@ -394,7 +312,7 @@ PeerServer.prototype._setCleanupIntervals = function() {
 };
 
 /** Process outstanding peer offers. */
-PeerServer.prototype._processOutstanding = function(key, id) {
+app._processOutstanding = function(key, id) {
   var offers = this._outstanding[key][id];
   if (!offers) {
     return;
@@ -405,7 +323,7 @@ PeerServer.prototype._processOutstanding = function(key, id) {
   delete this._outstanding[key][id];
 };
 
-PeerServer.prototype._removePeer = function(key, id) {
+app._removePeer = function(key, id) {
   if (this._clients[key] && this._clients[key][id]) {
     this._ips[this._clients[key][id].ip]--;
     delete this._clients[key][id];
@@ -414,7 +332,7 @@ PeerServer.prototype._removePeer = function(key, id) {
 };
 
 /** Handles passing on a message. */
-PeerServer.prototype._handleTransmission = function(key, message) {
+app._handleTransmission = function(key, message) {
   var type = message.type;
   var src = message.src;
   var dst = message.dst;
@@ -425,7 +343,7 @@ PeerServer.prototype._handleTransmission = function(key, message) {
   // User is connected!
   if (destination) {
     try {
-      util.log(type, 'from', src, 'to', dst);
+      this._log(type, 'from', src, 'to', dst);
       if (destination.socket) {
         destination.socket.send(data);
       } else if (destination.res) {
@@ -438,7 +356,6 @@ PeerServer.prototype._handleTransmission = function(key, message) {
     } catch (e) {
       // This happens when a peer disconnects without closing connections and
       // the associated WebSocket has not closed.
-      util.prettyError(e);
       // Tell other side to stop trying.
       this._removePeer(key, dst);
       this._handleTransmission(key, {
@@ -465,7 +382,7 @@ PeerServer.prototype._handleTransmission = function(key, message) {
   }
 };
 
-PeerServer.prototype._generateClientId = function(key) {
+app._generateClientId = function(key) {
   var clientId = util.randomId();
   if (!this._clients[key]) {
     return clientId;
@@ -476,4 +393,8 @@ PeerServer.prototype._generateClientId = function(key) {
   return clientId;
 };
 
-exports.PeerServer = PeerServer;
+app._log = function() {
+  if (this._options.debug) {
+    console.log.apply(console, arguments);
+  }
+};

+ 1 - 15
lib/util.js

@@ -1,4 +1,3 @@
-
 var util = {
   debug: false,
   inherits: function(ctor, superCtor) {
@@ -25,18 +24,7 @@ var util = {
     return (Math.random().toString(36) + '0000000000000000000').substr(2, 16);
   },
   prettyError: function (msg) {
-    if (util.debug) {
-      console.log('ERROR PeerServer: ', msg);
-    }
-  },
-  log: function() {
-    if (util.debug) {
-      var copy = [];
-      for (var i = 0; i < arguments.length; i += 1) {
-        copy[i] = arguments[i];
-      }
-      console.log.apply(console, copy);
-    }
+    console.log('ERROR PeerServer: ', msg);
   },
   allowCrossDomain: function(req, res, next) {
     res.setHeader('Access-Control-Allow-Origin', '*');
@@ -47,6 +35,4 @@ var util = {
   }
 };
 
-// if node
 module.exports = util;
-// end node

+ 5 - 4
package.json

@@ -2,7 +2,7 @@
   "name": "peer",
   "version": "0.2.7",
   "description": "PeerJS server component",
-  "main": "lib/server.js",
+  "main": "lib/index.js",
   "bin": {
     "peerjs": "./bin/peerjs"
   },
@@ -13,9 +13,10 @@
   "author": "Michelle Bu, Eric Zhang",
   "license": "MIT",
   "dependencies": {
-    "restify": "~2.6.0",
-    "ws": "~0.4.25",
-    "optimist": "*"
+    "body-parser": "^1.9.0",
+    "express": "^4.9.8",
+    "optimist": "~0.6.1",
+    "ws": "~0.4.25"
   },
   "devDependencies": {
     "expect.js": "*",

+ 112 - 172
test/server.js

@@ -1,212 +1,152 @@
-var PeerServer = require('../').PeerServer;
+var ExpressPeerServer = require('../').ExpressPeerServer;
 var expect = require('expect.js');
 var sinon = require('sinon');
 
-describe('PeerServer', function() {
-  describe('constructor', function() {
-    before(function() {
-      PeerServer.prototype._initializeWSS = sinon.stub();
-      PeerServer.prototype._initializeHTTP = sinon.stub();
-    });
-
-    it('should be able to be created without the `new` keyword', function() {
-      var p = PeerServer();
-      expect(p.constructor).to.be(PeerServer);
-    });
-
-    it('should default to port 80, key `peerjs`', function() {
-      var p = new PeerServer();
-      expect(p._options.key).to.be('peerjs');
-      expect(p._options.port).to.be(80);
-    });
-
-    it('should accept a custom port', function() {
-      var p = new PeerServer({ port: 8000 });
-      expect(p._options.port).to.be(8000);
-    });
-  });
-
-  describe('#_initializeWSS', function() {
-    WebSocketServer = sinon.stub();
-
-  });
-
-  describe('#_configureWS', function() {
-
-  });
-
-  describe('#_checkKey', function() {
+describe('ExpressPeerServer', function() {
+  describe('method', function() {
     var p;
+
     before(function() {
-      PeerServer.prototype._initializeHTTP = sinon.stub();
-      p = new PeerServer({ port: 8000 });
-      p._checkKey('peerjs', 'myip', function() {});
+      p = ExpressPeerServer(undefined, {port: 8000});
     });
 
-    it('should reject keys that are not the default', function(done) {
-      p._checkKey('bad key', null, function(response) {
-        expect(response).to.be('Invalid key provided');
-        done();
+    describe('#_checkKey', function() {
+      it('should reject keys that are not the default', function(done) {
+        p._checkKey('bad key', null, function(response) {
+          expect(response).to.be('Invalid key provided');
+          done();
+        });
       });
-    });
 
-    it('should accept valid key/ip pairs', function(done) {
-      p._checkKey('peerjs', 'myip', function(response) {
-        expect(response).to.be(null);
-        done();
+      it('should accept valid key/ip pairs', function(done) {
+        p._checkKey('peerjs', 'myip', function(response) {
+          expect(response).to.be(null);
+          done();
+        });
       });
-    });
 
-    it('should reject ips that are at their limit', function(done) {
-      p._options.ip_limit = 0;
-      p._checkKey('peerjs', 'myip', function(response) {
-        expect(response).to.be('myip has reached its concurrent user limit');
-        done();
+      it('should reject ips that are at their limit', function(done) {
+        p._options.ip_limit = 0;
+        p._checkKey('peerjs', 'myip', function(response) {
+          expect(response).to.be('myip has reached its concurrent user limit');
+          done();
+        });
       });
-    });
 
-    it('should reject when the server is at its limit', function(done) {
-      p._options.concurrent_limit = 0;
-      p._checkKey('peerjs', 'myip', function(response) {
-        expect(response).to.be('Server has reached its concurrent user limit');
-        done();
+      it('should reject when the server is at its limit', function(done) {
+        p._options.concurrent_limit = 0;
+        p._checkKey('peerjs', 'myip', function(response) {
+          expect(response).to.be('Server has reached its concurrent user limit');
+          done();
+        });
       });
     });
 
-  });
-
-  describe('#_initializeHTTP', function() {
-
-  });
-
-  describe('#_startStreaming', function() {
-
-  });
-
-  describe('#_pruneOutstanding', function() {
-
-  });
-
-  describe('#_processOutstanding', function() {
-
-  });
-
-  describe('#_removePeer', function() {
-    var p;
-    before(function() {
-      PeerServer.prototype._initializeHTTP = sinon.stub();
-      p = new PeerServer({ port: 8000 });
+    describe('#_removePeer', function() {
+      before(function() {
+        var fake = {ip: '0.0.0.0'};
+        p._ips[fake.ip] = 1;
+        p._clients['peerjs'] = {};
+        p._clients['peerjs']['test'] = fake;
+      });
 
-      var fake = {ip: '0.0.0.0'};
-      p._ips[fake.ip] = 1;
-      p._clients['peerjs'] = {};
-      p._clients['peerjs']['test'] = fake;
+      it('should decrement the number of ips being used and remove the connection', function() {
+        expect(p._ips['0.0.0.0']).to.be(1);
+        p._removePeer('peerjs', 'test');
+        expect(p._ips['0.0.0.0']).to.be(0);
+        expect(p._clients['peerjs']['test']).to.be(undefined);
+      });
     });
 
-    it('should decrement the number of ips being used and remove the connection', function() {
-      expect(p._ips['0.0.0.0']).to.be(1);
-      p._removePeer('peerjs', 'test');
-      expect(p._ips['0.0.0.0']).to.be(0);
-      expect(p._clients['peerjs']['test']).to.be(undefined);
-    });
-  });
+    describe('#_handleTransmission', function() {
+      var KEY = 'peerjs';
+      var ID = 'test';
 
-  describe('#_handleTransmission', function() {
-    var p;
-    var KEY = 'peerjs';
-    var ID = 'test';
-    before(function() {
-      PeerServer.prototype._initializeHTTP = sinon.stub();
-      p = new PeerServer({ port: 8000 });
-      p._clients[KEY] = {};
-    });
+      before(function() {
+        p._clients[KEY] = {};
+      });
 
-    it('should send to the socket when appropriate', function() {
-      var send = sinon.spy();
-      var write = sinon.spy();
-      var message = {dst: ID};
-      p._clients[KEY][ID] = {
-        socket: {
+      it('should send to the socket when appropriate', function() {
+        var send = sinon.spy();
+        var write = sinon.spy();
+        var message = {dst: ID};
+        p._clients[KEY][ID] = {
+          socket: {
           send: send
-        },
-        res: {
+          },
+          res: {
           write: write
+          }
         }
-      }
-      p._handleTransmission(KEY, message);
-      expect(send.calledWith(JSON.stringify(message))).to.be(true);
-      expect(write.calledWith(JSON.stringify(message))).to.be(false);
-    });
+        p._handleTransmission(KEY, message);
+        expect(send.calledWith(JSON.stringify(message))).to.be(true);
+        expect(write.calledWith(JSON.stringify(message))).to.be(false);
+      });
 
-    it('should write to the response with a newline when appropriate', function() {
-      var write = sinon.spy();
-      var message = {dst: ID};
-      p._clients[KEY][ID] = {
-        res: {
+      it('should write to the response with a newline when appropriate', function() {
+        var write = sinon.spy();
+        var message = {dst: ID};
+        p._clients[KEY][ID] = {
+          res: {
           write: write
+          }
         }
-      }
-      p._handleTransmission(KEY, message);
-      expect(write.calledWith(JSON.stringify(message) + '\n')).to.be(true);
-    });
+        p._handleTransmission(KEY, message);
+        expect(write.calledWith(JSON.stringify(message) + '\n')).to.be(true);
+      });
 
-    // no destination.
-    it('should push to outstanding messages if the destination is not found', function() {
-      var message = {dst: ID};
-      p._outstanding[KEY] = {};
-      p._clients[KEY] = {};
-      p._handleTransmission(KEY, message);
-      expect(p._outstanding[KEY][ID][0]).to.be(message);
-    });
+      // no destination.
+      it('should push to outstanding messages if the destination is not found', function() {
+        var message = {dst: ID};
+        p._outstanding[KEY] = {};
+        p._clients[KEY] = {};
+        p._handleTransmission(KEY, message);
+        expect(p._outstanding[KEY][ID][0]).to.be(message);
+      });
 
-    it('should not push to outstanding messages if the message is a LEAVE or EXPIRE', function() {
-      var message = {dst: ID, type: 'LEAVE'};
-      p._outstanding[KEY] = {};
-      p._clients[KEY] = {};
-      p._handleTransmission(KEY, message);
-      expect(p._outstanding[KEY][ID]).to.be(undefined);
+      it('should not push to outstanding messages if the message is a LEAVE or EXPIRE', function() {
+        var message = {dst: ID, type: 'LEAVE'};
+        p._outstanding[KEY] = {};
+        p._clients[KEY] = {};
+        p._handleTransmission(KEY, message);
+        expect(p._outstanding[KEY][ID]).to.be(undefined);
 
-      message = {dst: ID, type: 'EXPIRE'};
-      p._handleTransmission(KEY, message);
-      expect(p._outstanding[KEY][ID]).to.be(undefined);
-    });
+        message = {dst: ID, type: 'EXPIRE'};
+        p._handleTransmission(KEY, message);
+        expect(p._outstanding[KEY][ID]).to.be(undefined);
+      });
 
-    it('should remove the peer if there is no dst in the message', function() {
-      var message = {type: 'LEAVE'};
-      p._removePeer = sinon.spy();
-      p._outstanding[KEY] = {};
-      p._handleTransmission(KEY, message);
-      expect(p._removePeer.calledWith(KEY, undefined)).to.be(true);
-    });
+      it('should remove the peer if there is no dst in the message', function() {
+        var message = {type: 'LEAVE'};
+        p._removePeer = sinon.spy();
+        p._outstanding[KEY] = {};
+        p._handleTransmission(KEY, message);
+        expect(p._removePeer.calledWith(KEY, undefined)).to.be(true);
+      });
 
-    it('should remove the peer and send a LEAVE message if the socket appears to be closed', function() {
-      var send = sinon.stub().throws();
-      var message = {dst: ID};
-      var leaveMessage = {type: 'LEAVE', dst: undefined, src: ID};
-      var oldHandleTransmission = p._handleTransmission;
-      p._removePeer = function() {
-        // Hacks!
-        p._handleTransmission = sinon.spy();
-      };
-      p._clients[KEY][ID] = {
-        socket: {
+      it('should remove the peer and send a LEAVE message if the socket appears to be closed', function() {
+        var send = sinon.stub().throws();
+        var message = {dst: ID};
+        var leaveMessage = {type: 'LEAVE', dst: undefined, src: ID};
+        var oldHandleTransmission = p._handleTransmission;
+        p._removePeer = function() {
+          // Hacks!
+          p._handleTransmission = sinon.spy();
+        };
+        p._clients[KEY][ID] = {
+          socket: {
           send: send
+          }
         }
-      }
-      p._handleTransmission(KEY, message);
-      expect(p._handleTransmission.calledWith(KEY, leaveMessage)).to.be(true);
-    });
-  });
-
-  describe('#_generateClientId', function() {
-    var p;
-    before(function() {
-      PeerServer.prototype._initializeHTTP = sinon.stub();
-      p = new PeerServer({ port: 8000 });
+        p._handleTransmission(KEY, message);
+        expect(p._handleTransmission.calledWith(KEY, leaveMessage)).to.be(true);
+      });
     });
 
-    it('should generate a 16-character ID', function() {
+    describe('#_generateClientId', function() {
+      it('should generate a 16-character ID', function() {
       expect(p._generateClientId('anykey').length).to.be(16);
+      });
     });
   });
 });