From fbf79755d72e35b365729d6f7e7d85fdadfb1403 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Mon, 11 Feb 2013 19:49:38 -0800 Subject: Track which verstrings are being checked, so we don't request duplicates. --- sleekxmpp/plugins/xep_0115/caps.py | 50 +++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'sleekxmpp/plugins/xep_0115') diff --git a/sleekxmpp/plugins/xep_0115/caps.py b/sleekxmpp/plugins/xep_0115/caps.py index 8bad1410..1d8d9e42 100644 --- a/sleekxmpp/plugins/xep_0115/caps.py +++ b/sleekxmpp/plugins/xep_0115/caps.py @@ -9,8 +9,9 @@ import logging import hashlib import base64 +import threading -import sleekxmpp +from sleekxmpp import __version__ from sleekxmpp.stanza import StreamFeatures, Presence, Iq from sleekxmpp.xmlstream import register_stanza_plugin, JID from sleekxmpp.xmlstream.handler import Callback @@ -45,8 +46,7 @@ class XEP_0115(BasePlugin): 'md5': hashlib.md5} if self.caps_node is None: - ver = sleekxmpp.__version__ - self.caps_node = 'http://sleekxmpp.com/ver/%s' % ver + self.caps_node = 'http://sleekxmpp.com/ver/%s' % __version__ register_stanza_plugin(Presence, stanza.Capabilities) register_stanza_plugin(StreamFeatures, stanza.Capabilities) @@ -90,6 +90,9 @@ class XEP_0115(BasePlugin): disco.assign_verstring = self.assign_verstring disco.get_verstring = self.get_verstring + self._processing_lock = threading.Lock() + self._processing = set() + def plugin_end(self): self.xmpp['xep_0030'].del_feature(feature=stanza.Capabilities.namespace) self.xmpp.del_filter('out', self._filter_add_caps) @@ -139,13 +142,15 @@ class XEP_0115(BasePlugin): self.xmpp.event('entity_caps_legacy', pres) return + ver = pres['caps']['ver'] + existing_verstring = self.get_verstring(pres['from'].full) - if str(existing_verstring) == str(pres['caps']['ver']): + if str(existing_verstring) == str(ver): return - existing_caps = self.get_caps(verstring=pres['caps']['ver']) + existing_caps = self.get_caps(verstring=ver) if existing_caps is not None: - self.assign_verstring(pres['from'], pres['caps']['ver']) + self.assign_verstring(pres['from'], ver) return if pres['caps']['hash'] not in self.hashes: @@ -156,9 +161,16 @@ class XEP_0115(BasePlugin): except XMPPError: return - log.debug("New caps verification string: %s", pres['caps']['ver']) + # Only lookup the same caps once at a time. + with self._processing_lock: + if ver in self._processing: + log.debug('Already processing verstring %s' % ver) + return + self._processing.add(ver) + + log.debug("New caps verification string: %s", ver) try: - node = '%s#%s' % (pres['caps']['node'], pres['caps']['ver']) + node = '%s#%s' % (pres['caps']['node'], ver) caps = self.xmpp['xep_0030'].get_info(pres['from'], node) if isinstance(caps, Iq): @@ -168,7 +180,10 @@ class XEP_0115(BasePlugin): pres['caps']['ver']): self.assign_verstring(pres['from'], pres['caps']['ver']) except XMPPError: - log.debug("Could not retrieve disco#info results for caps") + log.debug("Could not retrieve disco#info results for caps for %s", node) + + with self._processing_lock: + self._processing.remove(ver) def _validate_caps(self, caps, hash, check_verstring): # Check Identities @@ -179,7 +194,6 @@ class XEP_0115(BasePlugin): return False # Check Features - full_features = caps.get_features(dedupe=False) deduped_features = caps.get_features() if len(full_features) != len(deduped_features): @@ -272,7 +286,7 @@ class XEP_0115(BasePlugin): binary = hash(S.encode('utf8')).digest() return base64.b64encode(binary).decode('utf-8') - def update_caps(self, jid=None, node=None): + def update_caps(self, jid=None, node=None, preserve=False): try: info = self.xmpp['xep_0030'].get_info(jid, node, local=True) if isinstance(info, Iq): @@ -286,19 +300,11 @@ class XEP_0115(BasePlugin): self.assign_verstring(jid, ver) if self.xmpp.session_started_event.is_set() and self.broadcast: - # Check if we've sent directed presence. If we haven't, we - # can just send a normal presence stanza. If we have, then - # we will send presence to each contact individually so - # that we don't clobber existing statuses. - directed = False or self.xmpp.is_component - for contact in self.xmpp.roster[jid]: - if self.xmpp.roster[jid][contact].last_status is not None: - directed = True - if not directed: - self.xmpp.roster[jid].send_last_presence() - else: + if self.xmpp.is_component or preserve: for contact in self.xmpp.roster[jid]: self.xmpp.roster[jid][contact].send_last_presence() + else: + self.xmpp.roster[jid].send_last_presence() except XMPPError: return -- cgit v1.2.3 From cdeae7e72fb1d624fc45ffafcef08e30ac606720 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Mon, 11 Feb 2013 19:53:57 -0800 Subject: Make legacy caps log more useful, until we support legacy caps. --- sleekxmpp/plugins/xep_0115/caps.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sleekxmpp/plugins/xep_0115') diff --git a/sleekxmpp/plugins/xep_0115/caps.py b/sleekxmpp/plugins/xep_0115/caps.py index 1d8d9e42..fac1cc7c 100644 --- a/sleekxmpp/plugins/xep_0115/caps.py +++ b/sleekxmpp/plugins/xep_0115/caps.py @@ -138,7 +138,10 @@ class XEP_0115(BasePlugin): def _process_caps(self, pres): if not pres['caps']['hash']: - log.debug("Received unsupported legacy caps.") + log.debug("Received unsupported legacy caps: %s, %s, %s", + pres['caps']['node'], + pres['caps']['ver'], + pres['caps']['ext']) self.xmpp.event('entity_caps_legacy', pres) return -- cgit v1.2.3 From 99ecb166d377ea316c95830a74efc73f5c2b9182 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Mon, 11 Feb 2013 20:01:53 -0800 Subject: More caps cleanup --- sleekxmpp/plugins/xep_0115/caps.py | 43 ++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 20 deletions(-) (limited to 'sleekxmpp/plugins/xep_0115') diff --git a/sleekxmpp/plugins/xep_0115/caps.py b/sleekxmpp/plugins/xep_0115/caps.py index fac1cc7c..41b5c52e 100644 --- a/sleekxmpp/plugins/xep_0115/caps.py +++ b/sleekxmpp/plugins/xep_0115/caps.py @@ -207,29 +207,32 @@ class XEP_0115(BasePlugin): form_types = [] deduped_form_types = set() for stanza in caps['substanzas']: - if isinstance(stanza, self.xmpp['xep_0004'].stanza.Form): - if 'FORM_TYPE' in stanza['fields']: - f_type = tuple(stanza['fields']['FORM_TYPE']['value']) - form_types.append(f_type) - deduped_form_types.add(f_type) - if len(form_types) != len(deduped_form_types): - log.debug("Duplicated FORM_TYPE values, " + \ - "invalid for caps") + if not isinstance(stanza, self.xmpp['xep_0004'].stanza.Form): + log.debug("Non form extension found, ignoring for caps") + caps.xml.remove(stanza.xml) + continue + if 'FORM_TYPE' in stanza['fields']: + f_type = tuple(stanza['fields']['FORM_TYPE']['value']) + form_types.append(f_type) + deduped_form_types.add(f_type) + if len(form_types) != len(deduped_form_types): + log.debug("Duplicated FORM_TYPE values, " + \ + "invalid for caps") + return False + + if len(f_type) > 1: + deduped_type = set(f_type) + if len(f_type) != len(deduped_type): + log.debug("Extra FORM_TYPE data, invalid for caps") return False - if len(f_type) > 1: - deduped_type = set(f_type) - if len(f_type) != len(deduped_type): - log.debug("Extra FORM_TYPE data, invalid for caps") - return False - - if stanza['fields']['FORM_TYPE']['type'] != 'hidden': - log.debug("Field FORM_TYPE type not 'hidden', " + \ - "ignoring form for caps") - caps.xml.remove(stanza.xml) - else: - log.debug("No FORM_TYPE found, ignoring form for caps") + if stanza['fields']['FORM_TYPE']['type'] != 'hidden': + log.debug("Field FORM_TYPE type not 'hidden', " + \ + "ignoring form for caps") caps.xml.remove(stanza.xml) + else: + log.debug("No FORM_TYPE found, ignoring form for caps") + caps.xml.remove(stanza.xml) verstring = self.generate_verstring(caps, hash) if verstring != check_verstring: -- cgit v1.2.3