#[cfg(feature = "rustls")]
#[allow(dead_code, unused_variables)]
pub mod rustls;
#[cfg(feature = "rustls")]
pub use self::rustls::hash;
#[cfg(feature = "native")]
#[allow(dead_code, unused_variables)]
pub mod native;
#[cfg(feature = "native")]
pub use self::native::hash;
#[cfg(feature = "openssl")]
#[allow(dead_code, unused_variables)]
pub mod openssl;
#[cfg(feature = "openssl")]
pub use self::openssl::hash;
#[cfg(not(any(feature = "rustls", feature = "native", feature = "openssl")))]
pub mod dummy;
#[cfg(not(any(feature = "rustls", feature = "native", feature = "openssl")))]
pub use self::dummy::hash;
use std::fmt;
use std::io;
use crate::{Error, Result};
use std::result;
#[allow(dead_code)]
pub enum HashType {
MD5,
SHA1,
SHA256,
SHA512,
}
pub trait TlsStreamImpl<S>: io::Read + io::Write + fmt::Debug + Send + Sync + 'static {
fn shutdown(&mut self) -> io::Result<()>;
fn get_mut(&mut self) -> &mut S;
fn get_ref(&self) -> &S;
fn peer_pubkey(&self) -> Vec<u8>;
fn peer_certificate(&self) -> Vec<u8>;
}
#[derive(Debug)]
pub struct TlsStream<S>(Box<dyn TlsStreamImpl<S> + 'static>);
impl<S: 'static> TlsStream<S> {
pub fn new<I: TlsStreamImpl<S> + 'static>(imp: I) -> TlsStream<S> {
TlsStream(Box::new(imp))
}
pub fn shutdown(&mut self) -> io::Result<()> {
self.0.shutdown()
}
pub fn get_mut(&mut self) -> &mut S {
self.0.get_mut()
}
pub fn get_ref(&self) -> &S {
self.0.get_ref()
}
pub fn peer_pubkey(&self) -> Vec<u8> {
let v = self.0.peer_pubkey();
if v.len() > 0 {
return v;
}
if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
let v = self.0.peer_certificate();
if v.len() > 0 {
return cert_pubkey(v);
}
}
v
}
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn cert_pubkey(_v: Vec<u8>) -> Vec<u8> {
Vec::new()
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
mod apple;
#[cfg(any(target_os = "macos", target_os = "ios"))]
use self::apple::cert_pubkey;
impl<S> io::Read for TlsStream<S> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
}
impl<S> io::Write for TlsStream<S> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.0.flush()
}
}
pub trait MidHandshakeTlsStreamImpl<S>: fmt::Debug + Sync + Send + 'static {
fn handshake(&mut self) -> result::Result<TlsStream<S>, HandshakeError<S>>;
}
#[derive(Debug)]
pub struct MidHandshakeTlsStream<S>(Box<dyn MidHandshakeTlsStreamImpl<S> + 'static>);
impl<S: 'static> MidHandshakeTlsStream<S> {
pub fn new<I: MidHandshakeTlsStreamImpl<S> + 'static>(stream: I) -> MidHandshakeTlsStream<S> {
MidHandshakeTlsStream(Box::new(stream))
}
pub fn handshake(mut self) -> result::Result<TlsStream<S>, HandshakeError<S>> {
self.0.handshake()
}
}
#[derive(Debug)]
pub enum HandshakeError<S> {
Failure(Error),
Interrupted(MidHandshakeTlsStream<S>),
}
pub trait TlsConnectorBuilder: Sized + Sync + Send + 'static {
type Connector: TlsConnector;
type Underlying;
fn add_der_certificate(&mut self, cert: &[u8]) -> Result<&mut Self>;
fn add_pem_certificate(&mut self, cert: &[u8]) -> Result<&mut Self>;
fn danger_accept_invalid_certs(&mut self) -> Result<&mut Self>;
fn build(self) -> Result<Self::Connector>;
}
pub trait TlsConnector: Sized + Sync + Send + 'static {
type Builder: TlsConnectorBuilder<Connector = Self>;
fn builder() -> Result<Self::Builder>;
fn connect<S>(
&self,
domain: &str,
stream: S,
) -> result::Result<TlsStream<S>, HandshakeError<S>>
where
S: io::Read + io::Write + fmt::Debug + Send + Sync + 'static;
}
fn _check_kinds() {
use std::net::TcpStream;
fn is_sync<T: Sync>() {}
fn is_send<T: Send>() {}
is_sync::<Error>();
is_send::<Error>();
is_sync::<TlsStream<TcpStream>>();
is_send::<TlsStream<TcpStream>>();
is_sync::<MidHandshakeTlsStream<TcpStream>>();
is_send::<MidHandshakeTlsStream<TcpStream>>();
}