pub mod factory;
pub mod iface;
pub mod local;
pub mod packet;
pub mod queue;
pub mod route;
use std::{
future::Future,
io,
task::{Context, Poll},
};
use bytes::BytesMut;
use qbase::net::{
addr::{BindUri, RealAddr},
route::PacketHeader,
};
pub trait QuicIO: Send + Sync {
fn bind_uri(&self) -> BindUri;
fn real_addr(&self) -> io::Result<RealAddr>;
fn max_segment_size(&self) -> io::Result<usize>;
fn max_segments(&self) -> io::Result<usize>;
fn poll_send(
&self,
cx: &mut Context,
pkts: &[io::IoSlice],
hdr: PacketHeader,
) -> Poll<io::Result<usize>>;
fn poll_recv(
&self,
cx: &mut Context,
pkts: &mut [BytesMut],
hdrs: &mut [PacketHeader],
) -> Poll<io::Result<usize>>;
fn poll_close(&self, cx: &mut Context) -> Poll<io::Result<()>>;
}
pub trait QuicIoExt: QuicIO {
#[inline]
fn sendmmsg(
&self,
mut bufs: &[io::IoSlice<'_>],
hdr: PacketHeader,
) -> impl Future<Output = io::Result<()>> + Send {
async move {
while !bufs.is_empty() {
let sent = core::future::poll_fn(|cx| self.poll_send(cx, bufs, hdr)).await?;
bufs = &bufs[sent..];
}
Ok(())
}
}
fn recvmmsg<'b>(
&self,
bufs: &'b mut Vec<BytesMut>,
hdrs: &'b mut Vec<PacketHeader>,
) -> impl Future<Output = io::Result<impl Iterator<Item = (BytesMut, PacketHeader)> + Send + 'b>>
+ Send {
async move {
let rcvd = std::future::poll_fn(|cx| {
let max_segments = self.max_segments()?;
let max_segment_size = self.max_segment_size()?;
bufs.resize_with(max_segments, || BytesMut::zeroed(max_segment_size));
hdrs.resize_with(max_segments, PacketHeader::empty);
self.poll_recv(cx, bufs, hdrs)
})
.await?;
Ok(bufs
.drain(..rcvd)
.zip(hdrs.drain(..rcvd))
.map(|(mut seg, hdr)| (seg.split_to(seg.len().min(hdr.seg_size() as _)), hdr)))
}
}
#[inline]
fn close(&self) -> impl std::future::Future<Output = io::Result<()>> + Send {
async { core::future::poll_fn(|cx| self.poll_close(cx)).await }
}
fn recvmpkt<'b>(
&self,
bufs: &'b mut Vec<BytesMut>,
hdrs: &'b mut Vec<PacketHeader>,
) -> impl Future<
Output = io::Result<impl Iterator<Item = (route::Packet, route::Way)> + Send + 'b>,
> + Send {
async {
use qbase::packet::{self, Packet, PacketReader};
fn is_initial_packet(pkt: &Packet) -> bool {
matches!(pkt, Packet::Data(packet) if matches!(packet.header, packet::DataHeader::Long(packet::long::DataHeader::Initial(..))))
}
let bind_uri = self.bind_uri();
Ok(self
.recvmmsg(bufs, hdrs)
.await?
.flat_map(move |(buf, hdr)| {
let size = buf.len();
let bind_uri = bind_uri.clone();
PacketReader::new(buf, 8)
.flatten()
.filter(move |pkt| !(is_initial_packet(pkt) && size < 1200))
.map(move |pkt| (pkt, (bind_uri.clone(), hdr.pathway(), hdr.link())))
}))
}
}
}
impl<IO: QuicIO + ?Sized> QuicIoExt for IO {}