socket.io logging options
[KiwiIRC.git] / server / client.js
CommitLineData
f3dbbd91
D
1var util = require('util'),
2 events = require('events'),
44197e59 3 _ = require('underscore'),
1360a454 4 config = require('./configuration.js'),
2a8e95d1
D
5 IrcConnection = require('./irc/connection.js').IrcConnection,
6 IrcCommands = require('./irc/commands.js'),
7 ClientCommands = require('./clientcommands.js');
a8bf3ea4 8
772a4bb6 9
a8bf3ea4 10var Client = function (websocket) {
772a4bb6 11 var that = this;
a8bf3ea4
JA
12
13 events.EventEmitter.call(this);
14 this.websocket = websocket;
15
772a4bb6 16 this.irc_connections = [];
a8bf3ea4
JA
17 this.next_connection = 0;
18
19 this.buffer = {
20 list: [],
21 motd: ''
22 };
23
f3dbbd91 24 // Handler for any commands sent from the client
2a8e95d1 25 this.client_commands = new ClientCommands(this);
f3dbbd91 26
a8bf3ea4 27 websocket.on('irc', function () {
772a4bb6 28 handleClientMessage.apply(that, arguments);
a8bf3ea4
JA
29 });
30 websocket.on('kiwi', function () {
772a4bb6 31 kiwiCommand.apply(that, arguments);
a8bf3ea4
JA
32 });
33 websocket.on('disconnect', function () {
772a4bb6 34 websocketDisconnect.apply(that, arguments);
a8bf3ea4
JA
35 });
36 websocket.on('error', function () {
772a4bb6 37 websocketError.apply(that, arguments);
a8bf3ea4
JA
38 });
39};
40util.inherits(Client, events.EventEmitter);
41
42module.exports.Client = Client;
43
44// Callback API:
45// Callbacks SHALL accept 2 arguments, error and response, in that order.
46// error MUST be null where the command is successul.
47// error MUST otherwise be a truthy value and SHOULD be a string where the cause of the error is known.
48// response MAY be given even if error is truthy
49
2f1e8a71 50Client.prototype.sendIrcCommand = function (command, data, callback) {
a8bf3ea4 51 var c = {command: command, data: data};
a8bf3ea4
JA
52 this.websocket.emit('irc', c, callback);
53};
54
d2d91c10
D
55Client.prototype.sendKiwiCommand = function (command, data, callback) {
56 var c = {command: command, data: data};
57 this.websocket.emit('kiwi', c, callback);
a8bf3ea4
JA
58};
59
c08717da
D
60Client.prototype.dispose = function () {
61 websocketDisconnect.apply(this);
62 this.removeAllListeners();
63};
64
772a4bb6 65function handleClientMessage(msg, callback) {
f3dbbd91
D
66 var server, args, obj, channels, keys;
67
68 // Make sure we have a server number specified
69 if ((msg.server === null) || (typeof msg.server !== 'number')) {
40af34d4 70 return (typeof callback === 'function') ? callback('server not specified') : undefined;
772a4bb6 71 } else if (!this.irc_connections[msg.server]) {
40af34d4 72 return (typeof callback === 'function') ? callback('not connected to server') : undefined;
a8bf3ea4 73 }
f3dbbd91
D
74
75 // The server this command is directed to
772a4bb6 76 server = this.irc_connections[msg.server];
f3dbbd91
D
77
78 if (typeof callback !== 'function') {
79 callback = null;
40ce1c01 80 }
f3dbbd91
D
81
82 try {
83 msg.data = JSON.parse(msg.data);
84 } catch (e) {
85 kiwi.log('[handleClientMessage] JSON parsing error ' + msg.data);
86 return;
a8bf3ea4 87 }
f3dbbd91
D
88
89 // Run the client command
90 this.client_commands.run(msg.data.method, msg.data.args, server, callback);
d2d91c10 91}
a8bf3ea4 92
f3dbbd91
D
93
94
95
772a4bb6 96function kiwiCommand(command, callback) {
b8e4d9f7 97 var that = this;
772a4bb6 98
a8bf3ea4
JA
99 if (typeof callback !== 'function') {
100 callback = function () {};
101 }
102 switch (command.command) {
103 case 'connect':
2a8e95d1 104 if (command.hostname && command.port && command.nick) {
772a4bb6 105 var con = new IrcConnection(command.hostname, command.port, command.ssl,
a8bf3ea4 106 command.nick, {hostname: this.websocket.handshake.revdns, address: this.websocket.handshake.address.address},
15fefff7 107 command.password);
a8bf3ea4
JA
108
109 var con_num = this.next_connection++;
772a4bb6 110 this.irc_connections[con_num] = con;
a8bf3ea4 111
2a8e95d1
D
112 var irc_commands = new IrcCommands(con, con_num, this);
113 irc_commands.bindEvents();
a8bf3ea4
JA
114
115 con.on('connected', function () {
116 console.log("con.on('connected')");
117 return callback(null, con_num);
118 });
119
120 con.on('error', function (err) {
d2d91c10
D
121 // TODO: Once multiple servers implemented, specify which server failed
122 //that.sendKiwiCommand('error', {server: con_num, error: err});
123 return callback(err.code, null);
a8bf3ea4 124 });
b8e4d9f7
JA
125
126 con.on('close', function () {
772a4bb6 127 that.irc_connections[con_num] = null;
b8e4d9f7 128 });
a8bf3ea4
JA
129 } else {
130 return callback('Hostname, port and nickname must be specified');
131 }
132 break;
133 default:
134 callback();
135 }
c08717da 136}
a8bf3ea4 137
a8bf3ea4 138
772a4bb6
D
139// Websocket has disconnected, so quit all the IRC connections
140function websocketDisconnect() {
141 _.each(this.irc_connections, function (irc_connection, i, cons) {
b8e4d9f7 142 if (irc_connection) {
1360a454 143 irc_connection.end('QUIT :' + (config.get().quit_message || ''));
c08717da 144 irc_connection.dispose();
b8e4d9f7
JA
145 cons[i] = null;
146 }
147 });
a8bf3ea4 148 this.emit('destroy');
c08717da 149}
a8bf3ea4 150
772a4bb6
D
151
152// TODO: Should this close all the websocket connections too?
153function websocketError() {
a8bf3ea4 154 this.emit('destroy');
c08717da 155}