1use crate::{
8 fsemul::errors::{FSEmulAPIError, FSEmulFSError, FSEmulProtocolError},
9 mion::errors::{MIONAPIError, MIONProtocolError},
10};
11use bytes::Bytes;
12use local_ip_address::Error as LocalIpAddressError;
13use miette::Diagnostic;
14use network_interface::Error as NetworkInterfaceError;
15use reqwest::Error as ReqwestError;
16use std::{ffi::FromBytesUntilNulError, str::Utf8Error, string::FromUtf8Error, time::Duration};
17use thiserror::Error;
18use tokio::{io::Error as IoError, sync::mpsc::error::SendError, task::JoinError};
19use walkdir::Error as WalkdirError;
20
21#[derive(Error, Diagnostic, Debug)]
24pub enum CatBridgeError {
25 #[error(transparent)]
27 #[diagnostic(transparent)]
28 API(#[from] APIError),
29 #[error("We could not send a message locally to another part of the process. This channel must've been closed unexpectedly.")]
40 #[diagnostic(code(cat_dev::closed_channel))]
41 ClosedChannel,
42 #[error(transparent)]
44 #[diagnostic(transparent)]
45 FS(#[from] FSError),
46 #[error("We could not await an asynchronous task we spawned: {0:?}")]
52 #[diagnostic(code(cat_dev::join_failure))]
53 JoinFailure(#[from] JoinError),
54 #[error(transparent)]
56 #[diagnostic(transparent)]
57 Network(#[from] NetworkError),
58 #[error("We could not spawn a task (a lightweight thread) to do work on.")]
63 #[diagnostic(code(cat_dev::spawn_failure))]
64 SpawnFailure(IoError),
65 #[error("This cat-dev API requires a 32 bit usize, and this machine does not have it, please upgrade your machine.")]
66 #[diagnostic(code(cat_dev::unsupported_bits_per_core))]
67 UnsupportedBitsPerCore,
68}
69
70#[derive(Error, Diagnostic, Debug, PartialEq, Eq)]
77pub enum APIError {
78 #[error(transparent)]
79 #[diagnostic(transparent)]
80 FSEmul(#[from] FSEmulAPIError),
81 #[error(transparent)]
82 #[diagnostic(transparent)]
83 MION(#[from] MIONAPIError),
84 #[error("We could not find the local hosts ipv4 address which is needed if an ip isn't explicitly passed in.")]
89 #[diagnostic(code(cat_dev::api::no_host_ip_found))]
90 NoHostIpFound,
91}
92
93#[derive(Error, Diagnostic, Debug)]
95pub enum FSError {
96 #[error("We can't find the path to store a complete list of host-bridges, please use explicit paths instead.")]
103 #[diagnostic(code(cat_dev::fs::cant_find_hostenv_path))]
104 CantFindHostEnvPath,
105 #[error(transparent)]
106 #[diagnostic(transparent)]
107 FSEmul(#[from] FSEmulFSError),
108 #[error("Data read from the filesystem was expected to be a valid INI file: {0}")]
111 #[diagnostic(code(cat_dev::fs::expected_ini))]
112 InvalidDataNeedsToBeINI(String),
113 #[error("Expected file magic of: {0}, got {1} as magic bytes")]
115 #[diagnostic(code(cat_dev::fs::invalid_file_magic))]
116 InvalidFileMagic(u32, u32),
117 #[error("Expected file size of: {0} bytes, got a file sized {1} bytes")]
119 #[diagnostic(code(cat_dev::fs::invalid_file_size))]
120 InvalidFileSize(usize, usize),
121 #[error("Error writing/reading data from the filesystem: {0}")]
123 #[diagnostic(code(cat_dev::fs::io))]
124 IO(#[from] IoError),
125 #[error("Error iterating through directory: {0:?}")]
126 #[diagnostic(code(cat_dev::fs::iterating_directory_error))]
127 IteratingDirectoryError(#[from] WalkdirError),
128 #[error("Expect file to have at least: {0} line(s), but it was only: {1} line(s) long.")]
129 #[diagnostic(code(cat_dev::fs::too_few_lines))]
130 TooFewLines(usize, usize),
131 #[error("File cannot be larger than: {0} bytes, is {1} bytes")]
133 #[diagnostic(code(cat_dev::fs::too_large))]
134 TooLarge(usize, usize),
135 #[error("File needs to be at least: {0} bytes, is {1} bytes")]
137 #[diagnostic(code(cat_dev::fs::too_small))]
138 TooSmall(usize, usize),
139 #[error("Data read from the filesystem was expected to be UTF-8, but was not: {0}")]
141 #[diagnostic(code(cat_dev::fs::utf8_expected))]
142 Utf8Expected(#[from] FromUtf8Error),
143}
144
145#[derive(Error, Diagnostic, Debug)]
151pub enum NetworkError {
152 #[error("Failed to bind to a local address to receive packets.")]
164 #[diagnostic(code(cat_dev::net::bind_failure))]
165 BindFailure,
166 #[error("Expected some sort of data from other side, but got none.")]
167 #[diagnostic(code(cat_dev::net::expected_data))]
168 ExpectedData,
169 #[error("Underlying HTTP client error: {0}")]
171 #[diagnostic(code(cat_dev::net::http_failure))]
172 HTTP(#[from] ReqwestError),
173 #[error("Error talking to the network could not send/receive data: {0}")]
175 #[diagnostic(code(cat_dev::net::io_error))]
176 IO(#[from] IoError),
177 #[error("Failed to list the network interfaces on your device: {0:?}.")]
179 #[diagnostic(code(cat_dev::net::list_interfaces_error))]
180 ListInterfacesFailure(NetworkInterfaceError),
181 #[error("Failure fetching local ip address: {0}")]
183 #[diagnostic(code(cat_dev::net::local_ip_failure))]
184 LocalIp(#[from] LocalIpAddressError),
185 #[error(transparent)]
187 #[diagnostic(transparent)]
188 Parse(#[from] NetworkParseError),
189 #[error("The client requested too many bytes to send over a connection at once (larger than usize::MAX on your architecture): {0}")]
191 #[diagnostic(code(cat_dev::net::requested_size_too_large))]
192 RequestedSizeTooLarge(u128),
193 #[error("Failed to set the socket we're bound on as a broadcast address, this is needed to discover CAT devices.")]
197 #[diagnostic(code(cat_dev::net::set_broadcast_failure))]
198 SetBroadcastFailure,
199 #[error("Error queueing up packet to be sent out over a conenction: {0:?}")]
201 #[diagnostic(code(cat_dev::net::send_queue_failure))]
202 SendQueueFailure(#[from] SendError<Bytes>),
203 #[error(
208 "Timed out while writing/reading data from the network, failed to send and receive data."
209 )]
210 #[diagnostic(code(cat_dev::net::timeout))]
211 Timeout(Duration),
212}
213
214impl From<ReqwestError> for CatBridgeError {
215 fn from(value: ReqwestError) -> Self {
216 Self::Network(value.into())
217 }
218}
219
220impl From<SendError<Bytes>> for CatBridgeError {
221 fn from(value: SendError<Bytes>) -> Self {
222 Self::Network(value.into())
223 }
224}
225
226#[derive(Error, Diagnostic, Debug, PartialEq, Eq)]
229pub enum NetworkParseError {
230 #[error("Failed reading c style string from packet: {0:?}")]
232 #[diagnostic(code(cat_dev::net::parse::bad_c_string))]
233 BadCString(#[from] FromBytesUntilNulError),
234 #[error("Tried to read Packet of type ({0}) from network, must be encoded exactly as [{1:02x?}], but got [{2:02x?}]")]
237 #[diagnostic(code(cat_dev::net::parse::doesnt_match_static_data))]
238 DoesntMatchStaticPayload(&'static str, &'static [u8], Bytes),
239 #[error("Reading Field {1} from Packet {0}, was not encoded correctly must be encoded as {2}")]
242 #[diagnostic(code(cat_dev::net::parse::field_encoded_incorrectly))]
243 FieldEncodedIncorrectly(&'static str, &'static str, &'static str),
244 #[error("Tried Reading Field {1} from Packet {0}. This Field requires at least {2} bytes, but only had {3}, bytes: {4:02x?}")]
247 #[diagnostic(code(cat_dev::net::parse::field_not_long_enough))]
248 FieldNotLongEnough(&'static str, &'static str, usize, usize, Bytes),
249 #[error("Tried Reading Field {1} from Packet {0}. This field is at max {2} bytes, but had {3}, bytes: {4:02x?}")]
251 #[diagnostic(code(cat_dev::net::parse::field_too_long))]
252 FieldTooLong(&'static str, &'static str, usize, usize, Bytes),
253 #[error(transparent)]
254 #[diagnostic(transparent)]
255 FSEmul(#[from] FSEmulProtocolError),
256 #[error(transparent)]
258 #[diagnostic(transparent)]
259 MION(#[from] MIONProtocolError),
260 #[error("Tried to read Packet of type ({0}) from network needs at least {1} bytes, but only got {2} bytes: {3:02x?}")]
263 #[diagnostic(code(cat_dev::net::parse::not_enough_data))]
264 NotEnoughData(&'static str, usize, usize, Bytes),
265 #[error("Unexpected Trailer for Packet `{0}` received from the network (we're not sure what do with this extra data), extra bytes: {1:02x?}")]
268 #[diagnostic(code(cat_dev::net::parse::unexpected_trailer))]
269 UnexpectedTrailer(&'static str, Bytes),
270 #[error("Data read from the network was expected to be UTF-8, but was not: {0}")]
272 #[diagnostic(code(cat_dev::net::parse::utf8_expected))]
273 Utf8Expected(#[from] FromUtf8Error),
274 #[error("Data read from a network slice was expected to be UTF-8, but was not: {0}")]
276 #[diagnostic(code(cat_dev::net::parse::utf8_expected_slice))]
277 Utf8ExpectedSlice(#[from] Utf8Error),
278}
279impl From<NetworkParseError> for CatBridgeError {
280 fn from(value: NetworkParseError) -> Self {
281 Self::Network(value.into())
282 }
283}