use std::fmt;
use std::net::SocketAddr;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::sync::mpsc;
use super::ServerError;
use super::qos::StationSocketQos;
use crate::types::{SignalingQos, StationTransport};
pub trait StationIo: AsyncRead + AsyncWrite + Unpin + Send {}
impl<T> StationIo for T where T: AsyncRead + AsyncWrite + Unpin + Send {}
pub(super) type BoxedStationIo = Box<dyn StationIo>;
pub(super) struct AcceptedStation {
pub stream: BoxedStationIo,
pub peer: SocketAddr,
pub local: SocketAddr,
pub transport: StationTransport,
pub socket_qos: Option<Box<dyn StationSocketQos>>,
}
impl fmt::Debug for AcceptedStation {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("AcceptedStation")
.field("stream", &"<station I/O>")
.field("peer", &self.peer)
.field("local", &self.local)
.field("transport", &self.transport)
.field(
"socket_qos",
&self.socket_qos.as_ref().map(|_| "<socket QoS control>"),
)
.finish()
}
}
#[derive(Clone, Debug)]
pub struct ServerIngress {
sender: mpsc::Sender<AcceptedStation>,
signaling_qos: SignalingQos,
}
impl ServerIngress {
pub(super) fn channel(
capacity: usize,
signaling_qos: SignalingQos,
) -> (Self, mpsc::Receiver<AcceptedStation>) {
let (sender, receiver) = mpsc::channel(capacity);
(
Self {
sender,
signaling_qos,
},
receiver,
)
}
pub async fn accept<S>(
&self,
stream: S,
peer: SocketAddr,
local: SocketAddr,
transport: StationTransport,
) -> Result<(), ServerError>
where
S: StationIo + 'static,
{
self.admit(Box::new(stream), peer, local, transport, None)
.await
}
pub async fn accept_with_socket_qos<S, Q>(
&self,
stream: S,
peer: SocketAddr,
local: SocketAddr,
transport: StationTransport,
socket_qos: Q,
) -> Result<(), ServerError>
where
S: StationIo + 'static,
Q: StationSocketQos + 'static,
{
super::report_socket_qos(None, peer, socket_qos.apply(self.signaling_qos));
self.admit(
Box::new(stream),
peer,
local,
transport,
Some(Box::new(socket_qos)),
)
.await
}
async fn admit(
&self,
stream: BoxedStationIo,
peer: SocketAddr,
local: SocketAddr,
transport: StationTransport,
socket_qos: Option<Box<dyn StationSocketQos>>,
) -> Result<(), ServerError> {
self.sender
.send(AcceptedStation {
stream,
peer,
local,
transport,
socket_qos,
})
.await
.map_err(|_| ServerError::Stopped)
}
}