pub mod quic;
#[cfg(feature = "webtransport")]
pub mod webtransport;
use bytes::Bytes;
#[derive(Debug, thiserror::Error)]
pub enum TransportError {
#[error("connection error: {0}")]
Connection(String),
#[error("write error: {0}")]
Write(String),
#[error("read error: {0}")]
Read(String),
#[error("stream closed")]
StreamClosed,
#[error("send datagram error: {0}")]
SendDatagram(String),
#[error("connection lost")]
ConnectionLost,
#[error("connect error: {0}")]
Connect(String),
}
pub enum Transport {
Quic(quic::QuicTransport),
#[cfg(feature = "webtransport")]
WebTransport(webtransport::WebTransportTransport),
}
impl Transport {
pub async fn open_bi(&self) -> Result<(SendStream, RecvStream), TransportError> {
match self {
Transport::Quic(t) => t.open_bi().await,
#[cfg(feature = "webtransport")]
Transport::WebTransport(t) => t.open_bi().await,
}
}
pub async fn accept_bi(&self) -> Result<(SendStream, RecvStream), TransportError> {
match self {
Transport::Quic(t) => t.accept_bi().await,
#[cfg(feature = "webtransport")]
Transport::WebTransport(t) => t.accept_bi().await,
}
}
pub async fn open_uni(&self) -> Result<SendStream, TransportError> {
match self {
Transport::Quic(t) => t.open_uni().await,
#[cfg(feature = "webtransport")]
Transport::WebTransport(t) => t.open_uni().await,
}
}
pub async fn accept_uni(&self) -> Result<RecvStream, TransportError> {
match self {
Transport::Quic(t) => t.accept_uni().await,
#[cfg(feature = "webtransport")]
Transport::WebTransport(t) => t.accept_uni().await,
}
}
pub fn send_datagram(&self, data: Bytes) -> Result<(), TransportError> {
match self {
Transport::Quic(t) => t.send_datagram(data),
#[cfg(feature = "webtransport")]
Transport::WebTransport(t) => t.send_datagram(data),
}
}
pub async fn recv_datagram(&self) -> Result<Bytes, TransportError> {
match self {
Transport::Quic(t) => t.recv_datagram().await,
#[cfg(feature = "webtransport")]
Transport::WebTransport(t) => t.recv_datagram().await,
}
}
pub fn close(&self, code: u32, reason: &[u8]) {
match self {
Transport::Quic(t) => t.close(code, reason),
#[cfg(feature = "webtransport")]
Transport::WebTransport(t) => t.close(code, reason),
}
}
}
pub enum SendStream {
Quic(quinn::SendStream),
#[cfg(feature = "webtransport")]
WebTransport(webtransport::WtSendStream),
}
impl SendStream {
pub fn stream_id(&self) -> u64 {
match self {
SendStream::Quic(s) => s.id().index(),
#[cfg(feature = "webtransport")]
SendStream::WebTransport(_) => 0, }
}
pub async fn write_all(&mut self, buf: &[u8]) -> Result<(), TransportError> {
match self {
SendStream::Quic(s) => {
s.write_all(buf).await.map_err(|e| TransportError::Write(e.to_string()))
}
#[cfg(feature = "webtransport")]
SendStream::WebTransport(s) => s.write_all(buf).await,
}
}
pub fn finish(&mut self) -> Result<(), TransportError> {
match self {
SendStream::Quic(s) => {
s.finish().map_err(|_| TransportError::StreamClosed)?;
Ok(())
}
#[cfg(feature = "webtransport")]
SendStream::WebTransport(s) => s.finish(),
}
}
}
pub enum RecvStream {
Quic(quinn::RecvStream),
#[cfg(feature = "webtransport")]
WebTransport(webtransport::WtRecvStream),
}
impl RecvStream {
pub fn stream_id(&self) -> u64 {
match self {
RecvStream::Quic(s) => s.id().index(),
#[cfg(feature = "webtransport")]
RecvStream::WebTransport(_) => 0,
}
}
pub async fn read(&mut self, buf: &mut [u8]) -> Result<Option<usize>, TransportError> {
match self {
RecvStream::Quic(s) => {
s.read(buf).await.map_err(|e| TransportError::Read(e.to_string()))
}
#[cfg(feature = "webtransport")]
RecvStream::WebTransport(s) => s.read(buf).await,
}
}
}