# HG changeset patch # User Goffi # Date 1545831433 -3600 # Node ID d0466af33483b3f509ee55edc5e549bbb2dc2ada # Parent 35a0ab3032bb513c66696f019a7b241fb7b0604e plugin XEP-0198: abort connection if ack is not received after a timeout: If ack is not received after a given time (currently 25s), connection is aborted. This avoid waiting forever when TCP link is lost (i.e. switching from cable to wifi), and allows to use resuming mechanism. diff -r 35a0ab3032bb -r d0466af33483 sat/plugins/plugin_xep_0198.py --- a/sat/plugins/plugin_xep_0198.py Wed Dec 12 08:58:52 2018 +0100 +++ b/sat/plugins/plugin_xep_0198.py Wed Dec 26 14:37:13 2018 +0100 @@ -59,6 +59,8 @@ MAX_DELAY_ACK_R = 30 MAX_COUNTER = 2**32 RESUME_MAX = 5*60 +# if we don't have an answer to ACK REQUEST after this delay, connection is aborted +ACK_R_TIMEOUT = 25 class ProfileSessionData(object): @@ -77,6 +79,9 @@ self.buffer_idx = 0 self._enabled = False self.timer = None + # time used when doing a ack request + # when it times out, connection is aborted + self.req_timer = None self.callback_data = (callback, kw) @property @@ -230,8 +235,12 @@ def requestAck(self, client): """Send a request element""" + session = client._xep_0198_session r_elt = domish.Element((NS_SM, 'r')) client.send(r_elt) + if session.req_timer is not None: + raise exceptions.InternalError("req_timer should not be set") + session.req_timer = reactor.callLater(ACK_R_TIMEOUT, self.onAckTimeOut, client) def _connectionFailed(self, failure_, connector): normal_host, normal_port = connector.normal_location @@ -404,6 +413,11 @@ def onAckAnswer(self, a_elt, client): session = client._xep_0198_session session.ack_requested = False + if session.req_timer is None: + log.error("reg_timer should be set") + else: + session.req_timer.cancel() + session.req_timer = None try: server_acked = int(a_elt['h']) except ValueError: @@ -421,6 +435,11 @@ self.updateBuffer(session, server_acked) self.checkAcks(client) + def onAckTimeOut(self, client): + """Called when a requested ACK has not been received in time""" + log.info(_(u"Ack was not received in time, aborting connection")) + client.xmlstream.transport.abortConnection() + class XEP_0198_handler(xmlstream.XMPPHandler): implements(iwokkel.IDisco)