From 09c26937aa9127e8c76a6aba1fcb958aa7b3ee09 Mon Sep 17 00:00:00 2001 From: Darren Date: Sat, 17 Aug 2013 18:03:52 +0100 Subject: [PATCH] Client broadcasting method + jump server command --- client/assets/src/models/application.js | 57 ++++++++++--- client/assets/src/models/gateway.js | 35 ++++---- server/kiwi.js | 105 ++++++++++++++++++------ 3 files changed, 141 insertions(+), 56 deletions(-) diff --git a/client/assets/src/models/application.js b/client/assets/src/models/application.js index b8832ab..cb804d4 100644 --- a/client/assets/src/models/application.js +++ b/client/assets/src/models/application.js @@ -353,10 +353,15 @@ _kiwi.model.Application = function () { */ (function () { var gw_stat = 0; + var unplanned_disconnect = false; gw.on('disconnect', function (event) { - var msg = _kiwi.global.i18n.translate('client_models_application_reconnecting').fetch() + '...'; - that.message.text(msg, {timeout: 10000}); + unplanned_disconnect = !gw.disconnect_requested; + + if (unplanned_disconnect) { + var msg = _kiwi.global.i18n.translate('client_models_application_reconnecting').fetch() + '...'; + that.message.text(msg, {timeout: 10000}); + } that.view.$el.removeClass('connected'); @@ -390,8 +395,10 @@ _kiwi.model.Application = function () { that.view.$el.addClass('connected'); if (gw_stat !== 1) return; - var msg = _kiwi.global.i18n.translate('client_models_application_reconnect_successfully').fetch() + ':)'; - that.message.text(msg, {timeout: 5000}); + if (unplanned_disconnect) { + var msg = _kiwi.global.i18n.translate('client_models_application_reconnect_successfully').fetch() + ':)'; + that.message.text(msg, {timeout: 5000}); + } // Mention the disconnection on every channel _kiwi.app.connections.forEach(function(connection) { @@ -409,17 +416,41 @@ _kiwi.model.Application = function () { }); })(); + gw.on('kiwi:reconfig', function () { $.getJSON(that.get('base_path') + '/assets/settings.json', function (data) { - console.log(data); - if (typeof data.kiwi_server !== 'undefined') { - _kiwi.app.kiwi_server = data.kiwi_server; - } - that.server_settings = data.server_settings || {}; that.translations = data.translations || {}; }); }); + + + gw.on('kiwi:jumpserver', function (data) { + // Switching kiwi server? + if (typeof data.kiwi_server !== 'undefined') { + _kiwi.app.kiwi_server = data.kiwi_server; + _kiwi.gateway.set('kiwi_server', data.kiwi_server); + } + + // Force the jumpserver now? + if (data.force) { + // Get an interval around 1 minute so everyone doesn't reconnect it all at once + var jump_server_interval = Math.random() * (90 - 60) + 60; + + var msg = 'In 1 minutes time you will be reconnected to a more stable server. Get ready!'; + that.message.text(msg, {timeout: 10000}); + + setTimeout(function forcedReconnect() { + var msg = 'Safely reconnecting you now..'; + that.message.text(msg, {timeout: 8000}); + + setTimeout(function forcedReconnectPartTwo() { + _kiwi.gateway.reconnect(); + }, 5000); + + }, jump_server_interval * 1000); + } + }); }; @@ -502,7 +533,7 @@ _kiwi.model.Application = function () { $script(ev.params[0] + '?' + (new Date().getTime())); }); - + controlbox.on('command:set', function (ev) { if (!ev.params[0]) return; @@ -572,7 +603,7 @@ _kiwi.model.Application = function () { controlbox.preprocessor.aliases[name] = rule; }); - + controlbox.on('command:ignore', function (ev) { var list = _kiwi.gateway.get('ignore_list'); @@ -652,7 +683,7 @@ _kiwi.model.Application = function () { } if (panel) panel.view.show(); - + } function msgCommand (ev) { @@ -784,7 +815,7 @@ _kiwi.model.Application = function () { return; } } - + _kiwi.app.connections.active_connection.panels.add(panel); panel.view.show(); } diff --git a/client/assets/src/models/gateway.js b/client/assets/src/models/gateway.js index 656590e..b6d4965 100644 --- a/client/assets/src/models/gateway.js +++ b/client/assets/src/models/gateway.js @@ -50,11 +50,14 @@ _kiwi.model.Gateway = function () { this.initialize = function () { that = this; - + // For ease of access. The socket.io object this.socket = this.get('socket'); this.applyEventHandlers(); + + // Used to check if a disconnection was unplanned + this.disconnect_requested = false; }; @@ -71,7 +74,7 @@ _kiwi.model.Gateway = function () { kiwi.gateway.on('quit', my_function); */ var that = this; - + // Some easier handler events this.on('onmsg', function (event) { var source, @@ -79,7 +82,7 @@ _kiwi.model.Gateway = function () { is_pm = (event.channel == connection.get('nick')); source = is_pm ? event.nick : event.channel; - + that.trigger('message:' + source, event); that.trigger('message', event); @@ -105,7 +108,7 @@ _kiwi.model.Gateway = function () { is_pm = (event.channel == connection.get('nick')); source = is_pm ? event.nick : event.channel; - + that.trigger('action:' + source, event); if (is_pm) { @@ -130,6 +133,14 @@ _kiwi.model.Gateway = function () { + this.reconnect = function (callback) { + this.disconnect_requested = true; + this.socket.disconnect(); + this.connect(callback); + }; + + + /** * Connects to the server * @param {Function} callback A callback function to be invoked once Kiwi's server has connected to the IRC server @@ -177,18 +188,10 @@ _kiwi.model.Gateway = function () { * IRCD and the nick has been accepted. */ this.socket.on('connect', function () { + // Reset the disconnect_requested flag + that.disconnect_requested = false; + callback && callback(); - /* - this.emit('kiwi', {command: 'connect', nick: that.get('nick'), hostname: host, port: port, ssl: ssl, password:password}, function (err, server_num) { - if (!err) { - that.server_num = server_num; - console.log("_kiwi.gateway.socket.on('connect')"); - } else { - console.log("_kiwi.gateway.socket.on('error')", {reason: err}); - callback(err); - } - }); - */ }); this.socket.on('too_many_connections', function () { @@ -239,7 +242,7 @@ _kiwi.model.Gateway = function () { console.log("_kiwi.gateway.socket.on('connect')"); callback_fn && callback_fn(err, connection); - + } else { console.log("_kiwi.gateway.socket.on('error')", {reason: err}); callback_fn && callback_fn(err); diff --git a/server/kiwi.js b/server/kiwi.js index 12e5106..11c7b97 100755 --- a/server/kiwi.js +++ b/server/kiwi.js @@ -111,12 +111,52 @@ global.clients = { } else { return 0; } + }, + + broadcastKiwiCommand: function (command, data, callback) { + var clients = []; + + // Get an array of clients for us to work with + for (var client in global.clients.clients) { + clients.push(global.clients.clients[client]); + } + + + // Sending of the command in batches + var sendCommandBatch = function (list) { + var batch_size = 100, + cutoff; + + if (list.length >= batch_size) { + // If we have more clients than our batch size, call ourself with the next batch + setTimeout(function () { + sendCommandBatch(list.slice(batch_size)); + }, 200); + + cutoff = batch_size; + + } else { + cutoff = list.length; + } + + list.slice(0, cutoff).forEach(function (client) { + if (!client.disposed) { + client.sendKiwiCommand(command, data); + } + }); + + if (cutoff === list.length && typeof callback === 'function') { + callback(); + } + }; + + sendCommandBatch(clients); } }; global.servers = { servers: Object.create(null), - + addConnection: function (connection) { var host = connection.irc_host.hostname; if (!this.servers[host]) { @@ -124,7 +164,7 @@ global.servers = { } this.servers[host].push(connection); }, - + removeConnection: function (connection) { var host = connection.irc_host.hostname if (this.servers[host]) { @@ -134,7 +174,7 @@ global.servers = { } } }, - + numOnHost: function (host) { if (this.servers[host]) { return this.servers[host].length; @@ -146,29 +186,12 @@ global.servers = { +/** + * When a new config is loaded, send out an alert to the clients so + * so they can reload it + */ config.on('loaded', function () { - var clients = []; - for (var client in global.clients.clients) { - clients.push(global.clients.clients[client]); - } - var sendReconfigCommand = function (list) { - var cutoff; - if (list.length >= 100) { - setTimeout(function () { - sendReconfigCommand(list.slice(100)); - }, 200); - cutoff = 100; - } else { - cutoff = list.length; - } - list.slice(0, cutoff).forEach(function (client) { - if (!client.disposed) { - client.sendKiwiCommand('reconfig'); - } - }); - }; - - sendReconfigCommand(clients); + global.clients.broadcastKiwiCommand('reconfig'); }); @@ -286,9 +309,11 @@ process.on('SIGUSR2', function() { process.stdin.resume(); process.stdin.on('data', function (buffered) { - var data = buffered.toString().trim(); + var data = buffered.toString().trim(), + data_parts = data.split(' '), + cmd = data_parts[0] || null; - switch (data) { + switch (cmd) { case 'stats': console.log('Connected clients: ' + _.size(global.clients.clients).toString()); console.log('Num. remote hosts: ' + _.size(global.clients.addresses).toString()); @@ -312,6 +337,32 @@ process.stdin.on('data', function (buffered) { break; + case 'jumpserver': + (function() { + var num_clients = _.size(global.clients.clients), + packet = {}, parts_idx; + + if (num_clients === 0) { + console.log('No connected clients'); + return; + } + + // For each word in the line minus the last, add it to the packet + for(parts_idx=1; parts_idx