From 72393ac06885b27b39d8c01257a81059e35f2a87 Mon Sep 17 00:00:00 2001
From: Yann Leboulanger <asterix@lagaule.org>
Date: Mon, 5 Sep 2005 13:28:09 +0000
Subject: [PATCH] autoreconnect of account is ready

---
 src/common/config.py     |   1 +
 src/common/connection.py | 174 ++++++++++++++++++++++++++-------------
 src/common/helpers.py    |   5 ++
 src/config.py            |   4 +
 src/gajim.py             |   2 +
 src/gtkgui.glade         |  19 +++++
 src/roster_window.py     |  15 ++--
 7 files changed, 156 insertions(+), 64 deletions(-)

diff --git a/src/common/config.py b/src/common/config.py
index 7a4896cb6d..4065fb2841 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 683934b5f3..86e06cabc2 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 d1efb78d7e..08d0cf7fe3 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 5e5ed7327a..dfd6a96151 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 587ef4cf19..f7326a6bf6 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 556bfcccb9..e1a6f80d45 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 fc1fc04f73..a9db644862 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:
-- 
GitLab