Skip to main content

odin_protocol/
protocol.rs

1//! Core protocol types and implementations for ODIN Protocol
2
3use 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/// Main ODIN Protocol instance for AI-to-AI communication
14#[derive(Debug)]
15pub struct OdinProtocol {
16    /// Configuration
17    config: OdinConfig,
18    /// Node identifier
19    node_id: String,
20    /// Network connections
21    connections: HashMap<String, Connection>,
22    /// Message broadcast channel
23    message_tx: broadcast::Sender<OdinMessage>,
24    /// Message receiver
25    message_rx: broadcast::Receiver<OdinMessage>,
26    /// Control channel
27    control_tx: mpsc::Sender<ControlMessage>,
28    /// Metrics collector
29    metrics: MetricsCollector,
30    /// Running state
31    is_running: bool,
32}
33
34impl OdinProtocol {
35    /// Create a new ODIN Protocol instance
36    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    /// Start the protocol instance
56    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        // Initialize network connections
65        self.initialize_network().await?;
66        
67        // Start heartbeat
68        self.start_heartbeat().await?;
69        
70        Ok(())
71    }
72    
73    /// Stop the protocol instance
74    pub async fn stop(&mut self) -> Result<()> {
75        if !self.is_running {
76            return Ok(());
77        }
78        
79        self.is_running = false;
80        
81        // Close all connections
82        for (_, mut connection) in self.connections.drain() {
83            connection.close().await?;
84        }
85        
86        self.metrics.record_shutdown();
87        Ok(())
88    }
89    
90    /// Send a message to a specific node
91    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        // Send through broadcast channel
107        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    /// Broadcast a message to all connected nodes
115    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    /// Subscribe to messages
138    pub fn subscribe_to_messages(&self) -> broadcast::Receiver<OdinMessage> {
139        self.message_tx.subscribe()
140    }
141    
142    /// Get protocol metrics
143    pub fn get_metrics(&self) -> HashMap<String, f64> {
144        self.metrics.get_metrics()
145    }
146    
147    /// Get node status
148    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    /// Initialize network connections
160    async fn initialize_network(&mut self) -> Result<()> {
161        // TODO: Implement actual network connection logic
162        // For now, create a mock connection
163        let connection = Connection::new(&self.config.network_endpoint).await?;
164        self.connections.insert("default".to_string(), connection);
165        Ok(())
166    }
167    
168    /// Start heartbeat mechanism
169    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; // Channel closed, stop heartbeat
190                }
191            }
192        });
193        
194        Ok(())
195    }
196}
197
198/// Network connection wrapper
199#[derive(Debug)]
200pub struct Connection {
201    endpoint: String,
202    is_connected: bool,
203}
204
205impl Connection {
206    /// Create a new connection
207    pub async fn new(endpoint: &str) -> Result<Self> {
208        // TODO: Implement actual WebSocket connection
209        Ok(Self {
210            endpoint: endpoint.to_string(),
211            is_connected: true,
212        })
213    }
214    
215    /// Close the connection
216    pub async fn close(&mut self) -> Result<()> {
217        self.is_connected = false;
218        Ok(())
219    }
220}
221
222/// Control messages for internal protocol management
223#[derive(Debug, Clone)]
224pub enum ControlMessage {
225    Connect(String),
226    Disconnect(String),
227    Shutdown,
228}
229
230/// Node status information
231#[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/// Trait for protocol handlers
242#[async_trait]
243pub trait ProtocolHandler: Send + Sync {
244    /// Handle incoming message
245    async fn handle_message(&self, message: &OdinMessage) -> Result<Option<OdinMessage>>;
246    
247    /// Handle connection events
248    async fn handle_connection_event(&self, event: ConnectionEvent) -> Result<()>;
249}
250
251/// Connection events
252#[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        // Send a message
301        protocol
302            .send_message("target-node", "test message", MessagePriority::Normal)
303            .await
304            .unwrap();
305        
306        // Receive the message
307        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}