2024-12-22 18:58:28 +00:00
|
|
|
use std::future::ready;
|
2024-12-06 06:31:20 +00:00
|
|
|
use std::pin::pin;
|
|
|
|
use std::pin::Pin;
|
|
|
|
use std::sync::Arc;
|
2024-12-22 18:58:28 +00:00
|
|
|
use std::task::Poll;
|
2024-12-06 06:31:20 +00:00
|
|
|
|
2024-12-22 18:58:28 +00:00
|
|
|
use futures::ready;
|
|
|
|
use futures::FutureExt;
|
2024-12-06 06:31:20 +00:00
|
|
|
use futures::{sink, stream, Sink, Stream};
|
|
|
|
use peanuts::{Reader, Writer};
|
|
|
|
use pin_project::pin_project;
|
|
|
|
use stanza::client::Stanza;
|
|
|
|
use tokio::io::{AsyncRead, AsyncWrite, ReadHalf, WriteHalf};
|
|
|
|
use tokio::sync::Mutex;
|
2024-12-22 18:58:28 +00:00
|
|
|
use tokio::task::JoinHandle;
|
2024-12-06 06:31:20 +00:00
|
|
|
|
|
|
|
use crate::Error;
|
|
|
|
|
|
|
|
use super::JabberStream;
|
|
|
|
|
|
|
|
#[pin_project]
|
2024-12-22 18:58:28 +00:00
|
|
|
pub struct BoundJabberStream<S>
|
2024-12-06 06:31:20 +00:00
|
|
|
where
|
|
|
|
S: AsyncWrite + AsyncRead + Unpin + Send,
|
|
|
|
{
|
2024-12-22 18:58:28 +00:00
|
|
|
reader: Arc<Mutex<Reader<ReadHalf<S>>>>,
|
|
|
|
writer: Arc<Mutex<Writer<WriteHalf<S>>>>,
|
|
|
|
write_handle: Option<JoinHandle<Result<(), Error>>>,
|
|
|
|
read_handle: Option<JoinHandle<Result<Stanza, Error>>>,
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
|
|
|
|
2024-12-22 18:58:28 +00:00
|
|
|
impl<S> BoundJabberStream<S>
|
2024-12-06 06:31:20 +00:00
|
|
|
where
|
|
|
|
S: AsyncWrite + AsyncRead + Unpin + Send,
|
|
|
|
{
|
|
|
|
// TODO: look into biased mutex, to close stream ASAP
|
2024-12-22 18:58:28 +00:00
|
|
|
// TODO: put into connection
|
|
|
|
// pub async fn close_stream(self) -> Result<JabberStream<S>, Error> {
|
|
|
|
// let reader = self.reader.lock().await.into_self();
|
|
|
|
// let writer = self.writer.lock().await.into_self();
|
|
|
|
// // TODO: writer </stream:stream>
|
|
|
|
// return Ok(JabberStream { reader, writer });
|
|
|
|
// }
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait JabberStreamTrait: AsyncWrite + AsyncRead + Unpin + Send {}
|
|
|
|
|
2024-12-22 18:58:28 +00:00
|
|
|
impl<S> Sink<Stanza> for BoundJabberStream<S>
|
2024-12-06 06:31:20 +00:00
|
|
|
where
|
2024-12-22 18:58:28 +00:00
|
|
|
S: AsyncWrite + AsyncRead + Unpin + Send + 'static,
|
2024-12-06 06:31:20 +00:00
|
|
|
{
|
2024-12-22 18:58:28 +00:00
|
|
|
type Error = Error;
|
2024-12-06 06:31:20 +00:00
|
|
|
|
|
|
|
fn poll_ready(
|
|
|
|
self: std::pin::Pin<&mut Self>,
|
|
|
|
cx: &mut std::task::Context<'_>,
|
|
|
|
) -> std::task::Poll<Result<(), Self::Error>> {
|
2024-12-22 18:58:28 +00:00
|
|
|
self.poll_flush(cx)
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn start_send(self: std::pin::Pin<&mut Self>, item: Stanza) -> Result<(), Self::Error> {
|
|
|
|
let this = self.project();
|
2024-12-22 18:58:28 +00:00
|
|
|
if let Some(_write_handle) = this.write_handle {
|
|
|
|
panic!("start_send called without poll_ready")
|
|
|
|
} else {
|
|
|
|
*this.write_handle = Some(tokio::spawn(write(this.writer.clone(), item)));
|
|
|
|
Ok(())
|
|
|
|
}
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn poll_flush(
|
|
|
|
self: std::pin::Pin<&mut Self>,
|
|
|
|
cx: &mut std::task::Context<'_>,
|
|
|
|
) -> std::task::Poll<Result<(), Self::Error>> {
|
|
|
|
let this = self.project();
|
2024-12-22 18:58:28 +00:00
|
|
|
Poll::Ready(if let Some(join_handle) = this.write_handle.as_mut() {
|
|
|
|
match ready!(join_handle.poll_unpin(cx)) {
|
|
|
|
Ok(state) => {
|
|
|
|
*this.write_handle = None;
|
|
|
|
state
|
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
*this.write_handle = None;
|
|
|
|
Err(err.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
})
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn poll_close(
|
|
|
|
self: std::pin::Pin<&mut Self>,
|
|
|
|
cx: &mut std::task::Context<'_>,
|
|
|
|
) -> std::task::Poll<Result<(), Self::Error>> {
|
2024-12-22 18:58:28 +00:00
|
|
|
self.poll_flush(cx)
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-22 18:58:28 +00:00
|
|
|
impl<S> Stream for BoundJabberStream<S>
|
2024-12-06 06:31:20 +00:00
|
|
|
where
|
2024-12-22 18:58:28 +00:00
|
|
|
S: AsyncWrite + AsyncRead + Unpin + Send + 'static,
|
2024-12-06 06:31:20 +00:00
|
|
|
{
|
2024-12-22 18:58:28 +00:00
|
|
|
type Item = Result<Stanza, Error>;
|
2024-12-06 06:31:20 +00:00
|
|
|
|
|
|
|
fn poll_next(
|
|
|
|
self: Pin<&mut Self>,
|
|
|
|
cx: &mut std::task::Context<'_>,
|
|
|
|
) -> std::task::Poll<Option<Self::Item>> {
|
|
|
|
let this = self.project();
|
2024-12-22 18:58:28 +00:00
|
|
|
|
|
|
|
loop {
|
|
|
|
if let Some(join_handle) = this.read_handle.as_mut() {
|
|
|
|
let stanza = ready!(join_handle.poll_unpin(cx));
|
|
|
|
if let Ok(item) = stanza {
|
|
|
|
*this.read_handle = None;
|
|
|
|
return Poll::Ready(Some(item));
|
|
|
|
} else if let Err(err) = stanza {
|
|
|
|
return Poll::Ready(Some(Err(err.into())));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*this.read_handle = Some(tokio::spawn(read(this.reader.clone())))
|
|
|
|
}
|
|
|
|
}
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S> JabberStream<S>
|
|
|
|
where
|
|
|
|
S: AsyncWrite + AsyncRead + Unpin + Send,
|
|
|
|
{
|
2024-12-22 18:58:28 +00:00
|
|
|
pub fn to_bound_jabber(self) -> BoundJabberStream<S> {
|
|
|
|
let reader = Arc::new(Mutex::new(self.reader));
|
|
|
|
let writer = Arc::new(Mutex::new(self.writer));
|
2024-12-06 06:31:20 +00:00
|
|
|
BoundJabberStream {
|
|
|
|
writer,
|
|
|
|
reader,
|
2024-12-22 18:58:28 +00:00
|
|
|
write_handle: None,
|
|
|
|
read_handle: None,
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn write<W: AsyncWrite + Unpin + Send>(
|
2024-12-22 18:58:28 +00:00
|
|
|
writer: Arc<Mutex<Writer<WriteHalf<W>>>>,
|
2024-12-06 06:31:20 +00:00
|
|
|
stanza: Stanza,
|
2024-12-22 18:58:28 +00:00
|
|
|
) -> Result<(), Error> {
|
2024-12-06 06:31:20 +00:00
|
|
|
{
|
2024-12-22 18:58:28 +00:00
|
|
|
let mut writer = writer.lock().await;
|
|
|
|
writer.write(&stanza).await?;
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
2024-12-22 18:58:28 +00:00
|
|
|
Ok(())
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn read<R: AsyncRead + Unpin + Send>(
|
2024-12-22 18:58:28 +00:00
|
|
|
reader: Arc<Mutex<Reader<ReadHalf<R>>>>,
|
|
|
|
) -> Result<Stanza, Error> {
|
2024-12-06 06:31:20 +00:00
|
|
|
let stanza: Result<Stanza, Error>;
|
|
|
|
{
|
2024-12-22 18:58:28 +00:00
|
|
|
let mut reader = reader.lock().await;
|
|
|
|
stanza = reader.read().await.map_err(|e| e.into());
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|
2024-12-22 18:58:28 +00:00
|
|
|
stanza
|
2024-12-06 06:31:20 +00:00
|
|
|
}
|