Skip to main content

moqtap_client/transport/
quic.rs

1//! QUIC transport implementation wrapping quinn.
2
3use bytes::Bytes;
4
5use super::{RecvStream, SendStream, TransportError};
6
7/// QUIC transport wrapping a `quinn::Connection`.
8pub struct QuicTransport {
9    conn: quinn::Connection,
10}
11
12impl QuicTransport {
13    /// Create a new QUIC transport from a quinn connection.
14    pub fn new(conn: quinn::Connection) -> Self {
15        Self { conn }
16    }
17
18    /// Open a bidirectional stream.
19    pub async fn open_bi(&self) -> Result<(SendStream, RecvStream), TransportError> {
20        let (send, recv) = self.conn.open_bi().await.map_err(conn_err)?;
21        Ok((SendStream::Quic(send), RecvStream::Quic(recv)))
22    }
23
24    /// Accept an incoming bidirectional stream.
25    pub async fn accept_bi(&self) -> Result<(SendStream, RecvStream), TransportError> {
26        let (send, recv) = self.conn.accept_bi().await.map_err(conn_err)?;
27        Ok((SendStream::Quic(send), RecvStream::Quic(recv)))
28    }
29
30    /// Open a unidirectional send stream.
31    pub async fn open_uni(&self) -> Result<SendStream, TransportError> {
32        let send = self.conn.open_uni().await.map_err(conn_err)?;
33        Ok(SendStream::Quic(send))
34    }
35
36    /// Accept an incoming unidirectional stream.
37    pub async fn accept_uni(&self) -> Result<RecvStream, TransportError> {
38        let recv = self.conn.accept_uni().await.map_err(conn_err)?;
39        Ok(RecvStream::Quic(recv))
40    }
41
42    /// Send a datagram.
43    pub fn send_datagram(&self, data: Bytes) -> Result<(), TransportError> {
44        self.conn.send_datagram(data).map_err(|e| TransportError::SendDatagram(e.to_string()))
45    }
46
47    /// Receive a datagram.
48    pub async fn recv_datagram(&self) -> Result<Bytes, TransportError> {
49        self.conn.read_datagram().await.map_err(conn_err)
50    }
51
52    /// Close the connection.
53    pub fn close(&self, code: u32, reason: &[u8]) {
54        self.conn.close(quinn::VarInt::from_u32(code), reason);
55    }
56}
57
58/// Convert a quinn connection error to a TransportError.
59fn conn_err(e: quinn::ConnectionError) -> TransportError {
60    TransportError::Connection(e.to_string())
61}
62
63// ── From impls for quinn error types ────────────────────────
64
65impl From<quinn::ConnectionError> for TransportError {
66    fn from(e: quinn::ConnectionError) -> Self {
67        TransportError::Connection(e.to_string())
68    }
69}
70
71impl From<quinn::WriteError> for TransportError {
72    fn from(e: quinn::WriteError) -> Self {
73        TransportError::Write(e.to_string())
74    }
75}
76
77impl From<quinn::ReadExactError> for TransportError {
78    fn from(e: quinn::ReadExactError) -> Self {
79        TransportError::Read(e.to_string())
80    }
81}
82
83impl From<quinn::ConnectError> for TransportError {
84    fn from(e: quinn::ConnectError) -> Self {
85        TransportError::Connect(e.to_string())
86    }
87}
88
89impl From<quinn::ClosedStream> for TransportError {
90    fn from(_e: quinn::ClosedStream) -> Self {
91        TransportError::StreamClosed
92    }
93}
94
95impl From<quinn::SendDatagramError> for TransportError {
96    fn from(e: quinn::SendDatagramError) -> Self {
97        TransportError::SendDatagram(e.to_string())
98    }
99}