#[cfg(feature = "tls")]
use slinger::tls::CustomTlsStream;
#[cfg(feature = "tls")]
use slinger::tls::{CustomTlsConnector, PeerCertificate};
#[cfg(feature = "tls")]
use slinger::{ConnectorBuilder, Result, Socket, StreamWrapper};
#[cfg(feature = "tls")]
use std::sync::Arc;
#[cfg(feature = "tls")]
struct MockTlsStream {
inner: tokio::net::TcpStream,
}
#[cfg(feature = "tls")]
impl CustomTlsStream for MockTlsStream {
fn peer_certificate(&self) -> Option<Vec<PeerCertificate>> {
None
}
fn alpn_protocol(&self) -> Option<Vec<u8>> {
None
}
}
#[cfg(feature = "tls")]
slinger::impl_tls_stream!(MockTlsStream, inner);
#[cfg(feature = "tls")]
struct MyCustomTlsConnector;
#[cfg(feature = "tls")]
impl CustomTlsConnector for MyCustomTlsConnector {
fn connect<'a>(
&'a self,
domain: &'a str,
stream: Socket,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Socket>> + Send + 'a>> {
Box::pin(async move {
println!("Performing mock TLS handshake for domain: {}", domain);
let tcp_stream = match stream.inner {
StreamWrapper::Tcp(tcp) => tcp,
_ => {
return Err(slinger::Error::Other(
"Expected plain TCP stream for TLS upgrade".to_string(),
));
}
};
let mock = MockTlsStream { inner: tcp_stream };
println!("✓ Mock TLS handshake completed successfully");
Ok(Socket::new(
StreamWrapper::Custom(Box::new(mock)),
stream.read_timeout,
stream.write_timeout,
))
})
}
}
#[cfg(feature = "tls")]
#[tokio::main]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("Custom TLS Connector Example");
println!("============================\n");
let custom_connector = Arc::new(MyCustomTlsConnector);
let _connector = ConnectorBuilder::default()
.custom_tls_connector(custom_connector)
.build()?;
println!("✓ Successfully created connector with custom TLS backend");
println!("\nThis example demonstrates:");
println!("1. Implementing CustomTlsStream trait for a mock TLS stream");
println!("2. Implementing CustomTlsConnector trait for custom TLS handshake");
println!("3. Extracting the TCP stream from a Socket");
println!("4. Wrapping the TLS stream back into a Socket");
println!("5. Providing peer certificate information via peer_certificate()");
println!("6. Providing access to underlying TcpStream via get_ref()");
println!("\nIn a full implementation, you would:");
println!(" - Use a real TLS library (openssl, boringssl, etc.)");
println!(" - Perform actual cryptographic handshake");
println!(" - Verify server certificates");
println!(" - Encrypt/decrypt data in AsyncRead/AsyncWrite implementations");
println!("\nExample libraries you could use:");
println!(" - openssl: Use openssl-sys or tokio-openssl");
println!(" - boring: Use boring (BoringSSL bindings)");
println!(" - native-tls: See native_tls_example.rs");
println!(" - Any other TLS library with async support");
Ok(())
}
#[cfg(not(feature = "tls"))]
fn main() {
eprintln!("This example requires the 'tls' feature.");
eprintln!("Run with: cargo run --example custom_tls --features tls");
}