|
@@ -1,10 +1,10 @@
|
|
|
-var util = require('./util');
|
|
|
-var bodyParser = require('body-parser');
|
|
|
-var WebSocketServer = require('ws').Server;
|
|
|
-var url = require('url');
|
|
|
-var cors = require('cors');
|
|
|
+var util = require("./util");
|
|
|
+var bodyParser = require("body-parser");
|
|
|
+var WebSocketServer = require("ws").Server;
|
|
|
+var url = require("url");
|
|
|
+var cors = require("cors");
|
|
|
|
|
|
-var app = exports = module.exports = {};
|
|
|
+var app = (exports = module.exports = {});
|
|
|
|
|
|
/** Initialize WebSocket server. */
|
|
|
app._initializeWSS = function(server) {
|
|
@@ -15,13 +15,12 @@ app._initializeWSS = function(server) {
|
|
|
}
|
|
|
|
|
|
var path = this.mountpath;
|
|
|
- var path = path + (path[path.length - 1] != '/' ? '/' : '') + 'peerjs';
|
|
|
+ var path = path + (path[path.length - 1] != "/" ? "/" : "") + "peerjs";
|
|
|
|
|
|
// Create WebSocket server as well.
|
|
|
- this._wss = new WebSocketServer({ path: path, server: server});
|
|
|
+ this._wss = new WebSocketServer({ path: path, server: server });
|
|
|
|
|
|
- this._wss.on('connection', function(socket, req) {
|
|
|
- if(!req.url) return;
|
|
|
+ this._wss.on("connection", function(socket, req) {
|
|
|
var query = url.parse(req.url, true).query;
|
|
|
var id = query.id;
|
|
|
var token = query.token;
|
|
@@ -29,7 +28,12 @@ app._initializeWSS = function(server) {
|
|
|
var ip = req.socket.remoteAddress;
|
|
|
|
|
|
if (!id || !token || !key) {
|
|
|
- socket.send(JSON.stringify({ type: 'ERROR', payload: { msg: 'No id, token, or key supplied to websocket server' } }));
|
|
|
+ socket.send(
|
|
|
+ JSON.stringify({
|
|
|
+ type: "ERROR",
|
|
|
+ payload: { msg: "No id, token, or key supplied to websocket server" }
|
|
|
+ })
|
|
|
+ );
|
|
|
socket.close();
|
|
|
return;
|
|
|
}
|
|
@@ -40,11 +44,11 @@ app._initializeWSS = function(server) {
|
|
|
if (!self._clients[key][id]) {
|
|
|
self._clients[key][id] = { token: token, ip: ip };
|
|
|
self._ips[ip]++;
|
|
|
- socket.send(JSON.stringify({ type: 'OPEN' }));
|
|
|
+ socket.send(JSON.stringify({ type: "OPEN" }));
|
|
|
}
|
|
|
self._configureWS(socket, key, id, token);
|
|
|
} else {
|
|
|
- socket.send(JSON.stringify({ type: 'ERROR', payload: { msg: err } }));
|
|
|
+ socket.send(JSON.stringify({ type: "ERROR", payload: { msg: err } }));
|
|
|
}
|
|
|
});
|
|
|
} else {
|
|
@@ -54,7 +58,6 @@ app._initializeWSS = function(server) {
|
|
|
};
|
|
|
|
|
|
app._configureWS = function(socket, key, id, token) {
|
|
|
-
|
|
|
var self = this;
|
|
|
var client = this._clients[key][id];
|
|
|
|
|
@@ -67,7 +70,9 @@ app._configureWS = function(socket, key, id, token) {
|
|
|
}
|
|
|
} else {
|
|
|
// ID-taken, invalid token
|
|
|
- socket.send(JSON.stringify({ type: 'ID-TAKEN', payload: { msg: 'ID is taken' } }));
|
|
|
+ socket.send(
|
|
|
+ JSON.stringify({ type: "ID-TAKEN", payload: { msg: "ID is taken" } })
|
|
|
+ );
|
|
|
socket.close();
|
|
|
return;
|
|
|
}
|
|
@@ -75,19 +80,21 @@ app._configureWS = function(socket, key, id, token) {
|
|
|
this._processOutstanding(key, id);
|
|
|
|
|
|
// Cleanup after a socket closes.
|
|
|
- socket.on('close', function() {
|
|
|
- self._log('Socket closed:', id);
|
|
|
+ socket.on("close", function() {
|
|
|
+ self._log("Socket closed:", id);
|
|
|
if (client.socket == socket) {
|
|
|
self._removePeer(key, id);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// Handle messages from peers.
|
|
|
- socket.on('message', function(data) {
|
|
|
+ socket.on("message", function(data) {
|
|
|
try {
|
|
|
var message = JSON.parse(data);
|
|
|
|
|
|
- if (['LEAVE', 'CANDIDATE', 'OFFER', 'ANSWER'].indexOf(message.type) !== -1) {
|
|
|
+ if (
|
|
|
+ ["LEAVE", "CANDIDATE", "OFFER", "ANSWER"].indexOf(message.type) !== -1
|
|
|
+ ) {
|
|
|
self._handleTransmission(key, {
|
|
|
type: message.type,
|
|
|
src: id,
|
|
@@ -95,17 +102,17 @@ app._configureWS = function(socket, key, id, token) {
|
|
|
payload: message.payload
|
|
|
});
|
|
|
} else {
|
|
|
- util.prettyError('Message unrecognized');
|
|
|
+ util.prettyError("Message unrecognized");
|
|
|
}
|
|
|
- } catch(e) {
|
|
|
- self._log('Invalid message', data);
|
|
|
+ } catch (e) {
|
|
|
+ self._log("Invalid message", data);
|
|
|
throw e;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// We're going to emit here, because for XHR we don't *know* when someone
|
|
|
// disconnects.
|
|
|
- this.emit('connection', id);
|
|
|
+ this.emit("connection", id);
|
|
|
};
|
|
|
|
|
|
app._checkAllowsDiscovery = function(key, cb) {
|
|
@@ -124,17 +131,19 @@ app._checkKey = function(key, ip, cb) {
|
|
|
this._ips[ip] = 0;
|
|
|
}
|
|
|
// Check concurrent limit
|
|
|
- if (Object.keys(this._clients[key]).length >= this._options.concurrent_limit) {
|
|
|
- cb('Server has reached its concurrent user limit');
|
|
|
+ if (
|
|
|
+ Object.keys(this._clients[key]).length >= this._options.concurrent_limit
|
|
|
+ ) {
|
|
|
+ cb("Server has reached its concurrent user limit");
|
|
|
return;
|
|
|
}
|
|
|
if (this._ips[ip] >= this._options.ip_limit) {
|
|
|
- cb(ip + ' has reached its concurrent user limit');
|
|
|
+ cb(ip + " has reached its concurrent user limit");
|
|
|
return;
|
|
|
}
|
|
|
cb(null);
|
|
|
} else {
|
|
|
- cb('Invalid key provided');
|
|
|
+ cb("Invalid key provided");
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -144,18 +153,18 @@ app._initializeHTTP = function() {
|
|
|
|
|
|
this.use(cors());
|
|
|
|
|
|
- this.get('/', function(req, res, next) {
|
|
|
- res.send(require('../app.json'));
|
|
|
+ this.get("/", function(req, res, next) {
|
|
|
+ res.send(require("../app.json"));
|
|
|
});
|
|
|
|
|
|
// Retrieve guaranteed random ID.
|
|
|
- this.get('/:key/id', function(req, res, next) {
|
|
|
- res.contentType = 'text/html';
|
|
|
+ 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('/: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;
|
|
@@ -168,7 +177,7 @@ app._initializeHTTP = function() {
|
|
|
self._ips[ip]++;
|
|
|
self._startStreaming(res, key, id, token, true);
|
|
|
} else {
|
|
|
- res.send(JSON.stringify({ type: 'HTTP-ERROR' }));
|
|
|
+ res.send(JSON.stringify({ type: "HTTP-ERROR" }));
|
|
|
}
|
|
|
});
|
|
|
} else {
|
|
@@ -177,7 +186,7 @@ app._initializeHTTP = function() {
|
|
|
});
|
|
|
|
|
|
// Get a list of all peers for a key, enabled by the `allowDiscovery` flag.
|
|
|
- this.get('/: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) {
|
|
@@ -226,36 +235,36 @@ app._initializeHTTP = function() {
|
|
|
|
|
|
var jsonParser = bodyParser.json();
|
|
|
|
|
|
- this.post('/:key/:id/:token/offer', jsonParser, handle);
|
|
|
+ this.post("/:key/:id/:token/offer", jsonParser, handle);
|
|
|
|
|
|
- this.post('/:key/:id/:token/candidate', jsonParser, handle);
|
|
|
+ this.post("/:key/:id/:token/candidate", jsonParser, handle);
|
|
|
|
|
|
- this.post('/:key/:id/:token/answer', jsonParser, handle);
|
|
|
+ this.post("/:key/:id/:token/answer", jsonParser, handle);
|
|
|
|
|
|
- this.post('/:key/:id/:token/leave', jsonParser, handle);
|
|
|
+ this.post("/:key/:id/:token/leave", jsonParser, handle);
|
|
|
};
|
|
|
|
|
|
/** Saves a streaming response and takes care of timeouts and headers. */
|
|
|
app._startStreaming = function(res, key, id, token, open) {
|
|
|
var self = this;
|
|
|
|
|
|
- res.writeHead(200, {'Content-Type': 'application/octet-stream'});
|
|
|
+ res.writeHead(200, { "Content-Type": "application/octet-stream" });
|
|
|
|
|
|
- var pad = '00';
|
|
|
+ var pad = "00";
|
|
|
for (var i = 0; i < 10; i++) {
|
|
|
pad += pad;
|
|
|
}
|
|
|
- res.write(pad + '\n');
|
|
|
+ res.write(pad + "\n");
|
|
|
|
|
|
if (open) {
|
|
|
- res.write(JSON.stringify({ type: 'OPEN' }) + '\n');
|
|
|
+ res.write(JSON.stringify({ type: "OPEN" }) + "\n");
|
|
|
}
|
|
|
|
|
|
var client = this._clients[key][id];
|
|
|
|
|
|
if (token === client.token) {
|
|
|
// Client already exists
|
|
|
- res.on('close', function() {
|
|
|
+ res.on("close", function() {
|
|
|
if (client.res === res) {
|
|
|
if (!client.socket) {
|
|
|
// No new request yet, peer dead
|
|
@@ -269,7 +278,7 @@ app._startStreaming = function(res, key, id, token, open) {
|
|
|
this._processOutstanding(key, id);
|
|
|
} else {
|
|
|
// ID-taken, invalid token
|
|
|
- res.end(JSON.stringify({ type: 'HTTP-ERROR' }));
|
|
|
+ res.end(JSON.stringify({ type: "HTTP-ERROR" }));
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -284,7 +293,11 @@ app._pruneOutstanding = function() {
|
|
|
for (var j = 0, jj = offers.length; j < jj; j += 1) {
|
|
|
var message = offers[j];
|
|
|
if (!seen[message.src]) {
|
|
|
- this._handleTransmission(key, { type: 'EXPIRE', src: message.dst, dst: message.src });
|
|
|
+ this._handleTransmission(key, {
|
|
|
+ type: "EXPIRE",
|
|
|
+ src: message.dst,
|
|
|
+ dst: message.src
|
|
|
+ });
|
|
|
seen[message.src] = true;
|
|
|
}
|
|
|
}
|
|
@@ -330,7 +343,7 @@ 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];
|
|
|
- this.emit('disconnect', id);
|
|
|
+ this.emit("disconnect", id);
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -346,11 +359,11 @@ app._handleTransmission = function(key, message) {
|
|
|
// User is connected!
|
|
|
if (destination) {
|
|
|
try {
|
|
|
- this._log(type, 'from', src, 'to', dst);
|
|
|
+ this._log(type, "from", src, "to", dst);
|
|
|
if (destination.socket) {
|
|
|
destination.socket.send(data);
|
|
|
} else if (destination.res) {
|
|
|
- data += '\n';
|
|
|
+ data += "\n";
|
|
|
destination.res.write(data);
|
|
|
} else {
|
|
|
// Neither socket no res available. Peer dead?
|
|
@@ -362,7 +375,7 @@ app._handleTransmission = function(key, message) {
|
|
|
// Tell other side to stop trying.
|
|
|
this._removePeer(key, dst);
|
|
|
this._handleTransmission(key, {
|
|
|
- type: 'LEAVE',
|
|
|
+ type: "LEAVE",
|
|
|
src: dst,
|
|
|
dst: src
|
|
|
});
|
|
@@ -370,13 +383,13 @@ app._handleTransmission = function(key, message) {
|
|
|
} else {
|
|
|
// Wait for this client to connect/reconnect (XHR) for important
|
|
|
// messages.
|
|
|
- if (type !== 'LEAVE' && type !== 'EXPIRE' && dst) {
|
|
|
+ if (type !== "LEAVE" && type !== "EXPIRE" && dst) {
|
|
|
var self = this;
|
|
|
if (!this._outstanding[key][dst]) {
|
|
|
this._outstanding[key][dst] = [];
|
|
|
}
|
|
|
this._outstanding[key][dst].push(message);
|
|
|
- } else if (type === 'LEAVE' && !dst) {
|
|
|
+ } else if (type === "LEAVE" && !dst) {
|
|
|
this._removePeer(key, src);
|
|
|
} else {
|
|
|
// Unavailable destination specified with message LEAVE or EXPIRE
|