1use async_trait::async_trait;
16use std::sync::Arc;
17use uuid::Uuid;
18
19#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
21pub struct NetworkAddress {
22 address: String,
23}
24
25impl NetworkAddress {
26 pub fn new(address: String) -> Self {
28 Self { address }
29 }
30
31 pub fn as_str(&self) -> &str {
33 &self.address
34 }
35}
36
37impl From<&str> for NetworkAddress {
38 fn from(address: &str) -> Self {
39 Self::new(address.to_string())
40 }
41}
42
43impl From<String> for NetworkAddress {
44 fn from(address: String) -> Self {
45 Self::new(address)
46 }
47}
48
49#[derive(Debug, thiserror::Error, serde::Serialize, serde::Deserialize)]
51pub enum NetworkError {
52 #[error("Failed to send message to {peer_id:?}: {reason}")]
54 SendFailed {
55 peer_id: Option<Uuid>,
57 reason: String,
59 },
60 #[error("Failed to receive message: {reason}")]
62 ReceiveFailed {
63 reason: String,
65 },
66 #[error("No message available")]
68 NoMessage,
69 #[error("Broadcast failed: {reason}")]
71 BroadcastFailed {
72 reason: String,
74 },
75 #[error("Connection failed: {0}")]
77 ConnectionFailed(String),
78 #[error("Unsupported operation")]
80 NotImplemented,
81 #[error("Serialization failed: {error}")]
83 SerializationFailed {
84 error: String,
86 },
87 #[error("Deserialization failed: {error}")]
89 DeserializationFailed {
90 error: String,
92 },
93 #[error("Operation '{operation}' timed out after {timeout_ms}ms")]
95 OperationTimeout {
96 operation: String,
98 timeout_ms: u64,
100 },
101 #[error("Retry limit exceeded after {attempts} attempts. Last error: {last_error}")]
103 RetryLimitExceeded {
104 attempts: u32,
106 last_error: String,
108 },
109 #[error("Circuit breaker is open: {reason}")]
111 CircuitBreakerOpen {
112 reason: String,
114 },
115 #[error("Peer unreachable: {peer_id}")]
117 PeerUnreachable {
118 peer_id: String,
120 },
121 #[error("Network partition detected: {details}")]
123 NetworkPartition {
124 details: String,
126 },
127 #[error("Message validation failed: {reason}")]
129 ValidationFailed {
130 reason: String,
132 },
133 #[error("Rate limit exceeded: {limit} requests per {window_ms}ms window")]
135 RateLimitExceeded {
136 limit: u32,
138 window_ms: u64,
140 },
141 #[error("Subscription failed: {reason}")]
143 SubscriptionFailed {
144 reason: String,
146 },
147}
148
149#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
151pub struct UdpEndpoint {
152 address: String,
153}
154
155impl UdpEndpoint {
156 pub fn new(address: impl Into<String>) -> Self {
158 Self {
159 address: address.into(),
160 }
161 }
162
163 pub fn as_str(&self) -> &str {
165 &self.address
166 }
167}
168
169impl std::fmt::Display for UdpEndpoint {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 write!(f, "{}", self.address)
172 }
173}
174
175impl From<&str> for UdpEndpoint {
176 fn from(address: &str) -> Self {
177 Self::new(address)
178 }
179}
180
181impl From<String> for UdpEndpoint {
182 fn from(address: String) -> Self {
183 Self::new(address)
184 }
185}
186
187#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
189#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
190pub trait UdpEndpointEffects: Send + Sync {
191 async fn set_broadcast(&self, enabled: bool) -> Result<(), NetworkError>;
193
194 async fn send_to(&self, payload: &[u8], addr: &UdpEndpoint) -> Result<usize, NetworkError>;
196
197 async fn recv_from(&self, buffer: &mut [u8]) -> Result<(usize, UdpEndpoint), NetworkError>;
199}
200
201#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
203#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
204pub trait UdpEffects: Send + Sync {
205 async fn udp_bind(
207 &self,
208 addr: UdpEndpoint,
209 ) -> Result<Arc<dyn UdpEndpointEffects>, NetworkError>;
210}
211
212#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
213#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
214impl<T: UdpEffects + ?Sized> UdpEffects for Arc<T> {
215 async fn udp_bind(
216 &self,
217 addr: UdpEndpoint,
218 ) -> Result<Arc<dyn UdpEndpointEffects>, NetworkError> {
219 (**self).udp_bind(addr).await
220 }
221}
222
223#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
224#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
225impl<T: UdpEndpointEffects + ?Sized> UdpEndpointEffects for Arc<T> {
226 async fn set_broadcast(&self, enabled: bool) -> Result<(), NetworkError> {
227 (**self).set_broadcast(enabled).await
228 }
229
230 async fn send_to(&self, payload: &[u8], addr: &UdpEndpoint) -> Result<usize, NetworkError> {
231 (**self).send_to(payload, addr).await
232 }
233
234 async fn recv_from(&self, buffer: &mut [u8]) -> Result<(usize, UdpEndpoint), NetworkError> {
235 (**self).recv_from(buffer).await
236 }
237}
238
239pub type PeerEventStream = std::pin::Pin<Box<dyn futures::Stream<Item = PeerEvent> + Send>>;
241
242#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
244pub enum PeerEvent {
245 Connected(Uuid),
247 Disconnected(Uuid),
249 ConnectionFailed(Uuid, String),
251}
252
253#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
255pub enum NetworkUsability {
256 Usable,
258 Unusable { reason: String },
260}
261
262#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
264pub struct NetworkChange {
265 pub generation: u64,
267 pub usability: NetworkUsability,
269 pub interfaces: Vec<NetworkAddress>,
271}
272
273#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
275#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
276pub trait NetworkChangeStream: Send {
277 async fn next_change(&mut self) -> Result<Option<NetworkChange>, NetworkError>;
279}
280
281#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
282#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
283impl<T: NetworkChangeStream + ?Sized> NetworkChangeStream for Box<T> {
284 async fn next_change(&mut self) -> Result<Option<NetworkChange>, NetworkError> {
285 (**self).next_change().await
286 }
287}
288
289#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
294#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
295pub trait NetworkChangeEffects: Send + Sync {
296 async fn subscribe_network_changes(
298 &self,
299 ) -> Result<Box<dyn NetworkChangeStream>, NetworkError> {
300 Err(NetworkError::NotImplemented)
301 }
302}
303
304#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
305#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
306impl<T: NetworkChangeEffects + ?Sized> NetworkChangeEffects for Arc<T> {
307 async fn subscribe_network_changes(
308 &self,
309 ) -> Result<Box<dyn NetworkChangeStream>, NetworkError> {
310 (**self).subscribe_network_changes().await
311 }
312}
313
314#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
323#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
324pub trait NetworkCoreEffects: Send + Sync {
325 async fn send_to_peer(&self, peer_id: Uuid, message: Vec<u8>) -> Result<(), NetworkError>;
329
330 async fn broadcast(&self, message: Vec<u8>) -> Result<(), NetworkError>;
332
333 async fn receive(&self) -> Result<(Uuid, Vec<u8>), NetworkError>;
335}
336
337#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
339#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
340pub trait NetworkExtendedEffects: NetworkCoreEffects + Send + Sync {
341 async fn receive_from(&self, _peer_id: Uuid) -> Result<Vec<u8>, NetworkError> {
343 Err(NetworkError::NotImplemented)
344 }
345
346 async fn connected_peers(&self) -> Vec<Uuid> {
348 Vec::new()
349 }
350
351 async fn is_peer_connected(&self, _peer_id: Uuid) -> bool {
353 false
354 }
355
356 async fn subscribe_to_peer_events(&self) -> Result<PeerEventStream, NetworkError> {
358 Err(NetworkError::NotImplemented)
359 }
360
361 async fn open(&self, _address: &str) -> Result<String, NetworkError> {
368 Err(NetworkError::NotImplemented)
369 }
370
371 async fn send(&self, _connection_id: &str, _data: Vec<u8>) -> Result<(), NetworkError> {
375 Err(NetworkError::NotImplemented)
376 }
377
378 async fn close(&self, _connection_id: &str) -> Result<(), NetworkError> {
382 Err(NetworkError::NotImplemented)
383 }
384}
385
386pub trait NetworkEffects: NetworkCoreEffects + NetworkExtendedEffects {}
388
389impl<T: NetworkCoreEffects + NetworkExtendedEffects + ?Sized> NetworkEffects for T {}
390#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
392#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
393impl<T: NetworkCoreEffects + ?Sized> NetworkCoreEffects for std::sync::Arc<T> {
394 async fn send_to_peer(&self, peer_id: Uuid, message: Vec<u8>) -> Result<(), NetworkError> {
395 (**self).send_to_peer(peer_id, message).await
396 }
397
398 async fn broadcast(&self, message: Vec<u8>) -> Result<(), NetworkError> {
399 (**self).broadcast(message).await
400 }
401
402 async fn receive(&self) -> Result<(Uuid, Vec<u8>), NetworkError> {
403 (**self).receive().await
404 }
405}
406
407#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
409#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
410impl<T: NetworkExtendedEffects + ?Sized> NetworkExtendedEffects for std::sync::Arc<T> {
411 async fn receive_from(&self, peer_id: Uuid) -> Result<Vec<u8>, NetworkError> {
412 (**self).receive_from(peer_id).await
413 }
414
415 async fn connected_peers(&self) -> Vec<Uuid> {
416 (**self).connected_peers().await
417 }
418
419 async fn is_peer_connected(&self, peer_id: Uuid) -> bool {
420 (**self).is_peer_connected(peer_id).await
421 }
422
423 async fn subscribe_to_peer_events(&self) -> Result<PeerEventStream, NetworkError> {
424 (**self).subscribe_to_peer_events().await
425 }
426
427 async fn open(&self, address: &str) -> Result<String, NetworkError> {
428 (**self).open(address).await
429 }
430
431 async fn send(&self, connection_id: &str, data: Vec<u8>) -> Result<(), NetworkError> {
432 (**self).send(connection_id, data).await
433 }
434
435 async fn close(&self, connection_id: &str) -> Result<(), NetworkError> {
436 (**self).close(connection_id).await
437 }
438}