commonware_p2p/authenticated/
channels.rs1use super::router::{Messenger, OwnedMessenger};
2use crate::{
3 Channel, Message as NetworkMessage, Recipients,
4 utils::limited::{CheckedSender, LimitedSender},
5};
6use commonware_actor::{
7 Feedback, Unreliable,
8 mailbox::{self, UnreliablePolicy},
9};
10use commonware_cryptography::PublicKey;
11use commonware_runtime::{Clock, IoBufs, Metrics, Quota};
12use std::{
13 collections::{BTreeMap, VecDeque},
14 fmt::Debug,
15 num::NonZeroUsize,
16 sync::Arc,
17 time::SystemTime,
18};
19use thiserror::Error;
20
21#[derive(Error, Debug)]
23pub enum Error {
24 #[error("network closed")]
25 NetworkClosed,
26}
27
28pub(crate) struct Inbound<P: PublicKey>(pub(crate) NetworkMessage<P>);
29
30impl<P: PublicKey> UnreliablePolicy for Inbound<P> {
31 type Overflow = VecDeque<Self>;
32
33 fn handle(_overflow: &mut Self::Overflow, _message: Self) -> bool {
34 false
35 }
36}
37
38#[derive(Debug, Clone)]
42pub struct UnlimitedSender<P: PublicKey> {
43 channel: Channel,
44 max_size: u32,
45 messenger: Messenger<P>,
46}
47
48impl<P: PublicKey> crate::UnlimitedSender for UnlimitedSender<P> {
49 type PublicKey = P;
50
51 fn send(
52 &mut self,
53 recipients: Recipients<Self::PublicKey>,
54 message: impl Into<IoBufs> + Send,
55 priority: bool,
56 ) -> Unreliable<Feedback> {
57 let message = message.into();
58 assert!(
59 message.len() <= self.max_size as usize,
60 "message too large: {} > {}",
61 message.len(),
62 self.max_size
63 );
64
65 self.messenger
66 .content(recipients, self.channel, message, priority)
67 }
68}
69
70pub struct Sender<P: PublicKey, C: Clock> {
76 limited_sender: LimitedSender<C, UnlimitedSender<P>, Messenger<P>>,
77}
78
79impl<P: PublicKey, C: Clock> Clone for Sender<P, C> {
80 fn clone(&self) -> Self {
81 Self {
82 limited_sender: self.limited_sender.clone(),
83 }
84 }
85}
86
87impl<P: PublicKey, C: Clock> Sender<P, C> {
88 pub(super) fn new(
89 channel: Channel,
90 max_size: u32,
91 messenger: Messenger<P>,
92 clock: C,
93 quota: Quota,
94 ) -> Self {
95 let master_sender = UnlimitedSender {
96 channel,
97 max_size,
98 messenger: messenger.clone(),
99 };
100 let limited_sender = LimitedSender::new(master_sender, quota, clock, messenger);
101 Self { limited_sender }
102 }
103}
104
105impl<P, C> crate::LimitedSender for Sender<P, C>
106where
107 P: PublicKey,
108 C: Clock + Send + 'static,
109{
110 type PublicKey = P;
111 type Checked<'a>
112 = CheckedSender<'a, UnlimitedSender<P>>
113 where
114 Self: 'a;
115
116 fn check(
117 &mut self,
118 recipients: Recipients<Self::PublicKey>,
119 ) -> Result<Self::Checked<'_>, SystemTime> {
120 self.limited_sender.check(recipients)
121 }
122}
123
124pub struct Receiver<P: PublicKey> {
130 receiver: mailbox::UnreliableReceiver<Inbound<P>>,
131}
132
133impl<P: PublicKey> Debug for Receiver<P> {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 f.debug_struct("Receiver").finish_non_exhaustive()
136 }
137}
138
139impl<P: PublicKey> Receiver<P> {
140 pub(super) const fn new(receiver: mailbox::UnreliableReceiver<Inbound<P>>) -> Self {
141 Self { receiver }
142 }
143}
144
145impl<P: PublicKey> crate::Receiver for Receiver<P> {
146 type Error = Error;
147 type PublicKey = P;
148
149 async fn recv(&mut self) -> Result<NetworkMessage<Self::PublicKey>, Error> {
154 let Inbound((sender, message)) = self.receiver.recv().await.ok_or(Error::NetworkClosed)?;
155
156 Ok((sender, message))
159 }
160}
161
162#[derive(Clone, Debug)]
163pub struct Channels<P: PublicKey> {
164 messenger: Arc<OwnedMessenger<P>>,
165 max_size: u32,
166 max_peers: NonZeroUsize,
167 outbound_capacity: usize,
168 receivers: BTreeMap<Channel, (Quota, mailbox::UnreliableSender<Inbound<P>>)>,
169}
170
171impl<P: PublicKey> Channels<P> {
172 pub const fn new(
173 messenger: Arc<OwnedMessenger<P>>,
174 max_size: u32,
175 max_peers: NonZeroUsize,
176 ) -> Self {
177 Self {
178 messenger,
179 max_size,
180 max_peers,
181 outbound_capacity: 0,
182 receivers: BTreeMap::new(),
183 }
184 }
185
186 pub(super) const fn outbound_mailbox_size(&self, base: NonZeroUsize) -> NonZeroUsize {
190 base.checked_add(self.outbound_capacity)
191 .expect("router mailbox capacity overflow")
192 }
193
194 pub(super) fn bind(&self, mailbox: super::router::Mailbox<P>) {
196 self.messenger.bind(mailbox);
197 }
198
199 pub fn register<C: Clock + Metrics>(
200 &mut self,
201 channel: Channel,
202 rate: Quota,
203 context: C,
204 ) -> (Sender<P, C>, Receiver<P>) {
205 if self.receivers.contains_key(&channel) {
206 panic!("duplicate channel registration: {channel}");
207 }
208 let capacity = self
209 .max_peers
210 .get()
211 .checked_mul(rate.burst_size().get() as usize)
212 .and_then(NonZeroUsize::new)
213 .expect("channel mailbox capacity overflow");
214 self.outbound_capacity = self
215 .outbound_capacity
216 .checked_add(capacity.get())
217 .expect("router mailbox capacity overflow");
218 let (sender, receiver) = mailbox::new_unreliable(context.child("mailbox"), capacity);
219 assert!(self.receivers.insert(channel, (rate, sender)).is_none());
220 (
221 Sender::new(
222 channel,
223 self.max_size,
224 self.messenger.handle(),
225 context,
226 rate,
227 ),
228 Receiver::new(receiver),
229 )
230 }
231
232 pub fn collect(self) -> BTreeMap<u64, (Quota, mailbox::UnreliableSender<Inbound<P>>)> {
233 self.receivers
234 }
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240 use commonware_cryptography::{
241 Signer as _,
242 ed25519::{PrivateKey, PublicKey},
243 };
244 use commonware_runtime::{
245 BufferPooler as _, IoBuf, Runner as _, Supervisor as _, deterministic,
246 };
247 use commonware_utils::{NZU32, NZUsize};
248
249 #[test]
250 fn registered_rate_sizes_inbound_mailbox_for_every_peer() {
251 deterministic::Runner::default().start(|context| async move {
252 let messenger = Messenger::unbound(context.network_buffer_pool().clone());
253 let mut channels = Channels::new(messenger, 1024, NZUsize!(2));
254 let quota = Quota::per_second(NZU32!(2));
255 let (_, mut receiver) = channels.register(1, quota, context.child("channel"));
256 let inbound = channels.receivers.get(&1).unwrap().1.clone();
257 let peer = PrivateKey::from_seed(1).public_key();
258
259 for _ in 0..4 {
262 assert!(
263 inbound
264 .enqueue(Inbound((peer.clone(), IoBuf::from(b"message"))))
265 .accepted()
266 );
267 }
268 assert_eq!(
269 inbound.enqueue(Inbound((peer, IoBuf::from(b"overflow")))),
270 Unreliable::Rejected
271 );
272
273 for _ in 0..4 {
274 assert!(receiver.receiver.try_recv().is_ok());
275 }
276 });
277 }
278
279 #[test]
280 fn registered_rates_size_shared_outbound_mailbox() {
281 deterministic::Runner::default().start(|context| async move {
282 let messenger = Messenger::<PublicKey>::unbound(context.network_buffer_pool().clone());
283 let mut channels = Channels::new(messenger, 1024, NZUsize!(2));
284 let quota = Quota::per_second(NZU32!(2));
285 let _ = channels.register(1, quota, context.child("first"));
286 let _ = channels.register(2, quota, context.child("second"));
287
288 assert_eq!(channels.outbound_mailbox_size(NZUsize!(2)), NZUsize!(10));
290 });
291 }
292
293 #[test]
294 #[should_panic(expected = "router mailbox capacity overflow")]
295 fn outbound_mailbox_size_panics_on_overflow() {
296 deterministic::Runner::default().start(|context| async move {
297 let messenger = Messenger::unbound(context.network_buffer_pool().clone());
298 let mut channels = Channels::<PublicKey>::new(messenger, 1024, NZUsize!(1));
299 channels.outbound_capacity = 1;
300
301 channels.outbound_mailbox_size(NonZeroUsize::new(usize::MAX).unwrap());
302 });
303 }
304
305 #[test]
306 #[should_panic(expected = "channel mailbox capacity overflow")]
307 fn derived_capacity_panics_on_overflow() {
308 let rate = Quota::per_second(NZU32!(2));
309 deterministic::Runner::default().start(|context| async move {
310 let messenger = Messenger::unbound(context.network_buffer_pool().clone());
311 let mut channels =
312 Channels::<PublicKey>::new(messenger, 1024, NonZeroUsize::new(usize::MAX).unwrap());
313 let _ = channels.register(0, rate, context);
314 });
315 }
316}