reddb_server/
transport.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum TransportKind {
9 Router,
10 Http,
11 Https,
12 Grpc,
13 GrpcTls,
14 Wire,
15 WireTls,
16 Postgres,
17}
18
19impl TransportKind {
20 pub const fn as_str(self) -> &'static str {
21 match self {
22 Self::Router => "router",
23 Self::Http => "http",
24 Self::Https => "https",
25 Self::Grpc => "grpc",
26 Self::GrpcTls => "grpc-tls",
27 Self::Wire => "wire",
28 Self::WireTls => "wire-tls",
29 Self::Postgres => "pg-wire",
30 }
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum TransportRole {
37 Primary,
40 Secondary,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct TransportDescriptor {
47 pub kind: TransportKind,
48 pub bind_addr: String,
49 pub explicit: bool,
50 pub role: TransportRole,
51}
52
53impl TransportDescriptor {
54 pub fn new(
55 kind: TransportKind,
56 bind_addr: String,
57 explicit: bool,
58 role: TransportRole,
59 ) -> Self {
60 Self {
61 kind,
62 bind_addr,
63 explicit,
64 role,
65 }
66 }
67}
68
69#[derive(Debug, Clone, Default, PartialEq, Eq)]
70pub struct TransportSet {
71 descriptors: Vec<TransportDescriptor>,
72}
73
74impl TransportSet {
75 pub fn new(descriptors: Vec<TransportDescriptor>) -> Self {
76 Self { descriptors }
77 }
78
79 pub fn descriptors(&self) -> &[TransportDescriptor] {
80 &self.descriptors
81 }
82
83 pub fn is_empty(&self) -> bool {
84 self.descriptors.is_empty()
85 }
86}
87
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct TransportListenerState {
90 pub transport: String,
91 pub bind_addr: String,
92 pub explicit: bool,
93}
94
95#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct TransportListenerFailure {
97 pub transport: String,
98 pub bind_addr: String,
99 pub explicit: bool,
100 pub reason: String,
101}
102
103#[derive(Debug, Clone, Default, PartialEq, Eq)]
104pub struct TransportReadiness {
105 pub active: Vec<TransportListenerState>,
106 pub failed: Vec<TransportListenerFailure>,
107}
108
109impl TransportReadiness {
110 pub(crate) fn active(&mut self, transport: &str, bind_addr: &str, explicit: bool) {
111 self.active.push(TransportListenerState {
112 transport: transport.to_string(),
113 bind_addr: bind_addr.to_string(),
114 explicit,
115 });
116 }
117
118 pub(crate) fn failed(
119 &mut self,
120 transport: &str,
121 bind_addr: &str,
122 explicit: bool,
123 reason: String,
124 ) {
125 self.failed.push(TransportListenerFailure {
126 transport: transport.to_string(),
127 bind_addr: bind_addr.to_string(),
128 explicit,
129 reason,
130 });
131 }
132}
133
134pub(crate) fn is_loopback_bind(bind_addr: &str) -> bool {
138 let host = bind_addr
139 .rsplit_once(':')
140 .map(|(host, _)| host.trim_matches(['[', ']']))
141 .unwrap_or(bind_addr);
142 if host.eq_ignore_ascii_case("localhost") {
143 return true;
144 }
145 host.parse::<std::net::IpAddr>()
146 .map(|addr| addr.is_loopback())
147 .unwrap_or(false)
148}