flare_core/common/message/
handler.rs1use crate::common::error::Result;
6use crate::common::protocol::flare::core::commands::{
7 notification_command::Type as NotificationType, payload_command::Type as PayloadType,
8 system_command::Type as SystemType,
9};
10use crate::common::protocol::{
11 CustomCommand, Frame, NotificationCommand, PayloadCommand, SystemCommand,
12};
13use std::sync::Arc;
14use std::sync::Mutex;
15
16#[derive(Debug, Clone)]
18pub enum MessageEvent {
19 System {
21 frame: Frame,
22 command: SystemCommand,
23 command_type: SystemType,
24 },
25 Message {
27 frame: Frame,
28 command: PayloadCommand,
29 command_type: PayloadType,
30 },
31 Notification {
33 frame: Frame,
34 command: NotificationCommand,
35 command_type: NotificationType,
36 },
37 Custom {
39 frame: Frame,
40 command: CustomCommand,
41 },
42 Unknown(Frame),
44}
45
46pub trait MessageObserver: Send + Sync {
50 fn on_system_command(
52 &self,
53 frame: &Frame,
54 command: &SystemCommand,
55 command_type: SystemType,
56 ) -> Result<()> {
57 let _ = (frame, command, command_type);
58 Ok(())
59 }
60
61 fn on_message_command(
63 &self,
64 frame: &Frame,
65 command: &PayloadCommand,
66 command_type: PayloadType,
67 ) -> Result<()> {
68 let _ = (frame, command, command_type);
69 Ok(())
70 }
71
72 fn on_notification_command(
74 &self,
75 frame: &Frame,
76 command: &NotificationCommand,
77 command_type: NotificationType,
78 ) -> Result<()> {
79 let _ = (frame, command, command_type);
80 Ok(())
81 }
82
83 fn on_custom_command(&self, frame: &Frame, command: &CustomCommand) -> Result<()> {
85 let _ = (frame, command);
86 Ok(())
87 }
88
89 fn on_unknown_command(&self, frame: &Frame) -> Result<()> {
91 let _ = frame;
92 Ok(())
93 }
94}
95
96pub type ArcMessageObserver = Arc<dyn MessageObserver>;
98
99pub struct MessageHandler {
103 observers: Arc<Mutex<Vec<ArcMessageObserver>>>,
104}
105
106impl MessageHandler {
107 pub fn new() -> Self {
109 Self {
110 observers: Arc::new(Mutex::new(Vec::new())),
111 }
112 }
113
114 pub fn add_observer(&self, observer: ArcMessageObserver) {
116 if let Ok(mut observers) = self.observers.lock() {
117 observers.push(observer);
118 }
119 }
120
121 pub fn remove_observer(&self, observer: ArcMessageObserver) {
123 if let Ok(mut observers) = self.observers.lock() {
124 observers.retain(|o| !Arc::ptr_eq(o, &observer));
125 }
126 }
127
128 pub fn handle_frame(&self, frame: Frame) -> Result<MessageEvent> {
132 let event = Self::parse_frame_to_event(frame.clone())?;
133
134 let observers = self.observers.lock().map_err(|_| {
135 crate::common::error::FlareError::general_error("Failed to lock observers")
136 })?;
137
138 match &event {
139 MessageEvent::System {
140 frame,
141 command,
142 command_type,
143 } => {
144 for observer in observers.iter() {
145 if let Err(e) = observer.on_system_command(frame, command, *command_type) {
146 eprintln!("Observer error handling system command: {:?}", e);
148 }
149 }
150 }
151 MessageEvent::Message {
152 frame,
153 command,
154 command_type,
155 } => {
156 for observer in observers.iter() {
157 if let Err(e) = observer.on_message_command(frame, command, *command_type) {
158 eprintln!("Observer error handling message command: {:?}", e);
159 }
160 }
161 }
162 MessageEvent::Notification {
163 frame,
164 command,
165 command_type,
166 } => {
167 for observer in observers.iter() {
168 if let Err(e) = observer.on_notification_command(frame, command, *command_type)
169 {
170 eprintln!("Observer error handling notification command: {:?}", e);
171 }
172 }
173 }
174 MessageEvent::Custom { frame, command } => {
175 for observer in observers.iter() {
176 if let Err(e) = observer.on_custom_command(frame, command) {
177 eprintln!("Observer error handling custom command: {:?}", e);
178 }
179 }
180 }
181 MessageEvent::Unknown(frame) => {
182 for observer in observers.iter() {
183 if let Err(e) = observer.on_unknown_command(frame) {
184 eprintln!("Observer error handling unknown command: {:?}", e);
185 }
186 }
187 }
188 }
189
190 Ok(event)
191 }
192
193 fn parse_frame_to_event(frame: Frame) -> Result<MessageEvent> {
195 let command = frame.command.as_ref().ok_or_else(|| {
196 crate::common::error::FlareError::protocol_error("Frame missing command")
197 })?;
198
199 match &command.r#type {
200 Some(crate::common::protocol::flare::core::commands::command::Type::System(
201 system_cmd,
202 )) => {
203 let command_type = match system_cmd.r#type {
205 0 => SystemType::Unspecified,
206 1 => SystemType::Connect,
207 2 => SystemType::ConnectAck,
208 3 => SystemType::Close,
209 4 => SystemType::Ping,
210 5 => SystemType::Pong,
211 6 => SystemType::Error,
212 7 => SystemType::Event,
213 8 => SystemType::Auth,
214 9 => SystemType::AuthAck,
215 _ => {
216 return Err(crate::common::error::FlareError::protocol_error(
217 "Invalid system command type",
218 ));
219 }
220 };
221 Ok(MessageEvent::System {
222 frame: frame.clone(),
223 command: system_cmd.clone(),
224 command_type,
225 })
226 }
227 Some(crate::common::protocol::flare::core::commands::command::Type::Payload(
228 msg_cmd,
229 )) => {
230 let command_type = match msg_cmd.r#type {
231 0 => PayloadType::Unspecified,
232 1 => PayloadType::Message,
233 2 => PayloadType::Event,
234 3 => PayloadType::Ack,
235 4 => PayloadType::Data,
236 _ => {
237 return Err(crate::common::error::FlareError::protocol_error(
238 "Invalid payload command type",
239 ));
240 }
241 };
242 Ok(MessageEvent::Message {
243 frame: frame.clone(),
244 command: msg_cmd.clone(),
245 command_type,
246 })
247 }
248 Some(crate::common::protocol::flare::core::commands::command::Type::Notification(
249 notif_cmd,
250 )) => {
251 let command_type = match notif_cmd.r#type {
252 0 => NotificationType::System,
253 1 => NotificationType::Broadcast,
254 2 => NotificationType::Alert,
255 3 => NotificationType::User,
256 4 => NotificationType::Connection,
257 _ => {
258 return Err(crate::common::error::FlareError::protocol_error(
259 "Invalid notification command type",
260 ));
261 }
262 };
263 Ok(MessageEvent::Notification {
264 frame: frame.clone(),
265 command: notif_cmd.clone(),
266 command_type,
267 })
268 }
269 Some(crate::common::protocol::flare::core::commands::command::Type::Custom(
270 custom_cmd,
271 )) => Ok(MessageEvent::Custom {
272 frame: frame.clone(),
273 command: custom_cmd.clone(),
274 }),
275 None => Ok(MessageEvent::Unknown(frame)),
276 }
277 }
278
279 pub fn observer_count(&self) -> usize {
281 self.observers.lock().map(|obs| obs.len()).unwrap_or(0)
282 }
283}
284
285impl Default for MessageHandler {
286 fn default() -> Self {
287 Self::new()
288 }
289}
290
291#[cfg(test)]
292mod tests {
293 use super::*;
294 use crate::common::protocol::{Command, FrameBuilder, ping};
295
296 struct TestObserver {
297 system_count: Arc<Mutex<usize>>,
298 }
299
300 impl MessageObserver for TestObserver {
301 fn on_system_command(
302 &self,
303 _frame: &Frame,
304 _command: &SystemCommand,
305 _command_type: SystemType,
306 ) -> Result<()> {
307 let mut count = self.system_count.lock().unwrap();
308 *count += 1;
309 Ok(())
310 }
311 }
312
313 #[test]
314 fn test_message_handler() {
315 let handler = MessageHandler::new();
316 let observer = Arc::new(TestObserver {
317 system_count: Arc::new(Mutex::new(0)),
318 });
319 handler.add_observer(observer.clone());
320
321 let frame = FrameBuilder::new()
322 .with_command(Command {
323 r#type: Some(crate::common::protocol::command::Type::System(ping())),
324 })
325 .build();
326
327 let event = handler.handle_frame(frame).unwrap();
328 match event {
329 MessageEvent::System { .. } => {
330 let count = observer.system_count.lock().unwrap();
331 assert_eq!(*count, 1);
332 }
333 _ => panic!("Expected System event"),
334 }
335 }
336}