From 916416a019c398a484b6a436ee908808780263f9 Mon Sep 17 00:00:00 2001 From: mathieui Date: Thu, 8 May 2014 01:37:52 +0200 Subject: Add an ugly fix to avoid endless disco#info queries with each message (with receipts) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to check if the remote entity supports 0184, but if it doesn’t support disco#info, then we will get an iq type="error" and nothing will be cached, leading to disco#info queries being sent each time. Keep a cache valid 2 hours of the JIDs which replied with an error. TODO: check that this the kind of time period we want. --- src/fixes.py | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) (limited to 'src/fixes.py') diff --git a/src/fixes.py b/src/fixes.py index 75ac6343..cb992e88 100644 --- a/src/fixes.py +++ b/src/fixes.py @@ -5,12 +5,15 @@ upstream. TODO: Check that they are fixed and remove those hacks """ - from sleekxmpp.stanza import Message from sleekxmpp.xmlstream import ET import logging +# used to avoid doing numerous useless disco#info requests +# especially with message receipts +IQ_ERRORS = set() + log = logging.getLogger(__name__) def has_identity(xmpp, jid, identity): @@ -96,3 +99,89 @@ def _filter_add_receipt_request(self, stanza): stanza['request_receipt'] = True return stanza + +def xep_30_supports(self, jid, node, ifrom, data): + """ + Check if a JID supports a given feature. + + The data parameter may provide: + feature -- The feature to check for support. + local -- If true, then the query is for a JID/node + combination handled by this Sleek instance and + no stanzas need to be sent. + Otherwise, a disco stanza must be sent to the + remove JID to retrieve the info. + cached -- If true, then look for the disco info data from + the local cache system. If no results are found, + send the query as usual. The self.use_cache + setting must be set to true for this option to + be useful. If set to false, then the cache will + be skipped, even if a result has already been + cached. Defaults to false. + """ + feature = data.get('feature', None) + + data = {'local': data.get('local', False), + 'cached': data.get('cached', True)} + + if not feature or jid.full in IQ_ERRORS: + return False + + try: + info = self.disco.get_info(jid=jid, node=node, + ifrom=ifrom, **data) + info = self.disco._wrap(ifrom, jid, info, True) + features = info['disco_info']['features'] + return feature in features + except: + IQ_ERRORS.add(jid.full) + log.debug('%s added to the list of entities that do' + 'not honor disco#info', jid.full) + return False + +def xep_115_supports(self, jid, node, ifrom, data): + """ + Check if a JID supports a given feature. + + The data parameter may provide: + feature -- The feature to check for support. + local -- If true, then the query is for a JID/node + combination handled by this Sleek instance and + no stanzas need to be sent. + Otherwise, a disco stanza must be sent to the + remove JID to retrieve the info. + cached -- If true, then look for the disco info data from + the local cache system. If no results are found, + send the query as usual. The self.use_cache + setting must be set to true for this option to + be useful. If set to false, then the cache will + be skipped, even if a result has already been + cached. Defaults to false. + """ + feature = data.get('feature', None) + + data = {'local': data.get('local', False), + 'cached': data.get('cached', True)} + + if not feature or jid.full in IQ_ERRORS: + return False + + if node in (None, ''): + info = self.caps.get_caps(jid) + if info and feature in info['features']: + return True + + try: + info = self.disco.get_info(jid=jid, node=node, + ifrom=ifrom, **data) + info = self.disco._wrap(ifrom, jid, info, True) + return feature in info['disco_info']['features'] + except: + IQ_ERRORS.add(jid.full) + log.debug('%s added to the list of entities that do' + 'not honor disco#info', jid.full) + return False + +def reset_iq_errors(): + "reset the iq error cache" + IQ_ERRORS.clear() -- cgit v1.2.3