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}