use std::io;
use std::net::SocketAddr;
use tokio::io::{AsyncRead, AsyncWrite};
pub mod tcp;
pub mod tls;
pub use tcp::TcpNetworkStream;
pub use tls::{TlsConfig, TlsNetworkStream};
pub trait NetworkStream: AsyncRead + AsyncWrite + Send + Sync + Unpin {
fn peer_addr(&self) -> io::Result<SocketAddr>;
fn local_addr(&self) -> io::Result<SocketAddr>;
fn is_secure(&self) -> bool;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SecurityProtocol {
Plaintext,
Ssl(TlsConfig),
SaslPlaintext,
SaslSsl(TlsConfig),
}
impl SecurityProtocol {
pub fn uses_tls(&self) -> bool {
matches!(
self,
SecurityProtocol::Ssl(_) | SecurityProtocol::SaslSsl(_)
)
}
pub fn uses_sasl(&self) -> bool {
matches!(
self,
SecurityProtocol::SaslPlaintext | SecurityProtocol::SaslSsl(_)
)
}
}
pub struct TransportConnector;
impl TransportConnector {
pub async fn connect(
addr: SocketAddr,
protocol: &SecurityProtocol,
) -> io::Result<Box<dyn NetworkStream>> {
match protocol {
SecurityProtocol::Plaintext | SecurityProtocol::SaslPlaintext => {
let stream = TcpNetworkStream::connect(addr).await?;
Ok(Box::new(stream) as Box<dyn NetworkStream>)
}
SecurityProtocol::Ssl(config) | SecurityProtocol::SaslSsl(config) => {
let stream = TlsNetworkStream::connect(addr, config.clone()).await?;
Ok(Box::new(stream) as Box<dyn NetworkStream>)
}
}
}
}