brainwires_network/routing/
direct.rs1use anyhow::{Result, bail};
2use async_trait::async_trait;
3
4use super::peer_table::PeerTable;
5use super::traits::{Router, RoutingStrategy};
6use crate::network::{MessageEnvelope, MessageTarget};
7use crate::transport::TransportAddress;
8
9#[derive(Debug, Default)]
14pub struct DirectRouter;
15
16impl DirectRouter {
17 pub fn new() -> Self {
19 Self
20 }
21}
22
23#[async_trait]
24impl Router for DirectRouter {
25 async fn route(
26 &self,
27 envelope: &MessageEnvelope,
28 peers: &PeerTable,
29 ) -> Result<Vec<TransportAddress>> {
30 match &envelope.recipient {
31 MessageTarget::Direct(id) => peers
32 .addresses(id)
33 .map(|addrs| addrs.to_vec())
34 .ok_or_else(|| anyhow::anyhow!("no route to peer {id}")),
35 MessageTarget::Broadcast => {
36 bail!("DirectRouter does not handle broadcast messages");
37 }
38 MessageTarget::Topic(_) => {
39 bail!("DirectRouter does not handle topic messages");
40 }
41 }
42 }
43
44 fn strategy(&self) -> RoutingStrategy {
45 RoutingStrategy::Direct
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52 use crate::identity::AgentIdentity;
53 use crate::network::Payload;
54 use uuid::Uuid;
55
56 #[tokio::test]
57 async fn direct_routes_to_known_peer() {
58 let router = DirectRouter::new();
59 let mut peers = PeerTable::new();
60
61 let identity = AgentIdentity::new("target");
62 let target_id = identity.id;
63 let addr = TransportAddress::Tcp("127.0.0.1:9090".parse().unwrap());
64 peers.upsert(identity, vec![addr.clone()]);
65
66 let env = MessageEnvelope::direct(Uuid::new_v4(), target_id, Payload::Text("hello".into()));
67
68 let addrs = router.route(&env, &peers).await.unwrap();
69 assert_eq!(addrs, vec![addr]);
70 }
71
72 #[tokio::test]
73 async fn direct_fails_for_unknown_peer() {
74 let router = DirectRouter::new();
75 let peers = PeerTable::new();
76
77 let env = MessageEnvelope::direct(
78 Uuid::new_v4(),
79 Uuid::new_v4(),
80 Payload::Text("hello".into()),
81 );
82
83 let result = router.route(&env, &peers).await;
84 assert!(result.is_err());
85 }
86
87 #[tokio::test]
88 async fn direct_rejects_broadcast() {
89 let router = DirectRouter::new();
90 let peers = PeerTable::new();
91
92 let env = MessageEnvelope::broadcast(Uuid::new_v4(), Payload::Text("hello".into()));
93 let result = router.route(&env, &peers).await;
94 assert!(result.is_err());
95 }
96}