trust_dns_proto/openssl/
tls_client_stream.rs1use std::future::Future;
9use std::io;
10use std::net::SocketAddr;
11use std::pin::Pin;
12
13use futures_util::TryFutureExt;
14#[cfg(feature = "mtls")]
15use openssl::pkcs12::Pkcs12;
16use openssl::x509::X509;
17use tokio_openssl::SslStream as TokioTlsStream;
18
19use crate::error::ProtoError;
20use crate::iocompat::AsyncIoStdAsTokio;
21use crate::iocompat::AsyncIoTokioAsStd;
22use crate::tcp::{Connect, DnsTcpStream, TcpClientStream};
23use crate::xfer::BufDnsStreamHandle;
24
25use super::TlsStreamBuilder;
26
27pub type TlsClientStream<S> =
29 TcpClientStream<AsyncIoTokioAsStd<TokioTlsStream<AsyncIoStdAsTokio<S>>>>;
30
31pub struct TlsClientStreamBuilder<S>(TlsStreamBuilder<S>);
33
34impl<S: DnsTcpStream> TlsClientStreamBuilder<S> {
35 pub fn new() -> Self {
37 Self(TlsStreamBuilder::new())
38 }
39
40 pub fn add_ca(&mut self, ca: X509) {
44 self.0.add_ca(ca);
45 }
46
47 pub fn add_ca_der(&mut self, ca_der: &[u8]) -> io::Result<()> {
51 let ca = X509::from_der(ca_der)
52 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?;
53 self.add_ca(ca);
54 Ok(())
55 }
56
57 #[cfg(feature = "mtls")]
59 pub fn identity(&mut self, pkcs12: Pkcs12) {
60 self.0.identity(pkcs12);
61 }
62
63 pub fn bind_addr(&mut self, bind_addr: SocketAddr) {
65 self.0.bind_addr(bind_addr);
66 }
67
68 #[allow(clippy::type_complexity)]
76 pub fn build_with_future<F>(
77 self,
78 future: F,
79 name_server: SocketAddr,
80 dns_name: String,
81 ) -> (
82 Pin<Box<dyn Future<Output = Result<TlsClientStream<S>, ProtoError>> + Send>>,
83 BufDnsStreamHandle,
84 )
85 where
86 F: Future<Output = io::Result<S>> + Send + Unpin + 'static,
87 {
88 let (stream_future, sender) = self.0.build_with_future(future, name_server, dns_name);
89
90 let new_future = Box::pin(
91 stream_future
92 .map_ok(TcpClientStream::from_stream)
93 .map_err(ProtoError::from),
94 );
95
96 (new_future, sender)
97 }
98}
99
100impl<S: DnsTcpStream> Default for TlsClientStreamBuilder<S> {
101 fn default() -> Self {
102 Self::new()
103 }
104}
105
106impl<S: Connect> TlsClientStreamBuilder<S> {
107 #[allow(clippy::type_complexity)]
115 pub fn build(
116 self,
117 name_server: SocketAddr,
118 dns_name: String,
119 ) -> (
120 Pin<Box<dyn Future<Output = Result<TlsClientStream<S>, ProtoError>> + Send>>,
121 BufDnsStreamHandle,
122 ) {
123 let (stream_future, sender) = self.0.build(name_server, dns_name);
124
125 let new_future = Box::pin(
126 stream_future
127 .map_ok(TcpClientStream::from_stream)
128 .map_err(ProtoError::from),
129 );
130
131 (new_future, sender)
132 }
133}