tokio-xmpp: split StanzaStream into Sender and Receiver
This commit is contained in:
parent
58735d6a70
commit
8f03661acb
2 changed files with 60 additions and 2 deletions
|
|
@ -18,6 +18,7 @@ Version NEXT:
|
||||||
always sending h='0' in our `<a/>`.
|
always sending h='0' in our `<a/>`.
|
||||||
* Changed:
|
* Changed:
|
||||||
- Update hickory-dns to 0.26 (!671)
|
- Update hickory-dns to 0.26 (!671)
|
||||||
|
- Drive the XMPP client stream in the background (!631)
|
||||||
|
|
||||||
Version 5.0.0:
|
Version 5.0.0:
|
||||||
2025-10-28 pep <pep@bouah.net>
|
2025-10-28 pep <pep@bouah.net>
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ use core::time::Duration;
|
||||||
// meant for that stream, replacing it is racy.
|
// meant for that stream, replacing it is racy.
|
||||||
|
|
||||||
use futures::{SinkExt, Stream};
|
use futures::{SinkExt, Stream};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
use xmpp_parsers::{jid::Jid, stream_features::StreamFeatures};
|
use xmpp_parsers::{jid::Jid, stream_features::StreamFeatures};
|
||||||
|
|
||||||
use crate::connect::ServerConnector;
|
use crate::connect::ServerConnector;
|
||||||
|
|
@ -258,6 +258,34 @@ impl StanzaStream {
|
||||||
self.assert_send(queue_entry).await;
|
self.assert_send(queue_entry).await;
|
||||||
token
|
token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Split the stream into the [`StanzaSender`] and [`StanzaReceiver`].
|
||||||
|
pub fn split(self) -> (StanzaSender, StanzaReceiver) {
|
||||||
|
let stream = Arc::new(Mutex::new(self));
|
||||||
|
|
||||||
|
let tx = StanzaSender(stream.clone());
|
||||||
|
let rx = StanzaReceiver(stream);
|
||||||
|
|
||||||
|
(tx, rx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reunite the [`StanzaSender`] and [`StanzaReceiver`] back into a single stream.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function panics if the `Sender` and `Receiver` don't come from
|
||||||
|
/// the same [`Stream`].
|
||||||
|
pub fn reunite(tx: StanzaSender, rx: StanzaReceiver) -> Self {
|
||||||
|
assert!(
|
||||||
|
Arc::ptr_eq(&tx.0, &rx.0),
|
||||||
|
"Unrelated Sender and Receiver passed to reunite."
|
||||||
|
);
|
||||||
|
|
||||||
|
drop(tx);
|
||||||
|
|
||||||
|
let inner = Arc::try_unwrap(rx.0).expect("Failed to unwrap Receiver Arc");
|
||||||
|
inner.into_inner()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream for StanzaStream {
|
impl Stream for StanzaStream {
|
||||||
|
|
@ -267,3 +295,32 @@ impl Stream for StanzaStream {
|
||||||
self.rx.poll_recv(cx)
|
self.rx.poll_recv(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send half of the [`StanzaStream`]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StanzaSender(pub(super) Arc<Mutex<StanzaStream>>);
|
||||||
|
|
||||||
|
impl StanzaSender {
|
||||||
|
/// Send a stanza via the stream.
|
||||||
|
///
|
||||||
|
/// See the documentation of [`StanzaStream::send()`].
|
||||||
|
pub async fn send(&self, stanza: Box<Stanza>) -> StanzaToken {
|
||||||
|
self.0.lock().await.send(stanza).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Receive half of the [`StanzaStream`]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StanzaReceiver(pub(super) Arc<Mutex<StanzaStream>>);
|
||||||
|
|
||||||
|
impl Stream for StanzaReceiver {
|
||||||
|
type Item = Event;
|
||||||
|
|
||||||
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||||
|
let Ok(mut stream) = self.0.try_lock() else {
|
||||||
|
return Poll::Pending;
|
||||||
|
};
|
||||||
|
|
||||||
|
stream.rx.poll_recv(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue