#![allow(unused_imports)]
#[cfg(feature = "boring")]
pub use tokio_boring::SslStream as TlsStream;
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
pub use tokio_rustls::client::TlsStream;
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
pub use super::rustls::*;
#[cfg(feature = "boring")]
pub use crate::tls::boring::*;
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
pub mod no_tls {
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use http::Uri;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use crate::{
client::{ConnectRequest, conn::Connection},
error::BoxError,
};
pub struct TlsStream<T>(pub T);
impl<T> TlsStream<T> {
pub fn get_ref(&self) -> &T {
&self.0
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.0
}
}
pub struct HttpsConnector<T>(pub T);
pub struct TlsConnector;
#[derive(Clone)]
pub struct TlsConnectorBuilder;
pub struct EstablishedConn<IO> {
pub io: IO,
pub req: ConnectRequest,
}
impl<IO> EstablishedConn<IO> {
pub fn new(io: IO, req: ConnectRequest) -> Self {
Self { io, req }
}
}
impl<T> Clone for HttpsConnector<T>
where
T: Clone,
{
fn clone(&self) -> Self {
HttpsConnector(self.0.clone())
}
}
impl<T> HttpsConnector<T> {
pub fn with_connector(connector: T, _tls: TlsConnector) -> Self {
HttpsConnector(connector)
}
pub fn no_alpn(&mut self) {}
}
impl<T> tower::Service<Uri> for HttpsConnector<T>
where
T: tower::Service<Uri>,
T::Future: Send + 'static,
T::Error: Into<BoxError> + Send + 'static,
T::Response: Send + 'static,
{
type Response = MaybeHttpsStream<T::Response>;
type Error = BoxError;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.0.poll_ready(cx).map_err(Into::into)
}
fn call(&mut self, req: Uri) -> Self::Future {
let fut = self.0.call(req);
Box::pin(async move {
let stream = fut.await.map_err(Into::into)?;
Ok(MaybeHttpsStream::Http(stream))
})
}
}
impl<T> tower::Service<ConnectRequest> for HttpsConnector<T>
where
T: tower::Service<Uri>,
T::Future: Send + 'static,
T::Error: Into<BoxError> + Send + 'static,
T::Response: Send + 'static,
{
type Response = MaybeHttpsStream<T::Response>;
type Error = BoxError;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.0.poll_ready(cx).map_err(Into::into)
}
fn call(&mut self, req: ConnectRequest) -> Self::Future {
let fut = self.0.call(req.uri().clone());
Box::pin(async move {
let stream = fut.await.map_err(Into::into)?;
Ok(MaybeHttpsStream::Http(stream))
})
}
}
impl<T, IO> tower::Service<EstablishedConn<IO>> for HttpsConnector<T>
where
T: Clone + Send,
IO: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
type Response = MaybeHttpsStream<IO>;
type Error = BoxError;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, conn: EstablishedConn<IO>) -> Self::Future {
let io = conn.io;
Box::pin(async move { Ok(MaybeHttpsStream::Http(io)) })
}
}
impl TlsConnector {
pub fn builder() -> TlsConnectorBuilder {
TlsConnectorBuilder
}
}
impl Clone for TlsConnector {
fn clone(&self) -> Self {
TlsConnector
}
}
impl TlsConnectorBuilder {
pub fn build(&self, _opts: &crate::tls::TlsOptions) -> Result<TlsConnector, crate::Error> {
Ok(TlsConnector)
}
pub fn alpn_protocol(self, _proto: Option<crate::tls::AlpnProtocol>) -> Self {
self
}
pub fn max_version(self, _version: Option<crate::tls::TlsVersion>) -> Self {
self
}
pub fn min_version(self, _version: Option<crate::tls::TlsVersion>) -> Self {
self
}
pub fn tls_sni(self, _enable: bool) -> Self {
self
}
pub fn verify_hostname(self, _verify: bool) -> Self {
self
}
pub fn cert_verification(self, _verify: bool) -> Self {
self
}
pub fn cert_store(self, _store: crate::tls::CertStore) -> Self {
self
}
pub fn identity(self, _identity: Option<crate::tls::Identity>) -> Self {
self
}
pub fn keylog(self, _keylog: Option<crate::tls::KeyLog>) -> Self {
self
}
}
use crate::client::conn::TlsInfoFactory;
impl<T> TlsInfoFactory for TlsStream<T> {
fn tls_info(&self) -> Option<crate::tls::TlsInfo> {
None
}
}
impl<T: AsyncRead + Unpin> AsyncRead for TlsStream<T> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.get_mut().0).poll_read(cx, buf)
}
}
impl<T: AsyncWrite + Unpin> AsyncWrite for TlsStream<T> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
Pin::new(&mut self.get_mut().0).poll_write(cx, buf)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.get_mut().0).poll_flush(cx)
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.get_mut().0).poll_shutdown(cx)
}
}
pub enum MaybeHttpsStream<T> {
Http(T),
Https(TlsStream<T>),
}
impl<T> MaybeHttpsStream<T> {
pub fn get_ref(&self) -> &T {
match self {
MaybeHttpsStream::Http(s) => s,
MaybeHttpsStream::Https(s) => &s.0,
}
}
pub fn get_mut(&mut self) -> &mut T {
match self {
MaybeHttpsStream::Http(s) => s,
MaybeHttpsStream::Https(s) => &mut s.0,
}
}
}
impl<T: AsyncRead + AsyncWrite + Unpin> AsyncRead for MaybeHttpsStream<T> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
match self.get_mut() {
MaybeHttpsStream::Http(s) => Pin::new(s).poll_read(cx, buf),
MaybeHttpsStream::Https(s) => Pin::new(&mut s.0).poll_read(cx, buf),
}
}
}
impl<T: AsyncRead + AsyncWrite + Unpin> AsyncWrite for MaybeHttpsStream<T> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
match self.get_mut() {
MaybeHttpsStream::Http(s) => Pin::new(s).poll_write(cx, buf),
MaybeHttpsStream::Https(s) => Pin::new(&mut s.0).poll_write(cx, buf),
}
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
match self.get_mut() {
MaybeHttpsStream::Http(s) => Pin::new(s).poll_flush(cx),
MaybeHttpsStream::Https(s) => Pin::new(&mut s.0).poll_flush(cx),
}
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
match self.get_mut() {
MaybeHttpsStream::Http(s) => Pin::new(s).poll_shutdown(cx),
MaybeHttpsStream::Https(s) => Pin::new(&mut s.0).poll_shutdown(cx),
}
}
}
impl<T: Connection> Connection for MaybeHttpsStream<T> {
fn connected(&self) -> crate::client::conn::Connected {
match self {
MaybeHttpsStream::Http(s) => s.connected(),
MaybeHttpsStream::Https(s) => s.0.connected(),
}
}
}
}
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
pub use self::no_tls::*;