progress
This commit is contained in:
parent
34f8ed4bc8
commit
6c02e9a0a5
@ -16,7 +16,10 @@ path = "src/bellande_mesh_sync.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.28", features = ["rt", "net", "time", "sync", "macros"] }
|
tokio = { version = "1.28", features = ["rt", "net", "time", "sync", "macros"] }
|
||||||
|
hyper-rustls = { version = "0.24", features = ["http1", "http2"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
hyper = { version = "0.14", features = ["full"] }
|
||||||
|
futures = "0.3"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
bincode = "1.3"
|
bincode = "1.3"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
30
README.md
30
README.md
@ -2,6 +2,36 @@
|
|||||||
|
|
||||||
- a comprehensive data synchronization system
|
- a comprehensive data synchronization system
|
||||||
|
|
||||||
|
# Features
|
||||||
|
**Full Protocol Support:**
|
||||||
|
- TCP/UDP handling
|
||||||
|
- HTTP/HTTPS servers
|
||||||
|
- TLS encryption
|
||||||
|
- Binary message protocol
|
||||||
|
|
||||||
|
**Node Management:**
|
||||||
|
- Node discovery
|
||||||
|
- Dead node cleanup
|
||||||
|
- Peer synchronization
|
||||||
|
- Data chunk handling
|
||||||
|
|
||||||
|
**Message Handling:**
|
||||||
|
- Asynchronous message processing
|
||||||
|
- Multiple message types
|
||||||
|
- Error handling
|
||||||
|
- Rate limiting
|
||||||
|
|
||||||
|
**Monitoring:**
|
||||||
|
- Network statistics
|
||||||
|
- Status reporting
|
||||||
|
- Error logging
|
||||||
|
- Performance metrics
|
||||||
|
|
||||||
|
**Security:**
|
||||||
|
- TLS encryption
|
||||||
|
- Token validation
|
||||||
|
- Node authentication
|
||||||
|
|
||||||
## Website Crates
|
## Website Crates
|
||||||
- https://crates.io/crates/bellande_mesh_sync
|
- https://crates.io/crates/bellande_mesh_sync
|
||||||
|
|
||||||
|
@ -38,5 +38,5 @@ pub async fn init(config: Config) -> Result<BellandeMeshSync, BellandeMeshError>
|
|||||||
/// Start the BellandeMeshSync System
|
/// Start the BellandeMeshSync System
|
||||||
/// This function takes a BellandeMeshSync instance and starts the mesh network operations.
|
/// This function takes a BellandeMeshSync instance and starts the mesh network operations.
|
||||||
pub async fn start(bellande_mesh: &BellandeMeshSync) -> Result<(), BellandeMeshError> {
|
pub async fn start(bellande_mesh: &BellandeMeshSync) -> Result<(), BellandeMeshError> {
|
||||||
bellande_mesh.start()
|
bellande_mesh.start().await
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ pub enum BellandeMeshError {
|
|||||||
NetworkError(String),
|
NetworkError(String),
|
||||||
ArrayConversionError(TryFromSliceError),
|
ArrayConversionError(TryFromSliceError),
|
||||||
Timeout,
|
Timeout,
|
||||||
|
Custom(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BellandeMeshError {
|
impl fmt::Display for BellandeMeshError {
|
||||||
@ -64,6 +65,7 @@ impl fmt::Display for BellandeMeshError {
|
|||||||
write!(f, "Array conversion error: {}", e)
|
write!(f, "Array conversion error: {}", e)
|
||||||
}
|
}
|
||||||
BellandeMeshError::Timeout => write!(f, "Operation timed out"),
|
BellandeMeshError::Timeout => write!(f, "Operation timed out"),
|
||||||
|
BellandeMeshError::Custom(err) => write!(f, "Custom error: {}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
661
src/mesh/mesh.rs
661
src/mesh/mesh.rs
@ -16,28 +16,108 @@
|
|||||||
use crate::config::config::Config;
|
use crate::config::config::Config;
|
||||||
use crate::error::error::BellandeMeshError;
|
use crate::error::error::BellandeMeshError;
|
||||||
use crate::node::node::{DataChunk, Message, Node, NodeId, PublicKey};
|
use crate::node::node::{DataChunk, Message, Node, NodeId, PublicKey};
|
||||||
|
use hyper::service::{make_service_fn, service_fn};
|
||||||
|
use hyper::{Body, Client, Request, Response, Server, StatusCode};
|
||||||
|
use hyper_rustls::HttpsConnectorBuilder;
|
||||||
|
use serde::Serialize;
|
||||||
|
use std::convert::Infallible;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::net::{SocketAddr, TcpListener, TcpStream};
|
use std::net::{SocketAddr, TcpStream};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::thread;
|
use std::time::{Duration, SystemTime};
|
||||||
use std::time::Duration;
|
use tokio::net::{TcpListener as TokioTcpListener, UdpSocket as TokioUdpSocket};
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
use tokio_rustls::rustls::{Certificate, PrivateKey, ServerConfig};
|
||||||
|
use tokio_rustls::TlsAcceptor;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
struct NetworkStats {
|
||||||
|
tcp_connections: usize,
|
||||||
|
udp_packets_received: usize,
|
||||||
|
http_requests: usize,
|
||||||
|
https_requests: usize,
|
||||||
|
active_nodes: usize,
|
||||||
|
total_messages: usize,
|
||||||
|
start_time: SystemTime,
|
||||||
|
last_sync: SystemTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NetworkStats {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
tcp_connections: 0,
|
||||||
|
udp_packets_received: 0,
|
||||||
|
http_requests: 0,
|
||||||
|
https_requests: 0,
|
||||||
|
active_nodes: 0,
|
||||||
|
total_messages: 0,
|
||||||
|
start_time: SystemTime::now(),
|
||||||
|
last_sync: SystemTime::now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BellandeMeshSync {
|
pub struct BellandeMeshSync {
|
||||||
config: Arc<Config>,
|
config: Arc<Config>,
|
||||||
nodes: Arc<RwLock<Vec<Node>>>,
|
nodes: Arc<RwLock<Vec<Node>>>,
|
||||||
running: Arc<RwLock<bool>>,
|
running: Arc<RwLock<bool>>,
|
||||||
|
tls_config: Arc<ServerConfig>,
|
||||||
|
http_client: Client<hyper::client::HttpConnector>,
|
||||||
|
https_client: Client<hyper_rustls::HttpsConnector<hyper::client::HttpConnector>>,
|
||||||
|
stats: Arc<RwLock<NetworkStats>>,
|
||||||
|
message_tx: mpsc::Sender<(Message, SocketAddr)>,
|
||||||
|
message_rx: Arc<tokio::sync::Mutex<mpsc::Receiver<(Message, SocketAddr)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BellandeMeshSync {
|
impl BellandeMeshSync {
|
||||||
pub fn new(config: &Config) -> Result<Self, BellandeMeshError> {
|
pub fn new(config: &Config) -> Result<Self, BellandeMeshError> {
|
||||||
|
let tls_config = Self::create_tls_config()?;
|
||||||
|
let http_client = Client::new();
|
||||||
|
let https_connector = HttpsConnectorBuilder::new()
|
||||||
|
.with_native_roots()
|
||||||
|
.https_only()
|
||||||
|
.enable_http1()
|
||||||
|
.build();
|
||||||
|
let https_client = Client::builder().build(https_connector);
|
||||||
|
|
||||||
|
let (message_tx, message_rx) = mpsc::channel(CHANNEL_BUFFER_SIZE);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
config: Arc::new(config.clone()),
|
config: Arc::new(config.clone()),
|
||||||
nodes: Arc::new(RwLock::new(Vec::new())),
|
nodes: Arc::new(RwLock::new(Vec::new())),
|
||||||
running: Arc::new(RwLock::new(true)),
|
running: Arc::new(RwLock::new(true)),
|
||||||
|
tls_config: Arc::new(tls_config),
|
||||||
|
http_client,
|
||||||
|
https_client,
|
||||||
|
stats: Arc::new(RwLock::new(NetworkStats::default())),
|
||||||
|
message_tx,
|
||||||
|
message_rx: Arc::new(tokio::sync::Mutex::new(message_rx)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&self) -> Result<(), BellandeMeshError> {
|
fn create_tls_config() -> Result<ServerConfig, BellandeMeshError> {
|
||||||
|
let cert_path = Path::new("certs/server.crt");
|
||||||
|
let key_path = Path::new("certs/server.key");
|
||||||
|
|
||||||
|
let cert_data = fs::read(cert_path)
|
||||||
|
.map_err(|e| BellandeMeshError::Custom(format!("Failed to read certificate: {}", e)))?;
|
||||||
|
let key_data = fs::read(key_path)
|
||||||
|
.map_err(|e| BellandeMeshError::Custom(format!("Failed to read key: {}", e)))?;
|
||||||
|
|
||||||
|
let cert = Certificate(cert_data);
|
||||||
|
let key = PrivateKey(key_data);
|
||||||
|
|
||||||
|
let config = ServerConfig::builder()
|
||||||
|
.with_safe_defaults()
|
||||||
|
.with_no_client_auth()
|
||||||
|
.with_single_cert(vec![cert], key)
|
||||||
|
.map_err(|e| BellandeMeshError::Custom(format!("TLS config error: {}", e)))?;
|
||||||
|
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start(&self) -> Result<(), BellandeMeshError> {
|
||||||
let mut running = self
|
let mut running = self
|
||||||
.running
|
.running
|
||||||
.write()
|
.write()
|
||||||
@ -45,12 +125,14 @@ impl BellandeMeshSync {
|
|||||||
*running = true;
|
*running = true;
|
||||||
drop(running);
|
drop(running);
|
||||||
|
|
||||||
self.start_listener()?;
|
self.start_message_handler().await?;
|
||||||
self.start_maintenance_tasks();
|
self.start_protocol_listeners().await?;
|
||||||
|
self.start_maintenance_tasks().await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop(&self) -> Result<(), BellandeMeshError> {
|
pub async fn stop(&self) -> Result<(), BellandeMeshError> {
|
||||||
let mut running = self
|
let mut running = self
|
||||||
.running
|
.running
|
||||||
.write()
|
.write()
|
||||||
@ -59,33 +141,74 @@ impl BellandeMeshSync {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_running(&self) -> Result<bool, BellandeMeshError> {
|
async fn start_message_handler(&self) -> Result<(), BellandeMeshError> {
|
||||||
self.running
|
let handler = self.clone();
|
||||||
.read()
|
tokio::spawn(async move {
|
||||||
.map_err(|_| BellandeMeshError::LockError)
|
while let Some((message, addr)) = handler.message_rx.recv().await {
|
||||||
.map(|guard| *guard)
|
if let Err(e) = handler.handle_message_internal(message, addr).await {
|
||||||
|
eprintln!("Message handling error from {}: {}", addr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_listener(&self) -> Result<(), BellandeMeshError> {
|
async fn start_protocol_listeners(&self) -> Result<(), BellandeMeshError> {
|
||||||
let listener = TcpListener::bind(&self.config.listen_address)?;
|
self.start_tcp_listener().await?;
|
||||||
let mesh = self.clone();
|
self.start_udp_listener().await?;
|
||||||
|
self.start_http_server().await?;
|
||||||
|
self.start_https_server().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
thread::spawn(move || {
|
async fn start_tcp_listener(&self) -> Result<(), BellandeMeshError> {
|
||||||
for stream in listener.incoming() {
|
let addr = self
|
||||||
if !mesh.is_running().unwrap_or(false) {
|
.config
|
||||||
break;
|
.listen_address
|
||||||
|
.parse::<SocketAddr>()
|
||||||
|
.map_err(|e| BellandeMeshError::Custom(format!("Invalid address: {}", e)))?;
|
||||||
|
let listener = TokioTcpListener::bind(addr).await?;
|
||||||
|
let handler = self.clone();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while handler.is_running().unwrap_or(false) {
|
||||||
|
if let Ok((stream, addr)) = listener.accept().await {
|
||||||
|
let handler = handler.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = handler.handle_tcp_connection(stream).await {
|
||||||
|
eprintln!("TCP error from {}: {}", addr, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
match stream {
|
Ok(())
|
||||||
Ok(stream) => {
|
}
|
||||||
let mesh_clone = mesh.clone();
|
|
||||||
thread::spawn(move || {
|
async fn start_udp_listener(&self) -> Result<(), BellandeMeshError> {
|
||||||
if let Err(e) = mesh_clone.handle_connection(stream) {
|
let addr = self
|
||||||
eprintln!("Connection error: {}", e);
|
.config
|
||||||
|
.listen_address
|
||||||
|
.parse::<SocketAddr>()
|
||||||
|
.map_err(|e| BellandeMeshError::Custom(format!("Invalid address: {}", e)))?;
|
||||||
|
let socket = TokioUdpSocket::bind(addr).await?;
|
||||||
|
let handler = self.clone();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut buf = [0u8; UDP_BUFFER_SIZE];
|
||||||
|
while handler.is_running().unwrap_or(false) {
|
||||||
|
match socket.recv_from(&mut buf).await {
|
||||||
|
Ok((len, src)) => {
|
||||||
|
let handler = handler.clone();
|
||||||
|
let data = buf[..len].to_vec();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = handler.handle_udp_packet(&data, src).await {
|
||||||
|
eprintln!("UDP error from {}: {}", src, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => eprintln!("Accept error: {}", e),
|
Err(e) => eprintln!("UDP receive error: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -93,130 +216,311 @@ impl BellandeMeshSync {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_maintenance_tasks(&self) {
|
async fn start_http_server(&self) -> Result<(), BellandeMeshError> {
|
||||||
// Start sync task
|
let addr = self
|
||||||
let mesh = self.clone();
|
.config
|
||||||
thread::spawn(move || {
|
.listen_address
|
||||||
while let Ok(true) = mesh.is_running() {
|
.parse::<SocketAddr>()
|
||||||
if let Err(e) = mesh.sync_with_peers() {
|
.map_err(|e| BellandeMeshError::Custom(format!("Invalid address: {}", e)))?;
|
||||||
eprintln!("Sync error: {}", e);
|
let http_addr = SocketAddr::new(addr.ip(), addr.port() + HTTP_PORT_OFFSET);
|
||||||
}
|
|
||||||
thread::sleep(Duration::from_secs(60));
|
let handler = self.clone();
|
||||||
|
let make_service = make_service_fn(move |_| {
|
||||||
|
let handler = handler.clone();
|
||||||
|
async move {
|
||||||
|
Ok::<_, Infallible>(service_fn(move |req| {
|
||||||
|
let handler = handler.clone();
|
||||||
|
async move { handler.handle_http_request(req).await }
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Start cleanup task
|
let server = Server::bind(&http_addr).serve(make_service);
|
||||||
let mesh = self.clone();
|
tokio::spawn(server);
|
||||||
thread::spawn(move || {
|
|
||||||
while let Ok(true) = mesh.is_running() {
|
Ok(())
|
||||||
if let Err(e) = mesh.cleanup_dead_nodes() {
|
|
||||||
eprintln!("Cleanup error: {}", e);
|
|
||||||
}
|
|
||||||
thread::sleep(Duration::from_secs(300));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_connection(&self, mut stream: TcpStream) -> Result<(), BellandeMeshError> {
|
async fn start_https_server(&self) -> Result<(), BellandeMeshError> {
|
||||||
stream.set_read_timeout(Some(Duration::from_secs(30)))?;
|
let addr = self
|
||||||
stream.set_write_timeout(Some(Duration::from_secs(30)))?;
|
.config
|
||||||
|
.listen_address
|
||||||
|
.parse::<SocketAddr>()
|
||||||
|
.map_err(|e| BellandeMeshError::Custom(format!("Invalid address: {}", e)))?;
|
||||||
|
let https_addr = SocketAddr::new(addr.ip(), addr.port() + HTTPS_PORT_OFFSET);
|
||||||
|
|
||||||
let running = self
|
let tls_cfg = self.tls_config.clone();
|
||||||
.running
|
let handler = self.clone();
|
||||||
.read()
|
let acceptor = TlsAcceptor::from(tls_cfg);
|
||||||
.map_err(|_| BellandeMeshError::LockError)?;
|
|
||||||
while *running {
|
let listener = TokioTcpListener::bind(https_addr).await?;
|
||||||
let message = self.read_message(&mut stream)?;
|
|
||||||
self.handle_message(message, &mut stream)?;
|
tokio::spawn(async move {
|
||||||
|
while handler.is_running().unwrap_or(false) {
|
||||||
|
if let Ok((stream, addr)) = listener.accept().await {
|
||||||
|
let acceptor = acceptor.clone();
|
||||||
|
let handler = handler.clone();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
match acceptor.accept(stream).await {
|
||||||
|
Ok(tls_stream) => {
|
||||||
|
if let Err(e) = handler.handle_https_connection(tls_stream).await {
|
||||||
|
eprintln!("HTTPS error from {}: {}", addr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => eprintln!("TLS accept error from {}: {}", addr, e),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn start_maintenance_tasks(&self) -> Result<(), BellandeMeshError> {
|
||||||
|
let sync_handler = self.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while sync_handler.is_running().unwrap_or(false) {
|
||||||
|
if let Err(e) = sync_handler.sync_with_peers().await {
|
||||||
|
eprintln!("Sync error: {}", e);
|
||||||
|
}
|
||||||
|
sleep(SYNC_INTERVAL).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let cleanup_handler = self.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while cleanup_handler.is_running().unwrap_or(false) {
|
||||||
|
if let Err(e) = cleanup_handler.cleanup_dead_nodes().await {
|
||||||
|
eprintln!("Cleanup error: {}", e);
|
||||||
|
}
|
||||||
|
sleep(CLEANUP_INTERVAL).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let ping_handler = self.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while ping_handler.is_running().unwrap_or(false) {
|
||||||
|
if let Err(e) = ping_handler.send_ping_to_all_nodes().await {
|
||||||
|
eprintln!("Ping error: {}", e);
|
||||||
|
}
|
||||||
|
sleep(PING_INTERVAL).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_tcp_connection<S>(&self, stream: S) -> Result<(), BellandeMeshError>
|
||||||
|
where
|
||||||
|
S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin,
|
||||||
|
{
|
||||||
|
let (mut reader, mut writer) = tokio::io::split(stream);
|
||||||
|
let mut buf = [0u8; MAX_MESSAGE_SIZE];
|
||||||
|
|
||||||
|
while self.is_running()? {
|
||||||
|
match self.read_async_message(&mut reader, &mut buf).await {
|
||||||
|
Ok(message) => {
|
||||||
|
self.update_stats(|stats| stats.total_messages += 1);
|
||||||
|
if let Err(e) = self.write_async_message(&mut writer, &message).await {
|
||||||
|
eprintln!("Write error: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Read error: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_message(&self, stream: &mut TcpStream) -> Result<Message, BellandeMeshError> {
|
async fn read_async_message<S>(
|
||||||
|
&self,
|
||||||
|
reader: &mut S,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<Message, BellandeMeshError>
|
||||||
|
where
|
||||||
|
S: tokio::io::AsyncRead + Unpin,
|
||||||
|
{
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
let mut len_buf = [0u8; 4];
|
let mut len_buf = [0u8; 4];
|
||||||
stream.read_exact(&mut len_buf)?;
|
reader.read_exact(&mut len_buf).await?;
|
||||||
let len = u32::from_be_bytes(len_buf) as usize;
|
let len = u32::from_be_bytes(len_buf) as usize;
|
||||||
|
|
||||||
let mut msg_buf = vec![0u8; len];
|
if len > MAX_MESSAGE_SIZE {
|
||||||
stream.read_exact(&mut msg_buf)?;
|
return Err(BellandeMeshError::Custom("Message too large".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
bincode::deserialize(&msg_buf)
|
reader.read_exact(&mut buf[..len]).await?;
|
||||||
|
bincode::deserialize(&buf[..len])
|
||||||
.map_err(|e| BellandeMeshError::Deserialization(e.to_string()))
|
.map_err(|e| BellandeMeshError::Deserialization(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_message(
|
async fn write_async_message<S>(
|
||||||
&self,
|
&self,
|
||||||
stream: &mut TcpStream,
|
writer: &mut S,
|
||||||
message: &Message,
|
message: &Message,
|
||||||
) -> Result<(), BellandeMeshError> {
|
) -> Result<(), BellandeMeshError>
|
||||||
|
where
|
||||||
|
S: tokio::io::AsyncWrite + Unpin,
|
||||||
|
{
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
let data = bincode::serialize(message)
|
let data = bincode::serialize(message)
|
||||||
.map_err(|e| BellandeMeshError::Serialization(e.to_string()))?;
|
.map_err(|e| BellandeMeshError::Serialization(e.to_string()))?;
|
||||||
let len = (data.len() as u32).to_be_bytes();
|
|
||||||
|
|
||||||
stream.write_all(&len)?;
|
if data.len() > MAX_MESSAGE_SIZE {
|
||||||
stream.write_all(&data)?;
|
return Err(BellandeMeshError::Custom("Message too large".to_string()));
|
||||||
stream.flush()?;
|
}
|
||||||
|
|
||||||
|
writer.write_all(&(data.len() as u32).to_be_bytes()).await?;
|
||||||
|
writer.write_all(&data).await?;
|
||||||
|
writer.flush().await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_message(
|
async fn handle_udp_packet(
|
||||||
|
&self,
|
||||||
|
data: &[u8],
|
||||||
|
src: SocketAddr,
|
||||||
|
) -> Result<(), BellandeMeshError> {
|
||||||
|
let message = bincode::deserialize(data)
|
||||||
|
.map_err(|e| BellandeMeshError::Deserialization(e.to_string()))?;
|
||||||
|
|
||||||
|
self.update_stats(|stats| stats.udp_packets_received += 1);
|
||||||
|
self.handle_message_internal(message, src).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_http_request(&self, req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||||
|
self.update_stats(|stats| stats.http_requests += 1);
|
||||||
|
|
||||||
|
let response = match (req.method(), req.uri().path()) {
|
||||||
|
(&hyper::Method::GET, "/status") => {
|
||||||
|
let status = self.get_status().await;
|
||||||
|
Response::new(Body::from(status))
|
||||||
|
}
|
||||||
|
(&hyper::Method::POST, "/join") => match hyper::body::to_bytes(req.into_body()).await {
|
||||||
|
Ok(bytes) => match self.handle_join_request(bytes.to_vec()).await {
|
||||||
|
Ok(_) => Response::new(Body::from("Joined successfully")),
|
||||||
|
Err(e) => Response::builder()
|
||||||
|
.status(StatusCode::BAD_REQUEST)
|
||||||
|
.body(Body::from(format!("Join failed: {}", e)))
|
||||||
|
.unwrap(),
|
||||||
|
},
|
||||||
|
Err(e) => Response::builder()
|
||||||
|
.status(StatusCode::BAD_REQUEST)
|
||||||
|
.body(Body::from(format!("Invalid request: {}", e)))
|
||||||
|
.unwrap(),
|
||||||
|
},
|
||||||
|
_ => Response::builder()
|
||||||
|
.status(StatusCode::NOT_FOUND)
|
||||||
|
.body(Body::from("Not Found"))
|
||||||
|
.unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_https_connection<S>(&self, stream: S) -> Result<(), BellandeMeshError>
|
||||||
|
where
|
||||||
|
S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin,
|
||||||
|
{
|
||||||
|
self.update_stats(|stats| stats.https_requests += 1);
|
||||||
|
self.handle_tcp_connection(stream).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_message_internal(
|
||||||
&self,
|
&self,
|
||||||
message: Message,
|
message: Message,
|
||||||
stream: &mut TcpStream,
|
src: SocketAddr,
|
||||||
) -> Result<(), BellandeMeshError> {
|
) -> Result<(), BellandeMeshError> {
|
||||||
match message {
|
match message {
|
||||||
Message::JoinRequest { id, public_key } => {
|
Message::JoinRequest { id, public_key } => {
|
||||||
let peer_addr = stream.peer_addr()?;
|
self.handle_join_request_internal(id, public_key, src)
|
||||||
self.handle_join_request(id, public_key, peer_addr)?;
|
.await?;
|
||||||
|
|
||||||
let nodes = self
|
|
||||||
.nodes
|
|
||||||
.read()
|
|
||||||
.map_err(|_| BellandeMeshError::LockError)?;
|
|
||||||
let response = Message::JoinResponse {
|
|
||||||
accepted: true,
|
|
||||||
nodes: nodes.clone(),
|
|
||||||
};
|
|
||||||
self.write_message(stream, &response)?;
|
|
||||||
}
|
}
|
||||||
Message::DataSync { chunks } => {
|
Message::DataSync { chunks } => {
|
||||||
self.handle_data_sync(chunks)?;
|
self.handle_data_sync(chunks).await?;
|
||||||
}
|
}
|
||||||
Message::DataRequest { ids } => {
|
Message::DataRequest { ids } => {
|
||||||
self.handle_data_request(&ids, stream)?;
|
self.handle_data_request(&ids, src).await?;
|
||||||
|
}
|
||||||
|
Message::Ping { sender, token } => {
|
||||||
|
self.handle_ping(sender, token, src).await?;
|
||||||
|
}
|
||||||
|
Message::Pong { sender, token } => {
|
||||||
|
self.handle_pong(sender, token, src).await?;
|
||||||
}
|
}
|
||||||
Message::Heartbeat => {
|
Message::Heartbeat => {
|
||||||
let addr = stream.peer_addr()?;
|
self.update_node_last_seen(src).await?;
|
||||||
self.update_node_last_seen(addr)?;
|
}
|
||||||
|
_ => {
|
||||||
|
eprintln!("Unhandled message type from {}", src);
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_join_request(
|
async fn update_node_last_seen(&self, addr: SocketAddr) -> Result<(), BellandeMeshError> {
|
||||||
|
let mut nodes = self
|
||||||
|
.nodes
|
||||||
|
.write()
|
||||||
|
.map_err(|_| BellandeMeshError::LockError)?;
|
||||||
|
if let Some(node) = nodes.iter_mut().find(|n| n.address == addr) {
|
||||||
|
node.update_last_seen();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_join_request(&self, data: Vec<u8>) -> Result<(), BellandeMeshError> {
|
||||||
|
let request: Message = bincode::deserialize(&data)
|
||||||
|
.map_err(|e| BellandeMeshError::Deserialization(e.to_string()))?;
|
||||||
|
|
||||||
|
match request {
|
||||||
|
Message::JoinRequest { id, public_key } => {
|
||||||
|
let addr = SocketAddr::new(
|
||||||
|
std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)),
|
||||||
|
rand::random::<u16>(),
|
||||||
|
);
|
||||||
|
self.handle_join_request_internal(id, public_key, addr)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
_ => Err(BellandeMeshError::Custom(
|
||||||
|
"Invalid message type".to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_join_request_internal(
|
||||||
&self,
|
&self,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
public_key: PublicKey,
|
public_key: PublicKey,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
) -> Result<(), BellandeMeshError> {
|
) -> Result<(), BellandeMeshError> {
|
||||||
let new_node = Node::new(id, addr, public_key);
|
let new_node = Node::new(id, addr, public_key);
|
||||||
let mut nodes = self
|
|
||||||
.nodes
|
|
||||||
.write()
|
|
||||||
.map_err(|_| BellandeMeshError::LockError)?;
|
|
||||||
|
|
||||||
if !nodes.iter().any(|n| n.id == new_node.id) {
|
{
|
||||||
nodes.push(new_node);
|
let mut nodes = self
|
||||||
|
.nodes
|
||||||
|
.write()
|
||||||
|
.map_err(|_| BellandeMeshError::LockError)?;
|
||||||
|
if !nodes.iter().any(|n| n.id == new_node.id) {
|
||||||
|
nodes.push(new_node.clone());
|
||||||
|
self.update_stats(|stats| stats.active_nodes += 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.broadcast_new_node(&new_node).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_data_sync(&self, chunks: Vec<DataChunk>) -> Result<(), BellandeMeshError> {
|
async fn handle_data_sync(&self, chunks: Vec<DataChunk>) -> Result<(), BellandeMeshError> {
|
||||||
let nodes = self
|
let nodes = self
|
||||||
.nodes
|
.nodes
|
||||||
.read()
|
.read()
|
||||||
@ -231,10 +535,10 @@ impl BellandeMeshSync {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_data_request(
|
async fn handle_data_request(
|
||||||
&self,
|
&self,
|
||||||
ids: &[NodeId],
|
ids: &[NodeId],
|
||||||
stream: &mut TcpStream,
|
src: SocketAddr,
|
||||||
) -> Result<(), BellandeMeshError> {
|
) -> Result<(), BellandeMeshError> {
|
||||||
let nodes = self
|
let nodes = self
|
||||||
.nodes
|
.nodes
|
||||||
@ -251,32 +555,69 @@ impl BellandeMeshSync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let response = Message::DataSync { chunks };
|
let response = Message::DataSync { chunks };
|
||||||
self.write_message(stream, &response)?;
|
self.send_message(src, &response).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_node_last_seen(&self, addr: SocketAddr) -> Result<(), BellandeMeshError> {
|
async fn handle_ping(
|
||||||
|
&self,
|
||||||
|
sender: NodeId,
|
||||||
|
token: u64,
|
||||||
|
src: SocketAddr,
|
||||||
|
) -> Result<(), BellandeMeshError> {
|
||||||
|
let response = Message::Pong {
|
||||||
|
sender: self.get_local_id()?,
|
||||||
|
token,
|
||||||
|
};
|
||||||
|
self.send_message(src, &response).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_pong(
|
||||||
|
&self,
|
||||||
|
sender: NodeId,
|
||||||
|
token: u64,
|
||||||
|
src: SocketAddr,
|
||||||
|
) -> Result<(), BellandeMeshError> {
|
||||||
let mut nodes = self
|
let mut nodes = self
|
||||||
.nodes
|
.nodes
|
||||||
.write()
|
.write()
|
||||||
.map_err(|_| BellandeMeshError::LockError)?;
|
.map_err(|_| BellandeMeshError::LockError)?;
|
||||||
|
if let Some(node) = nodes.iter_mut().find(|n| n.id == sender) {
|
||||||
if let Some(node) = nodes.iter_mut().find(|n| n.address == addr) {
|
|
||||||
node.update_last_seen();
|
node.update_last_seen();
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn broadcast_new_node(&self, new_node: &Node) -> Result<(), BellandeMeshError> {
|
||||||
|
let nodes = self
|
||||||
|
.nodes
|
||||||
|
.read()
|
||||||
|
.map_err(|_| BellandeMeshError::LockError)?;
|
||||||
|
let message = Message::JoinResponse {
|
||||||
|
accepted: true,
|
||||||
|
nodes: vec![new_node.clone()],
|
||||||
|
};
|
||||||
|
|
||||||
|
for node in nodes.iter() {
|
||||||
|
if node.id != new_node.id {
|
||||||
|
if let Err(e) = self.send_message(node.address, &message).await {
|
||||||
|
eprintln!("Failed to broadcast new node to {}: {}", node.address, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_with_peers(&self) -> Result<(), BellandeMeshError> {
|
async fn sync_with_peers(&self) -> Result<(), BellandeMeshError> {
|
||||||
// Take a snapshot of current nodes to avoid holding the lock
|
|
||||||
let nodes = {
|
let nodes = {
|
||||||
let nodes_guard = self
|
let nodes_guard = self
|
||||||
.nodes
|
.nodes
|
||||||
.read()
|
.read()
|
||||||
.map_err(|_| BellandeMeshError::LockError)?;
|
.map_err(|_| BellandeMeshError::LockError)?;
|
||||||
nodes_guard.clone()
|
nodes_guard.to_vec()
|
||||||
};
|
};
|
||||||
|
|
||||||
for node in nodes {
|
for node in nodes {
|
||||||
@ -287,28 +628,33 @@ impl BellandeMeshSync {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let request = Message::DataRequest { ids: chunks };
|
let request = Message::DataRequest { ids: chunks };
|
||||||
if let Err(e) = self.write_message(&mut stream, &request) {
|
if let Err(e) = self.send_message(node.address, &request).await {
|
||||||
eprintln!("Failed to sync with {}: {}", node.address, e);
|
eprintln!("Failed to sync with {}: {}", node.address, e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle response
|
match self.read_message(&mut stream).await {
|
||||||
if let Ok(Message::DataSync { chunks }) = self.read_message(&mut stream) {
|
Ok(Message::DataSync { chunks }) => {
|
||||||
self.handle_data_sync(chunks)?;
|
self.handle_data_sync(chunks).await?;
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("Unexpected response from {}", node.address),
|
||||||
|
Err(e) => eprintln!("Error reading sync response from {}: {}", node.address, e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.update_stats(|stats| stats.last_sync = SystemTime::now());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cleanup_dead_nodes(&self) -> Result<(), BellandeMeshError> {
|
async fn cleanup_dead_nodes(&self) -> Result<(), BellandeMeshError> {
|
||||||
let timeout = Duration::from_secs(self.config.node_timeout);
|
let timeout = Duration::from_secs(self.config.node_timeout);
|
||||||
let mut nodes = self
|
let mut nodes = self
|
||||||
.nodes
|
.nodes
|
||||||
.write()
|
.write()
|
||||||
.map_err(|_| BellandeMeshError::LockError)?;
|
.map_err(|_| BellandeMeshError::LockError)?;
|
||||||
|
|
||||||
|
let initial_count = nodes.len();
|
||||||
nodes.retain(|node| {
|
nodes.retain(|node| {
|
||||||
let is_alive = node.is_alive(timeout);
|
let is_alive = node.is_alive(timeout);
|
||||||
if !is_alive {
|
if !is_alive {
|
||||||
@ -317,8 +663,99 @@ impl BellandeMeshSync {
|
|||||||
is_alive
|
is_alive
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let removed = initial_count - nodes.len();
|
||||||
|
if removed > 0 {
|
||||||
|
self.update_stats(|stats| stats.active_nodes -= removed);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn send_ping_to_all_nodes(&self) -> Result<(), BellandeMeshError> {
|
||||||
|
let nodes = self
|
||||||
|
.nodes
|
||||||
|
.read()
|
||||||
|
.map_err(|_| BellandeMeshError::LockError)?;
|
||||||
|
let token = rand::random::<u64>();
|
||||||
|
let ping = Message::Ping {
|
||||||
|
sender: self.get_local_id()?,
|
||||||
|
token,
|
||||||
|
};
|
||||||
|
|
||||||
|
for node in nodes.iter() {
|
||||||
|
if let Err(e) = self.send_message(node.address, &ping).await {
|
||||||
|
eprintln!("Failed to ping {}: {}", node.address, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_message(&self, addr: SocketAddr, msg: &Message) -> Result<(), BellandeMeshError> {
|
||||||
|
let data =
|
||||||
|
bincode::serialize(msg).map_err(|e| BellandeMeshError::Serialization(e.to_string()))?;
|
||||||
|
|
||||||
|
if data.len() > MAX_MESSAGE_SIZE {
|
||||||
|
return Err(BellandeMeshError::Custom("Message too large".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut stream =
|
||||||
|
TcpStream::connect(addr).map_err(|e| BellandeMeshError::NetworkError(e.to_string()))?;
|
||||||
|
|
||||||
|
stream.write_all(&(data.len() as u32).to_be_bytes())?;
|
||||||
|
stream.write_all(&data)?;
|
||||||
|
stream.flush()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_message(&self, stream: &mut TcpStream) -> Result<Message, BellandeMeshError> {
|
||||||
|
let mut len_buf = [0u8; 4];
|
||||||
|
stream.read_exact(&mut len_buf)?;
|
||||||
|
let len = u32::from_be_bytes(len_buf) as usize;
|
||||||
|
|
||||||
|
if len > MAX_MESSAGE_SIZE {
|
||||||
|
return Err(BellandeMeshError::Custom("Message too large".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut msg_buf = vec![0u8; len];
|
||||||
|
stream.read_exact(&mut msg_buf)?;
|
||||||
|
|
||||||
|
bincode::deserialize(&msg_buf)
|
||||||
|
.map_err(|e| BellandeMeshError::Deserialization(e.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_status(&self) -> String {
|
||||||
|
let stats = self
|
||||||
|
.stats
|
||||||
|
.read()
|
||||||
|
.map(|stats| stats.clone())
|
||||||
|
.unwrap_or_else(|_| NetworkStats::default());
|
||||||
|
serde_json::to_string_pretty(&stats).unwrap_or_else(|_| "Error getting status".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_stats<F>(&self, updater: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut NetworkStats),
|
||||||
|
{
|
||||||
|
if let Ok(mut stats) = self.stats.write() {
|
||||||
|
updater(&mut stats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_running(&self) -> Result<bool, BellandeMeshError> {
|
||||||
|
self.running
|
||||||
|
.read()
|
||||||
|
.map_err(|_| BellandeMeshError::LockError)
|
||||||
|
.map(|guard| *guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_local_id(&self) -> Result<NodeId, BellandeMeshError> {
|
||||||
|
self.nodes
|
||||||
|
.read()
|
||||||
|
.map_err(|_| BellandeMeshError::LockError)
|
||||||
|
.map(|nodes| nodes.first().map(|n| n.id).unwrap_or_else(|| NodeId::new()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for BellandeMeshSync {
|
impl Clone for BellandeMeshSync {
|
||||||
@ -327,6 +764,12 @@ impl Clone for BellandeMeshSync {
|
|||||||
config: Arc::clone(&self.config),
|
config: Arc::clone(&self.config),
|
||||||
nodes: Arc::clone(&self.nodes),
|
nodes: Arc::clone(&self.nodes),
|
||||||
running: Arc::clone(&self.running),
|
running: Arc::clone(&self.running),
|
||||||
|
tls_config: Arc::clone(&self.tls_config),
|
||||||
|
http_client: self.http_client.clone(),
|
||||||
|
https_client: self.https_client.clone(),
|
||||||
|
stats: Arc::clone(&self.stats),
|
||||||
|
message_tx: self.message_tx.clone(),
|
||||||
|
message_rx: Arc::clone(&self.message_rx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user