Skip to main content

netsel/
lib.rs

1//! NetSel - Service Registration and Discovery System
2//! 
3//! A lightweight, Rust-based service registration and discovery system designed for distributed applications.
4//! 
5//! NetSel provides a simple yet powerful way to register services, discover them through a DNS server, and route traffic
6//! between them using built-in proxies. It's built with Tokio for high performance and reliability.
7//! 
8//! ## Features
9//! 
10//! - **Service Registration**: Simple API for services to register themselves
11//! - **Heartbeat Mechanism**: Automatic service health monitoring
12//! - **DNS Resolution**: Service name to IP address resolution
13//! - **TCP and HTTP Proxies**: Built-in traffic routing
14//! - **Virtual Network**: Simplified IP address management
15//! - **Concurrent Design**: Built with Tokio for high performance
16//! - **Fault Tolerance**: Graceful handling of service failures
17//! 
18//! ## Getting Started
19//! 
20//! ```rust,ignore
21//! use tokio::signal;
22//! use netsel::NetSelServer;
23//! 
24//! #[tokio::main]
25//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
26//!     // Create and start NetSel server with default configuration
27//!     let server = NetSelServer::new();
28//!     server.start().await?;
29//!     
30//!     // Wait for shutdown signal
31//!     signal::ctrl_c().await?;
32//!     println!("Shutting down NetSel Service...");
33//!     
34//!     Ok(())
35//! }
36//! ```
37//! 
38//! ## Service Client Example
39//! 
40//! ```rust,ignore
41//! use std::net::{IpAddr, SocketAddr};
42//! use std::str::FromStr;
43//! use tokio::time::Duration;
44//! use netsel::client::ServiceClient;
45//! 
46//! #[tokio::main]
47//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
48//!     let service_a_addr = SocketAddr::from_str("127.0.0.1:9000")?;
49//!     let hostname = "my-service";
50//!     
51//!     // Create service client
52//!     let mut client = ServiceClient::new(service_a_addr, hostname.to_string());
53//!     
54//!     // Register with Service A
55//!     let (assigned_ip, assigned_port) = client.register().await?;
56//!     let assigned_addr = SocketAddr::new(assigned_ip, assigned_port);
57//!     
58//!     println!("Successfully registered! Assigned address: {}", assigned_addr);
59//!     
60//!     // Start heartbeats
61//!     let heartbeat_client = client.clone();
62//!     tokio::spawn(async move {
63//!         loop {
64//!             if let Err(e) = heartbeat_client.send_heartbeat().await {
65//!                 eprintln!("Heartbeat failed: {}", e);
66//!             }
67//!             tokio::time::sleep(Duration::from_secs(10)).await;
68//!         }
69//!     });
70//!     
71//!     // ... start your service logic
72//!     
73//!     Ok(())
74//! }
75//! ```
76//! 
77//! ## Architecture
78//! 
79//! The NetSel system consists of several components working together:
80//! 
81//! 1. **Registry Server**: Manages service registration and heartbeat messages
82//! 2. **TCP Proxy**: Routes TCP traffic between registered services
83//! 3. **HTTP Proxy**: Routes HTTP requests between registered services
84//! 4. **DNS Server**: Resolves service names to IP addresses
85//! 5. **Virtual Network**: Manages IP address allocation for services
86//! 6. **Health Checker**: Monitors service health based on heartbeat messages
87//! 7. **Service Client**: Library for services to register and send heartbeats
88//! 
89//! ## Modules
90//! 
91//! - `client`: Service client implementation for registering services and sending heartbeats
92//! - `dns`: DNS server implementation for service discovery
93//! - `network`: Virtual network implementation for IP allocation
94//! - `proxy`: TCP and HTTP proxy implementations for traffic routing
95//! - `registry`: Service registry implementation for managing service information
96
97pub mod client;
98pub mod dns;
99pub mod network;
100pub mod proxy;
101pub mod registry;
102
103use std::net::{IpAddr, SocketAddr};
104use std::sync::Arc;
105use tokio::time::Duration;
106
107use crate::registry::SharedRegistry;
108
109/// Main NetSel server configuration
110/// 
111/// This struct defines the configuration for the NetSel server, including addresses for all components
112/// and health check settings.
113/// 
114/// # Example
115/// 
116/// ```rust
117/// use std::net::{IpAddr, SocketAddr};
118/// use netsel::NetSelConfig;
119/// 
120/// let config = NetSelConfig {
121///     registry_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 9000),
122///     tcp_proxy_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 8080),
123///     http_proxy_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 8081),
124///     dns_addr: SocketAddr::new(IpAddr::from([127, 0, 0, 1]), 5353),
125///     health_check_interval: 30,
126///     max_heartbeat_age: 60,
127/// };
128/// ```
129pub struct NetSelConfig {
130    /// Address for the registration server where services will register themselves
131    pub registry_addr: SocketAddr,
132    /// Address for the TCP proxy that routes TCP traffic between services
133    pub tcp_proxy_addr: SocketAddr,
134    /// Address for the HTTP proxy that routes HTTP requests between services
135    pub http_proxy_addr: SocketAddr,
136    /// Address for the DNS server that resolves service names to IP addresses
137    pub dns_addr: SocketAddr,
138    /// Health check interval in seconds - how often to check for inactive services
139    pub health_check_interval: u64,
140    /// Max allowed time since last heartbeat before removing a service (in seconds)
141    pub max_heartbeat_age: u64,
142}
143
144impl Default for NetSelConfig {
145    fn default() -> Self {
146        Self {
147            registry_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 9000),
148            tcp_proxy_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 8080),
149            http_proxy_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 8081),
150            dns_addr: SocketAddr::new(IpAddr::from([127, 0, 0, 1]), 5353),
151            health_check_interval: 30,
152            max_heartbeat_age: 60,
153        }
154    }
155}
156
157/// NetSel server instance
158/// 
159/// This struct represents a NetSel server instance, which manages all components of the NetSel system.
160/// It provides methods to create and start the server with default or custom configuration.
161/// 
162/// # Example
163/// 
164/// ```rust
165/// use std::net::{IpAddr, SocketAddr};
166/// use netsel::{NetSelConfig, NetSelServer};
167/// 
168/// #[tokio::main]
169/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
170///     // Create a custom configuration
171///     let config = NetSelConfig {
172///         registry_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 9000),
173///         tcp_proxy_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 8080),
174///         http_proxy_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 8081),
175///         dns_addr: SocketAddr::new(IpAddr::from([127, 0, 0, 1]), 5353),
176///         health_check_interval: 30,
177///         max_heartbeat_age: 60,
178///     };
179///     
180///     // Create server with custom configuration
181///     let server = NetSelServer::with_config(config);
182///     
183///     // Start the server
184///     server.start().await?;
185///     
186///     Ok(())
187/// }
188/// ```
189pub struct NetSelServer {
190    config: NetSelConfig,
191    registry: Arc<SharedRegistry>,
192}
193
194impl NetSelServer {
195    /// Create a new NetSel server with default configuration
196    /// 
197    /// This creates a NetSel server with the following default settings:
198    /// - Registry server: `0.0.0.0:9000`
199    /// - TCP proxy: `0.0.0.0:8080`
200    /// - HTTP proxy: `0.0.0.0:8081`
201    /// - DNS server: `127.0.0.1:5353`
202    /// - Health check interval: 30 seconds
203    /// - Max heartbeat age: 60 seconds
204    /// 
205    /// # Example
206    /// 
207    /// ```rust
208    /// use netsel::NetSelServer;
209    /// 
210    /// let server = NetSelServer::new();
211    /// ```
212    pub fn new() -> Self {
213        Self::with_config(NetSelConfig::default())
214    }
215
216    /// Create a new NetSel server with custom configuration
217    /// 
218    /// This creates a NetSel server with the specified configuration.
219    /// 
220    /// # Arguments
221    /// 
222    /// * `config` - The custom configuration for the NetSel server
223    /// 
224    /// # Example
225    /// 
226    /// ```rust
227    /// use std::net::{IpAddr, SocketAddr};
228    /// use netsel::{NetSelConfig, NetSelServer};
229    /// 
230    /// let config = NetSelConfig {
231    ///     registry_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 9000),
232    ///     // ... other configuration settings
233    ///     ..NetSelConfig::default()
234    /// };
235    /// 
236    /// let server = NetSelServer::with_config(config);
237    /// ```
238    pub fn with_config(config: NetSelConfig) -> Self {
239        let registry = Arc::new(SharedRegistry::new(registry::ServiceRegistry::new()));
240        
241        Self {
242            config,
243            registry,
244        }
245    }
246
247    /// Start the NetSel server and all its components
248    /// 
249    /// This method starts all components of the NetSel server in separate Tokio tasks:
250    /// 1. Virtual network
251    /// 2. DNS server
252    /// 3. TCP proxy
253    /// 4. HTTP proxy
254    /// 5. Registration server
255    /// 6. Health check task
256    /// 
257    /// # Returns
258    /// 
259    /// * `Ok(())` - If all components started successfully
260    /// * `Err(Box<dyn std::error::Error>)` - If any component failed to start
261    /// 
262    /// # Example
263    /// 
264    /// ```rust
265    /// use netsel::NetSelServer;
266    /// 
267    /// #[tokio::main]
268    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
269    ///     let server = NetSelServer::new();
270    ///     server.start().await?;
271    ///     Ok(())
272    /// }
273    /// ```
274    pub async fn start(&self) -> Result<(), Box<dyn std::error::Error>> {
275        println!("Starting NetSel Service...");
276        
277        // Start virtual network
278        let mut virtual_net = network::VirtualNetwork::new();
279        tokio::spawn(async move {
280            virtual_net.run().await;
281        });
282        
283        // Start DNS server
284        let dns_addr = self.config.dns_addr;
285        let registry_dns = self.registry.clone();
286        tokio::spawn(async move {
287            if let Err(e) = dns::start_dns_server(dns_addr, registry_dns).await {
288                eprintln!("DNS server error: {}", e);
289            }
290        });
291        
292        // Start TCP proxy
293        let tcp_proxy_addr = self.config.tcp_proxy_addr;
294        let registry_tcp = self.registry.clone();
295        tokio::spawn(async move {
296            if let Err(e) = proxy::start_tcp_proxy(tcp_proxy_addr, registry_tcp).await {
297                eprintln!("TCP proxy error: {}", e);
298            }
299        });
300        
301        // Start HTTP proxy
302        let http_proxy_addr = self.config.http_proxy_addr;
303        let registry_http = self.registry.clone();
304        tokio::spawn(async move {
305            if let Err(e) = proxy::start_http_proxy(http_proxy_addr, registry_http).await {
306                eprintln!("HTTP proxy error: {}", e);
307            }
308        });
309        
310        // Start registration server
311        let reg_server_addr = self.config.registry_addr;
312        let registry_reg = self.registry.clone();
313        tokio::spawn(async move {
314            if let Err(e) = registry::start_registration_server(reg_server_addr, registry_reg).await {
315                eprintln!("Registration server error: {}", e);
316            }
317        });
318        
319        // Start health check task
320        let registry_health = self.registry.clone();
321        let health_check_interval = self.config.health_check_interval;
322        let max_heartbeat_age = self.config.max_heartbeat_age;
323        tokio::spawn(async move {
324            let mut interval = tokio::time::interval(Duration::from_secs(health_check_interval));
325            loop {
326                interval.tick().await;
327                let mut registry_w = registry_health.write().await;
328                registry_w.cleanup_offline(Duration::from_secs(max_heartbeat_age));
329            }
330        });
331        
332        println!("NetSel Service started successfully!");
333        println!("- Registration server: {}", self.config.registry_addr);
334        println!("- TCP proxy: {}", self.config.tcp_proxy_addr);
335        println!("- HTTP proxy: {}", self.config.http_proxy_addr);
336        println!("- DNS server: {}", self.config.dns_addr);
337        
338        Ok(())
339    }
340}