Add canvas to this.canvas (favicon.js)
[KiwiIRC.git] / server / kiwi.js
CommitLineData
a8bf3ea4 1var fs = require('fs'),
f9ff7686 2 _ = require('lodash'),
2aeb721f 3 util = require('util'),
1360a454 4 WebListener = require('./weblistener.js'),
1286229a 5 config = require('./configuration.js'),
1920a38e 6 rehash = require('./rehash.js'),
adefb6bd
D
7 modules = require('./modules.js'),
8 Identd = require('./identd.js');
fd779420 9
186531ed
D
10
11
11dbb00f
D
12process.chdir(__dirname + '/../');
13config.loadConfig();
14
15
16// If we're not running in the forground and we have a log file.. switch
17// console.log to output to a file
38ef7086 18if (process.argv.indexOf('-f') === -1 && global.config && global.config.log) {
11dbb00f 19 (function () {
b737610b 20 var log_file_name = global.config.log;
11dbb00f
D
21
22 if (log_file_name[0] !== '/') {
23 log_file_name = __dirname + '/../' + log_file_name;
24 }
25
26
27
28 console.log = function() {
29 var logfile = fs.openSync(log_file_name, 'a'),
30 out;
31
2aeb721f 32 out = util.format.apply(util, arguments);
11dbb00f
D
33
34 // Make sure we out somthing to log and we have an open file
35 if (!out || !logfile) return;
36
37 out += '\n';
38 fs.writeSync(logfile, out, null);
39
40 fs.closeSync(logfile);
41 };
42 })();
43}
4a30a583 44
ab15f618 45
ab15f618 46
186531ed 47// Make sure we have a valid config file and at least 1 server
1f49a029
D
48if (!global.config || Object.keys(global.config).length === 0) {
49 console.log('Couldn\'t find a valid config.js file (Did you copy the config.example.js file yet?)');
a8bf3ea4 50 process.exit(1);
fd779420
D
51}
52
b737610b 53if ((!global.config.servers) || (global.config.servers.length < 1)) {
a8bf3ea4
JA
54 console.log('No servers defined in config file');
55 process.exit(2);
fd779420
D
56}
57
58
186531ed
D
59
60
1920a38e 61// Create a plugin interface
ae64bf07 62global.modules = new modules.Publisher();
1920a38e 63
874f28a5 64// Register as the active interface
ae64bf07 65modules.registerPublisher(global.modules);
1920a38e 66
991091b7 67// Load any modules in the config
d8002ae0
D
68if (global.config.module_dir) {
69 (global.config.modules || []).forEach(function (module_name) {
70 if (modules.load(global.config.module_dir + module_name + '.js')) {
71 console.log('Module ' + module_name + ' loaded successfuly');
72 } else {
73 console.log('Module ' + module_name + ' failed to load');
74 }
75 });
76}
1920a38e
D
77
78
79
186531ed 80
186531ed 81// Holder for all the connected clients
26322e8f
D
82global.clients = {
83 clients: Object.create(null),
c36ed4eb 84 addresses: Object.create(null),
26322e8f 85
c36ed4eb
JA
86 add: function (client) {
87 this.clients[client.hash] = client;
88 if (typeof this.addresses[client.real_address] === 'undefined') {
89 this.addresses[client.real_address] = Object.create(null);
90 }
91 this.addresses[client.real_address][client.hash] = client;
92 },
26322e8f 93
c36ed4eb
JA
94 remove: function (client) {
95 if (typeof this.clients[client.hash] !== 'undefined') {
96 delete this.clients[client.hash];
97 delete this.addresses[client.real_address][client.hash];
98 if (Object.keys(this.addresses[client.real_address]).length < 1) {
99 delete this.addresses[client.real_address];
100 }
101 }
102 },
26322e8f 103
c36ed4eb
JA
104 numOnAddress: function (addr) {
105 if (typeof this.addresses[addr] !== 'undefined') {
106 return Object.keys(this.addresses[addr]).length;
107 } else {
108 return 0;
109 }
110 }
111};
186531ed 112
8838bdd6
JA
113global.servers = {
114 servers: Object.create(null),
115
116 addConnection: function (connection) {
117 var host = connection.irc_host.hostname;
118 if (!this.servers[host]) {
119 this.servers[host] = [];
120 }
121 this.servers[host].push(connection);
122 },
123
124 removeConnection: function (connection) {
125 var host = connection.irc_host.hostname
126 if (this.servers[host]) {
127 this.servers[host] = _.without(this.servers[host], connection);
128 if (this.servers[host].length === 0) {
129 delete this.servers[host];
130 }
131 }
132 },
133
134 numOnHost: function (host) {
135 if (this.servers[host]) {
136 return this.servers[host].length;
137 } else {
138 return 0;
139 }
140 }
141};
142
26322e8f
D
143
144
145
adefb6bd
D
146/*
147 * Identd server
148 */
149if (global.config.identd && global.config.identd.enabled) {
150 new Identd({
151 bind_addr: global.config.identd.address,
152 bind_port: global.config.identd.port
153 }).start();
154}
155
156
157
158
26322e8f
D
159/*
160 * Web listeners
161 */
162
163
186531ed 164// Start up a weblistener for each found in the config
b737610b
JA
165_.each(global.config.servers, function (server) {
166 var wl = new WebListener(server, global.config.transports);
170a3d85 167
a8bf3ea4 168 wl.on('connection', function (client) {
c36ed4eb 169 clients.add(client);
a8bf3ea4 170 });
26322e8f 171
57566ca2 172 wl.on('client_dispose', function (client) {
c36ed4eb 173 clients.remove(client);
a8bf3ea4 174 });
e380bc9e 175
d558508c
JA
176 wl.on('listening', function () {
177 console.log('Listening on %s:%s %s SSL', server.address, server.port, (server.ssl ? 'with' : 'without'));
178 webListenerRunning();
179 });
180
181 wl.on('error', function (err) {
182 console.log('Error listening on %s:%s: %s', server.address, server.port, err.code);
183 // TODO: This should probably be refactored. ^JA
184 webListenerRunning();
185 });
a8bf3ea4 186});
68ad40c6 187
e380bc9e
D
188// Once all the listeners are listening, set the processes UID/GID
189var num_listening = 0;
190function webListenerRunning() {
191 num_listening++;
192 if (num_listening === global.config.servers.length) {
193 setProcessUid();
194 }
195}
b0ad9f0a 196
f52d8543 197
186531ed
D
198
199
200/*
201 * Process settings
202 */
203
204// Set process title
205process.title = 'kiwiirc';
206
207// Change UID/GID
e380bc9e
D
208function setProcessUid() {
209 if ((global.config.group) && (global.config.group !== '')) {
210 process.setgid(global.config.group);
211 }
212 if ((global.config.user) && (global.config.user !== '')) {
213 process.setuid(global.config.user);
214 }
fd779420 215}
709031df 216
186531ed 217
0bb21ab3
D
218// Make sure Kiwi doesn't simply quit on an exception
219process.on('uncaughtException', function (e) {
220 console.log('[Uncaught exception] ' + e);
caff44fe 221 console.log(e.stack);
0bb21ab3
D
222});
223
224
88f14637
D
225process.on('SIGUSR1', function() {
226 if (config.loadConfig()) {
227 console.log('New config file loaded');
228 } else {
229 console.log("No new config file was loaded");
230 }
231});
232
233
234
186531ed
D
235
236/*
237 * Listen for runtime commands
238 */
239
87a6abbe 240process.stdin.resume();
186531ed
D
241process.stdin.on('data', function (buffered) {
242 var data = buffered.toString().trim();
243
244 switch (data) {
245 case 'stats':
170a3d85
D
246 console.log('Connected clients: ' + _.size(global.clients.clients).toString());
247 console.log('Num. remote hosts: ' + _.size(global.clients.addresses).toString());
186531ed
D
248 break;
249
ab15f618 250 case 'reconfig':
88f14637
D
251 if (config.loadConfig()) {
252 console.log('New config file loaded');
253 } else {
254 console.log("No new config file was loaded");
255 }
ab15f618
D
256
257 break;
258
1286229a
D
259
260 case 'rehash':
261 (function () {
262 rehash.rehashAll();
263 console.log('Rehashed');
264 })();
265
266 break;
267
186531ed
D
268 default:
269 console.log('Unrecognised command: ' + data);
270 }
a8bf3ea4 271});