1#![allow(clippy::bool_assert_comparison)]
2
3use atm0s_sdn_identity::{NodeId, NodeIdType};
4pub mod core;
5pub mod shadow;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub enum ServiceBroadcastLevel {
9 Global,
10 Geo1,
11 Geo2,
12 Group,
13}
14
15impl ServiceBroadcastLevel {
16 pub fn same_level(&self, node1: NodeId, node2: NodeId) -> bool {
17 match self {
18 ServiceBroadcastLevel::Global => true,
19 ServiceBroadcastLevel::Geo1 => node1.geo1() == node2.geo1(),
20 ServiceBroadcastLevel::Geo2 => node1.geo1() == node2.geo1() && node1.geo2() == node2.geo2(),
21 ServiceBroadcastLevel::Group => node1.geo1() == node2.geo1() && node1.geo2() == node2.geo2() && node1.group() == node2.group(),
22 }
23 }
24}
25
26impl From<ServiceBroadcastLevel> for u8 {
27 fn from(val: ServiceBroadcastLevel) -> Self {
28 match val {
29 ServiceBroadcastLevel::Global => 0,
30 ServiceBroadcastLevel::Geo1 => 1,
31 ServiceBroadcastLevel::Geo2 => 2,
32 ServiceBroadcastLevel::Group => 3,
33 }
34 }
35}
36
37impl From<u8> for ServiceBroadcastLevel {
38 fn from(val: u8) -> Self {
39 match val {
40 0 => ServiceBroadcastLevel::Global,
41 1 => ServiceBroadcastLevel::Geo1,
42 2 => ServiceBroadcastLevel::Geo2,
43 _ => ServiceBroadcastLevel::Group,
44 }
45 }
46}
47
48#[derive(Clone, Debug, Eq, PartialEq)]
49pub enum RouteRule {
50 Direct,
51 ToNode(NodeId),
52 ToService(u8),
53 ToServices(u8, ServiceBroadcastLevel, u16),
55 ToKey(NodeId),
56}
57
58#[derive(Clone, Debug, Eq, PartialEq)]
60pub enum RouteAction<Remote> {
61 Reject,
63 Local,
65 Next(Remote),
67 Broadcast(bool, Vec<Remote>),
69}
70
71impl<Remote> RouteAction<Remote> {
72 pub fn is_local(&self) -> bool {
73 matches!(self, RouteAction::Local)
74 }
75
76 pub fn is_reject(&self) -> bool {
77 matches!(self, RouteAction::Reject)
78 }
79
80 pub fn is_remote(&self) -> bool {
81 matches!(self, RouteAction::Next(_))
82 }
83}
84
85pub trait RouterTable<Remote> {
86 fn closest_for(&self, key: NodeId) -> Option<Remote>;
88 fn next(&self, dest: NodeId) -> Option<Remote>;
90 fn path_to_node(&self, dest: NodeId) -> RouteAction<Remote>;
92 fn path_to_key(&self, key: NodeId) -> RouteAction<Remote>;
94 fn path_to_service(&self, service_id: u8) -> RouteAction<Remote>;
96 fn path_to_services(&self, service_id: u8, seq: u16, level: ServiceBroadcastLevel, source: Option<NodeId>, relay_from: Option<NodeId>) -> RouteAction<Remote>;
99 fn derive_action(&self, route: &RouteRule, source: Option<NodeId>, relay_from: Option<NodeId>) -> RouteAction<Remote> {
102 match route {
103 RouteRule::Direct => RouteAction::Local,
104 RouteRule::ToNode(dest) => self.path_to_node(*dest),
105 RouteRule::ToKey(key) => self.path_to_key(*key),
106 RouteRule::ToService(service) => self.path_to_service(*service),
107 RouteRule::ToServices(service, level, seq) => self.path_to_services(*service, *seq, *level, source, relay_from),
108 }
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use atm0s_sdn_identity::ConnId;
115 type RouteAction = super::RouteAction<ConnId>;
116
117 #[test]
118 fn test_is_local() {
119 let local = RouteAction::Local;
120 let remote = RouteAction::Next(ConnId::from_in(1, 1));
121 let reject = RouteAction::Reject;
122
123 assert!(local.is_local());
124 assert!(!remote.is_local());
125 assert!(!reject.is_local());
126 }
127
128 #[test]
129 fn test_is_reject() {
130 let local = RouteAction::Local;
131 let remote = RouteAction::Next(ConnId::from_in(1, 1));
132 let reject = RouteAction::Reject;
133
134 assert!(!local.is_reject());
135 assert!(!remote.is_reject());
136 assert!(reject.is_reject());
137 }
138
139 #[test]
140 fn test_is_remote() {
141 let local = RouteAction::Local;
142 let remote = RouteAction::Next(ConnId::from_in(1, 1));
143 let reject = RouteAction::Reject;
144
145 assert!(!local.is_remote());
146 assert!(remote.is_remote());
147 assert!(!reject.is_remote());
148 }
149}