actr_runtime/transport/
error.rs

1//! Network layer error definitions
2
3use thiserror::Error;
4
5/// Network layer error types
6#[derive(Error, Debug)]
7pub enum NetworkError {
8    /// Connection error
9    #[error("Connection error: {0}")]
10    ConnectionError(String),
11
12    /// Signaling error
13    #[error("Signaling error: {0}")]
14    SignalingError(String),
15
16    /// WebRTC error
17    #[error("WebRTC error: {0}")]
18    WebRtcError(String),
19
20    /// Protocol error
21    #[error("Protocol error: {0}")]
22    ProtocolError(String),
23
24    /// Serialization error
25    #[error("Serialization error: {0}")]
26    SerializationError(String),
27
28    /// Deserialization error
29    #[error("Deserialization error: {0}")]
30    DeserializationError(String),
31
32    /// Timeout error
33    #[error("Timeout error: {0}")]
34    TimeoutError(String),
35
36    /// Authentication error
37    #[error("Authentication error: {0}")]
38    AuthenticationError(String),
39
40    /// Permission error
41    #[error("Permission error: {0}")]
42    PermissionError(String),
43
44    /// Configuration error
45    #[error("Configuration error: {0}")]
46    ConfigurationError(String),
47
48    /// Resource exhausted error
49    #[error("Resource exhausted: {0}")]
50    ResourceExhaustedError(String),
51
52    /// Network unreachable error
53    #[error("Network unreachable: {0}")]
54    NetworkUnreachableError(String),
55
56    /// Service discovery error
57    #[error("Service discovery error: {0}")]
58    ServiceDiscoveryError(String),
59
60    /// NAT traversal error
61    #[error("NAT traversal error: {0}")]
62    NatTraversalError(String),
63
64    /// Data channel error
65    #[error("Data channel error: {0}")]
66    DataChannelError(String),
67
68    /// Broadcast error
69    #[error("Broadcast error: {0}")]
70    BroadcastError(String),
71
72    /// ICE error
73    #[error("ICE error: {0}")]
74    IceError(String),
75
76    /// DTLS error
77    #[error("DTLS error: {0}")]
78    DtlsError(String),
79
80    /// STUN/TURN error
81    #[error("STUN/TURN error: {0}")]
82    StunTurnError(String),
83
84    /// WebSocket error
85    #[error("WebSocket error: {0}")]
86    WebSocketError(String),
87
88    /// Connection not found error
89    #[error("Connection not found: {0}")]
90    ConnectionNotFound(String),
91
92    /// Feature not implemented error
93    #[error("Not implemented: {0}")]
94    NotImplemented(String),
95
96    /// Channel closed error
97    #[error("Channel closed: {0}")]
98    ChannelClosed(String),
99
100    /// Send error
101    #[error("Send error: {0}")]
102    SendError(String),
103
104    /// No route error
105    #[error("No route: {0}")]
106    NoRoute(String),
107
108    /// Invalid operation error
109    #[error("Invalid operation: {0}")]
110    InvalidOperation(String),
111
112    /// Invalid argument error
113    #[error("Invalid argument: {0}")]
114    InvalidArgument(String),
115
116    /// Channel not found error
117    #[error("Channel not found: {0}")]
118    ChannelNotFound(String),
119
120    /// IO error
121    #[error("IO error: {0}")]
122    IoError(#[from] std::io::Error),
123
124    /// URL parse error
125    #[error("URL parse error: {0}")]
126    UrlParseError(#[from] url::ParseError),
127
128    /// JSON error
129    #[error("JSON error: {0}")]
130    JsonError(#[from] serde_json::Error),
131
132    /// Other error
133    #[error("Other error: {0}")]
134    Other(#[from] anyhow::Error),
135}
136
137impl NetworkError {
138    /// Check if error is retryable
139    pub fn is_retryable(&self) -> bool {
140        matches!(
141            self,
142            NetworkError::ConnectionError(_)
143                | NetworkError::TimeoutError(_)
144                | NetworkError::NetworkUnreachableError(_)
145                | NetworkError::ResourceExhaustedError(_)
146        )
147    }
148
149    /// Check if error is temporary
150    pub fn is_temporary(&self) -> bool {
151        matches!(
152            self,
153            NetworkError::ConnectionError(_)
154                | NetworkError::TimeoutError(_)
155                | NetworkError::NetworkUnreachableError(_)
156                | NetworkError::ResourceExhaustedError(_)
157        )
158    }
159
160    /// Check if error is fatal
161    pub fn is_fatal(&self) -> bool {
162        matches!(
163            self,
164            NetworkError::AuthenticationError(_)
165                | NetworkError::PermissionError(_)
166                | NetworkError::ConfigurationError(_)
167        )
168    }
169
170    /// Get error category
171    pub fn category(&self) -> &'static str {
172        match self {
173            NetworkError::ConnectionError(_) => "connection",
174            NetworkError::SignalingError(_) => "signaling",
175            NetworkError::WebRtcError(_) => "webrtc",
176            NetworkError::ProtocolError(_) => "protocol",
177            NetworkError::SerializationError(_) | NetworkError::DeserializationError(_) => {
178                "serialization"
179            }
180            NetworkError::TimeoutError(_) => "timeout",
181            NetworkError::AuthenticationError(_) => "authentication",
182            NetworkError::PermissionError(_) => "permission",
183            NetworkError::ConfigurationError(_) => "configuration",
184            NetworkError::ResourceExhaustedError(_) => "resource_exhausted",
185            NetworkError::NetworkUnreachableError(_) => "network_unreachable",
186            NetworkError::ServiceDiscoveryError(_) => "service_discovery",
187            NetworkError::NatTraversalError(_) => "nat_traversal",
188            NetworkError::DataChannelError(_) => "data_channel",
189            NetworkError::IceError(_) => "ice",
190            NetworkError::DtlsError(_) => "dtls",
191            NetworkError::StunTurnError(_) => "stun_turn",
192            NetworkError::WebSocketError(_) => "websocket",
193            NetworkError::ConnectionNotFound(_) => "connection_not_found",
194            NetworkError::NotImplemented(_) => "not_implemented",
195            NetworkError::ChannelClosed(_) => "channel_closed",
196            NetworkError::SendError(_) => "send_error",
197            NetworkError::NoRoute(_) => "no_route",
198            NetworkError::InvalidOperation(_) => "invalid_operation",
199            NetworkError::InvalidArgument(_) => "invalid_argument",
200            NetworkError::ChannelNotFound(_) => "channel_not_found",
201            NetworkError::IoError(_) => "io",
202            NetworkError::UrlParseError(_) => "url_parse",
203            NetworkError::JsonError(_) => "json",
204            NetworkError::BroadcastError(_) => "broadcast",
205            NetworkError::Other(_) => "other",
206        }
207    }
208
209    /// Get error severity (1-10, 10 is most severe)
210    pub fn severity(&self) -> u8 {
211        match self {
212            NetworkError::ConfigurationError(_)
213            | NetworkError::AuthenticationError(_)
214            | NetworkError::PermissionError(_) => 10,
215
216            NetworkError::WebRtcError(_)
217            | NetworkError::SignalingError(_)
218            | NetworkError::ProtocolError(_) => 8,
219
220            NetworkError::ConnectionError(_) | NetworkError::NetworkUnreachableError(_) => 7,
221
222            NetworkError::NatTraversalError(_)
223            | NetworkError::IceError(_)
224            | NetworkError::DtlsError(_) => 6,
225
226            NetworkError::TimeoutError(_) | NetworkError::ResourceExhaustedError(_) => 5,
227
228            NetworkError::ServiceDiscoveryError(_)
229            | NetworkError::DataChannelError(_)
230            | NetworkError::BroadcastError(_) => 4,
231
232            NetworkError::SerializationError(_) | NetworkError::DeserializationError(_) => 3,
233
234            NetworkError::WebSocketError(_) | NetworkError::StunTurnError(_) => 3,
235
236            NetworkError::ConnectionNotFound(_)
237            | NetworkError::ChannelClosed(_)
238            | NetworkError::SendError(_)
239            | NetworkError::NoRoute(_)
240            | NetworkError::ChannelNotFound(_) => 4,
241
242            NetworkError::InvalidOperation(_) | NetworkError::InvalidArgument(_) => 6,
243
244            NetworkError::NotImplemented(_) => 8,
245
246            NetworkError::IoError(_)
247            | NetworkError::UrlParseError(_)
248            | NetworkError::JsonError(_) => 2,
249
250            NetworkError::Other(_) => 1,
251        }
252    }
253}
254
255// TODO: Implement UnifiedError trait (when actr-protocol provides error_unified module)
256// impl UnifiedError for NetworkError { ... }
257
258/// Network layer result type
259pub type NetworkResult<T> = Result<T, NetworkError>;
260
261/// Convert from actor error to network error
262impl From<actr_protocol::ActrError> for NetworkError {
263    fn from(err: actr_protocol::ActrError) -> Self {
264        NetworkError::Other(anyhow::anyhow!("Actor error: {err}"))
265    }
266}
267
268/// Convert from WebRTC error
269impl From<webrtc::Error> for NetworkError {
270    fn from(err: webrtc::Error) -> Self {
271        NetworkError::WebRtcError(err.to_string())
272    }
273}
274
275/// Convert from WebSocket error
276impl From<tokio_tungstenite::tungstenite::Error> for NetworkError {
277    fn from(err: tokio_tungstenite::tungstenite::Error) -> Self {
278        NetworkError::WebSocketError(err.to_string())
279    }
280}
281
282/// Convert from protobuf encode error
283impl From<actr_protocol::prost::EncodeError> for NetworkError {
284    fn from(err: actr_protocol::prost::EncodeError) -> Self {
285        NetworkError::SerializationError(err.to_string())
286    }
287}
288
289/// Convert from protobuf decode error
290impl From<actr_protocol::prost::DecodeError> for NetworkError {
291    fn from(err: actr_protocol::prost::DecodeError) -> Self {
292        NetworkError::DeserializationError(err.to_string())
293    }
294}
295
296// TODO: In future, if error statistics needed, can add ErrorStats struct
297// Recommend using arrays instead of HashMap (error categories and severities are fixed)