Merge branch 'ping-cancel-iqs-on-session-end' into 'master'

Cancel  0199 pings on session end

See merge request poezio/slixmpp!102
This commit is contained in:
mathieui 2021-01-24 11:30:51 +01:00
commit 0193667ace
2 changed files with 42 additions and 11 deletions

View File

@ -9,7 +9,8 @@
import time import time
import logging import logging
from typing import Optional, Callable from asyncio import Future
from typing import Optional, Callable, List
from slixmpp.jid import JID from slixmpp.jid import JID
from slixmpp.stanza import Iq from slixmpp.stanza import Iq
@ -64,9 +65,10 @@ class XEP_0199(BasePlugin):
""" """
Start the XEP-0199 plugin. Start the XEP-0199 plugin.
""" """
register_stanza_plugin(Iq, Ping) register_stanza_plugin(Iq, Ping)
self.__pending_futures: List[Future] = []
self.xmpp.register_handler( self.xmpp.register_handler(
Callback('Ping', Callback('Ping',
StanzaPath('iq@type=get/ping'), StanzaPath('iq@type=get/ping'),
@ -75,7 +77,9 @@ class XEP_0199(BasePlugin):
if self.keepalive: if self.keepalive:
self.xmpp.add_event_handler('session_start', self.xmpp.add_event_handler('session_start',
self.enable_keepalive) self.enable_keepalive)
self.xmpp.add_event_handler('session_end', self.xmpp.add_event_handler('session_resumed',
self.enable_keepalive)
self.xmpp.add_event_handler('disconnected',
self.disable_keepalive) self.disable_keepalive)
def plugin_end(self): def plugin_end(self):
@ -84,12 +88,23 @@ class XEP_0199(BasePlugin):
if self.keepalive: if self.keepalive:
self.xmpp.del_event_handler('session_start', self.xmpp.del_event_handler('session_start',
self.enable_keepalive) self.enable_keepalive)
self.xmpp.del_event_handler('session_end', self.xmpp.del_event_handler('session_resumed',
self.enable_keepalive)
self.xmpp.del_event_handler('disconnected',
self.disable_keepalive) self.disable_keepalive)
def session_bind(self, jid): def session_bind(self, jid):
self.xmpp['xep_0030'].add_feature(Ping.namespace) self.xmpp['xep_0030'].add_feature(Ping.namespace)
def _clear_pending_futures(self):
"""Cancel all pending ping futures"""
if self.__pending_futures:
log.debug('Clearing %s pdnding pings', len(self.__pending_futures))
for future in self.__pending_futures:
future.cancel()
self.__pending_futures.clear()
def enable_keepalive(self, interval=None, timeout=None): def enable_keepalive(self, interval=None, timeout=None):
if interval: if interval:
self.interval = interval self.interval = interval
@ -97,18 +112,31 @@ class XEP_0199(BasePlugin):
self.timeout = timeout self.timeout = timeout
self.keepalive = True self.keepalive = True
handler = lambda event=None: asyncio.ensure_future( def handler(event=None):
# Cleanup futures
if self.__pending_futures:
tmp_futures = []
for future in self.__pending_futures[:]:
if not future.done():
tmp_futures.append(future)
self.__pending_futures = tmp_futures
future = asyncio.ensure_future(
self._keepalive(event), self._keepalive(event),
loop=self.xmpp.loop, loop=self.xmpp.loop,
) )
self.__pending_futures.append(future)
self.xmpp.schedule('Ping keepalive', self.xmpp.schedule('Ping keepalive',
self.interval, self.interval,
handler, handler,
repeat=True) repeat=True)
def disable_keepalive(self, event=None): def disable_keepalive(self, event=None):
self._clear_pending_futures()
self.xmpp.cancel_schedule('Ping keepalive') self.xmpp.cancel_schedule('Ping keepalive')
session_end = disable_keepalive
async def _keepalive(self, event=None): async def _keepalive(self, event=None):
log.debug("Keepalive ping...") log.debug("Keepalive ping...")
try: try:

View File

@ -194,8 +194,10 @@ class Iq(RootStanza):
def callback_success(result): def callback_success(result):
type_ = result['type'] type_ = result['type']
if type_ == 'result': if type_ == 'result':
if not future.done():
future.set_result(result) future.set_result(result)
elif type_ == 'error': elif type_ == 'error':
if not future.done():
future.set_exception(IqError(result)) future.set_exception(IqError(result))
else: else:
# Most likely an iq addressed to ourself, rearm the callback. # Most likely an iq addressed to ourself, rearm the callback.
@ -212,6 +214,7 @@ class Iq(RootStanza):
callback(result) callback(result)
def callback_timeout(): def callback_timeout():
if not future.done():
future.set_exception(IqTimeout(self)) future.set_exception(IqTimeout(self))
self.stream.remove_handler('IqCallback_%s' % self['id']) self.stream.remove_handler('IqCallback_%s' % self['id'])
if timeout_callback is not None: if timeout_callback is not None: