1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::time::{SystemTime, UNIX_EPOCH};
6use tokio::sync::{broadcast, mpsc};
7use async_trait::async_trait;
8use crate::{Result, OdinError};
9use crate::message::{OdinMessage, MessageType, MessagePriority};
10use crate::config::OdinConfig;
11use crate::metrics::MetricsCollector;
12
13#[derive(Debug)]
15pub struct OdinProtocol {
16 config: OdinConfig,
18 node_id: String,
20 connections: HashMap<String, Connection>,
22 message_tx: broadcast::Sender<OdinMessage>,
24 message_rx: broadcast::Receiver<OdinMessage>,
26 control_tx: mpsc::Sender<ControlMessage>,
28 metrics: MetricsCollector,
30 is_running: bool,
32}
33
34impl OdinProtocol {
35 pub fn new(config: OdinConfig) -> Result<Self> {
37 config.validate()?;
38
39 let (message_tx, message_rx) = broadcast::channel(1024);
40 let (control_tx, _control_rx) = mpsc::channel(256);
41 let metrics = MetricsCollector::new();
42
43 Ok(Self {
44 node_id: config.node_id.clone(),
45 config,
46 connections: HashMap::new(),
47 message_tx,
48 message_rx,
49 control_tx,
50 metrics,
51 is_running: false,
52 })
53 }
54
55 pub async fn start(&mut self) -> Result<()> {
57 if self.is_running {
58 return Err(OdinError::Protocol("Protocol already running".to_string()));
59 }
60
61 self.is_running = true;
62 self.metrics.record_startup();
63
64 self.initialize_network().await?;
66
67 self.start_heartbeat().await?;
69
70 Ok(())
71 }
72
73 pub async fn stop(&mut self) -> Result<()> {
75 if !self.is_running {
76 return Ok(());
77 }
78
79 self.is_running = false;
80
81 for (_, mut connection) in self.connections.drain() {
83 connection.close().await?;
84 }
85
86 self.metrics.record_shutdown();
87 Ok(())
88 }
89
90 pub async fn send_message(&self, target_node: &str, content: &str, priority: MessagePriority) -> Result<String> {
92 if !self.is_running {
93 return Err(OdinError::Protocol("Protocol not running".to_string()));
94 }
95
96 let message = OdinMessage::new(
97 MessageType::Standard,
98 &self.node_id,
99 target_node,
100 content,
101 priority,
102 );
103
104 self.metrics.record_message_sent();
105
106 self.message_tx.send(message.clone()).map_err(|e| {
108 OdinError::Network(format!("Failed to send message: {}", e))
109 })?;
110
111 Ok(message.id.clone())
112 }
113
114 pub async fn broadcast_message(&self, content: &str, priority: MessagePriority) -> Result<String> {
116 if !self.is_running {
117 return Err(OdinError::Protocol("Protocol not running".to_string()));
118 }
119
120 let message = OdinMessage::new(
121 MessageType::Broadcast,
122 &self.node_id,
123 "all",
124 content,
125 priority,
126 );
127
128 self.metrics.record_broadcast_sent();
129
130 self.message_tx.send(message.clone()).map_err(|e| {
131 OdinError::Network(format!("Failed to broadcast message: {}", e))
132 })?;
133
134 Ok(message.id.clone())
135 }
136
137 pub fn subscribe_to_messages(&self) -> broadcast::Receiver<OdinMessage> {
139 self.message_tx.subscribe()
140 }
141
142 pub fn get_metrics(&self) -> HashMap<String, f64> {
144 self.metrics.get_metrics()
145 }
146
147 pub fn get_status(&self) -> NodeStatus {
149 NodeStatus {
150 node_id: self.node_id.clone(),
151 is_running: self.is_running,
152 connection_count: self.connections.len(),
153 uptime: self.metrics.get_uptime(),
154 messages_sent: self.metrics.get_messages_sent(),
155 messages_received: self.metrics.get_messages_received(),
156 }
157 }
158
159 async fn initialize_network(&mut self) -> Result<()> {
161 let connection = Connection::new(&self.config.network_endpoint).await?;
164 self.connections.insert("default".to_string(), connection);
165 Ok(())
166 }
167
168 async fn start_heartbeat(&self) -> Result<()> {
170 let interval = self.config.heartbeat_interval;
171 let tx = self.message_tx.clone();
172 let node_id = self.node_id.clone();
173
174 tokio::spawn(async move {
175 let mut interval_timer = tokio::time::interval(interval);
176
177 loop {
178 interval_timer.tick().await;
179
180 let heartbeat = OdinMessage::new(
181 MessageType::Heartbeat,
182 &node_id,
183 "all",
184 "heartbeat",
185 MessagePriority::Low,
186 );
187
188 if tx.send(heartbeat).is_err() {
189 break; }
191 }
192 });
193
194 Ok(())
195 }
196}
197
198#[derive(Debug)]
200pub struct Connection {
201 endpoint: String,
202 is_connected: bool,
203}
204
205impl Connection {
206 pub async fn new(endpoint: &str) -> Result<Self> {
208 Ok(Self {
210 endpoint: endpoint.to_string(),
211 is_connected: true,
212 })
213 }
214
215 pub async fn close(&mut self) -> Result<()> {
217 self.is_connected = false;
218 Ok(())
219 }
220}
221
222#[derive(Debug, Clone)]
224pub enum ControlMessage {
225 Connect(String),
226 Disconnect(String),
227 Shutdown,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct NodeStatus {
233 pub node_id: String,
234 pub is_running: bool,
235 pub connection_count: usize,
236 pub uptime: f64,
237 pub messages_sent: u64,
238 pub messages_received: u64,
239}
240
241#[async_trait]
243pub trait ProtocolHandler: Send + Sync {
244 async fn handle_message(&self, message: &OdinMessage) -> Result<Option<OdinMessage>>;
246
247 async fn handle_connection_event(&self, event: ConnectionEvent) -> Result<()>;
249}
250
251#[derive(Debug, Clone)]
253pub enum ConnectionEvent {
254 Connected(String),
255 Disconnected(String),
256 Error(String, String),
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262 use crate::config::OdinConfig;
263 use tokio::time::{timeout, Duration};
264
265 #[tokio::test]
266 async fn test_protocol_creation() {
267 let config = OdinConfig::default();
268 let protocol = OdinProtocol::new(config).unwrap();
269
270 assert!(!protocol.is_running);
271 assert_eq!(protocol.connections.len(), 0);
272 }
273
274 #[tokio::test]
275 async fn test_message_sending() {
276 let config = OdinConfig::default();
277 let mut protocol = OdinProtocol::new(config).unwrap();
278
279 protocol.start().await.unwrap();
280
281 let message_id = protocol
282 .send_message("target-node", "test message", MessagePriority::Normal)
283 .await
284 .unwrap();
285
286 assert!(!message_id.is_empty());
287
288 protocol.stop().await.unwrap();
289 }
290
291 #[tokio::test]
292 async fn test_message_subscription() {
293 let config = OdinConfig::default();
294 let mut protocol = OdinProtocol::new(config).unwrap();
295
296 protocol.start().await.unwrap();
297
298 let mut rx = protocol.subscribe_to_messages();
299
300 protocol
302 .send_message("target-node", "test message", MessagePriority::Normal)
303 .await
304 .unwrap();
305
306 let received = timeout(Duration::from_millis(100), rx.recv()).await;
308 assert!(received.is_ok());
309
310 let message = received.unwrap().unwrap();
311 assert_eq!(message.content, "test message");
312 assert_eq!(message.target_node, "target-node");
313
314 protocol.stop().await.unwrap();
315 }
316
317 #[tokio::test]
318 async fn test_protocol_status() {
319 let config = OdinConfig::default();
320 let protocol = OdinProtocol::new(config).unwrap();
321
322 let status = protocol.get_status();
323 assert!(!status.is_running);
324 assert_eq!(status.connection_count, 0);
325 assert_eq!(status.messages_sent, 0);
326 }
327}