Track which verstrings are being checked, so we don't request duplicates.
This commit is contained in:
parent
78bd21b7cf
commit
fbf79755d7
1 changed files with 28 additions and 22 deletions
|
@ -9,8 +9,9 @@
|
||||||
import logging
|
import logging
|
||||||
import hashlib
|
import hashlib
|
||||||
import base64
|
import base64
|
||||||
|
import threading
|
||||||
|
|
||||||
import sleekxmpp
|
from sleekxmpp import __version__
|
||||||
from sleekxmpp.stanza import StreamFeatures, Presence, Iq
|
from sleekxmpp.stanza import StreamFeatures, Presence, Iq
|
||||||
from sleekxmpp.xmlstream import register_stanza_plugin, JID
|
from sleekxmpp.xmlstream import register_stanza_plugin, JID
|
||||||
from sleekxmpp.xmlstream.handler import Callback
|
from sleekxmpp.xmlstream.handler import Callback
|
||||||
|
@ -45,8 +46,7 @@ class XEP_0115(BasePlugin):
|
||||||
'md5': hashlib.md5}
|
'md5': hashlib.md5}
|
||||||
|
|
||||||
if self.caps_node is None:
|
if self.caps_node is None:
|
||||||
ver = sleekxmpp.__version__
|
self.caps_node = 'http://sleekxmpp.com/ver/%s' % __version__
|
||||||
self.caps_node = 'http://sleekxmpp.com/ver/%s' % ver
|
|
||||||
|
|
||||||
register_stanza_plugin(Presence, stanza.Capabilities)
|
register_stanza_plugin(Presence, stanza.Capabilities)
|
||||||
register_stanza_plugin(StreamFeatures, stanza.Capabilities)
|
register_stanza_plugin(StreamFeatures, stanza.Capabilities)
|
||||||
|
@ -90,6 +90,9 @@ class XEP_0115(BasePlugin):
|
||||||
disco.assign_verstring = self.assign_verstring
|
disco.assign_verstring = self.assign_verstring
|
||||||
disco.get_verstring = self.get_verstring
|
disco.get_verstring = self.get_verstring
|
||||||
|
|
||||||
|
self._processing_lock = threading.Lock()
|
||||||
|
self._processing = set()
|
||||||
|
|
||||||
def plugin_end(self):
|
def plugin_end(self):
|
||||||
self.xmpp['xep_0030'].del_feature(feature=stanza.Capabilities.namespace)
|
self.xmpp['xep_0030'].del_feature(feature=stanza.Capabilities.namespace)
|
||||||
self.xmpp.del_filter('out', self._filter_add_caps)
|
self.xmpp.del_filter('out', self._filter_add_caps)
|
||||||
|
@ -139,13 +142,15 @@ class XEP_0115(BasePlugin):
|
||||||
self.xmpp.event('entity_caps_legacy', pres)
|
self.xmpp.event('entity_caps_legacy', pres)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
ver = pres['caps']['ver']
|
||||||
|
|
||||||
existing_verstring = self.get_verstring(pres['from'].full)
|
existing_verstring = self.get_verstring(pres['from'].full)
|
||||||
if str(existing_verstring) == str(pres['caps']['ver']):
|
if str(existing_verstring) == str(ver):
|
||||||
return
|
return
|
||||||
|
|
||||||
existing_caps = self.get_caps(verstring=pres['caps']['ver'])
|
existing_caps = self.get_caps(verstring=ver)
|
||||||
if existing_caps is not None:
|
if existing_caps is not None:
|
||||||
self.assign_verstring(pres['from'], pres['caps']['ver'])
|
self.assign_verstring(pres['from'], ver)
|
||||||
return
|
return
|
||||||
|
|
||||||
if pres['caps']['hash'] not in self.hashes:
|
if pres['caps']['hash'] not in self.hashes:
|
||||||
|
@ -156,9 +161,16 @@ class XEP_0115(BasePlugin):
|
||||||
except XMPPError:
|
except XMPPError:
|
||||||
return
|
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:
|
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)
|
caps = self.xmpp['xep_0030'].get_info(pres['from'], node)
|
||||||
|
|
||||||
if isinstance(caps, Iq):
|
if isinstance(caps, Iq):
|
||||||
|
@ -168,7 +180,10 @@ class XEP_0115(BasePlugin):
|
||||||
pres['caps']['ver']):
|
pres['caps']['ver']):
|
||||||
self.assign_verstring(pres['from'], pres['caps']['ver'])
|
self.assign_verstring(pres['from'], pres['caps']['ver'])
|
||||||
except XMPPError:
|
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):
|
def _validate_caps(self, caps, hash, check_verstring):
|
||||||
# Check Identities
|
# Check Identities
|
||||||
|
@ -179,7 +194,6 @@ class XEP_0115(BasePlugin):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check Features
|
# Check Features
|
||||||
|
|
||||||
full_features = caps.get_features(dedupe=False)
|
full_features = caps.get_features(dedupe=False)
|
||||||
deduped_features = caps.get_features()
|
deduped_features = caps.get_features()
|
||||||
if len(full_features) != len(deduped_features):
|
if len(full_features) != len(deduped_features):
|
||||||
|
@ -272,7 +286,7 @@ class XEP_0115(BasePlugin):
|
||||||
binary = hash(S.encode('utf8')).digest()
|
binary = hash(S.encode('utf8')).digest()
|
||||||
return base64.b64encode(binary).decode('utf-8')
|
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:
|
try:
|
||||||
info = self.xmpp['xep_0030'].get_info(jid, node, local=True)
|
info = self.xmpp['xep_0030'].get_info(jid, node, local=True)
|
||||||
if isinstance(info, Iq):
|
if isinstance(info, Iq):
|
||||||
|
@ -286,19 +300,11 @@ class XEP_0115(BasePlugin):
|
||||||
self.assign_verstring(jid, ver)
|
self.assign_verstring(jid, ver)
|
||||||
|
|
||||||
if self.xmpp.session_started_event.is_set() and self.broadcast:
|
if self.xmpp.session_started_event.is_set() and self.broadcast:
|
||||||
# Check if we've sent directed presence. If we haven't, we
|
if self.xmpp.is_component or preserve:
|
||||||
# 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:
|
|
||||||
for contact in self.xmpp.roster[jid]:
|
for contact in self.xmpp.roster[jid]:
|
||||||
self.xmpp.roster[jid][contact].send_last_presence()
|
self.xmpp.roster[jid][contact].send_last_presence()
|
||||||
|
else:
|
||||||
|
self.xmpp.roster[jid].send_last_presence()
|
||||||
except XMPPError:
|
except XMPPError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue