diff sat/plugins/plugin_xep_0384.py @ 3914:4cb38c8312a1

plugin XEP-0384, xml_tools: avoid `getItems` timeout + fix empty node crash + parsing: - use `max_items` in `getItems` calls for bundles, as otherwise some pubsub service may return full nodes, which may be huge is `max_items=1` is not set on the node, possibly resulting in timeouts. - the plugin was crashing when TWOMEMO devices list node has no items at all. This is not the case anymore. - a naive parsing method has been implemented in `xml_tools` to replace the serialisation/deserialisation method. This should be more efficient and will avoid annoying `ns0:` prefixes in XML logs.
author Goffi <goffi@goffi.org>
date Sat, 24 Sep 2022 16:37:46 +0200
parents 8289ac1b34f4
children e63f96e60f7b
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0384.py	Sat Sep 24 16:31:39 2022 +0200
+++ b/sat/plugins/plugin_xep_0384.py	Sat Sep 24 16:37:46 2022 +0200
@@ -419,7 +419,7 @@
     node = f"eu.siacs.conversations.axolotl.bundles:{device_id}"
 
     try:
-        items, __ = await xep_0060.getItems(client, jid.JID(bare_jid), node)
+        items, __ = await xep_0060.getItems(client, jid.JID(bare_jid), node, max_items=1)
     except Exception as e:
         raise omemo.BundleDownloadFailed(
             f"Bundle download failed for {bare_jid}: {device_id} under namespace"
@@ -432,7 +432,7 @@
             f" {namespace}: Unexpected number of items retrieved: {len(items)}."
         )
 
-    element = next(iter(domish_to_etree(cast(domish.Element, items[0]))), None)
+    element = next(iter(xml_tools.domish_elt_2_et_elt(cast(domish.Element, items[0]))), None)
     if element is None:
         raise omemo.BundleDownloadFailed(
             f"Bundle download failed for {bare_jid}: {device_id} under namespace"
@@ -476,7 +476,7 @@
                         client,
                         client.jid.userhostJID(),
                         node,
-                        etree_to_domish(element),
+                        xml_tools.et_elt_2_domish_elt(element),
                         item_id=str(bundle.device_id),
                         extra={
                             xep_0060.EXTRA_PUBLISH_OPTIONS: {
@@ -516,7 +516,7 @@
                         client,
                         client.jid.userhostJID(),
                         node,
-                        etree_to_domish(element),
+                        xml_tools.et_elt_2_domish_elt(element),
                         item_id=xep_0060.ID_SINGLETON,
                         extra={
                             xep_0060.EXTRA_PUBLISH_OPTIONS: { xep_0060.OPT_MAX_ITEMS: 1 },
@@ -563,7 +563,7 @@
                     )
 
                 element = next(
-                    iter(domish_to_etree(cast(domish.Element, items[0]))),
+                    iter(xml_tools.domish_elt_2_et_elt(cast(domish.Element, items[0]))),
                     None
                 )
                 if element is None:
@@ -650,7 +650,7 @@
                     client,
                     client.jid.userhostJID(),
                     node,
-                    etree_to_domish(element),
+                    xml_tools.et_elt_2_domish_elt(element),
                     item_id=xep_0060.ID_SINGLETON,
                     extra={
                         xep_0060.EXTRA_PUBLISH_OPTIONS: {
@@ -705,13 +705,15 @@
                     f" {namespace}"
                 ) from e
 
-            if len(items) != 1:
+            if len(items) == 0:
+                return {}
+            elif len(items) != 1:
                 raise omemo.DeviceListDownloadFailed(
                     f"Device list download failed for {bare_jid} under namespace"
                     f" {namespace}: Unexpected number of items retrieved: {len(items)}."
                 )
 
-            element = next(iter(domish_to_etree(cast(domish.Element, items[0]))), None)
+            element = next(iter(xml_tools.domish_elt_2_et_elt(cast(domish.Element, items[0]))), None)
             if element is None:
                 raise omemo.DeviceListDownloadFailed(
                     f"Device list download failed for {bare_jid} under namespace"
@@ -866,10 +868,10 @@
                 "timestamp": time.time()
             }))
 
-            message_data["xml"].addChild(etree_to_domish(element))
+            message_data["xml"].addChild(xml_tools.et_elt_2_domish_elt(element))
 
             try:
-                await client.send(message_data["xml"])
+                await client.a_send(message_data["xml"])
             except Exception as e:
                 raise omemo.MessageSendingFailed() from e
 
@@ -1493,7 +1495,6 @@
             encrypted.
         @return: Whether to continue the message received flow.
         """
-
         muc_plaintext_cache_key: Optional[MUCPlaintextCacheKey] = None
 
         sender_jid = jid.JID(message_elt["from"])
@@ -1583,7 +1584,7 @@
         if twomemo_encrypted_elt is not None:
             try:
                 message = twomemo.etree.parse_message(
-                    domish_to_etree(twomemo_encrypted_elt),
+                    xml_tools.domish_elt_2_et_elt(twomemo_encrypted_elt),
                     sender_bare_jid
                 )
             except (ValueError, XMLSchemaValidationError):
@@ -1597,7 +1598,7 @@
         if oldmemo_encrypted_elt is not None:
             try:
                 message = await oldmemo.etree.parse_message(
-                    domish_to_etree(oldmemo_encrypted_elt),
+                    xml_tools.domish_elt_2_et_elt(oldmemo_encrypted_elt),
                     sender_bare_jid,
                     client.jid.userhost(),
                     session_manager
@@ -1999,11 +2000,11 @@
 
         if namespace == twomemo.twomemo.NAMESPACE:
             # Add the encrypted element
-            stanza.addChild(etree_to_domish(twomemo.etree.serialize_message(message)))
+            stanza.addChild(xml_tools.et_elt_2_domish_elt(twomemo.etree.serialize_message(message)))
 
         if namespace == oldmemo.oldmemo.NAMESPACE:
             # Add the encrypted element
-            stanza.addChild(etree_to_domish(oldmemo.etree.serialize_message(message)))
+            stanza.addChild(xml_tools.et_elt_2_domish_elt(oldmemo.etree.serialize_message(message)))
 
         if muc_plaintext_cache_key is not None:
             self.__muc_plaintext_cache[muc_plaintext_cache_key] = plaintext
@@ -2031,7 +2032,7 @@
             log.debug("Ignoring empty device list update.")
             return
 
-        item_elt = domish_to_etree(item)
+        item_elt = xml_tools.domish_elt_2_et_elt(item)
 
         device_list: Dict[int, Optional[str]] = {}
         namespace: Optional[str] = None