1use rings_core::dht::Did;
3
4use crate::onion::OnionProxyTargetError;
5use crate::onion::OnionRouteError;
6use crate::prelude::rings_core;
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum OnionQueueKind {
11 RelayControl,
13 CircuitData,
15}
16
17impl OnionQueueKind {
18 pub(crate) const fn admission(self, peer: Did, reason: OnionQueueAdmissionReason) -> Error {
20 Error::OnionQueueAdmission {
21 queue: self,
22 peer,
23 reason,
24 }
25 }
26}
27
28#[derive(Clone, Copy, Debug, Eq, PartialEq)]
30pub enum OnionQueueAdmissionReason {
31 GlobalFull,
33 PeerFull,
35 CounterOverflow,
37}
38
39pub type Result<T> = std::result::Result<T, Error>;
41
42#[derive(Debug, thiserror::Error)]
46#[non_exhaustive]
47#[repr(u32)]
48pub enum Error {
49 #[error("Connect remote rpc server failed: {0}.")]
51 RemoteRpcError(String) = 100,
52 #[error("Unknown rpc error.")]
54 UnknownRpcError = 101,
55 #[error("Internal rpc services error: {0}.")]
57 InternalRpcError(#[from] jsonrpc_core::Error) = 102,
58 #[error("Uuid error: {0}")]
60 UuidError(#[from] uuid::Error) = 103,
61 #[error("Connection not found.")]
63 ConnectionNotFound = 203,
64 #[error("Create connection error: {0}.")]
66 NewConnectionError(rings_core::error::Error) = 204,
67 #[error("Close connection error: {0}.")]
69 CloseConnectionError(rings_core::error::Error) = 205,
70 #[error("Invalid connection id.")]
72 InvalidConnectionId = 206,
73 #[error("Create offer info failed: {0}.")]
75 CreateOffer(rings_core::error::Error) = 207,
76 #[error("Answer offer info failed: {0}.")]
78 AnswerOffer(rings_core::error::Error) = 208,
79 #[error("Accept answer info failed: {0}.")]
81 AcceptAnswer(rings_core::error::Error) = 209,
82 #[error("Decode error.")]
84 DecodeError = 300,
85 #[error("Encode error.")]
87 EncodeError = 301,
88 #[error("WASM compile error: {0}")]
90 WasmCompileError(String) = 400,
91 #[error("BackendMessage RwLock Error")]
93 WasmBackendMessageRwLockError = 401,
94 #[error("WASM instantiation error.")]
96 WasmInstantiationError = 402,
97 #[error("WASM export error.")]
99 WasmExportError = 403,
100 #[error("WASM runtime error: {0}")]
102 WasmRuntimeError(String) = 404,
103 #[error("WASM global memory mutex error.")]
105 WasmGlobalMemoryLockError = 405,
106 #[error("WASM failed to load file.")]
108 WasmFailedToLoadFile = 406,
109 #[error("Invalid did: {0}")]
111 InvalidDid(String) = 500,
112 #[error("Invalid method.")]
114 InvalidMethod = 501,
115 #[error("Internal error: {0}.")]
117 InternalError(rings_core::error::Error) = 502,
118 #[error("No Permission")]
120 NoPermission = 504,
121 #[error("Connect error, {0}")]
123 ConnectError(rings_core::error::Error) = 600,
124 #[error("Send message error: {0}")]
126 SendMessage(rings_core::error::Error) = 601,
127 #[error("entry action error: {0}")]
129 EntryError(rings_core::error::Error) = 603,
130 #[error("service register action error: {0}")]
132 ServiceRegisterError(rings_core::error::Error) = 604,
133 #[error("JsError: {0}")]
135 JsError(String) = 700,
136 #[error("Invalid message")]
138 InvalidMessage = 800,
139 #[error("Invalid http request: {0}")]
141 HttpRequestError(String) = 801,
142 #[error("Invalid data")]
144 InvalidData = 802,
145 #[error("Invalid service")]
147 InvalidService = 803,
148 #[error("Invalid address")]
150 InvalidAddress = 804,
151 #[error("Invalid auth data")]
153 InvalidAuthData = 805,
154 #[error("invalid headers")]
156 InvalidHeaders = 806,
157 #[error("Storage Error: {0}")]
159 Storage(rings_core::error::Error) = 807,
160 #[error("Swarm Error: {0}")]
162 Swarm(rings_core::error::Error) = 808,
163 #[error("Invalid logging level: {0}")]
165 InvalidLoggingLevel(String) = 809,
166 #[error("Invalid WebRTC UDP port range: {0}")]
168 InvalidWebrtcUdpPortRange(#[from] rings_transport::webrtc_config::WebrtcUdpPortRangeError) =
169 810,
170 #[error("Both webrtc_udp_port_min and webrtc_udp_port_max must be set together: min={min:?}, max={max:?}")]
172 IncompleteWebrtcUdpPortRange {
173 min: Option<u16>,
175 max: Option<u16>,
177 } = 811,
178 #[error("Invalid configuration: {0}")]
180 InvalidConfig(String) = 812,
181 #[error("Open browser storage \"{name}\" failed: {source}")]
183 BrowserStorageOpen {
184 name: String,
186 source: rings_core::error::Error,
188 } = 814,
189 #[error("registration task stopped")]
191 RegistrationStopped = 815,
192 #[error("Measurement runtime error: {0}")]
194 MeasurementRuntime(#[from] crate::measure::MeasureRuntimeError) = 816,
195 #[error("Create File Error: {0}")]
197 CreateFileError(String) = 900,
198 #[error("Open File Error: {0}")]
200 OpenFileError(String) = 901,
201 #[error("Acquire lock failed")]
203 Lock = 902,
204 #[error("Cannot find home directory")]
206 HomeDirError = 903,
207 #[error("Cannot find parent directory")]
209 ParentDirError = 904,
210 #[error("Path is not valid UTF-8: {0}")]
212 PathUtf8Error(String) = 905,
213 #[error("Serde json error: {0}")]
215 SerdeJsonError(#[from] serde_json::Error) = 1000,
216 #[error("Serde yaml error: {0}")]
218 SerdeYamlError(#[from] serde_yaml::Error) = 1001,
219 #[error("verify error: {0}")]
221 VerifyError(String) = 1002,
222 #[error("Core error: {0}")]
224 CoreError(#[from] rings_core::error::Error) = 1102,
225 #[error("External singer error: {0}")]
227 ExternalError(String) = 1202,
228 #[error("An error indicating that an interior nul byte was found: {0}")]
230 FFINulError(#[from] std::ffi::NulError) = 1203,
231 #[error("Failed to convert CStr to String: {0}")]
233 FFICStrError(#[from] std::str::Utf8Error) = 1204,
234 #[error("An error indicating that a ptr is null")]
236 FFINulPtrError = 1205,
237 #[error("Failed to convert bytes to String: {0}")]
239 FFIFromUtf8Error(#[from] std::string::FromUtf8Error) = 1206,
240 #[error("Extend Backend Error {0}")]
242 BackendError(String) = 1501,
243 #[error("Extension error: {0}")]
245 ExtensionError(String) = 1502,
246 #[error("Detached extension task closed before publishing its result")]
248 DetachedExtensionTaskClosed = 1503,
249 #[error("Onion route error: {0}")]
251 OnionRouteError(OnionRouteError) = 1601,
252 #[error("Onion proxy IO error: {0}")]
254 OnionProxyIoError(String) = 1602,
255 #[error("Onion proxy request timed out")]
257 OnionProxyRequestTimedOut = 1603,
258 #[error("{queue:?} queue rejected peer {peer}: {reason:?}")]
260 OnionQueueAdmission {
261 queue: OnionQueueKind,
263 peer: Did,
265 reason: OnionQueueAdmissionReason,
267 } = 1604,
268 #[error("Invalid onion proxy target: {0}")]
270 OnionProxyTarget(#[from] OnionProxyTargetError) = 1605,
271 #[error("Failed to resolve onion target {authority:?}: {source}")]
273 OnionTargetResolve {
274 authority: String,
276 source: std::io::Error,
278 } = 1606,
279 #[error("Onion target {authority:?} resolved no addresses")]
281 OnionTargetResolvedEmpty {
282 authority: String,
284 } = 1607,
285}
286
287impl Error {
288 fn discriminant(&self) -> u32 {
289 unsafe { *<*const _>::from(self).cast::<u32>() }
299 }
300
301 pub fn code(&self) -> u32 {
303 self.discriminant()
304 }
305}
306
307impl From<Error> for jsonrpc_core::Error {
308 fn from(e: Error) -> Self {
309 Self {
310 code: jsonrpc_core::ErrorCode::ServerError(e.code().into()),
311 message: e.to_string(),
312 data: None,
313 }
314 }
315}
316
317impl From<rings_rpc::error::Error> for Error {
318 fn from(e: rings_rpc::error::Error) -> Self {
319 match e {
320 rings_rpc::error::Error::InvalidMethod => Error::InvalidMethod,
321 rings_rpc::error::Error::RpcError(v) => Error::RemoteRpcError(v.to_string()),
322 rings_rpc::error::Error::InvalidSignature => Error::InvalidData,
323 rings_rpc::error::Error::InvalidHeaders => Error::InvalidHeaders,
324 _ => Error::UnknownRpcError,
325 }
326 }
327}
328
329#[cfg(all(feature = "browser", target_family = "wasm"))]
330impl From<Error> for wasm_bindgen::JsValue {
331 fn from(err: Error) -> Self {
332 wasm_bindgen::JsValue::from_str(&err.to_string())
333 }
334}
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339 #[test]
340 fn test_error_code() {
341 let err = Error::RemoteRpcError("Test".to_string());
342 assert_eq!(err.code(), 100);
343 }
344}