use crate::prefabs::ClientServerRemote;
use crate::prelude::*;
use crate::remote_ext::CitadelClientServerConnection;
use citadel_io::Mutex;
use citadel_proto::prelude::async_trait;
pub(crate) struct ServerlessKernel<R: Ratchet> {
conn_tx:
Mutex<Option<citadel_io::tokio::sync::oneshot::Sender<CitadelClientServerConnection<R>>>>,
node_remote: Option<NodeRemote<R>>,
}
impl<R: Ratchet> ServerlessKernel<R> {
pub(crate) fn new(
conn_tx: citadel_io::tokio::sync::oneshot::Sender<CitadelClientServerConnection<R>>,
) -> Self {
Self {
conn_tx: Mutex::new(Some(conn_tx)),
node_remote: None,
}
}
fn send_connection(&self, conn: CitadelClientServerConnection<R>) {
if let Some(tx) = self.conn_tx.lock().take() {
let _ = tx.send(conn);
}
}
}
#[async_trait]
impl<R: Ratchet> NetKernel<R> for ServerlessKernel<R> {
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> {
let remote = self.node_remote.clone().unwrap();
if *remote.local_node_type() == NodeType::Peer {
let sentinel = std::net::SocketAddr::from(([127, 0, 0, 1], 0));
let auth = AuthenticationRequest::transient(uuid::Uuid::new_v4(), sentinel);
let connect_success = remote
.connect(
auth,
Default::default(),
UdpMode::Disabled,
None,
Default::default(),
None,
)
.await?;
let conn_type = VirtualTargetType::LocalGroupServer {
session_cid: connect_success.cid,
};
let client_server_remote = ClientServerRemote::new(
conn_type,
remote,
connect_success.session_security_settings,
None,
None,
);
self.send_connection(CitadelClientServerConnection {
channel: connect_success.channel,
remote: client_server_remote,
udp_channel_rx: connect_success.udp_channel_rx,
services: connect_success.services,
cid: connect_success.cid,
session_security_settings: connect_success.session_security_settings,
});
futures::future::pending::<()>().await;
}
Ok(())
}
async fn on_node_event_received(&self, message: NodeResult<R>) -> Result<(), NetworkError> {
if let 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,
}) = message
{
let client_server_remote = ClientServerRemote::new(
conn_type,
self.node_remote.clone().unwrap(),
session_security_settings,
None,
None,
);
self.send_connection(CitadelClientServerConnection {
remote: client_server_remote,
channel: Some(*channel),
udp_channel_rx,
services,
cid,
session_security_settings,
});
} else {
log::trace!(target: "citadel", "[ServerlessKernel] Unhandled event: {message:?}");
}
Ok(())
}
async fn on_stop(&mut self) -> Result<(), NetworkError> {
Ok(())
}
}