mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 11:30:55 +01:00
Break some of Aphlict into reasonable classes with sensible responsibilities
Summary: Ref T4324. - Create `Listener` to represent listening clients. - Create `ListenerList` to represent the current list of clients. - Create `Logfile` to handle logging. Test Plan: Clicked "Send Test Notification", verified logs, status and notifications all work correctly. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T4324 Differential Revision: https://secure.phabricator.com/D8256
This commit is contained in:
parent
18f856ac6f
commit
28fe44da0a
7 changed files with 204 additions and 80 deletions
|
@ -170,7 +170,7 @@ return array(
|
|||
'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',
|
||||
|
|
|
@ -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 net = require('net');
|
|||
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 [
|
||||
'<?xml version="1.0"?>',
|
||||
|
@ -92,56 +85,38 @@ net.createServer(function(socket) {
|
|||
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 @@ var receive_server = http.createServer(function(request, response) {
|
|||
++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 @@ var receive_server = http.createServer(function(request, response) {
|
|||
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 @@ var receive_server = http.createServer(function(request, response) {
|
|||
}).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 @@ if (config.user) {
|
|||
process.setuid(config.user);
|
||||
}
|
||||
|
||||
debug.log('Started Server (PID %d)', process.pid);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
39
support/aphlict/server/lib/AphlictListener.js
Normal file
39
support/aphlict/server/lib/AphlictListener.js
Normal file
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
57
support/aphlict/server/lib/AphlictListenerList.js
Normal file
57
support/aphlict/server/lib/AphlictListenerList.js
Normal file
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
52
support/aphlict/server/lib/AphlictLog.js
Normal file
52
support/aphlict/server/lib/AphlictLog.js
Normal file
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
24
webroot/rsrc/externals/javelin/core/init_node.js
vendored
24
webroot/rsrc/externals/javelin/core/init_node.js
vendored
|
@ -27,17 +27,33 @@ JX.require = function(thing, relative) {
|
|||
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);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue