Merge pull request #477 from glowing-bear/reconnect

[WIP] Start implementing auto-reconnect
This commit is contained in:
Tor Hveem 2015-03-14 21:19:24 +01:00
commit afdcaadb72
6 changed files with 148 additions and 17 deletions

View file

@ -263,6 +263,19 @@ td.time {
font-family: sans-serif;
}
#reconnect {
top: 35px;
position: fixed;
z-index: 9999;
width: 80%;
margin: 0;
padding: 5px;
left: 10%;
}
#reconnect a {
color: white;
}
.footer {
position: fixed;
bottom: 0;

View file

@ -295,6 +295,11 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
</div>
</div>
<div id="soundNotification"></div>
<div id="reconnect" class="alert alert-danger" ng-click="reconnect()" ng-show="reconnecting">
<p><strong>Connection to WeeChat lost</strong></p>
<i class="glyphicon glyphicon-refresh"></i>
Reconnecting... <a class="btn btn-tiny" ng-click="reconnect()">Click to try to reconnect now</a>
</div>
<div id="settingsModal" class="gb-modal" data-state="hidden">
<div class="backdrop" ng-click="closeModal($event)"></div>
<div class="modal-dialog">

View file

@ -12,9 +12,12 @@ weechat.factory('connection',
var protocol = new weeChat.Protocol();
// Takes care of the connection and websocket hooks
var connectionData = [];
var reconnectTimer;
var connect = function (host, port, passwd, ssl, noCompression) {
// Takes care of the connection and websocket hooks
var connect = function (host, port, passwd, ssl, noCompression, successCallback, failCallback) {
connectionData = [host, port, passwd, ssl, noCompression];
var proto = ssl ? 'wss' : 'ws';
// If host is an IPv6 literal wrap it in brackets
if (host.indexOf(":") !== -1) {
@ -79,21 +82,15 @@ weechat.factory('connection',
// Connection is successful
// Send all the other commands required for initialization
_requestBufferInfos().then(function(bufinfo) {
//XXX move to handlers?
var bufferInfos = bufinfo.objects[0].content;
// buffers objects
for (var i = 0; i < bufferInfos.length ; i++) {
var buffer = new models.Buffer(bufferInfos[i]);
models.addBuffer(buffer);
// Switch to first buffer on startup
if (i === 0) {
models.setActiveBuffer(buffer.id);
}
}
handlers.handleBufferInfo(bufinfo);
});
_requestHotlist().then(function(hotlist) {
handlers.handleHotlistInfo(hotlist);
if (successCallback) {
successCallback();
}
});
_requestSync();
@ -123,10 +120,19 @@ weechat.factory('connection',
* Handles websocket disconnection
*/
$log.info("Disconnected from relay");
if ($rootScope.userdisconnect || !$rootScope.waseverconnected) {
handleClose(evt);
$rootScope.userdisconnect = false;
} else {
reconnect(evt);
}
};
var handleClose = function (evt) {
ngWebsockets.failCallbacks('disconnection');
$rootScope.connected = false;
$rootScope.$emit('relayDisconnect');
if (ssl && evt.code === 1006) {
if (ssl && evt && evt.code === 1006) {
// A password error doesn't trigger onerror, but certificate issues do. Check time of last error.
if (typeof $rootScope.lastError !== "undefined" && (Date.now() - $rootScope.lastError) < 1000) {
// abnormal disconnect by client, most likely ssl error
@ -166,11 +172,64 @@ weechat.factory('connection',
$rootScope.errorMessage = true;
$rootScope.securityError = true;
$rootScope.$emit('relayDisconnect');
if (failCallback) {
failCallback();
}
}
};
var attemptReconnect = function (bufferId, timeout) {
$log.info('Attempting to reconnect...');
var d = connectionData;
connect(d[0], d[1], d[2], d[3], d[4], function() {
$rootScope.reconnecting = false;
// on success, update active buffer
models.setActiveBuffer(bufferId);
$log.info('Sucessfully reconnected to relay');
}, function() {
// on failure, schedule another attempt
if (timeout >= 600000) {
// If timeout is ten minutes or more, give up
$log.info('Failed to reconnect, giving up');
handleClose();
} else {
$log.info('Failed to reconnect, scheduling next attempt in', timeout/1000, 'seconds');
// Clear previous timer, if exists
if (reconnectTimer !== undefined) {
clearTimeout(reconnectTimer);
}
reconnectTimer = setTimeout(function() {
// exponential timeout increase
attemptReconnect(bufferId, timeout * 1.5);
}, timeout);
}
});
};
var reconnect = function (evt) {
if (connectionData.length < 5) {
// something is wrong
$log.error('Cannot reconnect, connection information is missing');
return;
}
$rootScope.reconnecting = true;
// Have to do this to get the reconnect banner to show
$rootScope.$apply();
var bufferId = models.getActiveBuffer().id,
timeout = 3000; // start with a three-second timeout
reconnectTimer = setTimeout(function() {
attemptReconnect(bufferId, timeout);
}, timeout);
};
var disconnect = function() {
$rootScope.userdisconnect = true;
ngWebsockets.send(weeChat.Protocol.formatQuit());
};
@ -270,7 +329,8 @@ weechat.factory('connection',
sendMessage: sendMessage,
sendCoreCommand: sendCoreCommand,
fetchMoreLines: fetchMoreLines,
requestNicklist: requestNicklist
requestNicklist: requestNicklist,
attemptReconnect: attemptReconnect
};
}]);
})();

View file

@ -264,6 +264,8 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
$rootScope.connected = false;
$rootScope.waseverconnected = false;
$rootScope.userdisconnect = false;
$rootScope.reconnecting = false;
$rootScope.models = models;
@ -513,6 +515,10 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
$scope.connectbutton = 'Connect';
connection.disconnect();
};
$scope.reconnect = function() {
var bufferId = models.getActiveBuffer().id;
connection.attemptReconnect(bufferId, 3000);
};
//XXX this is a bit out of place here, either move up to the rest of the firefox install code or remove
$scope.install = function() {

View file

@ -43,6 +43,53 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
}
};
var handleBufferInfo = function(message) {
var bufferInfos = message.objects[0].content;
// buffers objects
for (var i = 0; i < bufferInfos.length ; i++) {
var bufferId = bufferInfos[i].pointers[0];
var buffer = models.getBuffer(bufferId);
if (buffer !== undefined) {
// We already know this buffer
handleBufferUpdate(buffer, bufferInfos[i]);
} else {
buffer = new models.Buffer(bufferInfos[i]);
models.addBuffer(buffer);
// Switch to first buffer on startup
if (i === 0) {
models.setActiveBuffer(buffer.id);
}
}
}
};
var handleBufferUpdate = function(buffer, message) {
if (message.pointers[0] !== buffer.id) {
// this is information about some other buffer!
return;
}
// weechat properties -- short name can be changed
buffer.shortName = message.short_name;
buffer.trimmedName = buffer.shortName.replace(/^[#&+]/, '');
buffer.title = message.title;
buffer.number = message.number;
// reset these, hotlist info will arrive shortly
buffer.notification = 0;
buffer.unread = 0;
buffer.lastSeen = -1;
if (message.local_variables.type !== undefined) {
buffer.type = message.local_variables.type;
buffer.indent = (['channel', 'private'].indexOf(buffer.type) >= 0);
}
if (message.notify !== undefined) {
buffer.notify = message.notify;
}
};
var handleBufferLineAdded = function(message) {
message.objects[0].content.forEach(function(l) {
handleLine(l, false);
@ -216,7 +263,8 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
handleEvent: handleEvent,
handleLineInfo: handleLineInfo,
handleHotlistInfo: handleHotlistInfo,
handleNicklist: handleNicklist
handleNicklist: handleNicklist,
handleBufferInfo: handleBufferInfo
};
}]);

View file

@ -110,7 +110,6 @@ function($rootScope, $q) {
$rootScope.$emit('onMessage', message);
}
$rootScope.$apply();
};
var connect = function(url,