summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Lukas <georg@op-co.de>2022-06-22 11:39:44 +0200
committerGeorg Lukas <georg@op-co.de>2022-06-22 11:39:44 +0200
commitb44ab17c8f2243a065d80755ce0492bfabb9b29d (patch)
treedd2a10c8f725c182bb576452c73a677e3e70c52f
parent5ceb48bbcd842962f8b8d206fddbce1dcfe7c069 (diff)
downloadslixmpp-b44ab17c8f2243a065d80755ce0492bfabb9b29d.tar.gz
slixmpp-b44ab17c8f2243a065d80755ce0492bfabb9b29d.tar.bz2
slixmpp-b44ab17c8f2243a065d80755ce0492bfabb9b29d.tar.xz
slixmpp-b44ab17c8f2243a065d80755ce0492bfabb9b29d.zip
Fix delayed reconnect after DNS failure
The XML stream will re-schedule a reconnect on socket errors, except for DNS failures. If a user has no uplink connection, then DNS will also fail, preventing an automatic reconnection. This patch consolidates the two code paths and sets a maximum back-off time of 5min (300s).
-rw-r--r--slixmpp/xmlstream/xmlstream.py23
1 files changed, 16 insertions, 7 deletions
diff --git a/slixmpp/xmlstream/xmlstream.py b/slixmpp/xmlstream/xmlstream.py
index 18143f87..06d48f5c 100644
--- a/slixmpp/xmlstream/xmlstream.py
+++ b/slixmpp/xmlstream/xmlstream.py
@@ -493,16 +493,11 @@ class XMLStream(asyncio.BaseProtocol):
except Socket.gaierror as e:
self.event('connection_failed',
'No DNS record available for %s' % self.default_domain)
+ self.reschedule_connection_attempt()
except OSError as e:
log.debug('Connection failed: %s', e)
self.event("connection_failed", e)
- if self._current_connection_attempt is None:
- return
- self._connect_loop_wait = self._connect_loop_wait * 2 + 1
- self._current_connection_attempt = asyncio.ensure_future(
- self._connect_routine(),
- loop=self.loop,
- )
+ self.reschedule_connection_attempt()
def process(self, *, forever: bool = True, timeout: Optional[int] = None) -> None:
"""Process all the available XMPP events (receiving or sending data on the
@@ -638,6 +633,20 @@ class XMLStream(asyncio.BaseProtocol):
self._set_disconnected_future()
self.event("disconnected", self.disconnect_reason or exception)
+ def reschedule_connection_attempt(self) -> None:
+ """
+ Increase the exponential back-off and initate another background
+ _connect_routine call to connect to the server.
+ """
+ # abort if there is no ongoing connection attempt
+ if self._current_connection_attempt is None:
+ return
+ self._connect_loop_wait = min(300, self._connect_loop_wait * 2 + 1)
+ self._current_connection_attempt = asyncio.ensure_future(
+ self._connect_routine(),
+ loop=self.loop,
+ )
+
def cancel_connection_attempt(self) -> None:
"""
Immediately cancel the current create_connection() Future.