use crate::coding;
#[derive(thiserror::Error, Debug, Clone)]
#[non_exhaustive]
pub enum Error {
#[error("transport error")]
Transport,
#[error("decode error")]
Decode,
#[error("unsupported versions")]
Version,
#[error("extension required")]
RequiredExtension,
#[error("unexpected stream type")]
UnexpectedStream,
#[error("varint bounds exceeded")]
BoundsExceeded,
#[error("duplicate")]
Duplicate,
#[error("cancelled")]
Cancel,
#[error("timeout")]
Timeout,
#[error("old")]
Old,
#[error("app code={0}")]
App(u16),
#[error("not found")]
NotFound,
#[error("wrong frame size")]
WrongSize,
#[error("protocol violation")]
ProtocolViolation,
#[error("unauthorized")]
Unauthorized,
#[error("unexpected message")]
UnexpectedMessage,
#[error("unsupported")]
Unsupported,
#[error("encode error")]
Encode,
#[error("too many parameters")]
TooManyParameters,
#[error("invalid role")]
InvalidRole,
#[error("unknown ALPN: {0}")]
UnknownAlpn(String),
#[error("dropped")]
Dropped,
#[error("closed")]
Closed,
}
impl Error {
pub fn to_code(&self) -> u32 {
match self {
Self::Cancel => 0,
Self::RequiredExtension => 1,
Self::Old => 2,
Self::Timeout => 3,
Self::Transport => 4,
Self::Decode => 5,
Self::Unauthorized => 6,
Self::Version => 9,
Self::UnexpectedStream => 10,
Self::BoundsExceeded => 11,
Self::Duplicate => 12,
Self::NotFound => 13,
Self::WrongSize => 14,
Self::ProtocolViolation => 15,
Self::UnexpectedMessage => 16,
Self::Unsupported => 17,
Self::Encode => 18,
Self::TooManyParameters => 19,
Self::InvalidRole => 20,
Self::UnknownAlpn(_) => 21,
Self::Dropped => 24,
Self::Closed => 25,
Self::App(app) => *app as u32 + 64,
}
}
pub fn from_code(code: u32) -> Self {
match code {
0 => Self::Cancel,
1 => Self::RequiredExtension,
2 => Self::Old,
3 => Self::Timeout,
4 => Self::Transport,
5 => Self::Decode,
6 => Self::Unauthorized,
9 => Self::Version,
10 => Self::UnexpectedStream,
11 => Self::BoundsExceeded,
12 => Self::Duplicate,
13 => Self::NotFound,
14 => Self::WrongSize,
15 => Self::ProtocolViolation,
16 => Self::UnexpectedMessage,
17 => Self::Unsupported,
18 => Self::Encode,
19 => Self::TooManyParameters,
20 => Self::InvalidRole,
24 => Self::Dropped,
25 => Self::Closed,
code if code >= 64 => match u16::try_from(code - 64) {
Ok(app) => Self::App(app),
Err(_) => Self::ProtocolViolation,
},
_ => Self::ProtocolViolation,
}
}
pub fn from_transport(err: impl web_transport_trait::Error) -> Self {
if let Some(code) = err.stream_error() {
return Self::from_code(code);
}
tracing::warn!(%err, "transport error");
Self::Transport
}
}
impl From<coding::DecodeError> for Error {
fn from(err: coding::DecodeError) -> Self {
tracing::warn!(%err, "decode error");
Error::Decode
}
}
impl From<coding::BoundsExceeded> for Error {
fn from(err: coding::BoundsExceeded) -> Self {
tracing::warn!(%err, "bounds exceeded");
Error::BoundsExceeded
}
}
impl From<coding::EncodeError> for Error {
fn from(err: coding::EncodeError) -> Self {
tracing::warn!(%err, "encode error");
Error::Encode
}
}
impl web_transport_trait::Error for Error {
fn session_error(&self) -> Option<(u32, String)> {
None
}
}
pub type Result<T> = std::result::Result<T, Error>;