use std::sync::Arc;
use tokio::net::TcpStream;
use tokio::io::{AsyncRead, AsyncWrite, AsyncReadExt, AsyncWriteExt};
use serde::{Serialize, Deserialize};
use crate::{QsshError, Result};
#[async_trait::async_trait]
pub trait QsslTransportLayer: Send + Sync {
async fn handshake(&mut self) -> Result<()>;
async fn send_message<T: Serialize + Send + Sync>(&self, message: &T) -> Result<()>;
async fn recv_message<T: for<'de> Deserialize<'de>>(&self) -> Result<T>;
fn cipher_suite(&self) -> String;
async fn is_established(&self) -> bool;
async fn close(&self) -> Result<()>;
}
pub struct QsslTransport {
inner: Option<Arc<dyn QsslTransportLayer>>,
stream: Option<TcpStream>,
is_client: bool,
}
impl QsslTransport {
pub fn new(stream: TcpStream, is_client: bool) -> Self {
Self {
inner: None,
stream: Some(stream),
is_client,
}
}
pub async fn init_with_qssl(&mut self) -> Result<()> {
if let Some(stream) = self.stream.take() {
return Err(QsshError::Protocol("QSSL not yet linked".to_string()));
}
Ok(())
}
pub async fn send<T: Serialize + Send + Sync>(&self, message: &T) -> Result<()> {
if let Some(inner) = &self.inner {
inner.send_message(message).await
} else {
Err(QsshError::Protocol("QSSL transport not initialized".to_string()))
}
}
pub async fn recv<T: for<'de> Deserialize<'de>>(&self) -> Result<T> {
if let Some(inner) = &self.inner {
inner.recv_message().await
} else {
Err(QsshError::Protocol("QSSL transport not initialized".to_string()))
}
}
}
#[derive(Debug, Clone)]
pub struct QsslConfig {
pub cipher_suites: Vec<String>,
pub session_resumption: bool,
pub zero_rtt: bool,
pub cert_path: Option<String>,
pub key_path: Option<String>,
pub ca_path: Option<String>,
}
impl Default for QsslConfig {
fn default() -> Self {
Self {
cipher_suites: vec![
"QSSL_KYBER768_FALCON512_AES256_SHA384".to_string(),
"QSSL_KYBER512_FALCON512_AES128_SHA256".to_string(),
],
session_resumption: true,
zero_rtt: false,
cert_path: None,
key_path: None,
ca_path: None,
}
}
}
pub struct QsslTransportFactory {
config: QsslConfig,
}
impl QsslTransportFactory {
pub fn new(config: QsslConfig) -> Self {
Self { config }
}
pub async fn create_client(&self, addr: &str) -> Result<QsslTransport> {
let stream = TcpStream::connect(addr).await.map_err(QsshError::Io)?;
let mut transport = QsslTransport::new(stream, true);
transport.init_with_qssl().await?;
Ok(transport)
}
pub async fn create_server(&self, stream: TcpStream) -> Result<QsslTransport> {
let mut transport = QsslTransport::new(stream, false);
transport.init_with_qssl().await?;
Ok(transport)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_qssl_config() {
let config = QsslConfig::default();
assert!(!config.cipher_suites.is_empty());
assert!(config.session_resumption);
assert!(!config.zero_rtt);
}
#[test]
fn test_qssl_transport_factory() {
let config = QsslConfig::default();
let factory = QsslTransportFactory::new(config);
}
}