1pub mod peer;
2pub mod server;
3
4use std::{fmt, ops::Deref, sync::Arc};
5
6use bon::Builder;
7use bytes::Bytes;
8use tokio::{
9 net::TcpListener,
10 sync::{
11 OwnedSemaphorePermit,
12 mpsc::{self, UnboundedReceiver, UnboundedSender},
13 oneshot, watch,
14 },
15};
16use tracing::{debug, info, warn};
17
18use crate::{
19 Config, Metrics, NetAddr, Role, error::NetworkError, metrics::NoMetrics, msg::Slot,
20 net::server::Server, x25519::PublicKey,
21};
22
23type PeerMessage = (PublicKey, Bytes, Option<OwnedSemaphorePermit>);
24
25#[derive(Debug)]
26pub struct Network {
27 recv: NetworkReceiver,
28 send: NetworkSender,
29}
30
31#[derive(Debug)]
32pub struct NetworkReceiver {
33 rx: UnboundedReceiver<PeerMessage>,
34}
35
36#[derive(Clone)]
37pub struct NetworkSender {
38 conf: Arc<Config>,
39 node: PublicKey,
40 tx: UnboundedSender<Command>,
41 next_slot: watch::Sender<Slot>,
42 metrics: Arc<dyn Metrics>,
43}
44
45impl fmt::Debug for NetworkSender {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 f.debug_struct("NetworkSender")
48 .field("node", &self.node)
49 .field("lower_bound", &*self.next_slot.borrow())
50 .field("conf", &self.conf)
51 .finish()
52 }
53}
54
55#[derive(Debug)]
57enum Command {
58 Peer(PeerCommand),
59 Send(SendCommand),
60 Shutdown(oneshot::Sender<()>),
61}
62
63#[derive(Debug)]
65enum PeerCommand {
66 Add(Role, Vec<(PublicKey, NetAddr)>),
68 Remove(Vec<PublicKey>),
70 Assign(Role, Vec<PublicKey>),
72}
73
74#[derive(Clone, Debug, Builder)]
76pub struct SendCommand {
77 slot: Slot,
78 action: SendAction,
79 #[builder(default)]
80 retry: RetryPolicy,
81}
82
83#[derive(Clone, Copy, Debug, Default)]
85pub enum RetryPolicy {
86 #[default]
87 Default,
88 NoRetry,
89}
90
91impl RetryPolicy {
92 pub fn is_retry(self) -> bool {
93 matches!(self, Self::Default)
94 }
95}
96
97#[derive(Clone, Debug)]
98pub enum SendAction {
99 Unicast(PublicKey, Vec<u8>),
101 Multicast(Vec<PublicKey>, Vec<u8>),
103 Broadcast(Vec<u8>),
105}
106
107impl Network {
108 pub async fn create(conf: Config) -> Result<Self, NetworkError> {
109 let listener = {
110 let result = match &conf.bind {
111 NetAddr::Inet(ip, port) => TcpListener::bind((*ip, *port)).await,
112 NetAddr::Name(hs, port) => TcpListener::bind((&**hs, *port)).await,
113 };
114 result.map_err(|e| NetworkError::Bind(conf.bind.clone(), e))?
115 };
116
117 let addr = listener.local_addr()?;
118 let node = conf.keypair.public_key();
119
120 let (otx, orx) = mpsc::unbounded_channel();
122
123 let (itx, irx) = mpsc::unbounded_channel();
125
126 let (etx, erx) = watch::channel(Slot::MIN);
127
128 let metr = conf.metrics.clone().unwrap_or_else(|| Arc::new(NoMetrics));
129 let conf = Arc::new(conf);
130
131 Server::spawn(
133 conf.clone(),
134 listener,
135 Role::Active,
136 itx,
137 orx,
138 erx,
139 metr.clone(),
140 );
141
142 let recv = NetworkReceiver { rx: irx };
143 let send = NetworkSender {
144 conf: conf.clone(),
145 node,
146 tx: otx,
147 next_slot: etx,
148 metrics: metr,
149 };
150
151 info!(name = %conf.name, %node, %addr, max_message_size = %conf.max_message_size, "listening");
152
153 Ok(Self { recv, send })
154 }
155
156 pub fn sender(&self) -> &NetworkSender {
157 &self.send
158 }
159
160 pub fn receiver(&self) -> &NetworkReceiver {
161 &self.recv
162 }
163
164 pub fn receiver_mut(&mut self) -> &mut NetworkReceiver {
165 &mut self.recv
166 }
167
168 pub fn split_into(self) -> (NetworkSender, NetworkReceiver) {
169 (self.send, self.recv)
170 }
171
172 pub async fn receive(&mut self) -> Option<(PublicKey, Bytes)> {
173 self.recv.receive().await
174 }
175}
176
177impl Deref for Network {
178 type Target = NetworkSender;
179
180 fn deref(&self) -> &Self::Target {
181 &self.send
182 }
183}
184
185impl NetworkReceiver {
186 pub async fn receive(&mut self) -> Option<(PublicKey, Bytes)> {
190 let (k, b, _) = self.rx.recv().await?;
191 debug!(peer = %k, len = b.len(), "message received");
192 Some((k, b))
193 }
194}
195
196impl NetworkSender {
197 pub fn config(&self) -> &Config {
198 &self.conf
199 }
200
201 pub fn unicast(&self, s: Slot, to: PublicKey, msg: Vec<u8>) -> Result<(), NetworkError> {
203 debug!(slot = %s, %to, len = msg.len(), "unicast");
204 self.length_check(&msg)?;
205 if self.lt_lower_bound(s) {
206 return Ok(());
207 }
208 let cmd = SendCommand::builder()
209 .slot(s)
210 .action(SendAction::Unicast(to, msg))
211 .build();
212 self.tx
213 .send(Command::Send(cmd))
214 .map_err(|_| NetworkError::ChannelClosed)
215 }
216
217 pub fn broadcast(&self, s: Slot, msg: Vec<u8>) -> Result<(), NetworkError> {
219 debug!(slot = %s, len = msg.len(), "broadcast");
220 self.length_check(&msg)?;
221 if self.lt_lower_bound(s) {
222 return Ok(());
223 }
224 let cmd = SendCommand::builder()
225 .slot(s)
226 .action(SendAction::Broadcast(msg))
227 .build();
228 self.tx
229 .send(Command::Send(cmd))
230 .map_err(|_| NetworkError::ChannelClosed)
231 }
232
233 pub fn multicast<P>(&self, s: Slot, to: P, msg: Vec<u8>) -> Result<(), NetworkError>
235 where
236 P: IntoIterator<Item = PublicKey>,
237 {
238 debug!(slot = %s, len = msg.len(), "multicast");
239 self.length_check(&msg)?;
240 if self.lt_lower_bound(s) {
241 return Ok(());
242 }
243 let cmd = SendCommand::builder()
244 .slot(s)
245 .action(SendAction::Multicast(to.into_iter().collect(), msg))
246 .build();
247 self.tx
248 .send(Command::Send(cmd))
249 .map_err(|_| NetworkError::ChannelClosed)
250 }
251
252 pub fn send(&self, cmd: SendCommand) -> Result<(), NetworkError> {
254 let bytes = msg_bytes(&cmd);
255 debug!(slot = %cmd.slot, len = %bytes.len(), "send");
256 self.length_check(bytes)?;
257 if self.lt_lower_bound(cmd.slot) {
258 return Ok(());
259 }
260 self.tx
261 .send(Command::Send(cmd))
262 .map_err(|_| NetworkError::ChannelClosed)
263 }
264
265 pub fn add_peers<P>(&self, r: Role, peers: P) -> Result<(), NetworkError>
267 where
268 P: IntoIterator<Item = (PublicKey, NetAddr)>,
269 {
270 debug!(role = %r, "add_peers");
271 let peers = peers.into_iter().collect::<Vec<_>>();
272 self.tx
273 .send(Command::Peer(PeerCommand::Add(r, peers)))
274 .map_err(|_| NetworkError::ChannelClosed)
275 }
276
277 pub fn remove_peers<P>(&self, peers: P) -> Result<(), NetworkError>
279 where
280 P: IntoIterator<Item = PublicKey>,
281 {
282 debug!("remove_peers");
283 let peers = peers.into_iter().collect::<Vec<_>>();
284 for p in &peers {
285 self.metrics.del(p);
286 }
287 self.tx
288 .send(Command::Peer(PeerCommand::Remove(peers)))
289 .map_err(|_| NetworkError::ChannelClosed)
290 }
291
292 pub fn assign_peers<P>(&self, r: Role, peers: P) -> Result<(), NetworkError>
294 where
295 P: IntoIterator<Item = PublicKey>,
296 {
297 debug!(role = %r, "assign_peers");
298 let peers = peers.into_iter().collect::<Vec<_>>();
299 self.tx
300 .send(Command::Peer(PeerCommand::Assign(r, peers)))
301 .map_err(|_| NetworkError::ChannelClosed)
302 }
303
304 pub fn gc(&self, s: Slot) -> Result<(), NetworkError> {
306 debug!(slot = %s, "gc");
307 if self.next_slot.is_closed() {
308 return Err(NetworkError::ChannelClosed);
309 }
310 self.next_slot.send_if_modified(|lower_bound| {
311 if s > *lower_bound {
312 *lower_bound = s;
313 true
314 } else {
315 false
316 }
317 });
318 Ok(())
319 }
320
321 pub fn shutdown(&self) -> Result<impl Future<Output = ()> + use<>, NetworkError> {
325 warn!(name = %self.conf.name, node = %self.node, "shutdown");
326 let (tx, rx) = oneshot::channel();
327 self.tx
328 .send(Command::Shutdown(tx))
329 .map_err(|_| NetworkError::ChannelClosed)?;
330 Ok(async move {
331 let _ = rx.await;
332 })
333 }
334
335 fn length_check(&self, msg: &[u8]) -> Result<(), NetworkError> {
337 if msg.len() > self.conf.max_message_size.get() {
338 warn!(
339 name = %self.conf.name,
340 node = %self.node,
341 len = %msg.len(),
342 max = %self.conf.max_message_size,
343 "message too large to send"
344 );
345 return Err(NetworkError::MessageTooLarge);
346 }
347 Ok(())
348 }
349
350 fn lt_lower_bound(&self, s: Slot) -> bool {
352 let lower_bound = *self.next_slot.borrow();
353 if s < lower_bound {
354 warn!(
355 name = %self.conf.name,
356 node = %self.node,
357 slot = %s,
358 %lower_bound,
359 "slot below lower bound"
360 );
361 return true;
362 }
363 false
364 }
365}
366
367fn msg_bytes(cmd: &SendCommand) -> &[u8] {
368 match &cmd.action {
369 SendAction::Unicast(_, b) => b,
370 SendAction::Multicast(_, b) => b,
371 SendAction::Broadcast(b) => b,
372 }
373}