diff --git a/src/common/config.py b/src/common/config.py index 7a4896cb6d7a4e1b77b180daaeed284d9e744f77..4065fb284177ca0e941fe7a373f04cfa8130d06f 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -159,6 +159,7 @@ class Config: 'resource': [ opt_str, 'gajim' ], 'priority': [ opt_int, 5 ], 'autoconnect': [ opt_bool, False ], + 'autoreconnect': [ opt_bool, False ], 'proxy': [ opt_str, '' ], 'keyid': [ opt_str, '' ], 'keyname': [ opt_str, '' ], diff --git a/src/common/connection.py b/src/common/connection.py index 683934b5f3483d21aefef7db4664a95398a80d5a..86e06cabc223fec440b7b2f6d09610dd4198cd80 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -124,6 +124,8 @@ class Connection: self.gpg = None self.vcard_sha = None self.status = '' + self.old_show = '' + self.time_to_reconnect = None self.new_account_info = None self.bookmarks = [] self.on_purpose = False @@ -138,6 +140,7 @@ class Connection: gajim.config.set('usegpg', True) else: gajim.config.set('usegpg', False) + self.retrycount = 0 # END __init__ def put_event(self, ev): @@ -217,9 +220,7 @@ class Connection: self.vcard_sha = '' self.dispatch('MYVCARD', vcard) #we re-send our presence with sha - sshow = STATUS_LIST[self.connected] - if sshow == 'online': - sshow = None + sshow = helpers.get_xmpp_show(STATUS_LIST[self.connected]) prio = unicode(gajim.config.get_per('accounts', self.name, 'priority')) p = common.xmpp.Presence(typ = None, priority = prio, show = sshow, @@ -409,8 +410,54 @@ class Connection: (_('Connection with account "%s" has been lost') % self.name, _('To continue sending and receiving messages, you will need to reconnect.'))) self.on_purpose = False - + # END disconenctedCB + + def _reconnect(self): + gajim.log.debug('reconnect') + signed = self.get_signed_msg(self.status) + self.connect_and_init(self.old_show, self.status, signed) + if self.connected < 2: #connection failed + if self.retrycount > 10: + self.connected = 0 + self.dispatch('STATUS', 'offline') + self.dispatch('ERROR', + (_('Connection with account "%s" has been lost') % self.name, + _('To continue sending and receiving messages, you will need to reconnect.'))) + self.time_to_reconnect = None + self.retrycount = 0 + return + self.retrycount = self.retrycount + 1 + if self.retrycount > 5: + self.time_to_reconnect = time.time() + 20 + else: + self.time_to_reconnect = time.time() + 10 + else: + #reconnect succeeded + self.time_to_reconnect = None + self.retrycount = 0 + + def _disconnectedReconnCB(self): + """Called when we are disconnected""" + gajim.log.debug('disconnectedReconnCB') + if not self.connection: + return + self.old_show = STATUS_LIST[self.connected] + self.connected = 0 + self.dispatch('STATUS', 'offline') + self.connection = None + if not self.on_purpose: + if gajim.config.get_per('accounts', self.name, 'autoreconnect'): + self.connected = 1 + self.dispatch('STATUS', 'connecting') + self.time_to_reconnect = time.time() + 10 + else: + self.dispatch('ERROR', + (_('Connection with account "%s" has been lost') % self.name, + _('To continue sending and receiving messages, you will need to reconnect.'))) + self.on_purpose = False + # END disconenctedReconnCB + def _bytestreamErrorCB(self, con, iq_obj): gajim.log.debug('_bytestreamErrorCB') frm = unicode(iq_obj.getFrom()) @@ -1244,7 +1291,7 @@ class Connection: con = common.xmpp.Client(hostname, debug = []) common.xmpp.dispatcher.DefaultTimeout = try_connecting_for_foo_secs con.UnregisterDisconnectHandler(con.DisconnectHandler) - con.RegisterDisconnectHandler(self._disconnectedCB) + con.RegisterDisconnectHandler(self._disconnectedReconnCB) h = hostname p = 5222 @@ -1260,10 +1307,11 @@ class Connection: con_type = con.connect((h, p), proxy = proxy, secure=secur) #FIXME: blocking if not con_type: gajim.log.debug("Couldn't connect to %s" % self.name) - self.connected = 0 - self.dispatch('STATUS', 'offline') - self.dispatch('ERROR', (_('Could not connect to "%s"') % self.name, - _('Check your connection or try again later'))) + if not self.time_to_reconnect: + self.connected = 0 + self.dispatch('STATUS', 'offline') + self.dispatch('ERROR', (_('Could not connect to "%s"') % self.name, + _('Check your connection or try again later'))) return None self.peerhost = con.get_peerhost() @@ -1326,7 +1374,7 @@ class Connection: self.dispatch('STATUS', 'offline') self.dispatch('ERROR', (_('Could not connect to "%s"') % self.name, _('Check your connection or try again later'))) - return None + return None con.RegisterEventHandler(self._event_dispatcher) if auth: con.initRoster() @@ -1402,7 +1450,52 @@ class Connection: #Get bookmarks from private namespace self.get_bookmarks() - + + def get_signed_msg(self, msg): + signed = '' + keyID = gajim.config.get_per('accounts', self.name, 'keyid') + if keyID and USE_GPG: + use_gpg_agent = gajim.config.get('use_gpg_agent') + if self.connected < 2 and self.gpg.passphrase is None and not use_gpg_agent: + # We didn't set a passphrase + self.dispatch('ERROR', (_('OpenPGP passphrase was not given'), + #%s is the account name here + _('You will be connected to %s without OpenPGP.') % self.name)) + elif self.gpg.passphrase is not None or use_gpg_agent: + signed = self.gpg.sign(msg, keyID) + if signed == 'BAD_PASSPHRASE': + signed = '' + if self.connected < 2: + self.dispatch('BAD_PASSPHRASE', ()) + return signed + + def connect_and_init(self, show, msg, signed): + self.connection = self.connect() + if self.connected == 2: + self.connected = STATUS_LIST.index(show) + sshow = helpers.get_xmpp_show(show) + #send our presence + if show == 'invisible': + self.send_invisible_presence(msg, signed, True) + return + prio = unicode(gajim.config.get_per('accounts', self.name, + 'priority')) + p = common.xmpp.Presence(typ = None, priority = prio, show = sshow) + p = self.add_sha(p) + if msg: + p.setStatus(msg) + if signed: + p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed) + + if self.connection: + self.connection.send(p) + self.dispatch('STATUS', show) + #ask our VCard + self.request_vcard(None) + + #Get bookmarks from private namespace + self.get_bookmarks() + def change_status(self, show, msg, sync = False, auto = False): if sync: self.change_status2(show, msg, auto) @@ -1413,9 +1506,7 @@ class Connection: def change_status2(self, show, msg, auto = False): if not show in STATUS_LIST: return -1 - sshow = show # show to be send - if show == 'online': - sshow = None + sshow = helpers.get_xmpp_show(show) if not msg: lowered_uf_status_msg = helpers.get_uf_show(show).lower() if lowered_uf_status_msg == _('invisible'): # do not show I'm invisible! @@ -1423,47 +1514,12 @@ class Connection: msg = _("I'm %s") % lowered_uf_status_msg signed = '' - keyID = gajim.config.get_per('accounts', self.name, 'keyid') - if keyID and USE_GPG and not auto and not show == 'offline': - use_gpg_agent = gajim.config.get('use_gpg_agent') - if self.connected < 2 and self.gpg.passphrase is None and not use_gpg_agent: - # We didn't set a passphrase - self.dispatch('ERROR', (_('OpenPGP passphrase was not given'), - #%s is the account name here - _('You will be connected to %s without OpenPGP.') % self.name)) - elif self.gpg.passphrase is not None or use_gpg_agent: - signed = self.gpg.sign(msg, keyID) - if signed == 'BAD_PASSPHRASE': - signed = '' - if self.connected < 2: - self.dispatch('BAD_PASSPHRASE', ()) + if not auto and not show == 'offline': + signed = self.get_signed_msg(msg) self.status = msg if show != 'offline' and not self.connected: - self.connection = self.connect() - if self.connected == 2: - self.connected = STATUS_LIST.index(show) - #send our presence - if show == 'invisible': - self.send_invisible_presence(msg, signed, True) - return - prio = unicode(gajim.config.get_per('accounts', self.name, - 'priority')) - p = common.xmpp.Presence(typ = None, priority = prio, show = sshow) - p = self.add_sha(p) - if msg: - p.setStatus(msg) - if signed: - p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed) + self.connect_and_init(show, msg, signed) - if self.connection: - self.connection.send(p) - self.dispatch('STATUS', show) - #ask our VCard - self.request_vcard(None) - - #Get bookmarks from private namespace - self.get_bookmarks() - elif show == 'offline' and self.connected: self.connected = 0 if self.connection: @@ -1764,10 +1820,8 @@ class Connection: def join_gc(self, nick, room, server, password): if not self.connection: return - show = STATUS_LIST[self.connected] + show = helpers.get_xmpp_show(STATUS_LIST[self.connected]) ptype = None - if show == 'online': - show = None p = common.xmpp.Presence(to = '%s@%s/%s' % (room, server, nick), show = show, status = self.status) p = self.add_sha(p) @@ -1807,9 +1861,7 @@ class Connection: ptype = None if show == 'offline': ptype = 'unavailable' - show = None - if show == 'online': - show = None + show = helpers.get_xmpp_show(show) p = common.xmpp.Presence(to = '%s/%s' % (jid, nick), typ = ptype, show = show, status = status) p = self.add_sha(p) @@ -1912,6 +1964,12 @@ class Connection: self.to_be_sent.append(' ') def process(self, timeout): + if self.time_to_reconnect: + if self.connected < 2: + if time.time() > self.time_to_reconnect: + self._reconnect() + else: + self.time_to_reconnect = None if not self.connection: return if self.connected: diff --git a/src/common/helpers.py b/src/common/helpers.py index d1efb78d7ebb3c6d6dcf098011ec658d3375476a..08d0cf7fe3ab043cf2cc5362b6e87bc303088728 100644 --- a/src/common/helpers.py +++ b/src/common/helpers.py @@ -312,4 +312,9 @@ def ensure_unicode_string(s): if isinstance(s, str): s = s.decode('utf-8') return s + +def get_xmpp_show(show): + if show in ['online', 'offline']: + return None + return show diff --git a/src/config.py b/src/config.py index 5e5ed7327a1e8cf70ceafb9bde8b2c62a8a7427e..dfd6a96151623f02e857d74037335498e8bfc7b7 100644 --- a/src/config.py +++ b/src/config.py @@ -1210,6 +1210,8 @@ class AccountModificationWindow: self.xml.get_widget('gpg_choose_button').set_sensitive(False) self.xml.get_widget('autoconnect_checkbutton').set_active(gajim.config.\ get_per('accounts', self.account, 'autoconnect')) + self.xml.get_widget('autoreconnect_checkbutton').set_active(gajim.config.\ + get_per('accounts', self.account, 'autoreconnect')) if len(gajim.connections) != 0: # only if we already have one account already @@ -1260,6 +1262,8 @@ _('To change the account name, you must be disconnected.')).get_response() get_value_as_int() config['autoconnect'] = self.xml.get_widget('autoconnect_checkbutton').\ get_active() + config['autoreconnect'] = self.xml.get_widget('autoreconnect_checkbutton').\ + get_active() if self.account: list_no_log_for = gajim.config.get_per('accounts', diff --git a/src/gajim.py b/src/gajim.py index 587ef4cf1985ca100150712fa40f516e82218851..f7326a6bf6dfa1d3c41f1f50a78c315fbe2e8277 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -200,6 +200,8 @@ class Interface: def handle_event_status(self, account, status): # OUR status #('STATUS', account, status) + if status == 'connecting': + self.roster.set_connecting_state(account) if status != 'offline': gobject.timeout_add(30000, self.allow_notif, account) else: diff --git a/src/gtkgui.glade b/src/gtkgui.glade index 556bfcccb9466cdb9c2d54354cac88a85a88e249..e1a6f80d4548f9080c748cb05b8a85dc3d498b7a 100644 --- a/src/gtkgui.glade +++ b/src/gtkgui.glade @@ -1037,6 +1037,25 @@ </packing> </child> + <child> + <widget class="GtkCheckButton" id="autoreconnect_checkbutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Reconnect automatically</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> <widget class="GtkCheckButton" id="log_history_checkbutton"> <property name="visible">True</property> diff --git a/src/roster_window.py b/src/roster_window.py index fc1fc04f73224936f3511db0491d03c253298a85..a9db644862b7cd9a82f504a5a5681c45977eccda 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1171,15 +1171,18 @@ _('If "%s" accepts this request you will know his status.') %jid) del self.gpg_passphrase[keyid] return False + def set_connecting_state(self, account): + model = self.tree.get_model() + accountIter = self.get_account_iter(account) + if accountIter: + model[accountIter][0] = self.jabber_state_images['connecting'] + if self.plugin.systray_enabled: + self.plugin.systray.change_status('connecting') + def send_status(self, account, status, txt, sync = False, auto = False): if status != 'offline': if gajim.connections[account].connected < 2: - model = self.tree.get_model() - accountIter = self.get_account_iter(account) - if accountIter: - model[accountIter][0] = self.jabber_state_images['connecting'] - if self.plugin.systray_enabled: - self.plugin.systray.change_status('connecting') + self.set_connecting_state(account) save_pass = gajim.config.get_per('accounts', account, 'savepass') if not save_pass and gajim.connections[account].connected < 2: