Skip to content

Instantly share code, notes, and snippets.

Created December 26, 2012 02:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/766833e32b319755c47b to your computer and use it in GitHub Desktop.
Save anonymous/766833e32b319755c47b to your computer and use it in GitHub Desktop.
Basic testing of SockJS-node connections and message passing.
var sockJsTest = (function sockJsTest() {
var
socketData,
ieversion,
socket = null;
hearbeatInterval = null;
reportTimeout = null;
useSSL = true,
sendOnConnect = "",
ajaxFile = "/system/ajax/ajax.Vine.php",
domain = "sockjs.example.com",
server = "https://" + domain + ":4002/sockjs";
// Determine server address
if ( useSSL ) {
// Even though we want to use SSL, IE 9- won't allow that
// on http:// pages.
if ( /MSIE (\d+\.\d+);/.test( navigator.userAgent ) ) {
if ( window.location.protocol === "http:" ) {
ieversion = new Number( RegExp.$1 );
if ( ieversion <= 9 ) {
server = "http://" + domain + ":4000/sockjs";
}
}
}
} else if ( window.location.protocol === "http:" ) {
server = "http://" + domain + ":4000/sockjs";
}
// Data that will be reported back
socketData = {
connects : 0,
disconnects : 0,
messages : 0,
errors : 0,
time : new Date().getTime()
};
// This is what will be sent to the server upon connect.
// The server will reply with an acknowledgement.
sendOnConnect = JSON.stringify({
__event : "information",
url : window.location.href,
agent : navigator.userAgent
});
//
// Log results once user has been on page for 8 seconds.
// While it is possible a user connects after 8 seconds,
// we consider that a failure, since we never want to
// wait that long.
//
reportTimeout = setTimeout( function() {
if ( socketData.connects <= 0 ) {
socketData.time = 0;
}
var data = {
action : "report",
data : JSON.stringify( socketData ),
transport : socket.protocol,
url : window.location.href,
server : "sockjs"
};
$.post( ajaxFile, data );
}, 8000 );
socket = new SockJS( server, false, {} );
socket.onopen = function() {
socketData.connects++;
socketData.time = new Date().getTime() - socketData.time;
// Send data 1/2 second after connect. We add this delay
// just to give the client and server some time to finish
// any needed processing. Techinically, we shouldn't need
// the timeout.
setTimeout( function() {
socket.send( sendOnConnect );
}, 500 );
// Send heartbeat every 30 seconds. This allows us
// to force close a connection that isn't dropped
// right away or perform whatever other logic we
// might want to do when the server doesn't see me.
heartbeatInterval = setInterval( function() {
socket.send( JSON.stringify( { __event : "heartbeat" } ) );
}, 30000 );
};
socket.onmessage = function(data) {
socketData.messages++;
};
socket.onclose = function() {
socketData.disconnects++;
};
return {
beforeUnload : function() {
if ( socket ) {
socket.close();
}
if ( heartbeatInterval ) {
clearInterval( heartbeatInterval );
}
if ( reportTimeout ) {
clearTimeout( reportTimeout );
}
}
};
})();
// *sigh* Why do so many pages use old jQuery?
// Hopefully this won't screw something else up - like dialogs
$(document).bind("keypress", function(e) {
if (e.keyCode === 27) {
return false;
}
});
window.onbeforeunload = function() {
sockJsTest.beforeUnload();
};
var
os = require("os"),
fs = require("fs"),
util = require("util"),
http = require("http"),
https = require("https"),
fs = require("fs"),
express = require("express"),
sockjs = require("sockjs"),
moment = require("moment"),
Log = require("log"),
tinycolor = require("tinycolor");
var
startTime = Date.now(),
web = express(),
sockjsHttp, sockjsHttps;
//
// Set up logging right away so we can log anything!
//
log = new Log("info", fs.createWriteStream("log.txt"));
//
// Cleans unused SockJS connections.
//
setInterval(function() {
var
id,
expires = Date.now() - 900000;
for (id in sockets) {
if (clients[id].activity < expires) {
log.error("Force close " + id);
console.log("Force close " + id);
counters.forceClose += 1;
sockets[id].close();
}
}
}, 70000);
//
// Client list. Information about each client.
//
var clients = {};
//
// Socket list. This is the actual SockJS socket object
//
var sockets = {}
//
// Counters
//
counters = {
packetsReceived : 0,
bytesReceived : 0,
packetsSent : 0,
bytesSent : 0,
connects : 0,
disconnects : 0,
current : 0,
errors : 0,
forceClose : 0
};
/***************************************************************************
____ ____ _
/ ___| ___ _ ____ _____ _ __ / ___| ___| |_ _ _ _ __
\___ \ / _ \ '__\ \ / / _ \ '__| \___ \ / _ \ __| | | | '_ \
___) | __/ | \ V / __/ | ___) | __/ |_| |_| | |_) |
|____/ \___|_| \_/ \___|_| |____/ \___|\__|\__,_| .__/
|_|
***************************************************************************/
(function() {
var httpServer, httpsServer;
//
// Web server
//
var sslOpts = {
key : fs.readFileSync( "ssl.key" ),
cert : fs.readFileSync( "ssl.crt" )
};
httpServer = http.createServer(web);
httpsServer = https.createServer(sslOpts, web);
var port = process.argv[2] || 4000;
if (port < 1024 && process.getuid() !== 0) {
console.log(("Must run server as root for ports below 1024.").red);
process.exit(1);
}
httpServer.listen(port);
httpsServer.listen(port + 2);
var sockjsOpts = {
sockjs_url : "http://cdn.sockjs.org/sockjs-0.3.min.js"
}
sockjsHttp = sockjs.createServer(sockjsOpts);
sockjsHttps = sockjs.createServer(sockjsOpts);
sockjsHttp.installHandlers(httpServer, { prefix : '/sockjs' });
sockjsHttps.installHandlers(httpsServer, { prefix : '/sockjs' });
console.log(("SockJS/Express Load Test listening on port " + port + ".").green);
console.log(("SSL listening on port " + (port + 2) + ".").green);
})();
// Remove root privs after ports have been setup
if (process.getuid() === 0) {
process.setuid("ec2-user");
}
/***************************************************************************
____ _
| _ \ ___ _ _| |_ ___ _ __ ___
| |_) / _ \| | | | __/ _ \ '__/ __|
| _ < (_) | |_| | || __/ | \__ \
|_| \_\___/ \__,_|\__\___|_| |___/
***************************************************************************/
web.get("/", function(req, res) {
res.send("SockJS/Express test server");
});
web.get("/stats", function(req, res) {
res.json([counters, clients]);
});
web.get("/kill/:id", function(req, res) {
var id = req.params['id'];
if (clients.hasOwnProperty(id) && sockets.hasOwnProperty(id)) {
sockets[id].close();
res.send("Killed " + id);
} else {
res.send("Invalid id " + id);
}
});
/***************************************************************************
____ _ _ _____ _
/ ___| ___ ___| | _____| |_ | ____|_ _____ _ __ | |_ ___
\___ \ / _ \ / __| |/ / _ \ __| | _| \ \ / / _ \ '_ \| __/ __|
___) | (_) | (__| < __/ |_ | |___ \ V / __/ | | | |_\__ \
|____/ \___/ \___|_|\_\___|\__| |_____| \_/ \___|_| |_|\__|___/
***************************************************************************/
attach(sockjsHttp);
attach(sockjsHttps);
function attach(server) {
server.on("connection", function(socket) {
if (!socket) return;
counters.connects += 1;
counters.current += 1;
clients[socket.id] = {
id : socket.id,
connected : moment().format("MMMM Do YYYY, h:mm:ss a"),
activity : Date.now()
}
sockets[socket.id] = socket;
socket.on("data", function(data) {
var json;
counters.packetsReceived += 1;
counters.bytesReceived += data.length;
try {
json = JSON.parse(data);
} catch (ex) {
return;
}
if (json.hasOwnProperty("__event"))
{
if (json.__event === "information") {
delete json.__event;
for (var property in json) {
clients[socket.id][property] = json[property];
}
}
// Respond with a dumb acknowledgement
counters.packetsSent += 1;
counters.bytesSent += socket.id.length;
socket.write(socket.id);
}
// Update client activity information
if (clients.hasOwnProperty(socket.id)) {
clients[socket.id].activity = Date.now();
clients[socket.id].lastActive = moment().format("MMMM Do YYYY, h:mm:ss a");
}
});
// Probably not a valid event - could not find in docs
socket.on("error", function(err) {
counters.errors += 1;
log.error("error", "Socket error: " + err.toString());
});
socket.on("close", function() {
// Seems to help memory
socket.removeAllListeners();
counters.disconnects += 1;
counters.current -= 1;
if (clients.hasOwnProperty(this.id)) {
delete clients[this.id];
}
if (sockets.hasOwnProperty(this.id)) {
delete sockets[this.id];
}
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment