From 7f8b4529eb8d92c97d44fc34c35548d4b17ab033 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Wed, 24 Mar 2021 17:21:20 +0800 Subject: [PATCH] add native tisl support for actix_tls::connect module --- actix-router/src/url.rs | 8 +-- actix-server/src/test_server.rs | 2 +- actix-service/src/map_err.rs | 2 +- actix-tls/src/connect/ssl/mod.rs | 3 + actix-tls/src/connect/ssl/nativetls.rs | 88 ++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 actix-tls/src/connect/ssl/nativetls.rs diff --git a/actix-router/src/url.rs b/actix-router/src/url.rs index d2dd7a19..904c473e 100644 --- a/actix-router/src/url.rs +++ b/actix-router/src/url.rs @@ -170,13 +170,11 @@ impl Quoter { idx += 1; } - if let Some(data) = cloned { + cloned.map(|data| { // Unsafe: we get data from http::Uri, which does utf-8 checks already // this code only decodes valid pct encoded values - Some(unsafe { String::from_utf8_unchecked(data) }) - } else { - None - } + unsafe { String::from_utf8_unchecked(data) } + }) } } diff --git a/actix-server/src/test_server.rs b/actix-server/src/test_server.rs index 864f391c..0611cf4b 100644 --- a/actix-server/src/test_server.rs +++ b/actix-server/src/test_server.rs @@ -92,10 +92,10 @@ impl TestServer { let port = addr.port(); TestServerRuntime { - system, addr, host, port, + system, } } diff --git a/actix-service/src/map_err.rs b/actix-service/src/map_err.rs index ff25c4f7..7b1ac2ab 100644 --- a/actix-service/src/map_err.rs +++ b/actix-service/src/map_err.rs @@ -180,7 +180,7 @@ where F: Fn(A::Error) -> E, { fn new(fut: A::Future, f: F) -> Self { - MapErrServiceFuture { f, fut } + MapErrServiceFuture { fut, f } } } diff --git a/actix-tls/src/connect/ssl/mod.rs b/actix-tls/src/connect/ssl/mod.rs index 8ace5ef1..648374ea 100644 --- a/actix-tls/src/connect/ssl/mod.rs +++ b/actix-tls/src/connect/ssl/mod.rs @@ -5,3 +5,6 @@ pub mod openssl; #[cfg(feature = "rustls")] pub mod rustls; + +#[cfg(feature = "native-tls")] +pub mod nativetls; diff --git a/actix-tls/src/connect/ssl/nativetls.rs b/actix-tls/src/connect/ssl/nativetls.rs new file mode 100644 index 00000000..c16e9dc9 --- /dev/null +++ b/actix-tls/src/connect/ssl/nativetls.rs @@ -0,0 +1,88 @@ +use std::io; + +use actix_rt::net::ActixStream; +use actix_service::{Service, ServiceFactory}; +use futures_core::future::LocalBoxFuture; +use log::trace; +use tokio_native_tls::{TlsConnector as TokioNativetlsConnector, TlsStream}; + +pub use tokio_native_tls::native_tls::TlsConnector; + +use crate::connect::{Address, Connection}; + +/// Native-tls connector factory and service +pub struct NativetlsConnector { + connector: TokioNativetlsConnector, +} + +impl NativetlsConnector { + pub fn new(connector: TlsConnector) -> Self { + Self { + connector: TokioNativetlsConnector::from(connector), + } + } +} + +impl NativetlsConnector { + pub fn service(connector: TlsConnector) -> Self { + Self::new(connector) + } +} + +impl Clone for NativetlsConnector { + fn clone(&self) -> Self { + Self { + connector: self.connector.clone(), + } + } +} + +impl ServiceFactory> for NativetlsConnector +where + U: ActixStream, +{ + type Response = Connection>; + type Error = io::Error; + type Config = (); + type Service = Self; + type InitError = (); + type Future = LocalBoxFuture<'static, Result>; + + fn new_service(&self, _: ()) -> Self::Future { + let connector = self.clone(); + Box::pin(async { Ok(connector) }) + } +} + +// NativetlsConnector is both it's ServiceFactory and Service impl type. +// As the factory and service share the same type and state. +impl Service> for NativetlsConnector +where + T: Address, + U: ActixStream, +{ + type Response = Connection>; + type Error = io::Error; + type Future = LocalBoxFuture<'static, Result>; + + actix_service::always_ready!(); + + fn call(&self, stream: Connection) -> Self::Future { + let (io, stream) = stream.replace_io(()); + let connector = self.connector.clone(); + Box::pin(async move { + trace!("SSL Handshake start for: {:?}", stream.host()); + connector + .connect(stream.host(), io) + .await + .map(|res| { + trace!("SSL Handshake success: {:?}", stream.host()); + stream.replace_io(res).1 + }) + .map_err(|e| { + trace!("SSL Handshake error: {:?}", e); + io::Error::new(io::ErrorKind::Other, format!("{}", e)) + }) + }) + } +}