skua_voice/driver/connection/
error.rs1use crate::{
4 driver::tasks::{error::Recipient, message::*},
5 ws::Error as WsError,
6};
7use crypto_secretbox::Error as CryptoError;
8use flume::SendError;
9use serde_json::Error as JsonError;
10use std::{error::Error as StdError, fmt, io::Error as IoError};
11use tokio::time::error::Elapsed;
12
13#[derive(Debug)]
15#[non_exhaustive]
16pub enum Error {
17 AttemptDiscarded,
20 Crypto(CryptoError),
22 CryptoInvalidLength,
24 CryptoModeInvalid,
26 CryptoModeUnavailable,
28 EndpointUrl,
30 IllegalDiscoveryResponse,
32 IllegalIp,
34 Io(IoError),
36 Json(JsonError),
38 InterconnectFailure(Recipient),
40 Ws(WsError),
42 TimedOut,
44}
45
46impl From<CryptoError> for Error {
47 fn from(e: CryptoError) -> Self {
48 Error::Crypto(e)
49 }
50}
51
52impl From<IoError> for Error {
53 fn from(e: IoError) -> Error {
54 Error::Io(e)
55 }
56}
57
58impl From<JsonError> for Error {
59 fn from(e: JsonError) -> Error {
60 Error::Json(e)
61 }
62}
63
64impl From<SendError<WsMessage>> for Error {
65 fn from(_e: SendError<WsMessage>) -> Error {
66 Error::InterconnectFailure(Recipient::AuxNetwork)
67 }
68}
69
70impl From<SendError<EventMessage>> for Error {
71 fn from(_e: SendError<EventMessage>) -> Error {
72 Error::InterconnectFailure(Recipient::Event)
73 }
74}
75
76impl From<SendError<MixerMessage>> for Error {
77 fn from(_e: SendError<MixerMessage>) -> Error {
78 Error::InterconnectFailure(Recipient::Mixer)
79 }
80}
81
82impl From<WsError> for Error {
83 fn from(e: WsError) -> Error {
84 Error::Ws(e)
85 }
86}
87
88impl From<Elapsed> for Error {
89 fn from(_e: Elapsed) -> Error {
90 Error::TimedOut
91 }
92}
93
94impl fmt::Display for Error {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 write!(f, "failed to connect to Discord RTP server: ")?;
97 match self {
98 Self::AttemptDiscarded => write!(f, "connection attempt was aborted/discarded"),
99 Self::Crypto(e) => e.fmt(f),
100 Self::CryptoInvalidLength => write!(f, "server supplied key of wrong length"),
101 Self::CryptoModeInvalid => write!(f, "server changed negotiated encryption mode"),
102 Self::CryptoModeUnavailable => write!(f, "server did not offer chosen encryption mode"),
103 Self::EndpointUrl => write!(f, "endpoint URL received from gateway was invalid"),
104 Self::IllegalDiscoveryResponse =>
105 write!(f, "IP discovery/NAT punching response was invalid"),
106 Self::IllegalIp => write!(f, "IP discovery/NAT punching response had bad IP value"),
107 Self::Io(e) => e.fmt(f),
108 Self::Json(e) => e.fmt(f),
109 Self::InterconnectFailure(e) => write!(f, "failed to contact other task ({e:?})"),
110 Self::Ws(e) => write!(f, "websocket issue ({e:?})."),
111 Self::TimedOut => write!(f, "connection attempt timed out"),
112 }
113 }
114}
115
116impl StdError for Error {
117 fn source(&self) -> Option<&(dyn StdError + 'static)> {
118 match self {
119 Error::AttemptDiscarded
120 | Error::CryptoInvalidLength
121 | Error::CryptoModeInvalid
122 | Error::CryptoModeUnavailable
123 | Error::EndpointUrl
124 | Error::IllegalDiscoveryResponse
125 | Error::IllegalIp
126 | Error::InterconnectFailure(_)
127 | Error::Ws(_)
128 | Error::TimedOut => None,
129 Error::Crypto(e) => e.source(),
130 Error::Io(e) => e.source(),
131 Error::Json(e) => e.source(),
132 }
133 }
134}
135
136pub type Result<T> = std::result::Result<T, Error>;