1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! # hydra-sync: A Lightweight Zero-Copy E2E SPMC Relay Network Library
//!
//! `hydra-sync` is a high-performance, end-to-end encrypted relay library for single producer,
//! multiple consumer (SPMC) network architectures. It provides a simple yet powerful abstraction
//! for building distributed systems where one producer broadcasts encrypted data to many consumers
//! with minimal latency and memory overhead.
//!
//! ### Overview
//!
//! The library is organized around two main components:
//!
//! - **Server** ([`server`]): Manages relay state, maintains active sessions, and routes encrypted frames
//! from producers to their respective consumers. Uses `DashMap` for thread-safe session storage.
//!
//! - **Client** ([`client`]): Connects to the relay server as either a producer or consumer. Producers
//! broadcast encrypted frames, while consumers receive and decrypt them from the internal memory pool.
//!
//! ### Protocol
//!
//! The protocol consists of two phases:
//!
//! 1. **Handshake**: Client and server establish a transport key via X25519 Diffie-Hellman key & nonce exchange.
//! This transport key encrypts join and control frames.
//!
//! 2. **Data Transfer**: Producers encrypt broadcast frames using AES-GCM with a session-specific key.
//! Consumers decrypt received frames using the same session key. Each frame includes an AEAD tag
//! for integrity verification. (NO SERVER INTERVENTION IN DATA TRANSFER, SERVER ONLY RELAYS ENCRYPTED FRAMES)
//!
//!
//! #### Quick Example
//!
//! ```no_run
//!use hydra_sync::client::HydraClient;
//!use hydra_sync::server::HydraServer;
//!use std::net::SocketAddr;
//!use anyhow::Result;
//!
//!#[tokio::main]
//!async fn main() -> anyhow::Result<()> {
//! let (server, server_addr) = HydraServer::bind_default().await?; // bind to os-assigned port
//! let session_id = [0xFFu8; 64];
//! let session_key = [0xAAu8; 32];
//!
//! tokio::spawn(async move { server.run(500).await }); // run in background
//!
//! // Producer; sends data to all consumers in the session
//! let mut producer =
//! HydraClient::connect_producer(server_addr, &session_id, session_key).await?;
//! producer.broadcast(b"you are an idiot").await?;
//!
//! // Consumer; receives and decrypts frames from the producer
//! let mut consumer =
//! HydraClient::connect_consumer(server_addr, &session_id, session_key).await?;
//!
//! loop {
//! let data = consumer.recv().await?;
//! println!("received {} bytes: {:?}", data.len(), data);
//!
//! // `data` borrows from `consumer`'s internal memory pool and is
//! // only valid until the next `recv()` or `broadcast()` call.
//! // Copy it out (e.g. `data.to_vec()`) if you need to keep it longer.
//! break;
//! }
//! producer.close().await?; // clean shutdown
//!
//! Ok(())
//!}
//! ```
//!
//! ### Memory Overhead
//!
//! Each client maintains a 18 MB internal memory pool (`BytesMut`) for:
//! - Buffering encrypted frames during read/write operations
//! - In-place encryption and decryption without allocating new buffers
//! - Reusing memory across multiple `recv()`/`broadcast()` calls
//!
//! This zero-copy design minimizes garbage collection pressure and reduces latency for
//! high-throughput scenarios.
//!
pub
pub
pub
/// Buffer size for `BufReader` and `BufWriter` in TCP operations (6 MB)
pub const BUFFER_SIZE: usize = 1024 * 1024 * 6;