use std::sync::{Arc, atomic::Ordering};
use tokio::sync::mpsc;
use crate::router::{Lease, QueuedFrame};
use crate::{Client, ClientResult, Delivery, IntoOutboundMessage, Message, Protocol, RawFrame};
pub struct RawStream<P: Protocol> {
sender: RawStreamSender<P>,
pub(crate) receiver: RawStreamReceiver<P>,
}
pub struct RawStreamSender<P: Protocol> {
client: Client<P>,
lease: Arc<Lease>,
}
pub struct RawStreamReceiver<P: Protocol> {
client: Client<P>,
pub(crate) lease: Arc<Lease>,
receiver: mpsc::Receiver<QueuedFrame>,
done: bool,
}
pub struct Stream<P: Protocol> {
raw: RawStream<P>,
}
pub struct StreamSender<P: Protocol> {
raw: RawStreamSender<P>,
}
pub struct StreamReceiver<P: Protocol> {
raw: RawStreamReceiver<P>,
}
impl<P: Protocol> RawStream<P> {
pub(crate) fn new(
client: Client<P>,
lease: Arc<Lease>,
receiver: mpsc::Receiver<QueuedFrame>,
) -> Self {
Self {
sender: RawStreamSender {
client: client.clone(),
lease: Arc::clone(&lease),
},
receiver: RawStreamReceiver {
client,
lease,
receiver,
done: false,
},
}
}
pub fn id(&self) -> u32 {
self.sender.id()
}
pub async fn send(&self, flags: u8, body: &[u8]) -> ClientResult<()> {
self.sender.send(flags, body).await
}
pub async fn recv(&mut self) -> ClientResult<Option<RawFrame>> {
self.receiver.recv().await
}
pub fn close(&mut self) {
self.receiver.close();
}
pub fn into_parts(self) -> (RawStreamSender<P>, RawStreamReceiver<P>) {
(self.sender, self.receiver)
}
}
impl<P: Protocol> RawStreamSender<P> {
pub fn id(&self) -> u32 {
self.lease.id
}
pub async fn send(&self, flags: u8, body: &[u8]) -> ClientResult<()> {
self.client.send_raw_owned(&self.lease, flags, body).await
}
}
impl<P: Protocol> RawStreamReceiver<P> {
pub fn id(&self) -> u32 {
self.lease.id
}
pub async fn recv(&mut self) -> ClientResult<Option<RawFrame>> {
if self.done {
return Ok(None);
}
match self.receiver.recv().await {
Some(queued) => {
if queued.frame.flags & microsandbox_protocol::message::FLAG_TERMINAL != 0 {
self.done = true;
}
Ok(Some(queued.frame))
}
None => {
self.done = true;
if self.lease.terminal.load(Ordering::Acquire) {
Ok(None)
} else {
Err(self
.client
.inner
.state
.error()
.with_delivery(self.lease.delivery()))
}
}
}
}
pub fn close(&mut self) {
self.client.inner.state.abandon(&self.lease);
self.receiver.close();
while self.receiver.try_recv().is_ok() {}
self.done = true;
}
}
impl<P: Protocol> Stream<P> {
pub(crate) fn from_raw(raw: RawStream<P>) -> Self {
Self { raw }
}
pub fn id(&self) -> u32 {
self.raw.id()
}
pub async fn send<M: IntoOutboundMessage<P>>(&self, message: M) -> ClientResult<()> {
self.raw
.sender
.client
.send_owned(&self.raw.sender.lease, message)
.await
}
pub async fn recv(&mut self) -> ClientResult<Option<Message>> {
self.raw
.recv()
.await?
.map(|frame| {
self.raw
.sender
.client
.inner
.codec
.decode(frame)
.map_err(|error| error.with_delivery(Delivery::Unknown))
})
.transpose()
}
pub fn close(&mut self) {
self.raw.close();
}
pub fn into_parts(self) -> (StreamSender<P>, StreamReceiver<P>) {
let (sender, receiver) = self.raw.into_parts();
(
StreamSender { raw: sender },
StreamReceiver { raw: receiver },
)
}
}
impl<P: Protocol> StreamSender<P> {
pub fn id(&self) -> u32 {
self.raw.id()
}
pub async fn send<M: IntoOutboundMessage<P>>(&self, message: M) -> ClientResult<()> {
self.raw.client.send_owned(&self.raw.lease, message).await
}
}
impl<P: Protocol> StreamReceiver<P> {
pub fn id(&self) -> u32 {
self.raw.id()
}
pub async fn recv(&mut self) -> ClientResult<Option<Message>> {
self.raw
.recv()
.await?
.map(|frame| {
self.raw
.client
.inner
.codec
.decode(frame)
.map_err(|error| error.with_delivery(Delivery::Unknown))
})
.transpose()
}
pub fn close(&mut self) {
self.raw.close();
}
}
impl<P: Protocol> Clone for RawStreamSender<P> {
fn clone(&self) -> Self {
Self {
client: self.client.clone(),
lease: Arc::clone(&self.lease),
}
}
}
impl<P: Protocol> Clone for StreamSender<P> {
fn clone(&self) -> Self {
Self {
raw: self.raw.clone(),
}
}
}
impl<P: Protocol> Drop for RawStreamReceiver<P> {
fn drop(&mut self) {
self.client.inner.state.abandon(&self.lease);
}
}