use crate::prefabs::client::serverless::ServerlessKernel;
use crate::prefabs::ClientServerRemote;
use crate::prelude::*;
pub struct BrowserConnection<R: Ratchet = StackedRatchet> {
channel: Option<PeerChannel<R>>,
remote: ClientServerRemote<R>,
_kernel_task: citadel_io::tokio::task::JoinHandle<Result<(), NetworkError>>,
}
impl<R: Ratchet> BrowserConnection<R> {
pub async fn new(config: ServerlessConfig) -> Result<Self, NetworkError> {
let (conn_tx, conn_rx) = citadel_io::tokio::sync::oneshot::channel();
let kernel = ServerlessKernel::<R>::new(conn_tx);
let node_future = NodeBuilder::<R, DefaultTransport>::default()
.with_no_central_server(config)
.with_backend(BackendType::InMemory)
.build(kernel)
.map_err(|err| {
citadel_io::error!(citadel_io::ErrorCode::NodeBuildFailed, err.to_string())
})?;
let kernel_task =
citadel_io::tokio::task::spawn_local(async move { node_future.await.map(|_| ()) });
let connection = match conn_rx.await {
Ok(conn) => conn,
Err(_) => {
kernel_task.abort();
return Err(citadel_io::error!(
citadel_io::ErrorCode::ServerlessKernelStoppedEarly
));
}
};
Ok(Self {
channel: connection.channel,
remote: connection.remote,
_kernel_task: kernel_task,
})
}
pub fn split(mut self) -> (PeerChannelSendHalf<R>, PeerChannelRecvHalf<R>) {
self.channel.take().expect("Channel already taken").split()
}
pub fn take_channel(&mut self) -> Option<PeerChannel<R>> {
self.channel.take()
}
pub fn remote(&self) -> &ClientServerRemote<R> {
&self.remote
}
}
impl<R: Ratchet> Drop for BrowserConnection<R> {
fn drop(&mut self) {
let remote = self.remote.inner.clone();
drop(citadel_io::tokio::task::spawn_local(async move {
let _ = remote.shutdown().await;
}));
}
}