diff --git a/README.md b/README.md index 7b679b0..13f1201 100644 --- a/README.md +++ b/README.md @@ -50,25 +50,35 @@ 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') } }); ``` ### Combining with existing express app -WebSocket server needs server instance to bootup, so we should create express app, then get server from `listen` method and only after that bind PeerServer to express application. - ```javascript var express = require('express'); var app = express(); -var PeerServer = require('peer').PeerServer; +var ExpressPeerServer = require('peer').ExpressPeerServer; app.get('/', function (req, res, next) { res.send('Hello world!'); }); var server = app.listen(9000); -app.use(PeerServer({ server: server, path: '/api' })); +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 diff --git a/bin/peerjs b/bin/peerjs index 27ea169..b65cb22 100755 --- a/bin/peerjs +++ b/bin/peerjs @@ -4,8 +4,8 @@ var path = require('path') , pkg = require('../package.json') , fs = require('fs') , version = pkg.version - , app = require('express')() - , PeerServer = require('../lib') + , PeerServer = require('../lib').PeerServer + , util = require('../lib/util') , opts = require('optimist') .usage('Usage: $0') .options({ @@ -54,7 +54,8 @@ var path = require('path') }, path: { demand: false, - description: 'custom path' + description: 'custom path', + default: '/' }, allow_discovery: { demand: false, @@ -64,22 +65,33 @@ 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); }); -opts.server = app.listen(opts.port); +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)) + } -app.use(PeerServer(opts)); + 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); + } +} -console.log( - 'Started PeerServer, port: ' + opts.port + ', path: ' + (opts.path || '/') + (" (v. %s)"), version -); +var path = opts.path; +var server = PeerServer(opts, function(server) { + var host = server.address().address; + var port = server.address().port; + + console.log( + 'Started PeerServer on ' + host + ', port: ' + port + ', path: ' + + path + (" (v. %s)"), version + ); +}); diff --git a/lib/index.js b/lib/index.js index 6ee38ea..8680fe2 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,42 +3,26 @@ var mixin = require('utils-merge'); var proto = require('./server'); var util = require('./util'); var http = require('http'); +var https = require('https'); + +function ExpressPeerServer(server, options) { + if (!server) { + throw new Error('Server is not passed to constructor - '+ + 'can\'t start PeerServer'); + } -function createPeerServer(options, callback) { var app = express(); mixin(app, proto); - app.options = { - host: '0.0.0.0', - port: null, - server: null, + options = app.options = mixin({ debug: false, timeout: 5000, key: 'peerjs', ip_limit: 5000, concurrent_limit: 5000, - ssl: {}, - path: '/', allow_discovery: false - }; - - mixin(app.options, options); - - // Print warning if only one of the two is given. - if (Object.keys(app.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.'); - } - - app.options.ssl.name = 'PeerServer'; - - if (app.options.path[0] !== '/') { - app.options.path = '/' + app.options.path; - } - if (app.options.path[app.options.path.length - 1] !== '/') { - app.options.path += '/'; - } + }, options); // Connected clients app._clients = {}; @@ -46,24 +30,66 @@ function createPeerServer(options, callback) { // Messages waiting for another peer. app._outstanding = {}; - // Initialize HTTP routes. This is only used for the first few milliseconds - // before a socket is opened for a Peer. - app._initializeHTTP(); - // Mark concurrent users per ip app._ips = {}; - app._setCleanupIntervals(); - - app._server = options.server; - - if (!app._server) { - throw new Error('Server is not passed to constructor - can\'t start PeerServer'); - } - - app._initializeWSS(); + app.on('mount', function() { + // 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; } -exports = module.exports = createPeerServer; +function PeerServer(options, callback) { + var app = express(); + + var path = options.path || '/'; + var port = options.port; + + delete options.path; + delete options.port; + + 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 +}; diff --git a/lib/server.js b/lib/server.js index 470e0d8..beda7e7 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1,5 +1,4 @@ var util = require('./util'); -var express = require('express'); var bodyParser = require('body-parser'); var WebSocketServer = require('ws').Server; var url = require('url'); @@ -7,11 +6,18 @@ var url = require('url'); var app = exports = module.exports = {}; /** Initialize WebSocket server. */ -app._initializeWSS = function() { +app._initializeWSS = function(server) { var self = this; + if (this.mountpath instanceof Array) { + throw new Error("This app can only be mounted on a single path"); + } + + 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._server}); + this._wss = new WebSocketServer({ path: path, server: server}); this._wss.on('connection', function(socket) { var query = url.parse(socket.upgradeReq.url, true).query; @@ -139,13 +145,13 @@ app._initializeHTTP = function() { this.use(util.allowCrossDomain); // Retrieve guaranteed random ID. - this.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)); }); // Server sets up HTTP streaming when you get post an ID. - this.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; @@ -167,7 +173,7 @@ app._initializeHTTP = function() { }); // Get a list of all peers for a key, enabled by the `allowDiscovery` flag. - this.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) { @@ -213,13 +219,13 @@ app._initializeHTTP = function() { } }; - this.post(this.options.path + ':key/:id/:token/offer', handle); + this.post('/:key/:id/:token/offer', handle); - this.post(this.options.path + ':key/:id/:token/candidate', handle); + this.post('/:key/:id/:token/candidate', handle); - this.post(this.options.path + ':key/:id/:token/answer', handle); + this.post('/:key/:id/:token/answer', handle); - this.post(this.options.path + ':key/:id/:token/leave', handle); + this.post('/:key/:id/:token/leave', handle); }; /** Saves a streaming response and takes care of timeouts and headers. */ diff --git a/lib/util.js b/lib/util.js index a4bd656..2c89ca8 100644 --- a/lib/util.js +++ b/lib/util.js @@ -25,9 +25,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) {