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 metrics: Option<Arc<dyn Metrics>>,
123}
124
125impl<S: config_builder::IsComplete> ConfigBuilder<S> {
126 pub fn build(self) -> Config {
127 let conf = self.internal_build();
128
129 let v1 = conf.noise_protocols.iter().map(|(k, _)| k);
130 let v2 = conf.noise_protocols.iter().map(|(k, _)| k).skip(1);
131 assert! {
132 v1.zip(v2).all(|(a, b)| u16::from(*a) + 1 == u16::from(*b)),
133 "cliquenet configuration requires consecutive noise protocol versions"
134 }
135
136 conf
137 }
138}
139
140impl fmt::Debug for Config {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 f.debug_struct("Config")
143 .field("name", &self.name)
144 .field("key", &self.keypair.public_key())
145 .field("bind", &self.bind)
146 .field("parties", &self.parties)
147 .field("peer_budget", &self.peer_budget)
148 .field("max_message_size", &self.max_message_size)
149 .field("connect_retry_delays", &self.connect_retry_delays)
150 .field("send_retry_delays", &self.send_retry_delays)
151 .field("random_connect_delay", &self.random_connect_delay)
152 .field("connect_timeout", &self.connect_timeout)
153 .field("handshake_timeout", &self.handshake_timeout)
154 .field("receive_timeout", &self.receive_timeout)
155 .field("backoff_duration", &self.backoff_duration)
156 .field("keepalive_after", &self.keep_alive_after)
157 .field("keepalive_interval", &self.keep_alive_interval)
158 .field("keepalive_retries", &self.keep_alive_retries)
159 .finish()
160 }
161}
162
163impl Config {
164 pub fn public_key(&self) -> PublicKey {
165 self.keypair.public_key()
166 }
167
168 pub fn with_metrics<M: Metrics + 'static>(mut self, m: M) -> Self {
169 self.metrics = Some(Arc::new(m));
170 self
171 }
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
176pub enum Role {
177 Active,
179 Passive,
184}
185
186impl Role {
187 pub fn is_active(self) -> bool {
188 matches!(self, Self::Active)
189 }
190}
191
192impl fmt::Display for Role {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 match self {
195 Self::Active => f.write_str("active"),
196 Self::Passive => f.write_str("passive"),
197 }
198 }
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
202pub struct Version(u16);
203
204impl From<u16> for Version {
205 fn from(v: u16) -> Self {
206 Self(v)
207 }
208}
209
210impl From<Version> for u16 {
211 fn from(v: Version) -> Self {
212 v.0
213 }
214}
215
216impl fmt::Display for Version {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 self.0.fmt(f)
219 }
220}