X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=server%2Fkiwi.js;h=014cac09a19ff74f40424b5f530d6da97614fb17;hb=dea06eac95ef40e2b79159009c1dd4b9e38999d2;hp=24c26d9d28afc52d8604c2f5ba04587b9a3c0861;hpb=265f976c6813b76f9b4842b344fcb3c483a50c27;p=KiwiIRC.git diff --git a/server/kiwi.js b/server/kiwi.js index 24c26d9..014cac0 100755 --- a/server/kiwi.js +++ b/server/kiwi.js @@ -1,70 +1,231 @@ var fs = require('fs'), - WebListener = require('./web.js').WebListener; + _ = require('lodash'), + WebListener = require('./weblistener.js'), + config = require('./configuration.js'), + rehash = require('./rehash.js'), + modules = require('./modules.js'), + Identd = require('./identd.js'); -//load config -var config_filename = 'config.json', - config_dirs = ['/etc/kiwiirc/', __dirname + '/']; -var config = Object.create(null); -for (var i in config_dirs) { - try { - if (fs.lstatSync(config_dirs[i] + config_filename).isDirectory() === false) { - config = JSON.parse(fs.readFileSync(config_dirs[i] + config_filename, 'utf-8')); - console.log('Loaded config file ' + config_dirs[i] + config_filename); - break; - } - } catch (e) { - switch (e.code) { - case 'ENOENT': // No file/dir - break; - default: - console.log('An error occured parsing the config file ' + config_dirs[i] + config_filename + ': ' + e.message); - return false; +process.chdir(__dirname + '/../'); +config.loadConfig(); + + +// If we're not running in the forground and we have a log file.. switch +// console.log to output to a file +if (process.argv.indexOf('-f') === -1 && global.config && global.config.log) { + (function () { + var log_file_name = global.config.log; + + if (log_file_name[0] !== '/') { + log_file_name = __dirname + '/../' + log_file_name; } - continue; - } + + + + console.log = function() { + var logfile = fs.openSync(log_file_name, 'a'), + out; + + out = Array.prototype.join.apply(arguments, [' ']); + + // Make sure we out somthing to log and we have an open file + if (!out || !logfile) return; + + out += '\n'; + fs.writeSync(logfile, out, null); + + fs.closeSync(logfile); + }; + })(); } -if (Object.keys(config).length === 0) { - console.log('Couldn\'t find a valid config file!'); + + +// Make sure we have a valid config file and at least 1 server +if (!global.config || Object.keys(global.config).length === 0) { + console.log('Couldn\'t find a valid config.js file (Did you copy the config.example.js file yet?)'); process.exit(1); } -if ((!config.servers) || (config.servers.length < 1)) { +if ((!global.config.servers) || (global.config.servers.length < 1)) { console.log('No servers defined in config file'); process.exit(2); } -//Create web listeners -var clients = []; -_.each(config.servers, function (server) { - var wl = new WebListener(server, config.transports); + + +// Create a plugin interface +global.modules = new modules.Publisher(); + +// Register as the active interface +modules.registerPublisher(global.modules); + +// Load any modules in the config +if (global.config.module_dir) { + (global.config.modules || []).forEach(function (module_name) { + if (modules.load(global.config.module_dir + module_name + '.js')) { + console.log('Module ' + module_name + ' loaded successfuly'); + } else { + console.log('Module ' + module_name + ' failed to load'); + } + }); +} + + + + +// Holder for all the connected clients +global.clients = { + clients: Object.create(null), + addresses: Object.create(null), + + add: function (client) { + this.clients[client.hash] = client; + if (typeof this.addresses[client.real_address] === 'undefined') { + this.addresses[client.real_address] = Object.create(null); + } + this.addresses[client.real_address][client.hash] = client; + }, + + remove: function (client) { + if (typeof this.clients[client.hash] !== 'undefined') { + delete this.clients[client.hash]; + delete this.addresses[client.real_address][client.hash]; + if (Object.keys(this.addresses[client.real_address]).length < 1) { + delete this.addresses[client.real_address]; + } + } + }, + + numOnAddress: function (addr) { + if (typeof this.addresses[addr] !== 'undefined') { + return Object.keys(this.addresses[addr]).length; + } else { + return 0; + } + } +}; + + + + +/* + * Identd server + */ +if (global.config.identd && global.config.identd.enabled) { + new Identd({ + bind_addr: global.config.identd.address, + bind_port: global.config.identd.port + }).start(); +} + + + + +/* + * Web listeners + */ + + +// Start up a weblistener for each found in the config +_.each(global.config.servers, function (server) { + var wl = new WebListener(server, global.config.transports); + wl.on('connection', function (client) { - clients.push(client); + clients.add(client); }); - wl.on('destroy', function (client) { - clients = _.reject(clients, function (c) { - return client === c; - }); + + wl.on('client_dispose', function (client) { + clients.remove(client); }); + + wl.on('listening', webListenerRunning); }); +// Once all the listeners are listening, set the processes UID/GID +var num_listening = 0; +function webListenerRunning() { + num_listening++; + if (num_listening === global.config.servers.length) { + setProcessUid(); + } +} + -//Set process title -process.title = 'Kiwi IRC'; -//Change UID/GID -if ((config.user) && (config.user !== '')) { - process.setuid(config.user); -} -if ((config.group) && (config.group !== '')) { - process.setgid(config.group); + +/* + * Process settings + */ + +// Set process title +process.title = 'kiwiirc'; + +// Change UID/GID +function setProcessUid() { + if ((global.config.group) && (global.config.group !== '')) { + process.setgid(global.config.group); + } + if ((global.config.user) && (global.config.user !== '')) { + process.setuid(global.config.user); + } } -//Listen to STDIN + +// Make sure Kiwi doesn't simply quit on an exception +process.on('uncaughtException', function (e) { + console.log('[Uncaught exception] ' + e); + console.log(e.stack); +}); + + +process.on('SIGUSR1', function() { + if (config.loadConfig()) { + console.log('New config file loaded'); + } else { + console.log("No new config file was loaded"); + } +}); + + + + +/* + * Listen for runtime commands + */ + process.stdin.resume(); -process.stdin.on('data', function (data) { - console.log(data.toString()); +process.stdin.on('data', function (buffered) { + var data = buffered.toString().trim(); + + switch (data) { + case 'stats': + console.log('Connected clients: ' + _.size(global.clients.clients).toString()); + console.log('Num. remote hosts: ' + _.size(global.clients.addresses).toString()); + break; + + case 'reconfig': + if (config.loadConfig()) { + console.log('New config file loaded'); + } else { + console.log("No new config file was loaded"); + } + + break; + + + case 'rehash': + (function () { + rehash.rehashAll(); + console.log('Rehashed'); + })(); + + break; + + default: + console.log('Unrecognised command: ' + data); + } });