Skip to main content

citadel_sdk/prefabs/server/internal_service/
mod.rs

1//! Internal Service Integration
2//!
3//! This module provides a network kernel that enables integration of internal services,
4//! such as HTTP servers, within the Citadel Protocol network. It's particularly useful
5//! for implementing web services that need to communicate over secure Citadel channels.
6//!
7//! # Features
8//! - Internal service integration
9//! - HTTP server support
10//! - Custom service handlers
11//! - Asynchronous processing
12//! - Type-safe communication
13//! - Automatic channel management
14//! - Service lifecycle handling
15//!
16//! # Example
17//! ```rust
18//! use std::convert::Infallible;
19//! use bytes::Bytes;
20//! use citadel_sdk::prelude::*;
21//! use http_body_util::Full;
22//! use hyper::body::Incoming;
23//! use hyper::service::service_fn;
24//! use hyper::{Request, Response};
25//! use hyper_util::rt::TokioIo;
26//! use citadel_sdk::prefabs::server::internal_service::InternalServiceKernel;
27//!
28//! // Create a kernel with an HTTP server bridged over the secure channel
29//! let kernel = InternalServiceKernel::<_, _, StackedRatchet>::new(|comm| async move {
30//!
31//!     let service = service_fn(|_: Request<Incoming>| async move {
32//!         Ok::<_, Infallible>(
33//!             Response::new(Full::new(Bytes::from("Hello!")))
34//!         )
35//!     });
36//!
37//!     // Serve HTTP/1.1 over the internal service communicator
38//!     hyper::server::conn::http1::Builder::new()
39//!         .serve_connection(TokioIo::new(comm), service)
40//!         .await
41//!         .map_err(|e| citadel_io::error!(
42//!             citadel_io::ErrorCode::InternalServiceHyperError,
43//!             e.to_string()
44//!         ))?;
45//!
46//!    Ok(())
47//! });
48//! ```
49//!
50//! # Important Notes
51//! - Services run in isolated contexts
52//! - Communication is bidirectional
53//! - Supports HTTP/1.1 and HTTP/2
54//! - Automatic error handling
55//! - Resource cleanup on shutdown
56//!
57//! # Related Components
58//! - [`NetKernel`]: Base trait for network kernels
59//! - [`InternalServerCommunicator`]: Service communication
60//! - [`ClientConnectListenerKernel`]: Connection handling
61//! - [`NodeResult`]: Network event handling
62//!
63//! [`NetKernel`]: crate::prelude::NetKernel
64//! [`InternalServerCommunicator`]: crate::prefabs::shared::internal_service::InternalServerCommunicator
65//! [`ClientConnectListenerKernel`]: crate::prefabs::server::client_connect_listener::ClientConnectListenerKernel
66//! [`NodeResult`]: crate::prelude::NodeResult
67
68use crate::prefabs::shared::internal_service::InternalServerCommunicator;
69use crate::prelude::*;
70use std::future::Future;
71use std::marker::PhantomData;
72
73pub struct InternalServiceKernel<'a, F, Fut, R: Ratchet = StackedRatchet> {
74    inner_kernel: Box<dyn NetKernel<R> + 'a>,
75    _pd: PhantomData<fn() -> (&'a F, Fut)>,
76}
77
78impl<F, Fut, R: Ratchet> InternalServiceKernel<'_, F, Fut, R>
79where
80    F: Send + Copy + Sync + FnOnce(InternalServerCommunicator) -> Fut,
81    Fut: Send + Sync + Future<Output = Result<(), NetworkError>>,
82{
83    pub fn new(on_create_webserver: F) -> Self {
84        Self {
85            _pd: Default::default(),
86            inner_kernel: Box::new(
87                super::client_connect_listener::ClientConnectListenerKernel::new(
88                    move |connect_success| async move {
89                        crate::prefabs::shared::internal_service::internal_service(
90                            connect_success,
91                            on_create_webserver,
92                        )
93                        .await
94                    },
95                ),
96            ),
97        }
98    }
99}
100
101#[async_trait]
102impl<F, Fut, R: Ratchet> NetKernel<R> for InternalServiceKernel<'_, F, Fut, R> {
103    fn load_remote(&mut self, node_remote: NodeRemote<R>) -> Result<(), NetworkError> {
104        self.inner_kernel.load_remote(node_remote)
105    }
106
107    async fn on_start(&self) -> Result<(), NetworkError> {
108        self.inner_kernel.on_start().await
109    }
110
111    async fn on_node_event_received(&self, message: NodeResult<R>) -> Result<(), NetworkError> {
112        self.inner_kernel.on_node_event_received(message).await
113    }
114
115    async fn on_stop(&mut self) -> Result<(), NetworkError> {
116        self.inner_kernel.on_stop().await
117    }
118}
119
120#[cfg(all(test, feature = "localhost-testing"))]
121mod tests;