use std::path::PathBuf;
use thiserror::Error;
pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum PersistError {
#[error("cannot determine system data directory")]
SystemDataDirUnavailable,
#[error("{op} `{path}` failed: {source}")]
PathIo {
op: &'static str,
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("invalid key file length: expected {expected} bytes, got {actual} bytes")]
InvalidKeyLength { expected: usize, actual: usize },
#[cfg(feature = "persist")]
#[error("failed to parse profile `{path}`: {source}")]
ProfileParse {
path: PathBuf,
#[source]
source: toml::de::Error,
},
#[cfg(feature = "persist")]
#[error(transparent)]
ProfileSerialize(#[from] toml::ser::Error),
#[error("invalid relay URL: {0}")]
RelayUrlParse(String),
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum TicketError {
#[error(transparent)]
UrlParse(#[from] url::ParseError),
#[error("invalid scheme: expected \"{expected}\", got \"{actual}\"")]
InvalidScheme {
expected: &'static str,
actual: String,
},
#[error("missing endpoint id in ticket URL")]
MissingEndpointId,
#[error("invalid endpoint id: {0}")]
EndpointIdParse(String),
#[error("invalid relay URL: {0}")]
RelayUrlParse(String),
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum TunnelError {
#[error("mutex poisoned: {name}")]
MutexPoisoned { name: &'static str },
#[error("bind host endpoint failed")]
BindHostEndpoint(#[source] BoxError),
#[error("bind join endpoint failed")]
BindJoinEndpoint(#[source] BoxError),
#[error("bind local tcp listener failed")]
BindLocalListener(#[source] BoxError),
#[error("accept host connection failed")]
AcceptHostConnection(#[source] BoxError),
#[error("accept QUIC bi stream failed")]
AcceptQuicBiStream(#[source] BoxError),
#[error("accept local tcp client failed")]
AcceptLocalTcpClient(#[source] BoxError),
#[error("connect host endpoint failed")]
ConnectHostEndpoint(#[source] BoxError),
#[error("initial connection failed after {attempts} attempts")]
InitialConnectionExhausted { attempts: u32 },
#[error("open auth stream failed")]
OpenAuthStream(#[source] BoxError),
#[error("accept auth stream failed")]
AcceptAuthStream(#[source] BoxError),
#[error("read auth result failed")]
ReadAuthResult(#[source] BoxError),
#[error("read auth payload failed")]
ReadAuthPayload(#[source] BoxError),
#[error("write auth payload failed")]
WriteAuthPayload(#[source] BoxError),
#[error("write auth rejected failed")]
WriteAuthRejected(#[source] BoxError),
#[error("write auth decision failed")]
WriteAuthDecision(#[source] BoxError),
#[error("finish auth stream failed")]
FinishAuthStream(#[source] BoxError),
#[error("auth rejected by host")]
AuthRejectedByHost,
#[error("bridge tcp->quic failed")]
BridgeTcpToQuic(#[source] BoxError),
#[error("bridge quic->tcp failed")]
BridgeQuicToTcp(#[source] BoxError),
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum SculkError {
#[error(transparent)]
Persist(#[from] PersistError),
#[error(transparent)]
Ticket(#[from] TicketError),
#[error(transparent)]
Tunnel(#[from] TunnelError),
}
impl TunnelError {
pub fn mutex_poisoned(name: &'static str) -> Self {
Self::MutexPoisoned { name }
}
}
pub type Result<T> = std::result::Result<T, SculkError>;