1use bincode;
2use futures::{SinkExt, StreamExt};
3use std::net::SocketAddr;
4use std::sync::Arc;
5use std::time::Duration;
6use tokio::net::{TcpListener, TcpStream};
7use tokio::sync::{mpsc, oneshot, Mutex};
8use tokio::task::JoinSet;
9use tokio::time;
10use tokio_util::codec::Framed;
11use tracing::{debug, error, info, instrument, warn};
12
13use crate::config::ServerConfig;
14
15use crate::utils::timeout::with_timeout_error;
16
17use crate::core::codec::PacketCodec;
18use crate::core::packet::Packet;
19use crate::protocol::message::Message;
20use crate::error::{ProtocolError, Result};
22use crate::protocol::dispatcher::Dispatcher;
23use crate::protocol::handshake::{
24 server_secure_handshake_finalize, server_secure_handshake_response,
25};
26use crate::protocol::heartbeat::{build_ping, is_pong};
27use crate::protocol::keepalive::KeepAliveManager;
28use crate::service::secure::SecureConnection;
29use crate::utils::replay_cache::ReplayCache;
30
31#[instrument(skip(addr), fields(address = %addr))]
33pub async fn start(addr: &str) -> Result<()> {
34 let (_, shutdown_rx) = oneshot::channel::<()>();
36 start_with_shutdown(addr, shutdown_rx).await
37}
38
39#[instrument(skip(config), fields(address = %config.address))]
41pub async fn start_with_config(config: ServerConfig) -> Result<()> {
42 let (_, shutdown_rx) = oneshot::channel::<()>();
44 start_with_config_and_shutdown(config, shutdown_rx).await
45}
46
47#[instrument(skip(addr, shutdown_rx), fields(address = %addr))]
49pub async fn start_with_shutdown(addr: &str, shutdown_rx: oneshot::Receiver<()>) -> Result<()> {
50 let config = ServerConfig {
52 address: addr.to_string(),
53 ..Default::default()
54 };
55 start_with_config_and_shutdown(config, shutdown_rx).await
56}
57
58#[instrument(skip(config, shutdown_rx), fields(address = %config.address))]
60pub async fn start_with_config_and_shutdown(
61 config: ServerConfig,
62 shutdown_rx: oneshot::Receiver<()>,
63) -> Result<()> {
64 let dispatcher = Arc::new(Dispatcher::new());
66 register_default_handlers(&dispatcher)?;
67
68 run_server(config, dispatcher, shutdown_rx, true).await
69}
70
71async fn run_server(
79 config: ServerConfig,
80 dispatcher: Arc<Dispatcher>,
81 shutdown_rx: oneshot::Receiver<()>,
82 handle_ctrl_c: bool,
83) -> Result<()> {
84 let listener = TcpListener::bind(&config.address).await?;
85 info!(address = %config.address, "Server listening");
86
87 let active_connections = Arc::new(Mutex::new(0u32));
89
90 let (internal_shutdown_tx, mut internal_shutdown_rx) = mpsc::channel::<()>(1);
92
93 let shutdown_timeout = config.shutdown_timeout;
95 let heartbeat_interval = config.heartbeat_interval;
96
97 if handle_ctrl_c {
98 let shutdown_tx_clone = internal_shutdown_tx.clone();
99 tokio::spawn(async move {
100 match tokio::signal::ctrl_c().await {
101 Ok(()) => {
102 info!("Shutdown signal received");
103 let _ = shutdown_tx_clone.send(()).await;
104 }
105 Err(err) => {
106 error!(error = %err, "Failed to listen for shutdown signal");
107 }
108 }
109 });
110 }
111
112 let internal_shutdown_tx_clone = internal_shutdown_tx.clone();
114 tokio::spawn(async move {
115 if shutdown_rx.await.is_ok() {
116 info!("External shutdown signal received");
117 let _ = internal_shutdown_tx_clone.send(()).await;
118 }
119 });
120
121 let mut connections = JoinSet::new();
123
124 loop {
126 tokio::select! {
127 _ = internal_shutdown_rx.recv() => {
129 info!(connections = connections.len(), "Shutting down server. Waiting for connections to close...");
130 close_connections(&mut connections, shutdown_timeout).await;
131 return Ok(());
132 }
133
134 Some(_) = connections.join_next(), if !connections.is_empty() => {}
136
137 accept_result = listener.accept() => {
139 match accept_result {
140 Ok((stream, peer)) => {
141 {
143 let mut count = active_connections.lock().await;
144 if *count as usize >= config.max_connections {
145 warn!(peer = %peer, limit = config.max_connections, "Connection limit reached, closing new connection");
146 drop(stream);
147 continue;
148 }
149 *count += 1;
150 }
151
152 info!(peer = %peer, "New connection established");
153 let dispatcher = dispatcher.clone();
154 let active_connections = active_connections.clone();
155
156 let active_connections_clone = active_connections.clone();
158 let config_clone = config.clone();
159
160 connections.spawn(async move {
161 handle_connection(stream, peer, dispatcher, active_connections_clone, config_clone, heartbeat_interval).await;
162 });
163 }
164 Err(e) => {
165 error!(error = %e, "Error accepting connection");
166 }
167 }
168 }
169 }
170 }
171}
172
173pub(crate) async fn close_connections(connections: &mut JoinSet<()>, grace: Duration) {
177 let drained = time::timeout(grace, async {
178 while connections.join_next().await.is_some() {}
179 })
180 .await;
181 if drained.is_ok() {
182 info!("All connections closed, shutting down");
183 } else {
184 warn!(
185 remaining = connections.len(),
186 "Shutdown timeout reached, closing remaining connections"
187 );
188 connections.shutdown().await;
189 }
190}
191
192#[instrument(skip(stream, dispatcher, active_connections, config, heartbeat_interval), fields(peer = %peer))]
194async fn handle_connection(
195 stream: tokio::net::TcpStream,
196 peer: std::net::SocketAddr,
197 dispatcher: Arc<Dispatcher>,
198 active_connections: Arc<Mutex<u32>>,
199 config: ServerConfig,
200 heartbeat_interval: Duration,
201) {
202 let result = process_connection(stream, dispatcher, peer, config, heartbeat_interval).await;
206
207 match result {
209 Ok(_) => info!("Connection closed gracefully"),
210 Err(ProtocolError::Timeout) => warn!("Connection timed out"),
211 Err(e) => error!(error = %e, "Connection error"),
212 }
213
214 {
216 let mut count = active_connections.lock().await;
217 *count -= 1;
218 }
219
220 info!("Client disconnected");
221}
222
223#[instrument(skip(stream, dispatcher, peer, config, heartbeat_interval), fields(peer = %peer))]
225async fn process_connection(
226 stream: TcpStream,
227 dispatcher: Arc<Dispatcher>,
228 peer: SocketAddr,
229 config: ServerConfig,
230 heartbeat_interval: Duration,
231) -> Result<()> {
232 let mut framed = Framed::new(stream, PacketCodec);
234
235 let init = with_timeout_error(
237 async {
238 match framed.next().await {
239 Some(Ok(pkt)) => bincode::deserialize::<Message>(&pkt.payload)
240 .map_err(|e| ProtocolError::DeserializeError(e.to_string())),
241 Some(Err(e)) => Err(ProtocolError::TransportError(e.to_string())),
242 None => Err(ProtocolError::ConnectionClosed),
243 }
244 },
245 config.connection_timeout,
246 )
247 .await?;
248
249 let (client_pub_key, client_timestamp, client_nonce) = match init {
251 Message::SecureHandshakeInit {
252 pub_key,
253 timestamp,
254 nonce,
255 } => (pub_key, timestamp, nonce),
256 _ => {
257 return Err(ProtocolError::HandshakeError(
258 "Unexpected message type".to_string(),
259 ))
260 }
261 };
262
263 let mut replay_cache = ReplayCache::new();
265 let (server_state, response) = server_secure_handshake_response(
266 client_pub_key,
267 client_nonce,
268 client_timestamp,
269 &peer.to_string(),
270 &mut replay_cache,
271 )?;
272
273 let response_bytes =
274 bincode::serialize(&response).map_err(|e| ProtocolError::SerializeError(e.to_string()))?;
275
276 framed
277 .send(Packet {
278 version: 1,
279 payload: response_bytes,
280 })
281 .await
282 .map_err(|e| ProtocolError::TransportError(e.to_string()))?;
283
284 let confirm = with_timeout_error(
286 async {
287 match framed.next().await {
288 Some(Ok(pkt)) => bincode::deserialize::<Message>(&pkt.payload)
289 .map_err(|e| ProtocolError::DeserializeError(e.to_string())),
290 Some(Err(e)) => Err(ProtocolError::TransportError(e.to_string())),
291 None => Err(ProtocolError::ConnectionClosed),
292 }
293 },
294 config.connection_timeout,
295 )
296 .await?;
297
298 let nonce_verification = match confirm {
299 Message::SecureHandshakeConfirm { nonce_verification } => nonce_verification,
300 _ => {
301 return Err(ProtocolError::HandshakeError(
302 "Expected handshake confirmation".to_string(),
303 ))
304 }
305 };
306
307 let session_key = server_secure_handshake_finalize(server_state, nonce_verification)?;
309
310 let conn = SecureConnection::new(framed, session_key);
314
315 handle_secure_connection(
317 conn,
318 dispatcher,
319 peer,
320 heartbeat_interval,
321 config.backpressure_limit,
322 )
323 .await?;
324
325 Ok(())
326}
327
328#[instrument(skip(dispatcher))]
330fn register_default_handlers(dispatcher: &Arc<Dispatcher>) -> Result<()> {
331 dispatcher.register("PING", |_| {
333 debug!("Responding to ping with pong");
334 Ok(Message::Pong)
335 })?;
336
337 dispatcher.register("ECHO", |msg| {
339 if let Message::Echo(text) = msg {
340 debug!(text = %text, "Echoing message");
341 Ok(Message::Echo(text.clone()))
342 } else {
343 Err(ProtocolError::Custom(
344 "Invalid Echo message format".to_string(),
345 ))
346 }
347 })?;
348
349 Ok(())
350}
351
352#[derive(Debug)]
354enum ProcessingMessage {
355 Message(Message),
357 Terminate,
359}
360
361#[derive(Debug)]
363struct ProcessingResult {
364 original_id: usize,
366 response: Option<Message>,
368}
369
370#[instrument(skip(conn, dispatcher, heartbeat_interval, backpressure_limit), fields(peer = %peer))]
372async fn handle_secure_connection(
373 mut conn: SecureConnection,
374 dispatcher: Arc<Dispatcher>,
375 peer: std::net::SocketAddr,
376 heartbeat_interval: Duration,
377 backpressure_limit: usize,
378) -> Result<()> {
379 let dead_timeout = heartbeat_interval.mul_f32(4.0); let mut keep_alive = KeepAliveManager::with_settings(heartbeat_interval, dead_timeout);
382 let mut ping_interval = time::interval(keep_alive.ping_interval());
383
384 let capacity = backpressure_limit.max(1);
388 let (msg_tx, msg_rx) = mpsc::channel::<ProcessingMessage>(capacity);
389 let (resp_tx, mut resp_rx) = mpsc::channel::<ProcessingResult>(capacity);
390
391 let dispatcher_clone = dispatcher.clone();
393 let processor_handle =
394 tokio::spawn(async move { process_messages(msg_rx, resp_tx, dispatcher_clone).await });
395
396 let mut final_result = Ok(());
398 let mut next_msg_id: usize = 0;
399
400 'main: loop {
402 tokio::select! {
403 _ = ping_interval.tick() => {
405 if keep_alive.should_ping() {
406 debug!("Sending keep-alive ping");
407 let ping = build_ping();
408 if let Err(e) = conn.secure_send(ping).await {
409 warn!(error = %e, "Failed to send ping");
410 final_result = Err(e);
411 break 'main;
412 }
413 keep_alive.update_send();
414 }
415
416 if keep_alive.is_connection_dead() {
418 warn!(dead_seconds = ?keep_alive.time_since_last_recv().as_secs(),
419 "Connection appears dead, closing");
420 final_result = Err(ProtocolError::ConnectionTimeout);
421 break 'main;
422 }
423 }
424
425 Some(result) = resp_rx.recv() => {
427 if let Some(response) = result.response {
428 debug!("Sending response for message {}", result.original_id);
429 if let Err(e) = conn.secure_send(response).await {
430 warn!(error = %e, "Failed to send response");
431 final_result = Err(e);
432 break 'main;
433 }
434 keep_alive.update_send();
435 }
436 }
437
438 recv_result = conn.secure_recv::<Message>() => {
440 match recv_result {
441 Ok(msg) => {
442 debug!(message = ?msg, "Received message");
443 keep_alive.update_recv();
444
445 if matches!(msg, Message::Disconnect) {
447 info!("Received disconnect request");
448 break 'main;
449 }
450
451 if is_pong(&msg) {
453 debug!("Received pong response");
454 continue;
455 }
456
457 next_msg_id = next_msg_id.wrapping_add(1);
459
460 if msg_tx.capacity() == 0 {
462 debug!("Channel full - applying backpressure");
463
464 match msg_tx.reserve().await {
466 Ok(permit) => {
467 permit.send(ProcessingMessage::Message(msg));
469 },
470 Err(_) => {
471 warn!("Processing channel closed unexpectedly");
473 break 'main;
474 }
475 }
476 } else {
477 if (msg_tx.send(ProcessingMessage::Message(msg)).await).is_err() {
479 warn!("Failed to send message to processing channel");
481 break 'main;
482 }
483 }
484 }
485 Err(ProtocolError::Timeout) => {
486 continue;
488 }
489 Err(e) => {
490 final_result = Err(e);
491 break 'main;
492 }
493 }
494 }
495 }
496 }
497
498 debug!("Signaling processor to terminate");
500 let _ = msg_tx.send(ProcessingMessage::Terminate).await;
501
502 debug!("Waiting for processor to terminate");
504 let _ = processor_handle.await;
505
506 final_result
507}
508
509#[instrument(skip(rx, resp_tx, dispatcher), level = "debug")]
511async fn process_messages(
512 mut rx: mpsc::Receiver<ProcessingMessage>,
513 resp_tx: mpsc::Sender<ProcessingResult>,
514 dispatcher: Arc<Dispatcher>,
515) {
516 let mut msg_counter: usize = 0;
517
518 while let Some(proc_msg) = rx.recv().await {
519 match proc_msg {
520 ProcessingMessage::Message(msg) => {
521 let msg_id = msg_counter;
522 msg_counter += 1;
523
524 debug!(msg_id = msg_id, message = ?msg, "Processing message from channel");
525
526 let response = match dispatcher.dispatch(&msg) {
527 Ok(reply) => {
528 Some(reply)
530 }
531 Err(e) => {
532 warn!(error = %e, "Error dispatching message");
534 None
535 }
536 };
537
538 let result = ProcessingResult {
540 original_id: msg_id,
541 response,
542 };
543
544 if (resp_tx.send(result).await).is_err() {
545 warn!("Failed to send processing result - reader likely disconnected");
546 break;
547 }
548 }
549 ProcessingMessage::Terminate => {
550 debug!("Processor received terminate signal");
551 break;
552 }
553 }
554 }
555
556 debug!("Message processor terminated");
557}
558
559#[derive(Debug)]
561pub struct Daemon {
562 pub address: String,
564 shutdown_tx: Option<oneshot::Sender<()>>,
566}
567
568impl Daemon {
569 pub fn new(address: String, shutdown_tx: oneshot::Sender<()>) -> Self {
571 Self {
572 address,
573 shutdown_tx: Some(shutdown_tx),
574 }
575 }
576
577 #[deprecated(
582 since = "1.3.0",
583 note = "does nothing: the server started by start_daemon_no_signals() is already running"
584 )]
585 pub async fn run(self) -> Result<()> {
586 Ok(())
589 }
590
591 pub async fn shutdown(&mut self) -> Result<()> {
593 if let Some(tx) = self.shutdown_tx.take() {
594 let _ = tx.send(());
595 Ok(())
596 } else {
597 Err(ProtocolError::Custom("Shutdown already called".to_string()))
598 }
599 }
600
601 #[deprecated(
607 since = "1.3.0",
608 note = "the timeout argument is ignored; set ServerConfig::shutdown_timeout and call shutdown()"
609 )]
610 pub async fn shutdown_with_timeout(&mut self, _timeout: Duration) -> Result<()> {
611 self.shutdown().await
613 }
614}
615
616#[instrument(skip(config, dispatcher), fields(address = %config.address))]
623pub async fn start_daemon_no_signals(
624 config: ServerConfig,
625 dispatcher: Arc<Dispatcher>,
626) -> Result<Daemon> {
627 let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();
629
630 let address = config.address.clone();
631
632 tokio::spawn(async move {
634 if let Err(e) = run_server(config, dispatcher, shutdown_rx, false).await {
635 error!(error = ?e, "Server error");
636 }
637 });
638
639 Ok(Daemon::new(address, shutdown_tx))
641}
642
643#[deprecated(
648 since = "1.3.0",
649 note = "starts nothing and ignores the dispatcher; use start_daemon_no_signals()"
650)]
651pub fn new_with_config(config: ServerConfig, _dispatcher: Arc<Dispatcher>) -> Daemon {
652 let (shutdown_tx, _) = oneshot::channel::<()>();
653 Daemon::new(config.address.clone(), shutdown_tx)
654}