d41dc52e3db96568ccc86567c3fa6f87727bab82
1 var util
= require('util'),
2 events
= require('events'),
3 crypto
= require('crypto'),
5 State
= require('./irc/state.js'),
6 IrcConnection
= require('./irc/connection.js').IrcConnection
,
7 ClientCommands
= require('./clientcommands.js'),
8 WebsocketRpc
= require('./websocketrpc.js');
11 var Client = function (websocket
) {
14 events
.EventEmitter
.call(this);
15 this.websocket
= websocket
;
16 this.rpc
= new WebsocketRpc(this.websocket
);
19 this.real_address
= this.websocket
.meta
.real_address
;
21 // A hash to identify this client instance
22 this.hash
= crypto
.createHash('sha256')
23 .update(this.real_address
)
24 .update('' + Date
.now())
25 .update(Math
.floor(Math
.random() * 100000).toString())
28 this.state
= new State(this);
35 // Handler for any commands sent from the client
36 this.client_commands
= new ClientCommands(this);
38 this.rpc
.on('irc', function (response
, data
) {
39 handleClientMessage
.call(that
, data
, response
);
41 this.rpc
.on('kiwi', function (response
, data
) {
42 kiwiCommand
.call(that
, data
, response
);
44 websocket
.on('close', function () {
45 websocketDisconnect
.apply(that
, arguments
);
47 websocket
.on('error', function () {
48 websocketError
.apply(that
, arguments
);
51 this.disposed
= false;
53 // Let the client know it's finished connecting
54 this.sendKiwiCommand('connected');
56 util
.inherits(Client
, events
.EventEmitter
);
58 module
.exports
.Client
= Client
;
61 // Callbacks SHALL accept 2 arguments, error and response, in that order.
62 // error MUST be null where the command is successul.
63 // error MUST otherwise be a truthy value and SHOULD be a string where the cause of the error is known.
64 // response MAY be given even if error is truthy
66 Client
.prototype.sendIrcCommand = function (command
, data
, callback
) {
67 var c
= {command
: command
, data
: data
};
68 this.rpc
.call('irc', c
, callback
);
71 Client
.prototype.sendKiwiCommand = function (command
, data
, callback
) {
72 var c
= {command
: command
, data
: data
};
73 this.rpc
.call('kiwi', c
, callback
);
76 Client
.prototype.dispose = function () {
80 this.removeAllListeners();
83 function handleClientMessage(msg
, callback
) {
87 // Make sure we have a server number specified
88 if ((msg
.server
=== null) || (typeof msg
.server
!== 'number')) {
89 return (typeof callback
=== 'function') ? callback('server not specified') : undefined;
90 } else if (!this.state
.irc_connections
[msg
.server
]) {
91 return (typeof callback
=== 'function') ? callback('not connected to server') : undefined;
94 // The server this command is directed to
95 server
= this.state
.irc_connections
[msg
.server
];
97 if (typeof callback
!== 'function') {
102 msg
.data
= JSON
.parse(msg
.data
);
104 kiwi
.log('[handleClientMessage] JSON parsing error ' + msg
.data
);
108 // Run the client command
109 global
.modules
.emit('client command', {
114 that
.client_commands
.run(msg
.data
.method
, msg
.data
.args
, server
, callback
);
121 function kiwiCommand(command
, callback
) {
122 if (typeof callback
!== 'function') {
123 callback = function () {};
126 switch (command
.command
) {
128 if (command
.hostname
&& command
.port
&& command
.nick
) {
131 // Get any optional parameters that may have been passed
132 if (command
.encoding
)
133 options
.encoding
= command
.encoding
;
135 options
.password
= global
.config
.restrict_server_password
|| command
.password
;
138 (global
.config
.restrict_server
|| command
.hostname
),
139 (global
.config
.restrict_server_port
|| command
.port
),
140 (typeof global
.config
.restrict_server_ssl
!== 'undefined' ?
141 global
.config
.restrict_server_ssl
:
144 {hostname
: this.websocket
.meta
.revdns
, address
: this.websocket
.meta
.real_address
},
148 return callback('Hostname, port and nickname must be specified');
157 // Websocket has disconnected, so quit all the IRC connections
158 function websocketDisconnect() {
159 this.emit('disconnect');
165 // TODO: Should this close all the websocket connections too?
166 function websocketError() {