citadel_sdk/prefabs/server/client_connect_listener.rs
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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
//! Client Connection Event Handler
//!
//! This module provides a network kernel that executes custom logic whenever a client
//! establishes a connection. It's particularly useful for implementing server-side
//! connection handling, authentication, and session initialization.
//!
//! # Features
//! - Custom connection handling
//! - Asynchronous event processing
//! - Type-safe callback execution
//! - Session security management
//! - UDP channel support
//! - Service discovery integration
//!
//! # Example:
//! ```rust
//! use citadel_sdk::prelude::*;
//! use citadel_sdk::prefabs::server::client_connect_listener::ClientConnectListenerKernel;
//!
//! # fn main() -> Result<(), NetworkError> {
//! let kernel = Box::new(ClientConnectListenerKernel::<_, _, StackedRatchet>::new(|conn| async move {
//! println!("Client connected!");
//! Ok(())
//! }));
//! # Ok(())
//! # }
//! ```
//!
//! # Important Notes
//! - Callbacks must be Send + Sync
//! - Futures must be Send + Sync
//! - Handles both TCP and UDP channels
//! - Automatic security settings handling
//!
//! # Related Components
//! - [`NetKernel`]: Base trait for network kernels
//! - [`ClientServerRemote`]: Client-server communication
//! - [`CitadelClientServerConnection`]: Connection event data
//! - [`NodeResult`]: Network event handling
//!
//! [`NetKernel`]: crate::prelude::NetKernel
//! [`ClientServerRemote`]: crate::prelude::ClientServerRemote
//! [`CitadelClientServerConnection`]: crate::prelude::CitadelClientServerConnection
//! [`NodeResult`]: crate::prelude::NodeResult
use crate::prefabs::ClientServerRemote;
use crate::prelude::*;
use citadel_proto::prelude::async_trait;
use futures::Future;
use std::marker::PhantomData;
/// A kernel that executes a user-provided function each time
/// a client makes a connection
pub struct ClientConnectListenerKernel<F, Fut, R: Ratchet> {
on_channel_received: F,
node_remote: Option<NodeRemote<R>>,
_pd: PhantomData<Fut>,
}
impl<F, Fut, R: Ratchet> ClientConnectListenerKernel<F, Fut, R>
where
F: Fn(CitadelClientServerConnection<R>) -> Fut + Send + Sync,
Fut: Future<Output = Result<(), NetworkError>> + Send + Sync,
{
pub fn new(on_channel_received: F) -> Self {
Self {
on_channel_received,
node_remote: None,
_pd: Default::default(),
}
}
}
#[async_trait]
impl<F, Fut, R: Ratchet> NetKernel<R> for ClientConnectListenerKernel<F, Fut, R>
where
F: Fn(CitadelClientServerConnection<R>) -> Fut + Send + Sync,
Fut: Future<Output = Result<(), NetworkError>> + Send + Sync,
{
fn load_remote(&mut self, server_remote: NodeRemote<R>) -> Result<(), NetworkError> {
self.node_remote = Some(server_remote);
Ok(())
}
async fn on_start(&self) -> Result<(), NetworkError> {
Ok(())
}
async fn on_node_event_received(&self, message: NodeResult<R>) -> Result<(), NetworkError> {
match message {
NodeResult::ConnectSuccess(ConnectSuccess {
ticket: _,
session_cid: cid,
remote_addr: _,
is_personal: _,
v_conn_type: conn_type,
services,
welcome_message: _,
channel,
udp_rx_opt: udp_channel_rx,
session_security_settings,
}) => {
let client_server_remote = ClientServerRemote::new(
conn_type,
self.node_remote.clone().unwrap(),
session_security_settings,
None,
None,
);
(self.on_channel_received)(CitadelClientServerConnection {
remote: client_server_remote.clone(),
channel: Some(channel),
udp_channel_rx,
services,
cid,
session_security_settings,
})
.await
}
other => {
log::trace!(target: "citadel", "Unhandled server signal: {:?}", other);
Ok(())
}
}
}
async fn on_stop(&mut self) -> Result<(), NetworkError> {
Ok(())
}
}