plugin XEP-0115: Implement "Stream Feature":

Server features are now checked to find capabilities data and use it for disco caching.
This is §6.3 of the XEP.
This commit is contained in:
Goffi 2026-05-03 11:20:33 +02:00
commit b4f41fe4a5

View file

@ -415,8 +415,47 @@ class XEP_0115_handler(XMPPHandler):
def client(self) -> SatXMPPEntity:
return self.parent # type: ignore[return-value]
def _caps_node_cb(self, disco_infos, ver):
"""Callback for caps node query."""
G.host.memory.disco.hashes[ver] = disco_infos
log.debug(f"Cached disco info for caps hash {ver}")
def _caps_node_eb(self, failure_, server_jid, ver):
"""Errback for caps node query."""
log.warning(
f"Failed to query caps node for {server_jid} (ver={ver}): {failure_}"
)
def connectionInitialized(self) -> None:
assert self.xmlstream is not None
# Check if server advertised caps in stream features (XEP-0115 §6.3)
# xmlstream.features is a dict mapping (ns, name) to element
caps_key = (NS_ENTITY_CAPABILITY, "c")
if caps_key in self.xmlstream.features:
c_elt = self.xmlstream.features[caps_key]
ver = c_elt.getAttribute("ver")
node = c_elt.getAttribute("node")
if ver:
server_jid = self.client.server_jid
G.host.memory.update_entity_data(
self.client, server_jid, C.ENTITY_CAP_HASH, ver
)
# If we already have the disco info, we're done
if ver in G.host.memory.disco.hashes:
log.debug(
f"Cached server caps from stream feature: {server_jid} ver={ver}"
)
else:
# Query the caps node to get disco info (XEP-0115 §6.2)
caps_node = f"{node}#{ver}" if node else ver
log.debug(
f"Querying caps node {caps_node} for server {server_jid}"
)
d = self.client.disco.requestInfo(server_jid, nodeIdentifier=caps_node)
d.addCallback(self._caps_node_cb, ver)
d.addErrback(self._caps_node_eb, server_jid, ver)
self.xmlstream.addObserver(
CAPABILITY_UPDATE, self.plugin_parent._update, client=self.client
)