use crate::config::ZitiConfig;
use crate::connection::ZitiStream;
use crate::error::ZitiResult;
use crate::identity::credentials::Credentials;
use crate::identity::{self, IdentityConfig, IdentityManager};
use crate::session::SessionManager;
use std::path::Path;
use std::sync::Arc;
use std::time::Duration;
const DEFAULT_CONNECT_TIMEOUT: Duration = Duration::from_secs(30);
#[derive(Clone)]
pub struct Context {
identity_manager: Arc<IdentityManager>,
session_manager: SessionManager,
connect_timeout: Duration,
}
impl Context {
pub async fn new(config: ZitiConfig) -> ZitiResult<Self> {
let identity_config = IdentityConfig::new(
config.controller_url.to_string(),
config.identity.id.clone(),
String::new(),
String::new(),
String::new(),
);
let credentials = Credentials::new(
config.identity.certificate_chain.clone(),
config.identity.private_key.clone_key(),
config.identity.ca_store.clone(),
);
let identity_manager = IdentityManager::new(identity_config, credentials);
let session_manager = SessionManager::new(identity_manager.clone());
Ok(Self {
identity_manager: Arc::new(identity_manager),
session_manager,
connect_timeout: config.connect_timeout,
})
}
pub fn from_managers(identity_manager: IdentityManager, session_manager: SessionManager) -> Self {
Self {
identity_manager: Arc::new(identity_manager),
session_manager,
connect_timeout: DEFAULT_CONNECT_TIMEOUT,
}
}
pub async fn from_file<P: AsRef<Path>>(path: P) -> ZitiResult<Self> {
let identity_manager = identity::load_from_file(path).await?;
let session_manager = SessionManager::new(identity_manager.clone());
Ok(Self {
identity_manager: Arc::new(identity_manager),
session_manager,
connect_timeout: DEFAULT_CONNECT_TIMEOUT,
})
}
pub(crate) fn set_connect_timeout(&mut self, timeout: Duration) {
self.connect_timeout = timeout;
}
pub fn connect_timeout(&self) -> Duration {
self.connect_timeout
}
pub async fn dial(&self, service_name: &str) -> ZitiResult<ZitiStream> {
crate::connection::dial(service_name, self).await
}
pub async fn listen(&self, service_name: &str) -> ZitiResult<crate::connection::ZitiListener> {
crate::connection::listen(service_name, self).await
}
pub async fn listen_with_options(
&self,
service_name: &str,
options: &crate::config::ListenOptions,
) -> ZitiResult<crate::connection::ZitiListener> {
crate::connection::listen_with_options(service_name, self, options).await
}
pub fn identity_manager(&self) -> &IdentityManager {
&self.identity_manager
}
pub fn session_manager(&self) -> &SessionManager {
&self.session_manager
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::identity::{credentials::Credentials, IdentityConfig};
use rustls::RootCertStore;
use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
fn create_test_identity_manager() -> IdentityManager {
let config = IdentityConfig::new(
"https://controller.example.com".to_string(),
"test-identity".to_string(),
"cert.pem".to_string(),
"key.pem".to_string(),
"ca.pem".to_string(),
);
let cert_data = b"test certificate data";
let key_data = b"test private key data";
let credentials = Credentials::new(
vec![CertificateDer::from(cert_data.to_vec())],
PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(key_data.to_vec())),
RootCertStore::empty(),
);
IdentityManager::new(config, credentials)
}
#[test]
fn test_context_from_managers() {
let identity_manager = create_test_identity_manager();
let session_manager = SessionManager::new(identity_manager.clone());
let context = Context::from_managers(identity_manager.clone(), session_manager);
assert_eq!(context.identity_manager().id(), identity_manager.id());
}
#[test]
fn test_context_clone() {
let identity_manager = create_test_identity_manager();
let session_manager = SessionManager::new(identity_manager.clone());
let context = Context::from_managers(identity_manager, session_manager);
let cloned_context = context.clone();
assert_eq!(
context.identity_manager().id(),
cloned_context.identity_manager().id()
);
}
#[test]
fn test_context_getters() {
let identity_manager = create_test_identity_manager();
let session_manager = SessionManager::new(identity_manager.clone());
let context = Context::from_managers(identity_manager.clone(), session_manager);
let _identity_mgr = context.identity_manager();
let _session_mgr = context.session_manager();
assert_eq!(context.identity_manager().id(), identity_manager.id());
}
}