use super::protocols::{StarttlsNegotiator, StarttlsProtocol};
use crate::Result;
use async_trait::async_trait;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
pub struct TelnetNegotiator;
impl Default for TelnetNegotiator {
fn default() -> Self {
Self::new()
}
}
impl TelnetNegotiator {
pub fn new() -> Self {
Self
}
}
#[async_trait]
impl StarttlsNegotiator for TelnetNegotiator {
async fn negotiate_starttls(&self, stream: &mut TcpStream) -> Result<()> {
let starttls_request = [0xFF, 0xFB, 0x2E];
stream.write_all(&starttls_request).await?;
stream.flush().await?;
let mut response = [0u8; 3];
stream.read_exact(&mut response).await?;
if response[0] == 0xFF && response[1] == 0xFD && response[2] == 0x2E {
Ok(())
} else {
Err(crate::error::TlsError::StarttlsError {
protocol: "Telnet".to_string(),
details: "STARTTLS negotiation failed".to_string(),
})
}
}
fn protocol(&self) -> StarttlsProtocol {
StarttlsProtocol::Telnet
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_telnet_negotiator_creation() {
let negotiator = TelnetNegotiator::new();
assert_eq!(negotiator.protocol(), StarttlsProtocol::Telnet);
}
}