mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 16:22:43 +01:00
Improve Aphlict server
Summary: - Move to port 22280 by default. - Warn when running as non-root. - Allow subscription and publish/admin ports to be configured. - Allow server to drop root after binding to 843. - Allow log path to be configured. - Add /status/ admin URI which shows server status. - Return HTTP 400 Bad Request for other requests, instead of hanging. - Minor formatting cleanup. Test Plan: Ran without root: $ node aphlict_server.js ...got a good error message. Ran with --user: $ sudo node aphlict_server.js --user=epriestley ...verified server dropped permissions. Ran with --port / --admin. Hit /status/ with GET, got status. Hit other URLs with GET, got 400. Reviewers: allenjohnashton, ddfisher, keebuhm Reviewed By: ddfisher CC: aran Differential Revision: https://secure.phabricator.com/D2737
This commit is contained in:
parent
9a4243b4b3
commit
86040227b0
5 changed files with 91 additions and 13 deletions
|
@ -737,7 +737,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-aphlict' =>
|
'javelin-aphlict' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/50cae715/rsrc/js/application/aphlict/Aphlict.js',
|
'uri' => '/res/c0b9e53f/rsrc/js/application/aphlict/Aphlict.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -39,7 +39,7 @@ final class PhabricatorAphlictTestPageController
|
||||||
array(
|
array(
|
||||||
'id' => $object_id,
|
'id' => $object_id,
|
||||||
'server' => '127.0.0.1',
|
'server' => '127.0.0.1',
|
||||||
'port' => 2600,
|
'port' => 22280,
|
||||||
));
|
));
|
||||||
|
|
||||||
return $this->buildStandardPageResponse(
|
return $this->buildStandardPageResponse(
|
||||||
|
|
|
@ -397,7 +397,7 @@ final class PhabricatorStandardPageView extends AphrontPageView {
|
||||||
array(
|
array(
|
||||||
'id' => $aphlict_object_id,
|
'id' => $aphlict_object_id,
|
||||||
'server' => $server_domain,
|
'server' => $server_domain,
|
||||||
'port' => 2600,
|
'port' => 22280,
|
||||||
'pageObjects' => $this->pageObjects,
|
'pageObjects' => $this->pageObjects,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,49 @@
|
||||||
|
/**
|
||||||
|
* Notification server. Launch with:
|
||||||
|
*
|
||||||
|
* sudo node aphlict_server.js --user=aphlict
|
||||||
|
*
|
||||||
|
* You can also specify `port`, `admin` and `log`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var config = parse_command_line_arguments(process.argv);
|
||||||
|
|
||||||
|
function parse_command_line_arguments(argv) {
|
||||||
|
var config = {
|
||||||
|
port : 22280,
|
||||||
|
admin : 22281,
|
||||||
|
user : null,
|
||||||
|
log: '/var/log/aphlict.log'
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var ii = 2; ii < argv.length; ii++) {
|
||||||
|
var arg = argv[ii];
|
||||||
|
var matches = arg.match(/^--([^=]+)=(.*)$/);
|
||||||
|
if (!matches) {
|
||||||
|
throw new Error("Unknown argument '"+arg+"'!");
|
||||||
|
}
|
||||||
|
if (!(matches[1] in config)) {
|
||||||
|
throw new Error("Unknown argument '"+matches[1]+"'!");
|
||||||
|
}
|
||||||
|
config[matches[1]] = matches[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
config.port = parseInt(config.port, 10);
|
||||||
|
config.admin = parseInt(config.admin, 10);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.getuid() != 0) {
|
||||||
|
console.log(
|
||||||
|
"ERROR: "+
|
||||||
|
"This server must be run as root because it needs to bind to privileged "+
|
||||||
|
"port 843 to start a Flash policy server. It will downgrade to run as a "+
|
||||||
|
"less-privileged user after binding if you pass a user in the command "+
|
||||||
|
"line arguments with '--user=alincoln'.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
var net = require('net');
|
var net = require('net');
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var url = require('url');
|
var url = require('url');
|
||||||
|
@ -5,7 +51,7 @@ var querystring = require('querystring');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
// set up log file
|
// set up log file
|
||||||
logfile = fs.createWriteStream('/var/log/aphlict.log',
|
var logfile = fs.createWriteStream(config.log,
|
||||||
{ flags: 'a',
|
{ flags: 'a',
|
||||||
encoding: null,
|
encoding: null,
|
||||||
mode: 0666 });
|
mode: 0666 });
|
||||||
|
@ -23,7 +69,7 @@ function getFlashPolicy() {
|
||||||
'<!DOCTYPE cross-domain-policy SYSTEM ' +
|
'<!DOCTYPE cross-domain-policy SYSTEM ' +
|
||||||
'"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">',
|
'"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">',
|
||||||
'<cross-domain-policy>',
|
'<cross-domain-policy>',
|
||||||
'<allow-access-from domain="*" to-ports="2600"/>',
|
'<allow-access-from domain="*" to-ports="'+config.port+'"/>',
|
||||||
'</cross-domain-policy>'
|
'</cross-domain-policy>'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
@ -97,16 +143,20 @@ var send_server = net.createServer(function(socket) {
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('error', function (e) {
|
socket.on('error', function (e) {
|
||||||
console.log('Uncaught error in send server: ' + e);
|
log('Uncaught error in send server: ' + e);
|
||||||
});
|
});
|
||||||
}).listen(2600);
|
}).listen(config.port);
|
||||||
|
|
||||||
|
|
||||||
|
var messages_out = 0;
|
||||||
|
var messages_in = 0;
|
||||||
|
var start_time = new Date().getTime();
|
||||||
|
|
||||||
var receive_server = http.createServer(function(request, response) {
|
var receive_server = http.createServer(function(request, response) {
|
||||||
response.writeHead(200, {'Content-Type' : 'text/plain'});
|
response.writeHead(200, {'Content-Type' : 'text/plain'});
|
||||||
|
|
||||||
if (request.method == 'POST') { // Only pay attention to POST requests
|
// Publishing a notification.
|
||||||
|
if (request.method == 'POST') {
|
||||||
var body = '';
|
var body = '';
|
||||||
|
|
||||||
request.on('data', function (data) {
|
request.on('data', function (data) {
|
||||||
|
@ -114,24 +164,52 @@ var receive_server = http.createServer(function(request, response) {
|
||||||
});
|
});
|
||||||
|
|
||||||
request.on('end', function () {
|
request.on('end', function () {
|
||||||
|
++messages_in;
|
||||||
|
|
||||||
var data = querystring.parse(body);
|
var data = querystring.parse(body);
|
||||||
log('notification: ' + JSON.stringify(data));
|
log('notification: ' + JSON.stringify(data));
|
||||||
broadcast(data);
|
broadcast(data);
|
||||||
response.end();
|
response.end();
|
||||||
});
|
});
|
||||||
|
} else if (request.url == '/status/') {
|
||||||
|
request.on('end', function() {
|
||||||
|
var status = {
|
||||||
|
'uptime': (new Date().getTime() - start_time),
|
||||||
|
'clients.active': current_connections,
|
||||||
|
'clients.total': generate_id.current_id || 0,
|
||||||
|
'messages.in': messages_in,
|
||||||
|
'messages.out': messages_out,
|
||||||
|
'log': config.log
|
||||||
|
};
|
||||||
|
|
||||||
|
response.write(JSON.stringify(status));
|
||||||
|
response.end();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
response.statusCode = 400;
|
||||||
|
response.write('400 Bad Request');
|
||||||
|
response.end();
|
||||||
}
|
}
|
||||||
}).listen(22281, '127.0.0.1');
|
|
||||||
|
}).listen(config.admin, '127.0.0.1');
|
||||||
|
|
||||||
function broadcast(data) {
|
function broadcast(data) {
|
||||||
for(var client_id in clients) {
|
for (var client_id in clients) {
|
||||||
try {
|
try {
|
||||||
write_json(clients[client_id], data);
|
write_json(clients[client_id], data);
|
||||||
log(' wrote to client ' + client_id);
|
++messages_out;
|
||||||
|
log('wrote to client ' + client_id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
delete clients[client_id];
|
delete clients[client_id];
|
||||||
current_connections--;
|
current_connections--;
|
||||||
log(' ERROR: could not write to client ' + client_id);
|
log('ERROR: could not write to client ' + client_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're configured to drop permissions, get rid of them now that we've
|
||||||
|
// bound to the ports we need and opened logfiles.
|
||||||
|
if (config.user) {
|
||||||
|
process.setuid(config.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
/**
|
/**
|
||||||
* Simple JS API for the Flash Aphlict client. Example usage:
|
* Simple JS API for the Flash Aphlict client. Example usage:
|
||||||
*
|
*
|
||||||
* var aphlict = new JX.Aphlict('aphlict_swf', '127.0.0.1', 2600)
|
* var aphlict = new JX.Aphlict('aphlict_swf', '127.0.0.1', 22280)
|
||||||
* .setHandler(function(type, message) {
|
* .setHandler(function(type, message) {
|
||||||
* JX.log("Got " + type + " event!")
|
* JX.log("Got " + type + " event!")
|
||||||
* })
|
* })
|
||||||
|
|
Loading…
Reference in a new issue