From fc62229dc58aba74607479c730cb3618efd81fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=A4fer?= Date: Sat, 25 Jan 2025 10:16:24 +0100 Subject: [PATCH] tokio_xmpp: fix Client on servers without Stream Management The Client::send_stanza method blocks on the stanza actually being sent over the stream. Without this change, the method will never return on streams without XEP-0198 Stream Management because `sm_state` is then None and thus the StanzaToken's state is never advanced: it would be stuck in Queued state. In addition, a lack of advancement to Sent state may cause a deadlock on XEP-0198-enabled streams if data is received so fast that the frontend_tx mpsc::Sender in the stanzastream::Worker is filled up. In such a case, the Worker cannot obtain a permit and will only service writes. However, that will mean that no StanzaTokens can be advanced beyond Queued state, because for that, reads need to be serviced (to receive the SM acks). If a burst of stanzas is then received while Client::send_stanza is being awaited, send_stanza can only return if something reads from the frontend mpsc in the meantime. We do not want to require user code to drive the Client in full-duplex mode, hence this is a bug. skip-changelog, because this fixes an unreleased feature. --- tokio-xmpp/src/stanzastream/connected.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tokio-xmpp/src/stanzastream/connected.rs b/tokio-xmpp/src/stanzastream/connected.rs index 0438a0e5bf77617f197f9664159fda162c52f5b1..48c384f3cc1c899bae4b5ed784217b6a6ec607da 100644 --- a/tokio-xmpp/src/stanzastream/connected.rs +++ b/tokio-xmpp/src/stanzastream/connected.rs @@ -260,6 +260,7 @@ impl ConnectedState { let next = next.take(); match stream.as_mut().start_send(&next.stanza) { Ok(()) => { + next.token.send_replace(StanzaState::Sent {}); if let Some(sm_state) = sm_state.as_mut() { sm_state.enqueue(next); }