web_transport_quinn/
error.rs

1use std::sync::Arc;
2
3use thiserror::Error;
4
5use crate::{ConnectError, SettingsError};
6use quinn::rustls;
7
8/// An error returned when connecting to a WebTransport endpoint.
9#[derive(Error, Debug, Clone)]
10pub enum ClientError {
11    #[error("unexpected end of stream")]
12    UnexpectedEnd,
13
14    #[error("connection error: {0}")]
15    Connection(#[from] quinn::ConnectionError),
16
17    #[error("failed to write: {0}")]
18    WriteError(#[from] quinn::WriteError),
19
20    #[error("failed to read: {0}")]
21    ReadError(#[from] quinn::ReadError),
22
23    #[error("failed to exchange h3 settings: {0}")]
24    SettingsError(#[from] SettingsError),
25
26    #[error("failed to exchange h3 connect: {0}")]
27    HttpError(#[from] ConnectError),
28
29    #[error("quic error: {0}")]
30    QuinnError(#[from] quinn::ConnectError),
31
32    #[error("invalid DNS name: {0}")]
33    InvalidDnsName(String),
34
35    #[error("rustls error: {0}")]
36    Rustls(#[from] rustls::Error),
37}
38
39/// An errors returned by [`crate::Session`], split based on if they are underlying QUIC errors or WebTransport errors.
40#[derive(Clone, Error, Debug)]
41pub enum SessionError {
42    #[error("connection error: {0}")]
43    ConnectionError(#[from] quinn::ConnectionError),
44
45    #[error("webtransport error: {0}")]
46    WebTransportError(#[from] WebTransportError),
47
48    #[error("send datagram error: {0}")]
49    SendDatagramError(#[from] quinn::SendDatagramError),
50}
51
52/// An error that can occur when reading/writing the WebTransport stream header.
53#[derive(Clone, Error, Debug)]
54pub enum WebTransportError {
55    #[error("unknown session")]
56    UnknownSession,
57
58    #[error("read error: {0}")]
59    ReadError(#[from] quinn::ReadExactError),
60
61    #[error("write error: {0}")]
62    WriteError(#[from] quinn::WriteError),
63}
64
65/// An error when writing to [`crate::SendStream`]. Similar to [`quinn::WriteError`].
66#[derive(Clone, Error, Debug)]
67pub enum WriteError {
68    #[error("STOP_SENDING: {0}")]
69    Stopped(u32),
70
71    #[error("invalid STOP_SENDING: {0}")]
72    InvalidStopped(quinn::VarInt),
73
74    #[error("session error: {0}")]
75    SessionError(#[from] SessionError),
76
77    #[error("stream closed")]
78    ClosedStream,
79}
80
81impl From<quinn::WriteError> for WriteError {
82    fn from(e: quinn::WriteError) -> Self {
83        match e {
84            quinn::WriteError::Stopped(code) => {
85                match web_transport_proto::error_from_http3(code.into_inner()) {
86                    Some(code) => WriteError::Stopped(code),
87                    None => WriteError::InvalidStopped(code),
88                }
89            }
90            quinn::WriteError::ClosedStream => WriteError::ClosedStream,
91            quinn::WriteError::ConnectionLost(e) => WriteError::SessionError(e.into()),
92            quinn::WriteError::ZeroRttRejected => unreachable!("0-RTT not supported"),
93        }
94    }
95}
96
97/// An error when reading from [`crate::RecvStream`]. Similar to [`quinn::ReadError`].
98#[derive(Clone, Error, Debug)]
99pub enum ReadError {
100    #[error("session error: {0}")]
101    SessionError(#[from] SessionError),
102
103    #[error("RESET_STREAM: {0}")]
104    Reset(u32),
105
106    #[error("invalid RESET_STREAM: {0}")]
107    InvalidReset(quinn::VarInt),
108
109    #[error("stream already closed")]
110    ClosedStream,
111
112    #[error("ordered read on unordered stream")]
113    IllegalOrderedRead,
114}
115
116impl From<quinn::ReadError> for ReadError {
117    fn from(value: quinn::ReadError) -> Self {
118        match value {
119            quinn::ReadError::Reset(code) => {
120                match web_transport_proto::error_from_http3(code.into_inner()) {
121                    Some(code) => ReadError::Reset(code),
122                    None => ReadError::InvalidReset(code),
123                }
124            }
125            quinn::ReadError::ConnectionLost(e) => ReadError::SessionError(e.into()),
126            quinn::ReadError::IllegalOrderedRead => ReadError::IllegalOrderedRead,
127            quinn::ReadError::ClosedStream => ReadError::ClosedStream,
128            quinn::ReadError::ZeroRttRejected => unreachable!("0-RTT not supported"),
129        }
130    }
131}
132
133/// An error returned by [`crate::RecvStream::read_exact`]. Similar to [`quinn::ReadExactError`].
134#[derive(Clone, Error, Debug)]
135pub enum ReadExactError {
136    #[error("finished early")]
137    FinishedEarly(usize),
138
139    #[error("read error: {0}")]
140    ReadError(#[from] ReadError),
141}
142
143impl From<quinn::ReadExactError> for ReadExactError {
144    fn from(e: quinn::ReadExactError) -> Self {
145        match e {
146            quinn::ReadExactError::FinishedEarly(size) => ReadExactError::FinishedEarly(size),
147            quinn::ReadExactError::ReadError(e) => ReadExactError::ReadError(e.into()),
148        }
149    }
150}
151
152/// An error returned by [`crate::RecvStream::read_to_end`]. Similar to [`quinn::ReadToEndError`].
153#[derive(Clone, Error, Debug)]
154pub enum ReadToEndError {
155    #[error("too long")]
156    TooLong,
157
158    #[error("read error: {0}")]
159    ReadError(#[from] ReadError),
160}
161
162impl From<quinn::ReadToEndError> for ReadToEndError {
163    fn from(e: quinn::ReadToEndError) -> Self {
164        match e {
165            quinn::ReadToEndError::TooLong => ReadToEndError::TooLong,
166            quinn::ReadToEndError::Read(e) => ReadToEndError::ReadError(e.into()),
167        }
168    }
169}
170
171/// An error indicating the stream was already closed.
172#[derive(Clone, Error, Debug)]
173#[error("stream closed")]
174pub struct ClosedStream;
175
176impl From<quinn::ClosedStream> for ClosedStream {
177    fn from(_: quinn::ClosedStream) -> Self {
178        ClosedStream
179    }
180}
181
182/// An error returned when receiving a new WebTransport session.
183#[derive(Error, Debug, Clone)]
184pub enum ServerError {
185    #[error("unexpected end of stream")]
186    UnexpectedEnd,
187
188    #[error("connection error")]
189    Connection(#[from] quinn::ConnectionError),
190
191    #[error("failed to write")]
192    WriteError(#[from] quinn::WriteError),
193
194    #[error("failed to read")]
195    ReadError(#[from] quinn::ReadError),
196
197    #[error("failed to exchange h3 settings")]
198    SettingsError(#[from] SettingsError),
199
200    #[error("failed to exchange h3 connect")]
201    ConnectError(#[from] ConnectError),
202
203    #[error("io error: {0}")]
204    IoError(Arc<std::io::Error>),
205
206    #[error("rustls error: {0}")]
207    Rustls(#[from] rustls::Error),
208}
209
210// #[derive(Clone, Error, Debug)]
211// pub enum SendDatagramError {
212//     #[error("Unsupported peer")]
213//     UnsupportedPeer,
214
215//     #[error("Datagram support Disabled by peer")]
216//     DatagramSupportDisabled,
217
218//     #[error("Datagram Too large")]
219//     TooLarge,
220
221//     #[error("Session errorr: {0}")]
222//     SessionError(#[from] SessionError),
223// }
224
225// impl From<quinn::SendDatagramError> for SendDatagramError {
226//     fn from(value: quinn::SendDatagramError) -> Self {
227//          match value {
228//              quinn::SendDatagramError::UnsupportedByPeer => SendDatagramError::UnsupportedPeer,
229//              quinn::SendDatagramError::Disabled => SendDatagramError::DatagramSupportDisabled,
230//              quinn::SendDatagramError::TooLarge => SendDatagramError::TooLarge,
231//              quinn::SendDatagramError::ConnectionLost(e) => SendDatagramError::SessionError(e.into()),
232//          }
233//     }
234// }