use crate::NetworkAddress;
use avila_error::{Error, ErrorKind, Result};
use tokio::net::TcpStream;
use tokio_rustls::{TlsAcceptor, TlsConnector, client::TlsStream};
use rustls::{ServerConfig, ClientConfig};
use std::sync::Arc;
pub struct TlsServer {
acceptor: TlsAcceptor,
}
impl TlsServer {
pub fn new(config: Arc<ServerConfig>) -> Self {
Self {
acceptor: TlsAcceptor::from(config),
}
}
pub async fn accept(&self, stream: TcpStream) -> Result<tokio_rustls::server::TlsStream<TcpStream>> {
self.acceptor
.accept(stream)
.await
.map_err(|e| Error::new(ErrorKind::Tls, format!("Falha TLS: {}", e)))
}
}
pub struct TlsClient {
connector: TlsConnector,
}
impl TlsClient {
pub fn new(config: Arc<ClientConfig>) -> Self {
Self {
connector: TlsConnector::from(config),
}
}
pub async fn connect(&self, domain: &str, stream: TcpStream) -> Result<TlsStream<TcpStream>> {
let domain = rustls::pki_types::ServerName::try_from(domain.to_string())
.map_err(|e| Error::new(ErrorKind::Tls, format!("Nome de servidor inválido: {}", e)))?
.to_owned();
self.connector
.connect(domain, stream)
.await
.map_err(|e| Error::new(ErrorKind::Tls, format!("Falha ao conectar TLS: {}", e)))
}
}
pub fn default_client_config() -> Result<Arc<ClientConfig>> {
let mut root_store = rustls::RootCertStore::empty();
let certs = rustls_native_certs::load_native_certs();
for cert in certs.certs {
root_store.add(cert).ok();
}
let config = ClientConfig::builder()
.with_root_certificates(root_store)
.with_no_client_auth();
Ok(Arc::new(config))
}