666384cb521e6079f72f8396a24f77d2432690c5
1 var util
= require('util'),
2 events
= require('events'),
3 crypto
= require('crypto'),
4 _
= require('underscore'),
5 config
= require('./configuration.js'),
6 IrcConnection
= require('./irc/connection.js').IrcConnection
,
7 IrcCommands
= require('./irc/commands.js'),
8 ClientCommands
= require('./clientcommands.js');
11 var Client = function (websocket
) {
14 events
.EventEmitter
.call(this);
15 this.websocket
= websocket
;
18 this.real_address
= this.websocket
.handshake
.real_address
;
20 // A hash to identify this client instance
21 this.hash
= crypto
.createHash('sha256').update(this.real_address
).update('' + Date
.now()).digest('hex');
23 this.irc_connections
= [];
24 this.next_connection
= 0;
31 // Handler for any commands sent from the client
32 this.client_commands
= new ClientCommands(this);
34 websocket
.on('irc', function () {
35 handleClientMessage
.apply(that
, arguments
);
37 websocket
.on('kiwi', function () {
38 kiwiCommand
.apply(that
, arguments
);
40 websocket
.on('disconnect', function () {
41 websocketDisconnect
.apply(that
, arguments
);
43 websocket
.on('error', function () {
44 websocketError
.apply(that
, arguments
);
47 util
.inherits(Client
, events
.EventEmitter
);
49 module
.exports
.Client
= Client
;
52 // Callbacks SHALL accept 2 arguments, error and response, in that order.
53 // error MUST be null where the command is successul.
54 // error MUST otherwise be a truthy value and SHOULD be a string where the cause of the error is known.
55 // response MAY be given even if error is truthy
57 Client
.prototype.sendIrcCommand = function (command
, data
, callback
) {
58 var c
= {command
: command
, data
: data
};
59 this.websocket
.emit('irc', c
, callback
);
62 Client
.prototype.sendKiwiCommand = function (command
, data
, callback
) {
63 var c
= {command
: command
, data
: data
};
64 this.websocket
.emit('kiwi', c
, callback
);
67 Client
.prototype.dispose = function () {
69 this.removeAllListeners();
72 function handleClientMessage(msg
, callback
) {
73 var server
, args
, obj
, channels
, keys
;
75 // Make sure we have a server number specified
76 if ((msg
.server
=== null) || (typeof msg
.server
!== 'number')) {
77 return (typeof callback
=== 'function') ? callback('server not specified') : undefined;
78 } else if (!this.irc_connections
[msg
.server
]) {
79 return (typeof callback
=== 'function') ? callback('not connected to server') : undefined;
82 // The server this command is directed to
83 server
= this.irc_connections
[msg
.server
];
85 if (typeof callback
!== 'function') {
90 msg
.data
= JSON
.parse(msg
.data
);
92 kiwi
.log('[handleClientMessage] JSON parsing error ' + msg
.data
);
96 // Run the client command
97 this.client_commands
.run(msg
.data
.method
, msg
.data
.args
, server
, callback
);
103 function kiwiCommand(command
, callback
) {
106 if (typeof callback
!== 'function') {
107 callback = function () {};
109 switch (command
.command
) {
111 if (command
.hostname
&& command
.port
&& command
.nick
) {
112 var con
= new IrcConnection(command
.hostname
, command
.port
, command
.ssl
,
113 command
.nick
, {hostname
: this.websocket
.handshake
.revdns
, address
: this.websocket
.handshake
.address
.address
},
116 var con_num
= this.next_connection
++;
117 this.irc_connections
[con_num
] = con
;
119 var irc_commands
= new IrcCommands(con
, con_num
, this);
120 irc_commands
.bindEvents();
122 con
.on('connected', function () {
123 console
.log("con.on('connected')");
124 return callback(null, con_num
);
127 con
.on('error', function (err
) {
128 // TODO: Once multiple servers implemented, specify which server failed
129 //that.sendKiwiCommand('error', {server: con_num, error: err});
130 return callback(err
.code
, null);
133 con
.on('close', function () {
134 that
.irc_connections
[con_num
] = null;
137 return callback('Hostname, port and nickname must be specified');
146 // Websocket has disconnected, so quit all the IRC connections
147 function websocketDisconnect() {
148 _
.each(this.irc_connections
, function (irc_connection
, i
, cons
) {
149 if (irc_connection
) {
150 irc_connection
.end('QUIT :' + (config
.get().quit_message
|| ''));
151 irc_connection
.dispose();
160 // TODO: Should this close all the websocket connections too?
161 function websocketError() {