1use crate::{
8 fsemul::errors::{FSEmulAPIError, FSEmulFSError, FSEmulNetworkError, FSEmulProtocolError},
9 mion::errors::{MionAPIError, MionProtocolError},
10};
11use bytes::Bytes;
12use miette::{Diagnostic, Report};
13use std::{ffi::FromBytesUntilNulError, str::Utf8Error, string::FromUtf8Error, time::Duration};
14use thiserror::Error;
15use tokio::{io::Error as IoError, task::JoinError};
16use walkdir::Error as WalkdirError;
17
18#[cfg(feature = "clients")]
19use crate::net::client::errors::CommonNetClientNetworkError;
20#[cfg(feature = "clients")]
21use local_ip_address::Error as LocalIpAddressError;
22#[cfg(feature = "clients")]
23use network_interface::Error as NetworkInterfaceError;
24#[cfg(feature = "clients")]
25use reqwest::Error as ReqwestError;
26
27#[cfg(any(feature = "clients", feature = "servers"))]
28use crate::net::errors::{CommonNetAPIError, CommonNetNetworkError};
29
30#[cfg(feature = "servers")]
31use crate::net::server::models::ResponseStreamMessage;
32#[cfg(feature = "servers")]
33use tokio::sync::mpsc::error::SendError;
34
35#[derive(Error, Diagnostic, Debug)]
38pub enum CatBridgeError {
39 #[error(transparent)]
41 #[diagnostic(transparent)]
42 API(#[from] APIError),
43 #[error(
54 "We could not send a message locally to another part of the process. This channel must've been closed unexpectedly."
55 )]
56 #[diagnostic(code(cat_dev::closed_channel))]
57 ClosedChannel,
58 #[error(transparent)]
60 #[diagnostic(transparent)]
61 FS(#[from] FSError),
62 #[error("We could not await an asynchronous task we spawned: {0:?}")]
68 #[diagnostic(code(cat_dev::join_failure))]
69 JoinFailure(#[from] JoinError),
70 #[error(transparent)]
72 #[diagnostic(transparent)]
73 Network(#[from] NetworkError),
74 #[error("We could not spawn a task (a lightweight thread) to do work on.")]
79 #[diagnostic(code(cat_dev::spawn_failure))]
80 SpawnFailure(IoError),
81 #[error("An unknown error we couldn't pin down occured: {0:?}")]
83 #[diagnostic(code(cat_dev::unknown))]
84 UnknownError(Report),
85 #[error(
86 "This cat-dev API requires a 32 bit usize, and this machine does not have it, please upgrade your machine."
87 )]
88 #[diagnostic(code(cat_dev::unsupported_bits_per_core))]
89 UnsupportedBitsPerCore,
90}
91
92#[non_exhaustive]
99#[derive(Error, Diagnostic, Debug)]
100pub enum APIError {
101 #[cfg_attr(docsrs, doc(cfg(any(feature = "clients", feature = "servers"))))]
103 #[cfg(any(feature = "clients", feature = "servers"))]
104 #[error(transparent)]
105 #[diagnostic(transparent)]
106 CommonNet(#[from] CommonNetAPIError),
107 #[error(transparent)]
108 #[diagnostic(transparent)]
109 FSEmul(#[from] FSEmulAPIError),
110 #[error(transparent)]
111 #[diagnostic(transparent)]
112 Mion(#[from] MionAPIError),
113 #[error(
118 "We could not find the local hosts ipv4 address which is needed if an ip isn't explicitly passed in."
119 )]
120 #[diagnostic(code(cat_dev::api::no_host_ip_found))]
121 NoHostIpFound,
122}
123
124#[cfg_attr(docsrs, doc(cfg(any(feature = "clients", feature = "servers"))))]
125#[cfg(any(feature = "clients", feature = "servers"))]
126impl From<CommonNetAPIError> for CatBridgeError {
127 fn from(value: CommonNetAPIError) -> Self {
128 Self::from(APIError::CommonNet(value))
129 }
130}
131
132#[derive(Error, Diagnostic, Debug)]
134pub enum FSError {
135 #[error(
142 "We can't find the path to store a complete list of host-bridges, please use explicit paths instead."
143 )]
144 #[diagnostic(code(cat_dev::fs::cant_find_hostenv_path))]
145 CantFindHostEnvPath,
146 #[error(transparent)]
147 #[diagnostic(transparent)]
148 FSEmul(#[from] FSEmulFSError),
149 #[error("Data read from the filesystem was expected to be a valid INI file: {0}")]
152 #[diagnostic(code(cat_dev::fs::expected_ini))]
153 InvalidDataNeedsToBeINI(String),
154 #[error("Expected file magic of: {0}, got {1} as magic bytes")]
156 #[diagnostic(code(cat_dev::fs::invalid_file_magic))]
157 InvalidFileMagic(u32, u32),
158 #[error("Expected file size of: {0} bytes, got a file sized {1} bytes")]
160 #[diagnostic(code(cat_dev::fs::invalid_file_size))]
161 InvalidFileSize(usize, usize),
162 #[error("Error writing/reading data from the filesystem: {0}")]
164 #[diagnostic(code(cat_dev::fs::io))]
165 IO(#[from] IoError),
166 #[error("Error iterating through folder: {0:?}")]
167 #[diagnostic(code(cat_dev::fs::iterating_folder_error))]
168 IteratingFolderError(#[from] WalkdirError),
169 #[error("Expect file to have at least: {0} line(s), but it was only: {1} line(s) long.")]
170 #[diagnostic(code(cat_dev::fs::too_few_lines))]
171 TooFewLines(usize, usize),
172 #[error("File cannot be larger than: {0} bytes, is {1} bytes")]
174 #[diagnostic(code(cat_dev::fs::too_large))]
175 TooLarge(usize, usize),
176 #[error("File needs to be at least: {0} bytes, is {1} bytes")]
178 #[diagnostic(code(cat_dev::fs::too_small))]
179 TooSmall(usize, usize),
180 #[error("Data read from the filesystem was expected to be UTF-8, but was not: {0}")]
182 #[diagnostic(code(cat_dev::fs::utf8_expected))]
183 Utf8Expected(#[from] FromUtf8Error),
184}
185
186#[derive(Error, Diagnostic, Debug)]
192#[non_exhaustive]
193pub enum NetworkError {
194 #[error("Failed to bind to a local address to receive packets.")]
206 #[diagnostic(code(cat_dev::net::bind_failure))]
207 BindFailure,
208 #[cfg_attr(docsrs, doc(cfg(feature = "clients")))]
209 #[cfg(feature = "clients")]
210 #[error(transparent)]
211 #[diagnostic(transparent)]
212 CommonClient(#[from] CommonNetClientNetworkError),
213 #[cfg_attr(docsrs, doc(cfg(any(feature = "clients", feature = "servers"))))]
215 #[cfg(any(feature = "clients", feature = "servers"))]
216 #[error(transparent)]
217 #[diagnostic(transparent)]
218 CommonNet(#[from] CommonNetNetworkError),
219 #[error("Expected some sort of data from other side, but got none.")]
220 #[diagnostic(code(cat_dev::net::expected_data))]
221 ExpectedData,
222 #[error(transparent)]
223 #[diagnostic(transparent)]
224 FSEmul(#[from] FSEmulNetworkError),
225 #[cfg_attr(docsrs, doc(cfg(feature = "clients")))]
226 #[cfg(feature = "clients")]
227 #[error("Underlying HTTP client error: {0}")]
229 #[diagnostic(code(cat_dev::net::http_failure))]
230 HTTP(#[from] ReqwestError),
231 #[error("Error talking to the network could not send/receive data: {0}")]
233 #[diagnostic(code(cat_dev::net::io_error))]
234 IO(#[from] IoError),
235 #[cfg_attr(docsrs, doc(cfg(feature = "clients")))]
236 #[cfg(feature = "clients")]
237 #[error("Failed to list the network interfaces on your device: {0:?}.")]
239 #[diagnostic(code(cat_dev::net::list_interfaces_error))]
240 ListInterfacesFailure(NetworkInterfaceError),
241 #[cfg_attr(docsrs, doc(cfg(feature = "clients")))]
242 #[cfg(feature = "clients")]
243 #[error("Failure fetching local ip address: {0}")]
245 #[diagnostic(code(cat_dev::net::local_ip_failure))]
246 LocalIp(#[from] LocalIpAddressError),
247 #[error(transparent)]
249 #[diagnostic(transparent)]
250 Parse(#[from] NetworkParseError),
251 #[error(
255 "Failed to set the socket we're bound on as a broadcast address, this is needed to discover CAT devices."
256 )]
257 #[diagnostic(code(cat_dev::net::set_broadcast_failure))]
258 SetBroadcastFailure,
259 #[cfg_attr(docsrs, doc(cfg(feature = "servers")))]
261 #[cfg(feature = "servers")]
262 #[error("Error queueing up packet to be sent out over a conenction: {0:?}")]
263 #[diagnostic(code(cat_dev::net::send_queue_failure))]
264 SendQueueMessageFailure(#[from] SendError<ResponseStreamMessage>),
265 #[error(
270 "Timed out while writing/reading data from the network, failed to send and receive data."
271 )]
272 #[diagnostic(code(cat_dev::net::timeout))]
273 Timeout(Duration),
274}
275
276#[cfg_attr(docsrs, doc(cfg(feature = "clients")))]
277#[cfg(feature = "clients")]
278impl From<CommonNetClientNetworkError> for CatBridgeError {
279 fn from(value: CommonNetClientNetworkError) -> Self {
280 Self::Network(value.into())
281 }
282}
283
284#[cfg_attr(docsrs, doc(cfg(any(feature = "clients", feature = "servers"))))]
285#[cfg(any(feature = "clients", feature = "servers"))]
286impl From<CommonNetNetworkError> for CatBridgeError {
287 fn from(value: CommonNetNetworkError) -> Self {
288 Self::Network(value.into())
289 }
290}
291
292#[cfg_attr(docsrs, doc(cfg(feature = "clients")))]
293#[cfg(feature = "clients")]
294impl From<ReqwestError> for CatBridgeError {
295 fn from(value: ReqwestError) -> Self {
296 Self::Network(value.into())
297 }
298}
299
300#[derive(Error, Diagnostic, Debug, PartialEq, Eq)]
303pub enum NetworkParseError {
304 #[error("Failed reading c style string from packet: {0:?}")]
306 #[diagnostic(code(cat_dev::net::parse::bad_c_string))]
307 BadCString(#[from] FromBytesUntilNulError),
308 #[error(
311 "Tried to read Packet of type ({0}) from network, must be encoded exactly as [{1:02x?}], but got [{2:02x?}]"
312 )]
313 #[diagnostic(code(cat_dev::net::parse::doesnt_match_static_data))]
314 DoesntMatchStaticPayload(&'static str, &'static [u8], Bytes),
315 #[error("Internal Protocol responded with an error code: {0}")]
316 #[diagnostic(code(cat_dev::net::parse::error_code))]
317 ErrorCode(u32),
318 #[error("Reading Field {1} from Packet {0}, was not encoded correctly must be encoded as {2}")]
321 #[diagnostic(code(cat_dev::net::parse::field_encoded_incorrectly))]
322 FieldEncodedIncorrectly(&'static str, &'static str, &'static str),
323 #[error(
326 "Tried Reading Field {1} from Packet {0}. This Field requires at least {2} bytes, but only had {3}, bytes: {4:02x?}"
327 )]
328 #[diagnostic(code(cat_dev::net::parse::field_not_long_enough))]
329 FieldNotLongEnough(&'static str, &'static str, usize, usize, Bytes),
330 #[error(transparent)]
331 #[diagnostic(transparent)]
332 FSEmul(#[from] FSEmulProtocolError),
333 #[error(transparent)]
335 #[diagnostic(transparent)]
336 Mion(#[from] MionProtocolError),
337 #[error(
340 "Tried to read Packet of type ({0}) from network needs at least {1} bytes, but only got {2} bytes: {3:02x?}"
341 )]
342 #[diagnostic(code(cat_dev::net::parse::not_enough_data))]
343 NotEnoughData(&'static str, usize, usize, Bytes),
344 #[error(
347 "Unexpected Trailer for Packet `{0}` received from the network (we're not sure what do with this extra data), extra bytes: {1:02x?}"
348 )]
349 #[diagnostic(code(cat_dev::net::parse::unexpected_trailer))]
350 UnexpectedTrailer(&'static str, Bytes),
351 #[error("Data read from the network was expected to be UTF-8, but was not: {0}")]
353 #[diagnostic(code(cat_dev::net::parse::utf8_expected))]
354 Utf8Expected(#[from] FromUtf8Error),
355 #[error("Data read from a network slice was expected to be UTF-8, but was not: {0}")]
357 #[diagnostic(code(cat_dev::net::parse::utf8_expected_slice))]
358 Utf8ExpectedSlice(#[from] Utf8Error),
359}
360impl From<NetworkParseError> for CatBridgeError {
361 fn from(value: NetworkParseError) -> Self {
362 Self::Network(value.into())
363 }
364}