Skip to main content

tap_node/message/
router.rs

1//! PlainMessage routing implementation.
2//!
3//! This module provides message routing capabilities for the TAP Node.
4
5use log::debug;
6use std::sync::Arc;
7use tap_agent::Agent;
8use tap_msg::didcomm::PlainMessage;
9
10use crate::agent::AgentRegistry;
11use crate::error::{Error, Result};
12use crate::message::PlainMessageRouter;
13
14/// Default implementation of PlainMessageRouter
15#[derive(Debug, Clone)]
16pub struct DefaultPlainMessageRouter {
17    /// Registry of agents
18    agents: Option<Arc<AgentRegistry>>,
19}
20
21impl Default for DefaultPlainMessageRouter {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27impl DefaultPlainMessageRouter {
28    /// Create a new default message router
29    pub fn new() -> Self {
30        Self { agents: None }
31    }
32
33    /// Set the agent registry
34    pub fn with_agents(mut self, agents: Arc<AgentRegistry>) -> Self {
35        self.agents = Some(agents);
36        self
37    }
38}
39
40impl PlainMessageRouter for DefaultPlainMessageRouter {
41    fn route_message_impl(&self, message: &PlainMessage) -> Result<String> {
42        // Check if the message has a "to" field
43        if !message.to.is_empty() {
44            {
45                // Check if the first to DID exists in our registry
46                let to_did = message.to[0].clone();
47
48                // If we have an agent registry, check if the agent exists
49                if let Some(agents) = &self.agents {
50                    if agents.has_agent(&to_did) {
51                        debug!("Routing message to: {}", to_did);
52                        return Ok(to_did);
53                    }
54                } else {
55                    // If we don't have an agent registry, just return the first DID
56                    debug!("No agent registry available, routing to: {}", to_did);
57                    return Ok(to_did);
58                }
59            }
60        }
61
62        // If we get here, we couldn't route the message
63        Err(Error::Dispatch(format!(
64            "No route found for message: {}",
65            message.id
66        )))
67    }
68}
69
70/// Composite message router that can delegate to multiple routers
71#[derive(Debug, Default)]
72pub struct CompositePlainMessageRouter {
73    /// The routers to use, in order
74    routers: Vec<crate::message::PlainMessageRouterType>,
75}
76
77impl CompositePlainMessageRouter {
78    /// Create a new composite router
79    pub fn new() -> Self {
80        Self::default()
81    }
82
83    /// Add a router to the chain
84    pub fn add_router(&mut self, router: crate::message::PlainMessageRouterType) {
85        self.routers.push(router);
86    }
87}
88
89impl PlainMessageRouter for CompositePlainMessageRouter {
90    fn route_message_impl(&self, message: &PlainMessage) -> Result<String> {
91        // Try each router in sequence
92        for router in &self.routers {
93            match router {
94                crate::message::PlainMessageRouterType::Default(r) => {
95                    match r.route_message_impl(message) {
96                        Ok(target) => return Ok(target),
97                        Err(_) => continue, // Try the next router
98                    }
99                }
100                crate::message::PlainMessageRouterType::IntraNode(r) => {
101                    match r.route_message_impl(message) {
102                        Ok(target) => return Ok(target),
103                        Err(_) => continue, // Try the next router
104                    }
105                }
106            }
107        }
108
109        // If we get here, no router could handle the message
110        Err(Error::Dispatch(format!(
111            "No route found for message: {}",
112            message.id
113        )))
114    }
115}
116
117/// Intra-node router that handles routing between local agents
118#[derive(Debug, Clone)]
119pub struct IntraNodePlainMessageRouter {
120    /// Registry of agents
121    agents: Option<Arc<AgentRegistry>>,
122}
123
124impl Default for IntraNodePlainMessageRouter {
125    fn default() -> Self {
126        Self::new()
127    }
128}
129
130impl IntraNodePlainMessageRouter {
131    /// Create a new intra-node router
132    pub fn new() -> Self {
133        Self { agents: None }
134    }
135
136    /// Set the agent registry
137    pub fn with_agents(mut self, agents: Arc<AgentRegistry>) -> Self {
138        self.agents = Some(agents);
139        self
140    }
141
142    /// Route a message to local agents if possible
143    async fn route_to_local_agents(&self, message: &PlainMessage) -> Result<Vec<String>> {
144        let mut local_recipients = Vec::new();
145
146        if let Some(agents) = &self.agents {
147            // Check each recipient to see if they're local
148            for recipient in &message.to {
149                if agents.has_agent(recipient) {
150                    local_recipients.push(recipient.clone());
151                }
152            }
153        }
154
155        Ok(local_recipients)
156    }
157
158    /// Send message to local agents
159    pub async fn deliver_to_local_agents(&self, message: &PlainMessage) -> Result<()> {
160        if let Some(agents) = &self.agents {
161            let local_recipients = self.route_to_local_agents(message).await?;
162
163            for recipient_did in local_recipients {
164                if let Ok(agent) = agents.get_agent(&recipient_did).await {
165                    // Send message to local agent
166                    if let Err(e) = agent.receive_plain_message(message.clone()).await {
167                        log::warn!(
168                            "Failed to deliver message {} to local agent {}: {}",
169                            message.id,
170                            recipient_did,
171                            e
172                        );
173                    } else {
174                        log::debug!(
175                            "Delivered message {} to local agent {}",
176                            message.id,
177                            recipient_did
178                        );
179                    }
180                }
181            }
182        }
183
184        Ok(())
185    }
186}
187
188impl PlainMessageRouter for IntraNodePlainMessageRouter {
189    fn route_message_impl(&self, message: &PlainMessage) -> Result<String> {
190        // This router prioritizes local agents
191        if let Some(agents) = &self.agents {
192            for recipient in &message.to {
193                if agents.has_agent(recipient) {
194                    debug!("Routing message to local agent: {}", recipient);
195                    return Ok(recipient.clone());
196                }
197            }
198        }
199
200        // If no local agents found, fall back to external routing
201        Err(Error::Dispatch(format!(
202            "No local agents found for message: {}",
203            message.id
204        )))
205    }
206}