Index: resources/celerity/map.php =================================================================== --- resources/celerity/map.php +++ resources/celerity/map.php @@ -170,7 +170,7 @@ 'rsrc/externals/javelin/core/__tests__/stratcom.js' => 'da194d4b', 'rsrc/externals/javelin/core/__tests__/util.js' => 'd3b157a9', 'rsrc/externals/javelin/core/init.js' => 'b88ab49e', - 'rsrc/externals/javelin/core/init_node.js' => '9fe4895f', + 'rsrc/externals/javelin/core/init_node.js' => 'd7dde471', 'rsrc/externals/javelin/core/install.js' => '52a92793', 'rsrc/externals/javelin/core/util.js' => '7501647b', 'rsrc/externals/javelin/docs/Base.js' => '3b9ca7eb', Index: support/aphlict/server/aphlict_server.js =================================================================== --- support/aphlict/server/aphlict_server.js +++ support/aphlict/server/aphlict_server.js @@ -7,12 +7,21 @@ */ var JX = require('./lib/javelin').JX; -JX.require('lib/AphlictIDGenerator', __dirname); -var id_generator = new JX.AphlictIDGenerator(); +JX.require('lib/AphlictListenerList', __dirname); +JX.require('lib/AphlictLog', __dirname); + +var debug = new JX.AphlictLog() + .addConsole(console); + +var clients = new JX.AphlictListenerList(); var config = parse_command_line_arguments(process.argv); +if (config.logfile) { + debug.addLogfile(config.logfile); +} + function parse_command_line_arguments(argv) { var config = { port : 22280, @@ -54,29 +63,13 @@ var http = require('http'); var url = require('url'); var querystring = require('querystring'); -var fs = require('fs'); - -// set up log file -var logfile = fs.createWriteStream( - config.log, - { - flags: 'a', - encoding: null, - mode: 0666 - }); -function log(str) { - console.log(str); - logfile.write(str + '\n'); -} process.on('uncaughtException', function (err) { log("\n<<< UNCAUGHT EXCEPTION! >>>\n\n" + err); process.exit(1); }); -log('----- ' + (new Date()).toLocaleString() + ' -----\n'); - function getFlashPolicy() { return [ '', @@ -92,56 +85,38 @@ socket.write(getFlashPolicy() + '\0'); socket.end(); - log('[' + socket.remoteAddress + '] Sent Flash Policy'); + debug.log('[' + socket.remoteAddress + '] Sent Flash Policy'); socket.on('error', function (e) { - log('Error in policy server: ' + e); + debug.log('Error in policy server: ' + e); }); }).listen(843); -function write_json(socket, data) { - var serial = JSON.stringify(data); - var length = Buffer.byteLength(serial, 'utf8'); - length = length.toString(); - while (length.length < 8) { - length = '0' + length; - } - socket.write(length + serial); -} - - -var clients = {}; -var current_connections = 0; - var send_server = net.createServer(function(socket) { - var client_id = id_generator.generateNext(); - var client_name = '[' + socket.remoteAddress + '] [#' + client_id + '] '; + var listener = clients.addListener(socket); - clients[client_id] = socket; - current_connections++; - log(client_name + 'connected\t\t(' + - current_connections + ' current connections)'); + debug.log('<%s> Connected from %s', + listener.getDescription(), + socket.remoteAddress); socket.on('close', function() { - delete clients[client_id]; - current_connections--; - log(client_name + 'closed\t\t(' + - current_connections + ' current connections)'); + clients.removeListener(listener); + debug.log('<%s> Disconnected', listener.getDescription()); }); socket.on('timeout', function() { - log(client_name + 'timed out!'); + debug.log('<%s> Timed Out', listener.getDescription()); }); socket.on('end', function() { - log(client_name + 'ended the connection'); - // node automatically closes half-open connections + debug.log('<%s> Ended Connection', listener.getDescription()); }); socket.on('error', function (e) { - log(client_name + 'Uncaught error in send server: ' + e); + debug.log('<%s> Error: %s', listener.getDescription(), e); }); + }).listen(config.port); @@ -164,7 +139,7 @@ ++messages_in; var data = querystring.parse(body); - log('notification: ' + JSON.stringify(data)); + debug.log('notification: ' + JSON.stringify(data)); broadcast(data); response.end(); }); @@ -177,8 +152,8 @@ request.on('end', function() { var status = { 'uptime': (new Date().getTime() - start_time), - 'clients.active': current_connections, - 'clients.total': id_generator.getTotalCount(), + 'clients.active': clients.getActiveListenerCount(), + 'clients.total': clients.getTotalListenerCount(), 'messages.in': messages_in, 'messages.out': messages_out, 'log': config.log, @@ -197,15 +172,17 @@ }).listen(config.admin, config.host); function broadcast(data) { - for (var client_id in clients) { + var listeners = clients.getListeners(); + for (var id in listeners) { + var listener = listeners[id]; try { - write_json(clients[client_id], data); + listener.writeMessage(data); + ++messages_out; - log('wrote to client ' + client_id); + debug.log('<%s> Wrote Message', listener.getDescription()); } catch (error) { - delete clients[client_id]; - current_connections--; - log('ERROR: could not write to client ' + client_id); + clients.removeListener(listener); + debug.log('<%s> Write Error: %s', error); } } } @@ -216,3 +193,4 @@ process.setuid(config.user); } +debug.log('Started Server (PID %d)', process.pid); Index: support/aphlict/server/lib/AphlictIDGenerator.js =================================================================== --- support/aphlict/server/lib/AphlictIDGenerator.js +++ /dev/null @@ -1,18 +0,0 @@ -var JX = require('javelin').JX; - -JX.install('AphlictIDGenerator', { - - members : { - _next : 0, - - generateNext : function() { - this._next = ((this._next + 1) % 1000000000000); - return this._next; - }, - - getTotalCount : function() { - return this._next; - } - } - -}); Index: support/aphlict/server/lib/AphlictListener.js =================================================================== --- /dev/null +++ support/aphlict/server/lib/AphlictListener.js @@ -0,0 +1,39 @@ +var JX = require('javelin').JX; + +JX.install('AphlictListener', { + construct : function(id, socket) { + this._id = id; + this._socket = socket; + }, + + members : { + _id : null, + _socket : null, + + getID : function() { + return this._id; + }, + + getSocket : function() { + return this._socket; + }, + + getDescription : function() { + return 'Listener/' + this.getID(); + }, + + writeMessage : function(message) { + var serial = JSON.stringify(message); + + var length = Buffer.byteLength(serial, 'utf8'); + length = length.toString(); + while (length.length < 8) { + length = '0' + length; + } + + this._socket.write(length + serial); + } + + } + +}); Index: support/aphlict/server/lib/AphlictListenerList.js =================================================================== --- /dev/null +++ support/aphlict/server/lib/AphlictListenerList.js @@ -0,0 +1,57 @@ +var JX = require('javelin').JX; +JX.require('AphlictListener', __dirname); + +JX.install('AphlictListenerList', { + construct : function() { + this._listeners = {}; + }, + + members : { + _listeners : null, + _nextID : 0, + _activeListenerCount : 0, + _totalListenerCount : 0, + + addListener : function(socket) { + var listener = new JX.AphlictListener( + this._generateNextID(), + socket); + + this._listeners[listener.getID()] = listener; + this._activeListenerCount++; + this._totalListenerCount++; + + return listener; + }, + + removeListener : function(listener) { + var id = listener.getID(); + if (id in this._listeners) { + delete this._listeners[id]; + this._activeListenerCount--; + } + }, + + getListeners : function() { + return this._listeners; + }, + + getActiveListenerCount : function() { + return this._activeListenerCount; + }, + + getTotalListenerCount : function() { + return this._totalListenerCount; + }, + + _generateNextID : function() { + do { + this._nextID = ((this._nextID + 1) % 1000000000000); + } while (this._nextID in this._listeners); + + return this._nextID; + } + + } + +}); Index: support/aphlict/server/lib/AphlictLog.js =================================================================== --- /dev/null +++ support/aphlict/server/lib/AphlictLog.js @@ -0,0 +1,52 @@ +var JX = require('javelin').JX; + +var fs = require('fs'); +var util = require('util'); + +JX.install('AphlictLog', { + construct : function() { + this._writeToLogs = []; + this._writeToConsoles = []; + }, + + members : { + _writeToConsoles : null, + _writeToLogs : null, + + addLogfile : function(path) { + var options = { + flags: 'a', + encoding: 'utf8', + mode: 066 + }; + + var logfile = fs.createWriteSteam(path, options); + + this._writeToLogs.push(logfile); + + return this; + }, + + addConsole : function(console) { + this._writeToConsoles.push(console); + return this; + }, + + log : function(pattern) { + var str = util.format.apply(null, arguments); + var date = new Date().toLocaleString(); + str = '[' + date + '] ' + str; + + var ii; + for (ii = 0; ii < this._writeToConsoles.length; ii++) { + this._writeToConsoles[ii].log(str); + } + + for (ii = 0; ii < this._writeToLogs.length; ii++) { + this._writeToLogs[ii].write(str + "\n"); + } + } + + } + +}); Index: webroot/rsrc/externals/javelin/core/init_node.js =================================================================== --- webroot/rsrc/externals/javelin/core/init_node.js +++ webroot/rsrc/externals/javelin/core/init_node.js @@ -27,17 +27,33 @@ relative = relative || __dirname + '/..'; var path = relative + '/' + thing + '.js'; var content = fs.readFileSync(path); + var dir = pathModule.dirname(path); - var sandbox = { + var k; + var sandbox = {}; + + for (k in global) { + sandbox[k] = global[k]; + } + + var extra = { JX : this, __DEV__ : 0, - console : console, window : {}, - require : function (thing) { - return require(pathModule.dirname(path) + '/' + thing); + __dirname : dir, + require : function(thing) { + if (thing == 'javelin') { + return require(dir + '/' + thing); + } else { + return require(thing); + } } }; + for (k in extra) { + sandbox[k] = extra[k]; + } + vm.createScript(content, path) .runInNewContext(sandbox, path); };