use core::net::SocketAddr;
use std::io;
use quinn::{Endpoint, Incoming, ServerConfig};
use super::Stream;
pub type QuicConnecting = Incoming;
pub type QuicConfig = ServerConfig;
#[derive(Debug)]
pub struct QuicListener {
endpoint: Endpoint,
}
impl QuicListener {
pub fn new(endpoint: Endpoint) -> Self {
Self { endpoint }
}
pub fn endpoint(&self) -> &Endpoint {
&self.endpoint
}
}
impl QuicListener {
pub async fn accept(&self) -> io::Result<QuicStream> {
let connecting = self
.endpoint
.accept()
.await
.ok_or_else(|| io::Error::new(io::ErrorKind::BrokenPipe, "quinn endpoint is closed"))?;
Ok(QuicStream { connecting })
}
}
pub struct QuicListenerBuilder {
addr: SocketAddr,
config: ServerConfig,
backlog: u32,
}
impl QuicListenerBuilder {
pub const fn new(addr: SocketAddr, config: ServerConfig) -> Self {
Self {
addr,
config,
backlog: 2048,
}
}
pub fn backlog(mut self, backlog: u32) -> Self {
self.backlog = backlog;
self
}
pub fn build(self) -> io::Result<QuicListener> {
let Self { config, addr, .. } = self;
Endpoint::server(config, addr).map(|endpoint| QuicListener { endpoint })
}
}
pub struct QuicStream {
connecting: QuicConnecting,
}
impl QuicStream {
pub fn connecting(self) -> QuicConnecting {
self.connecting
}
pub fn peer_addr(&self) -> SocketAddr {
self.connecting.remote_address()
}
}
impl TryFrom<Stream> for QuicStream {
type Error = io::Error;
fn try_from(stream: Stream) -> Result<Self, Self::Error> {
<(QuicStream, SocketAddr)>::try_from(stream).map(|(udp, _)| udp)
}
}
impl TryFrom<Stream> for (QuicStream, SocketAddr) {
type Error = io::Error;
fn try_from(stream: Stream) -> Result<Self, Self::Error> {
match stream {
Stream::Udp(udp, addr) => Ok((udp, addr)),
_ => unreachable!("Can not be casted to UdpStream"),
}
}
}