1mod connection;
2mod delay;
3mod metrics;
4mod msg;
5mod net;
6mod queue;
7mod time;
8mod util;
9
10pub mod error;
11pub mod noise;
12
13use std::{collections::BTreeMap, fmt, num::NonZeroUsize, sync::Arc, time::Duration};
14
15use bon::Builder;
16pub use cliquenet_types::{
17 addr::{self, NetAddr},
18 x25519,
19};
20pub use error::NetworkError;
21pub use metrics::Metrics;
22pub use msg::Slot;
23pub use net::{
24 Network, NetworkReceiver, NetworkSender, RetryPolicy, SendAction, SendCommand,
25 SendCommandBuilder,
26};
27
28use crate::{
29 util::nonempty::NonEmpty,
30 x25519::{Keypair, PublicKey},
31};
32
33#[derive(Builder)]
34#[builder(finish_fn(vis = "", name = "internal_build"))]
35#[non_exhaustive]
36pub struct Config {
37 #[builder(with = |s: impl Into<String>| Arc::new(s.into()))]
39 name: Arc<String>,
40
41 #[builder(with = |it: impl IntoIterator<Item = (Version, noise::Protocol)>| {
50 NonEmpty::assert_non_empty_map(it)
51 })]
52 noise_protocols: NonEmpty<BTreeMap<Version, noise::Protocol>>,
53
54 keypair: Keypair,
56
57 bind: NetAddr,
59
60 #[builder(with = <_>::from_iter)]
62 parties: Vec<(PublicKey, NetAddr)>,
63
64 #[builder(default = NonZeroUsize::new(100).expect("100 > 0"))]
65 peer_budget: NonZeroUsize,
66
67 #[builder(default = NonZeroUsize::new(10485760).expect("10485760 > 0"))]
69 max_message_size: NonZeroUsize,
70
71 #[builder(
73 default = NonEmpty::new(1, [3, 5, 15, 30]),
74 with = |it: impl IntoIterator<Item = u8>| NonEmpty::assert_non_empty_vec(it)
75 )]
76 connect_retry_delays: NonEmpty<Vec<u8>>,
77
78 #[builder(
80 default = NonEmpty::new(5, [15, 30]),
81 with = |it: impl IntoIterator<Item = u8>| NonEmpty::assert_non_empty_vec(it)
82 )]
83 send_retry_delays: NonEmpty<Vec<u8>>,
84
85 #[builder(default = true)]
87 random_connect_delay: bool,
88
89 #[builder(default = Duration::from_secs(30))]
91 connect_timeout: Duration,
92
93 #[builder(default = Duration::from_secs(10))]
95 handshake_timeout: Duration,
96
97 #[builder(default = Duration::from_secs(30))]
101 receive_timeout: Duration,
102
103 #[builder(default = Duration::from_secs(30))]
107 backoff_duration: Duration,
108
109 #[builder(default = Duration::from_secs(30))]
111 keep_alive_after: Duration,
112
113 #[builder(default = Duration::from_secs(5))]
115 keep_alive_interval: Duration,
116
117 #[builder(default = 6)]
119 keep_alive_retries: u8,
120
121 #[builder(default = (3 * parties.len()).max(100))]
123 max_accept_tasks: usize,
124
125 metrics: Option<Arc<dyn Metrics>>,
127}
128
129impl<S: config_builder::IsComplete> ConfigBuilder<S> {
130 pub fn build(self) -> Config {
131 let conf = self.internal_build();
132
133 let v1 = conf.noise_protocols.iter().map(|(k, _)| k);
134 let v2 = conf.noise_protocols.iter().map(|(k, _)| k).skip(1);
135 assert! {
136 v1.zip(v2).all(|(a, b)| u16::from(*a) + 1 == u16::from(*b)),
137 "cliquenet configuration requires consecutive noise protocol versions"
138 }
139
140 conf
141 }
142}
143
144impl fmt::Debug for Config {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 f.debug_struct("Config")
147 .field("name", &self.name)
148 .field("key", &self.keypair.public_key())
149 .field("bind", &self.bind)
150 .field("parties", &self.parties)
151 .field("peer_budget", &self.peer_budget)
152 .field("max_message_size", &self.max_message_size)
153 .field("connect_retry_delays", &self.connect_retry_delays)
154 .field("send_retry_delays", &self.send_retry_delays)
155 .field("random_connect_delay", &self.random_connect_delay)
156 .field("connect_timeout", &self.connect_timeout)
157 .field("handshake_timeout", &self.handshake_timeout)
158 .field("receive_timeout", &self.receive_timeout)
159 .field("backoff_duration", &self.backoff_duration)
160 .field("keepalive_after", &self.keep_alive_after)
161 .field("keepalive_interval", &self.keep_alive_interval)
162 .field("keepalive_retries", &self.keep_alive_retries)
163 .field("max_accept_tasks", &self.max_accept_tasks)
164 .finish()
165 }
166}
167
168impl Config {
169 pub fn public_key(&self) -> PublicKey {
170 self.keypair.public_key()
171 }
172
173 pub fn max_message_size(&self) -> NonZeroUsize {
174 self.max_message_size
175 }
176
177 pub fn with_metrics<M: Metrics + 'static>(mut self, m: M) -> Self {
178 self.metrics = Some(Arc::new(m));
179 self
180 }
181}
182
183#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
185pub enum Role {
186 Active,
188 Passive,
193}
194
195impl Role {
196 pub fn is_active(self) -> bool {
197 matches!(self, Self::Active)
198 }
199}
200
201impl fmt::Display for Role {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203 match self {
204 Self::Active => f.write_str("active"),
205 Self::Passive => f.write_str("passive"),
206 }
207 }
208}
209
210#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
211pub struct Version(u16);
212
213impl From<u16> for Version {
214 fn from(v: u16) -> Self {
215 Self(v)
216 }
217}
218
219impl From<Version> for u16 {
220 fn from(v: Version) -> Self {
221 v.0
222 }
223}
224
225impl fmt::Display for Version {
226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 self.0.fmt(f)
228 }
229}