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.
This commit is contained in:
Goffi 2022-09-24 16:37:46 +02:00
commit 8444115262

View file

@ -419,7 +419,7 @@ async def download_oldmemo_bundle(
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 @@ async def download_oldmemo_bundle(
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 @@ def make_session_manager(sat: SAT, profile: str) -> Type[omemo.SessionManager]:
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 @@ def make_session_manager(sat: SAT, profile: str) -> Type[omemo.SessionManager]:
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 @@ def make_session_manager(sat: SAT, profile: str) -> Type[omemo.SessionManager]:
)
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 @@ def make_session_manager(sat: SAT, profile: str) -> Type[omemo.SessionManager]:
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 @@ def make_session_manager(sat: SAT, profile: str) -> Type[omemo.SessionManager]:
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 @@ def make_session_manager(sat: SAT, profile: str) -> Type[omemo.SessionManager]:
"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 @@ class OMEMO:
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 @@ class OMEMO:
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 @@ class OMEMO:
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 @@ class OMEMO:
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 @@ class OMEMO:
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