1use crate::asn1::Frame;
2use crate::policy::TransitStatus;
3
4#[cfg(feature = "derive")]
5use crate::Errorizable;
6#[cfg(not(feature = "std"))]
7use alloc::boxed::Box;
8
9pub type Result<T> = core::result::Result<T, TransportError>;
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq)]
13pub enum TransportFailure {
14 EncodingFailed,
16 EncryptionFailed,
18 SizeExceeded,
20 EncryptorUnavailable,
22 NonceGenerationFailed,
24 Busy,
26 Forbidden,
28 Unauthorized,
30 Timeout,
32 PolicyRejection,
34}
35
36#[cfg_attr(feature = "derive", derive(Errorizable))]
38#[derive(Debug)]
39pub enum TransportError {
40 #[cfg_attr(feature = "derive", error("Connection closed gracefully"))]
41 ConnectionClosed,
42 #[cfg_attr(feature = "derive", error("Connection failed"))]
43 ConnectionFailed,
44 #[cfg_attr(feature = "derive", error("Send failed"))]
45 SendFailed,
46 #[cfg_attr(feature = "derive", error("Encryption required but not provided"))]
47 MissingEncryption,
48 #[cfg_attr(
49 feature = "derive",
50 error("Handshake protocol not supported by this transport: {0:?}")
51 )]
52 UnsupportedHandshakeProtocol(crate::transport::handshake::HandshakeProtocolKind),
53 #[cfg_attr(
54 feature = "derive",
55 error("Server certificate chain required but not provisioned")
56 )]
57 MissingServerCertificateChain,
58 #[cfg_attr(feature = "derive", error("Invalid message"))]
59 InvalidMessage,
60 #[cfg_attr(feature = "derive", error("Invalid reply"))]
61 InvalidReply,
62 #[cfg_attr(feature = "derive", error("Missing request"))]
63 MissingRequest,
64 #[cfg_attr(feature = "derive", error("Max retries exceeded"))]
65 MaxRetriesExceeded,
66 #[cfg_attr(feature = "derive", error("Invalid address"))]
67 InvalidAddress,
68 #[cfg_attr(feature = "derive", error("Invalid state"))]
69 InvalidState,
70 #[cfg(feature = "x509")]
71 #[cfg_attr(feature = "derive", error("Invalid certificate: {0}"))]
72 #[cfg_attr(feature = "derive", from)]
73 InvalidCertificate(crate::crypto::x509::error::CertificateValidationError),
74 #[cfg_attr(feature = "derive", error("Message not sent: {1:?} - {0:?}"))]
75 MessageNotSent(Box<Frame>, TransportFailure),
76 #[cfg_attr(feature = "derive", error("Operation failed: {0:?}"))]
77 OperationFailed(TransportFailure),
78 #[cfg(feature = "x509")]
79 #[cfg_attr(feature = "derive", error("Handshake error: {0}"))]
80 #[cfg_attr(feature = "derive", from)]
81 HandshakeError(crate::transport::handshake::HandshakeError),
82 #[cfg_attr(feature = "derive", error("DER error: {0}"))]
83 #[cfg_attr(feature = "derive", from)]
84 DerError(der::Error),
85 #[cfg(feature = "std")]
86 #[cfg_attr(feature = "derive", error("I/O error: {0}"))]
87 #[cfg_attr(feature = "derive", from)]
88 IoError(std::io::Error),
89}
90
91crate::impl_error_display!(TransportError {
92 ConnectionClosed => "Connection closed gracefully",
93 ConnectionFailed => "Connection failed",
94 SendFailed => "Send failed",
95 MissingEncryption => "Encryption required but not provided",
96 UnsupportedHandshakeProtocol(kind) => "Handshake protocol not supported by this transport: {kind:?}",
97 MissingServerCertificateChain => "Server certificate chain required but not provisioned",
98 InvalidMessage => "Invalid message",
99 InvalidReply => "Invalid reply",
100 MissingRequest => "Missing request",
101 MaxRetriesExceeded => "Max retries exceeded",
102 InvalidAddress => "Invalid address",
103 InvalidState => "Invalid state",
104 MessageNotSent(frame, failure) => "Message not sent: {failure:?} - {frame:?}",
105 OperationFailed(failure) => "Operation failed: {failure:?}",
106 DerError(err) => "DER error: {err}",
107
108 #[cfg(feature = "x509")]
109 InvalidCertificate(err) => "Invalid certificate: {err}",
110 #[cfg(feature = "x509")]
111 HandshakeError(err) => "Handshake error: {err}",
112 #[cfg(feature = "std")]
113 IoError(err) => "I/O error: {err}",
114});
115
116impl From<crate::error::TightBeamError> for TransportError {
119 fn from(err: crate::error::TightBeamError) -> Self {
120 use crate::error::TightBeamError;
121 match err {
122 TightBeamError::TransportError(t) => t,
123 TightBeamError::SerializationError(e) => TransportError::DerError(e),
124
125 #[cfg(feature = "x509")]
126 TightBeamError::HandshakeError(h) => TransportError::HandshakeError(h),
127 #[cfg(feature = "x509")]
128 TightBeamError::CertificateValidationError(e) => TransportError::InvalidCertificate(e),
129 #[cfg(feature = "std")]
130 TightBeamError::IoError(e) => TransportError::IoError(e),
131 _ => TransportError::InvalidMessage,
132 }
133 }
134}
135
136impl From<TransitStatus> for TransportError {
137 fn from(status: TransitStatus) -> Self {
138 match status {
139 TransitStatus::Request => TransportError::InvalidMessage,
140 TransitStatus::Accepted => TransportError::InvalidMessage,
141 TransitStatus::Busy => TransportError::OperationFailed(TransportFailure::Busy),
142 TransitStatus::Unauthorized => TransportError::OperationFailed(TransportFailure::Unauthorized),
143 TransitStatus::Forbidden => TransportError::OperationFailed(TransportFailure::Forbidden),
144 TransitStatus::Timeout => TransportError::OperationFailed(TransportFailure::Timeout),
145 }
146 }
147}
148
149#[cfg(all(feature = "std", not(feature = "derive")))]
150crate::impl_from!(std::io::Error => TransportError::IoError);
151#[cfg(not(feature = "derive"))]
152crate::impl_from!(der::Error => TransportError::DerError);
153#[cfg(all(feature = "x509", not(feature = "derive")))]
154crate::impl_from!(crate::transport::handshake::HandshakeError => TransportError::HandshakeError);
155#[cfg(all(feature = "x509", not(feature = "derive")))]
156crate::impl_from!(crate::crypto::x509::error::CertificateValidationError => TransportError::InvalidCertificate);
157
158crate::impl_from!(
159 spki::Error => TransportError::DerError extract spki::Error::Asn1(der_err) =>
160 der_err else der::Error::from(der::ErrorKind::Failed)
161);
162#[cfg(feature = "x509")]
163crate::impl_from!(
164 x509_cert::builder::Error => TransportError::DerError extract x509_cert::builder::Error::Asn1(der_err) =>
165 der_err else der::Error::from(der::ErrorKind::Failed)
166);
167
168#[cfg(all(feature = "std", feature = "tcp"))]
170impl From<std::net::AddrParseError> for TransportError {
171 fn from(err: std::net::AddrParseError) -> Self {
172 TransportError::IoError(std::io::Error::new(std::io::ErrorKind::InvalidInput, err))
173 }
174}
175
176#[cfg(feature = "tokio")]
178impl From<tokio::task::JoinError> for TransportError {
179 fn from(err: tokio::task::JoinError) -> Self {
180 TransportError::IoError(std::io::Error::other(err))
181 }
182}
183
184#[cfg(feature = "tokio")]
186impl From<tokio::time::error::Elapsed> for TransportError {
187 fn from(_: tokio::time::error::Elapsed) -> Self {
188 TransportError::OperationFailed(TransportFailure::Timeout)
189 }
190}
191
192#[cfg(all(feature = "x509", feature = "secp256k1"))]
194impl From<k256::ecdsa::Error> for TransportError {
195 fn from(err: k256::ecdsa::Error) -> Self {
196 TransportError::HandshakeError(crate::transport::handshake::HandshakeError::from(err))
197 }
198}
199
200impl TransportError {
201 pub fn from_failure(frame: Frame, failure: TransportFailure) -> Self {
202 TransportError::MessageNotSent(Box::new(frame), failure)
203 }
204
205 pub fn take_frame(self) -> Option<crate::asn1::Frame> {
207 match self {
208 TransportError::MessageNotSent(frame, _) => Some(*frame),
209 _ => None,
210 }
211 }
212
213 pub fn frame(&self) -> Option<&crate::asn1::Frame> {
215 match self {
216 TransportError::MessageNotSent(frame, _) => Some(frame),
217 _ => None,
218 }
219 }
220
221 pub fn failure_reason(&self) -> Option<&TransportFailure> {
223 match self {
224 TransportError::MessageNotSent(_, reason) => Some(reason),
225 _ => None,
226 }
227 }
228
229 pub fn is_connection_error(&self) -> bool {
234 matches!(
235 self,
236 TransportError::ConnectionClosed
237 | TransportError::ConnectionFailed
238 | TransportError::OperationFailed(TransportFailure::Timeout)
239 ) || {
240 #[cfg(feature = "std")]
241 {
242 matches!(self, TransportError::IoError(_))
243 }
244 #[cfg(not(feature = "std"))]
245 {
246 false
247 }
248 }
249 }
250}
251
252impl From<TransportFailure> for TransportError {
253 fn from(failure: TransportFailure) -> Self {
254 match failure {
255 TransportFailure::EncodingFailed => TransportError::InvalidMessage,
256 TransportFailure::SizeExceeded => TransportError::InvalidMessage,
257 TransportFailure::PolicyRejection => TransportError::InvalidReply,
258 TransportFailure::NonceGenerationFailed => TransportError::SendFailed,
259 other => TransportError::OperationFailed(other),
261 }
262 }
263}
264
265impl TransportFailure {
266 pub fn with_frame(self, frame: Frame) -> TransportError {
267 TransportError::from_failure(frame, self)
268 }
269
270 pub fn with_optional_frame(self, frame: Option<Frame>) -> TransportError {
271 if let Some(frame) = frame {
272 self.with_frame(frame)
273 } else {
274 self.into()
275 }
276 }
277}