netgauze_bmp_service/
lib.rs1use netgauze_bmp_pkt::BmpMessage;
17use netgauze_bmp_pkt::codec::BmpCodecDecoderError;
18use serde::{Deserialize, Serialize};
19use std::fmt::{Display, Formatter};
20use std::io;
21use std::net::SocketAddr;
22use std::sync::Arc;
23
24pub mod actor;
25pub mod handle;
26pub mod server;
27pub mod supervisor;
28pub mod transport;
29
30pub type ActorId = u32;
31pub type SubscriberId = u32;
32pub type BmpRequest = (AddrInfo, BmpMessage);
33
34pub type BmpSender = async_channel::Sender<Arc<BmpRequest>>;
35pub type BmpReceiver = async_channel::Receiver<Arc<BmpRequest>>;
36
37pub fn create_bmp_channel(buffer_size: usize) -> (BmpSender, BmpReceiver) {
38 async_channel::bounded(buffer_size)
39}
40
41#[derive(Debug, Clone)]
42pub struct Subscription {
43 actor_id: ActorId,
44 id: SubscriberId,
45}
46
47impl Subscription {
48 pub const fn new(actor_id: ActorId, id: SubscriberId) -> Self {
49 Self { actor_id, id }
50 }
51
52 pub const fn actor_id(&self) -> ActorId {
53 self.actor_id
54 }
55
56 pub const fn id(&self) -> SubscriberId {
57 self.id
58 }
59}
60impl Display for Subscription {
61 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
62 write!(
63 f,
64 "Subscription {{ actor_id: {}, id: {} }}",
65 self.actor_id, self.id
66 )
67 }
68}
69
70#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
72pub struct AddrInfo {
73 local_socket: SocketAddr,
74 remote_socket: SocketAddr,
75}
76
77impl AddrInfo {
78 pub const fn new(local_socket: SocketAddr, remote_socket: SocketAddr) -> Self {
79 Self {
80 local_socket,
81 remote_socket,
82 }
83 }
84
85 pub const fn local_socket(&self) -> SocketAddr {
86 self.local_socket
87 }
88
89 pub const fn remote_socket(&self) -> SocketAddr {
90 self.remote_socket
91 }
92}
93
94#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
96pub struct TaggedData<T, V> {
97 tag: T,
98 value: V,
99}
100
101impl<T: Copy, V> TaggedData<T, V> {
102 pub const fn new(tag: T, value: V) -> Self {
103 Self { tag, value }
104 }
105
106 pub const fn tag(&self) -> T {
107 self.tag
108 }
109
110 pub const fn value(&self) -> &V {
111 &self.value
112 }
113}
114
115impl Display for TaggedData<AddrInfo, BmpCodecDecoderError> {
116 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
117 write!(f, "{self:?}")
118 }
119}
120
121impl std::error::Error for TaggedData<AddrInfo, BmpCodecDecoderError> {}
122
123pub fn new_tcp_reuse_port(
126 local_addr: SocketAddr,
127 device: Option<String>,
128 backlog: i32,
129) -> io::Result<tokio::net::TcpListener> {
130 let tcp_sock = socket2::Socket::new(
131 if local_addr.is_ipv4() {
132 socket2::Domain::IPV4
133 } else {
134 socket2::Domain::IPV6
135 },
136 socket2::Type::STREAM,
137 None,
138 )?;
139 tcp_sock.set_reuse_address(true)?;
140 #[cfg(all(unix, not(any(target_os = "solaris", target_os = "illumos"))))]
141 tcp_sock.set_reuse_port(true)?;
142 #[cfg(unix)]
143 tcp_sock.set_cloexec(true)?;
144 tcp_sock.set_nonblocking(true)?;
145
146 #[cfg(any(
147 target_os = "ios",
148 target_os = "macos",
149 target_os = "tvos",
150 target_os = "watchos",
151 target_os = "android",
152 target_os = "fuchsia",
153 target_os = "linux"
154 ))]
155 if let Some(name) = device {
156 #[cfg(any(
157 target_os = "ios",
158 target_os = "macos",
159 target_os = "tvos",
160 target_os = "watchos",
161 ))]
162 {
163 let c_str = std::ffi::CString::new(name)?;
164 let c_index = unsafe { libc::if_nametoindex(c_str.as_ptr() as *const libc::c_char) };
165 let index = std::num::NonZeroU32::new(c_index as u32);
166 if local_addr.is_ipv4() {
167 tcp_sock.bind_device_by_index_v4(index)?;
168 } else {
169 tcp_sock.bind_device_by_index_v6(index)?;
170 }
171 }
172 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
173 tcp_sock.bind_device(Some(name.as_bytes()))?
174 }
175
176 tcp_sock.bind(&socket2::SockAddr::from(local_addr))?;
177 tcp_sock.listen(backlog)?;
178 let tcp_sock: std::net::TcpListener = tcp_sock.into();
179 tokio::net::TcpListener::from_std(tcp_sock)
180}