use std::net::SocketAddr;
use async_trait::async_trait;
use tokio::sync::mpsc;
use crate::error::{Result, RiftError};
use crate::frame::Frame;
use crate::protocol::close::CloseCode;
use crate::transport::TransportConnection;
use crate::transport::frame_codec::{decode_binary_frame, decode_text_frame, encode_frame};
pub struct BridgeConnection {
inbox: tokio::sync::Mutex<mpsc::Receiver<Vec<u8>>>,
outbox: mpsc::Sender<Vec<u8>>,
peer: Option<SocketAddr>,
}
pub fn spawn_bridge(
peer: Option<SocketAddr>,
capacity: usize,
spawn_reader: impl FnOnce(mpsc::Sender<Vec<u8>>) + Send + 'static,
spawn_writer: impl FnOnce(mpsc::Receiver<Vec<u8>>) + Send + 'static,
) -> Box<dyn TransportConnection> {
let (inbox_tx, inbox_rx) = mpsc::channel::<Vec<u8>>(capacity);
let (outbox_tx, outbox_rx) = mpsc::channel::<Vec<u8>>(capacity);
spawn_reader(inbox_tx);
spawn_writer(outbox_rx);
Box::new(BridgeConnection {
inbox: tokio::sync::Mutex::new(inbox_rx),
outbox: outbox_tx,
peer,
})
}
pub fn spawn_bridge_local(
peer: Option<SocketAddr>,
capacity: usize,
spawn_reader: impl FnOnce(mpsc::Sender<Vec<u8>>) + 'static,
spawn_writer: impl FnOnce(mpsc::Receiver<Vec<u8>>) + 'static,
) -> Box<dyn TransportConnection> {
let (inbox_tx, inbox_rx) = mpsc::channel::<Vec<u8>>(capacity);
let (outbox_tx, outbox_rx) = mpsc::channel::<Vec<u8>>(capacity);
spawn_reader(inbox_tx);
spawn_writer(outbox_rx);
Box::new(BridgeConnection {
inbox: tokio::sync::Mutex::new(inbox_rx),
outbox: outbox_tx,
peer,
})
}
#[async_trait]
impl TransportConnection for BridgeConnection {
async fn read_frame(&mut self) -> Result<Frame> {
let raw = self.inbox.lock().await.recv().await.ok_or_else(|| {
RiftError::other(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"bridge channel closed",
))
})?;
match raw.first() {
Some(b'B') => decode_binary_frame(&raw[1..]),
Some(b'T') => decode_text_frame(&raw[1..]),
Some(b'C') => Err(RiftError::Session(crate::error::SessionReject::Expired)),
_ => Err(RiftError::other(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"invalid bridge frame tag",
))),
}
}
async fn write_frame(&mut self, frame: &Frame) -> Result<()> {
let payload = encode_frame(frame)?;
let mut buf = Vec::with_capacity(1 + payload.len());
buf.push(b'B');
buf.extend_from_slice(&payload);
self.outbox.send(buf).await.map_err(|_| {
RiftError::other(std::io::Error::new(
std::io::ErrorKind::BrokenPipe,
"bridge write channel closed",
))
})
}
async fn close(&mut self, _code: CloseCode, _reason: &str) -> Result<()> {
let _ = self.outbox.send(vec![b'C']).await;
Ok(())
}
fn peer_addr(&self) -> Option<SocketAddr> {
self.peer
}
}