#[cfg(not(target_os = "windows"))]
use std::path::PathBuf;
use std::sync::Arc;
use async_trait::async_trait;
use rustls::{ClientConfig, RootCertStore, pki_types::CertificateDer};
use tokio::{
io::{AsyncRead, AsyncWrite},
net::TcpStream,
};
use tokio_rustls::TlsConnector;
use crate::error::Error;
#[cfg(feature = "settings")]
use crate::{settings::Shared, tls::load_certificate};
#[cfg_attr(not(target_os = "windows"), path = "unix.rs")]
#[cfg_attr(target_os = "windows", path = "windows.rs")]
mod platform;
pub use platform::*;
#[async_trait]
pub trait Listener: Sync + Send {
async fn accept<'a>(&'a self) -> Result<GenericStream, Error>;
}
pub type GenericListener = Box<dyn Listener>;
pub type GenericStream = Box<dyn Stream>;
pub enum ConnectionSettings<'a> {
#[cfg(not(target_os = "windows"))]
UnixSocket { path: PathBuf },
TlsTcpSocket {
host: String,
port: String,
certificate: CertificateDer<'a>,
},
}
#[cfg(feature = "settings")]
impl TryFrom<Shared> for ConnectionSettings<'_> {
type Error = crate::error::Error;
fn try_from(value: Shared) -> Result<Self, Self::Error> {
#[cfg(not(target_os = "windows"))]
{
if value.use_unix_socket {
return Ok(ConnectionSettings::UnixSocket {
path: value.unix_socket_path()?,
});
}
}
let cert = load_certificate(&value.daemon_cert())?;
Ok(ConnectionSettings::TlsTcpSocket {
host: value.host,
port: value.port,
certificate: cert,
})
}
}
pub trait Stream: AsyncRead + AsyncWrite + Unpin + Send {}
impl Stream for tokio_rustls::server::TlsStream<TcpStream> {}
impl Stream for tokio_rustls::client::TlsStream<TcpStream> {}
pub async fn get_tls_connector(cert: CertificateDer<'_>) -> Result<TlsConnector, Error> {
let mut cert_store = RootCertStore::empty();
cert_store.add(cert).map_err(|err| {
Error::CertificateFailure(format!("Failed to build RootCertStore: {err}"))
})?;
let config: ClientConfig = ClientConfig::builder()
.with_root_certificates(cert_store)
.with_no_client_auth();
Ok(TlsConnector::from(Arc::new(config)))
}