web_transport_quinn/
error.rs1use std::sync::Arc;
2
3use thiserror::Error;
4
5use crate::{ConnectError, SettingsError};
6use quinn::rustls;
7
8#[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#[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#[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#[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#[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#[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#[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#[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#[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