1use slim_datapath::api::ProtoName;
5use slim_datapath::errors::{ErrorPayload, MessageContext};
6use thiserror::Error;
8
9use slim_auth::errors::AuthError;
11use slim_datapath::api::{ProtoMessage, ProtoSessionMessageType, ProtoSessionType};
12use slim_datapath::messages::utils::MessageError;
13use slim_mls::errors::MlsError;
14use tonic::Status;
15
16use crate::SessionMessage;
17use crate::subscription_manager::SubscriptionAckError;
18
19#[derive(Error, Debug)]
20pub enum SessionError {
21 #[error("SLIM channel closed")]
23 SlimChannelClosed,
24 #[error("error receiving message from SLIM")]
25 SlimReception(#[from] Status),
26
27 #[error("message error")]
29 MessageError(#[from] MessageError),
30 #[error("missing removed participant in GroupRemove message")]
31 MissingRemovedParticipantInGroupRemove,
32 #[error("missing group name in JoinRequest message")]
33 MissingGroupNameInJoinRequest,
34 #[error("ping state not initialized")]
35 PingStateNotInitialized,
36 #[error("missing channel name for group session")]
37 MissingChannelName,
38 #[error("session type unknown: {0:?}")]
39 SessionTypeUnknown(ProtoSessionType),
40 #[error("session message type unexpected: {0:?}")]
41 SessionMessageInternalUnexpected(Box<SessionMessage>),
42 #[error("session message type unknown: {0:?}")]
43 SessionMessageTypeUnknown(ProtoSessionMessageType),
44 #[error("message type unexpected: {0:?}")]
45 MessageTypeUnexpected(Box<ProtoMessage>),
46 #[error("session message type unexpected: {0:?}")]
47 SessionMessageTypeUnexpected(ProtoSessionMessageType),
48 #[error("error getting the participants list")]
49 ParticipantsListQueryFailed,
50 #[error("malformed participant settings")]
51 MalformedParticipant,
52 #[error("missing participant settings")]
53 MissingParticipantSettings,
54 #[error("unexpected error")]
55 UnexpectedError { source: Box<SessionError> },
56
57 #[error("session not found: {0}")]
59 SessionNotFound(u32),
60 #[error("subscription not found: {0}")]
61 SubscriptionNotFound(ProtoName),
62
63 #[error("session builder: not all required fields set")]
65 SessionBuilderIncomplete,
66 #[error("message lost for session id: {0}")]
67 MessageLost(u32),
68 #[error("session closed")]
69 SessionClosed,
70 #[error("receive timeout waiting for message")]
71 ReceiveTimeout,
72 #[error("session id already used: {0}")]
73 SessionIdAlreadyUsed(u32),
74 #[error("invalid session id: {0}")]
75 InvalidSessionId(u32),
76
77 #[error("mls operation error")]
79 MlsOp(#[from] MlsError),
80
81 #[error("auth error")]
83 Auth(#[from] AuthError),
84
85 #[error("error receiving ack for message: {0}")]
87 AckReception(String),
88 #[error("subscription ack failed: {0}")]
89 SubscriptionAckFailed(#[source] SubscriptionAckError),
90 #[error("unknown destination: {0}")]
91 UnknownDestination(ProtoName),
92
93 #[error("participant not found in group: {0}")]
95 ParticipantNotFound(ProtoName),
96 #[error("participant already in group: {0}")]
97 ParticipantAlreadyInGroup(ProtoName),
98 #[error("cannot invite participant to point-to-point session")]
99 CannotInviteToP2P,
100 #[error("cannot remove participant from point-to-point session")]
101 CannotRemoveFromP2P,
102 #[error("only initiator can modify participants")]
103 NotInitiator,
104
105 #[error("error sending session internal message to session controller")]
107 SessionControllerSendFailed,
108 #[error("error sending new session notification to app")]
109 NewSessionSendFailed,
110 #[error("error sending session delete message to session layer")]
111 SessionDeleteMessageSendFailed,
112 #[error("error sending data message to application")]
113 ApplicationMessageSendFailed,
114 #[error("error sending data message to slim")]
115 SlimMessageSendFailed,
116 #[error("send failure reported from slim: {ctx}")]
117 SlimSendFailure { ctx: Box<ErrorPayload> },
118
119 #[error("session is draining - drop message")]
121 SessionDrainingDrop,
122 #[error("session already closed")]
123 SessionAlreadyClosed,
124 #[error("session cleanup failed: {details}")]
125 SessionCleanupFailed { details: String },
126 #[error("message send retries exhausted for id={id}")]
127 MessageSendRetryFailed { id: u32 },
128 #[error("message receive retries exhausted for id={id}")]
129 MessageReceiveRetryFailed { id: u32 },
130 #[error("session sender is shutdown, cannot send messages")]
131 SessionSenderShutdown,
132 #[error("session receiver is shutdown, cannot receive messages")]
133 SessionReceiverShutdown,
134 #[error("missing participant name on timer")]
135 MissingParticipantNameOnTimer,
136
137 #[error("missing payload: {context}")]
139 MissingPayload { context: &'static str },
140 #[error("message build failed: {0}")]
141 MessageBuild(MessageError),
142 #[error("message payload extract failed in {context}: {source}")]
143 PayloadExtract {
144 context: &'static str,
145 source: MessageError,
146 },
147
148 #[error("missing mls payload in welcome message")]
150 WelcomeMessageMissingMlsPayload,
151 #[error("invalid join request payload")]
152 InvalidJoinRequestPayload,
153 #[error("participant disconnected: {0}")]
154 ParticipantDisconnected(ProtoName),
155 #[error("missing participant name on disconnection event")]
156 MissingParticipantNameOnDisconnection,
157
158 #[error("no pending requests for the given key: {0}")]
160 TimerNotFound(u32),
161 #[error("phase not supported for task")]
162 ModeratorTaskUnsupportedPhase,
163 #[error("unexpected timer id: {0}")]
164 ModeratorTaskUnexpectedTimerId(u32),
165 #[error("failed to add participant to session")]
166 ModeratorTaskAddFailed { source: Box<SessionError> },
167 #[error("failed to remove participant from session")]
168 ModeratorTaskRemoveFailed { source: Box<SessionError> },
169 #[error("failed to update session")]
170 ModeratorTaskUpdateFailed { source: Box<SessionError> },
171 #[error("failed to close session")]
172 ModeratorTaskCloseFailed { source: Box<SessionError> },
173}
174
175impl SessionError {
176 pub fn build_error(err: MessageError) -> Self {
178 SessionError::MessageBuild(err)
179 }
180 pub fn extract_error(context: &'static str, err: MessageError) -> Self {
181 SessionError::PayloadExtract {
182 context,
183 source: err,
184 }
185 }
186 pub fn cleanup_failed<E: std::fmt::Display>(e: E) -> Self {
187 SessionError::SessionCleanupFailed {
188 details: e.to_string(),
189 }
190 }
191
192 pub fn send_retry_failed(id: u32) -> Self {
194 SessionError::MessageSendRetryFailed { id }
195 }
196
197 pub fn receive_retry_failed(id: u32) -> Self {
198 SessionError::MessageReceiveRetryFailed { id }
199 }
200
201 pub fn session_context(&self) -> Option<&MessageContext> {
204 match self {
205 SessionError::SlimSendFailure { ctx } => ctx.session_context.as_ref(),
206 _ => None,
207 }
208 }
209
210 pub fn is_command_message_error(&self) -> bool {
212 self.session_context()
213 .map(|ctx| ctx.get_session_message_type().is_command_message())
214 .unwrap_or(false)
215 }
216}