summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/api/plugins/xep_0115.rst46
-rw-r--r--slixmpp/plugins/xep_0115/caps.py70
-rw-r--r--slixmpp/plugins/xep_0115/static.py12
3 files changed, 99 insertions, 29 deletions
diff --git a/docs/api/plugins/xep_0115.rst b/docs/api/plugins/xep_0115.rst
index 73d0e77b..39ea1333 100644
--- a/docs/api/plugins/xep_0115.rst
+++ b/docs/api/plugins/xep_0115.rst
@@ -8,6 +8,52 @@ XEP-0115: Entity Capabilities
:members:
:exclude-members: session_bind, plugin_init, plugin_end
+Internal API methods
+--------------------
+
+This internal API extends the Disco internal API, and also manages an
+in-memory cache of verstring→disco info, and fulljid→verstring.
+
+.. glossary::
+
+ cache_caps
+ - **jid**: unused
+ - **node**: unused
+ - **ifrom**: unused
+ - **args**: a ``dict`` containing the verstring and
+ :class:`~.DiscoInfo` payload (
+ ``{'verstring': Optional[str], 'info': Optional[DiscoInfo]}``)
+
+ Cache a verification string with its payload.
+
+ get_caps
+ - **jid**: JID to retrieve the verstring for (unused with the default
+ handler)
+ - **node**: unused
+ - **ifrom**: unused
+ - **args**: a ``dict`` containing the verstring
+ ``{'verstring': str}``
+ - **returns**: The :class:`~.DiscoInfo` payload for that verstring.
+
+ Get a disco payload from a verstring.
+
+ assign_verstring
+ - **jid**: :class:`~.JID` (full) to assign the verstring to
+ - **node**: unused
+ - **ifrom**: unused
+ - **args**: a ``dict`` containing the verstring
+ ``{'verstring': str}``
+
+ Cache JID→verstring information.
+
+ get_verstring
+ - **jid**: :class:`~.JID` to use for fetching the verstring
+ - **node**: unused
+ - **ifrom**: unused
+ - **args**: unused
+ - **returns**: ``str``, the verstring
+
+ Retrieve a verstring for a JID.
Stanza elements
---------------
diff --git a/slixmpp/plugins/xep_0115/caps.py b/slixmpp/plugins/xep_0115/caps.py
index 5f71165c..75c96410 100644
--- a/slixmpp/plugins/xep_0115/caps.py
+++ b/slixmpp/plugins/xep_0115/caps.py
@@ -7,6 +7,8 @@ import logging
import hashlib
import base64
+from asyncio import Future
+
from slixmpp import __version__
from slixmpp.stanza import StreamFeatures, Presence, Iq
from slixmpp.xmlstream import register_stanza_plugin, JID
@@ -104,14 +106,14 @@ class XEP_0115(BasePlugin):
def session_bind(self, jid):
self.xmpp['xep_0030'].add_feature(stanza.Capabilities.namespace)
- def _filter_add_caps(self, stanza):
+ async def _filter_add_caps(self, stanza):
if not isinstance(stanza, Presence) or not self.broadcast:
return stanza
if stanza['type'] not in ('available', 'chat', 'away', 'dnd', 'xa'):
return stanza
- ver = self.get_verstring(stanza['from'])
+ ver = await self.get_verstring(stanza['from'])
if ver:
stanza['caps']['node'] = self.caps_node
stanza['caps']['hash'] = self.hash
@@ -145,13 +147,13 @@ class XEP_0115(BasePlugin):
ver = pres['caps']['ver']
- existing_verstring = self.get_verstring(pres['from'].full)
+ existing_verstring = await self.get_verstring(pres['from'].full)
if str(existing_verstring) == str(ver):
return
- existing_caps = self.get_caps(verstring=ver)
+ existing_caps = await self.get_caps(verstring=ver)
if existing_caps is not None:
- self.assign_verstring(pres['from'], ver)
+ await self.assign_verstring(pres['from'], ver)
return
ifrom = pres['to'] if self.xmpp.is_component else None
@@ -174,13 +176,13 @@ class XEP_0115(BasePlugin):
if isinstance(caps, Iq):
caps = caps['disco_info']
- if self._validate_caps(caps, pres['caps']['hash'],
- pres['caps']['ver']):
- self.assign_verstring(pres['from'], pres['caps']['ver'])
+ if await self._validate_caps(caps, pres['caps']['hash'],
+ pres['caps']['ver']):
+ await self.assign_verstring(pres['from'], pres['caps']['ver'])
except XMPPError:
log.debug("Could not retrieve disco#info results for caps for %s", node)
- def _validate_caps(self, caps, hash, check_verstring):
+ async def _validate_caps(self, caps, hash, check_verstring):
# Check Identities
full_ids = caps.get_identities(dedupe=False)
deduped_ids = caps.get_identities()
@@ -232,7 +234,7 @@ class XEP_0115(BasePlugin):
verstring, check_verstring))
return False
- self.cache_caps(verstring, caps)
+ await self.cache_caps(verstring, caps)
return True
def generate_verstring(self, info, hash):
@@ -290,12 +292,13 @@ class XEP_0115(BasePlugin):
if isinstance(info, Iq):
info = info['disco_info']
ver = self.generate_verstring(info, self.hash)
- self.xmpp['xep_0030'].set_info(
- jid=jid,
- node='%s#%s' % (self.caps_node, ver),
- info=info)
- self.cache_caps(ver, info)
- self.assign_verstring(jid, ver)
+ await self.xmpp['xep_0030'].set_info(
+ jid=jid,
+ node='%s#%s' % (self.caps_node, ver),
+ info=info
+ )
+ await self.cache_caps(ver, info)
+ await self.assign_verstring(jid, ver)
if self.xmpp.sessionstarted and self.broadcast:
if self.xmpp.is_component or preserve:
@@ -306,32 +309,53 @@ class XEP_0115(BasePlugin):
except XMPPError:
return
- def get_verstring(self, jid=None):
+ def get_verstring(self, jid=None) -> Future:
+ """Get the stored verstring for a JID.
+
+ .. versionchanged:: 1.8.0
+ This function now returns a Future.
+ """
if jid in ('', None):
jid = self.xmpp.boundjid.full
if isinstance(jid, JID):
jid = jid.full
return self.api['get_verstring'](jid)
- def assign_verstring(self, jid=None, verstring=None):
+ def assign_verstring(self, jid=None, verstring=None) -> Future:
+ """Assign a vertification string to a jid.
+
+ .. versionchanged:: 1.8.0
+ This function now returns a Future.
+ """
if jid in (None, ''):
jid = self.xmpp.boundjid.full
if isinstance(jid, JID):
jid = jid.full
return self.api['assign_verstring'](jid, args={
- 'verstring': verstring})
+ 'verstring': verstring
+ })
- def cache_caps(self, verstring=None, info=None):
+ def cache_caps(self, verstring=None, info=None) -> Future:
+ """Add caps to the cache.
+
+ .. versionchanged:: 1.8.0
+ This function now returns a Future.
+ """
data = {'verstring': verstring, 'info': info}
return self.api['cache_caps'](args=data)
- def get_caps(self, jid=None, verstring=None):
+ async def get_caps(self, jid=None, verstring=None):
+ """Get caps for a JID.
+
+ .. versionchanged:: 1.8.0
+ This function is now a coroutine.
+ """
if verstring is None:
if jid is not None:
- verstring = self.get_verstring(jid)
+ verstring = await self.get_verstring(jid)
else:
return None
if isinstance(jid, JID):
jid = jid.full
data = {'verstring': verstring}
- return self.api['get_caps'](jid, args=data)
+ return await self.api['get_caps'](jid, args=data)
diff --git a/slixmpp/plugins/xep_0115/static.py b/slixmpp/plugins/xep_0115/static.py
index 2461d2e3..74f2beb8 100644
--- a/slixmpp/plugins/xep_0115/static.py
+++ b/slixmpp/plugins/xep_0115/static.py
@@ -32,7 +32,7 @@ class StaticCaps(object):
self.static = static
self.jid_vers = {}
- def supports(self, jid, node, ifrom, data):
+ async def supports(self, jid, node, ifrom, data):
"""
Check if a JID supports a given feature.
@@ -65,8 +65,8 @@ class StaticCaps(object):
return True
try:
- info = self.disco.get_info(jid=jid, node=node,
- ifrom=ifrom, **data)
+ info = await 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 IqError:
@@ -74,7 +74,7 @@ class StaticCaps(object):
except IqTimeout:
return None
- def has_identity(self, jid, node, ifrom, data):
+ async def has_identity(self, jid, node, ifrom, data):
"""
Check if a JID has a given identity.
@@ -110,8 +110,8 @@ class StaticCaps(object):
return True
try:
- info = self.disco.get_info(jid=jid, node=node,
- ifrom=ifrom, **data)
+ info = await self.disco.get_info(jid=jid, node=node,
+ ifrom=ifrom, **data)
info = self.disco._wrap(ifrom, jid, info, True)
return identity in map(trunc, info['disco_info']['identities'])
except IqError: