From bb27bac2168eb886229d4354af3d30e32311038a Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Fri, 26 Mar 2021 17:20:17 -0700 Subject: [PATCH] Add native tls support for actix_tls::connect module (#295) Co-authored-by: Rob Ede --- actix-router/src/url.rs | 10 +-- actix-server/CHANGES.md | 3 + actix-server/src/test_server.rs | 2 +- actix-service/src/map_err.rs | 2 +- actix-tls/CHANGES.md | 4 + actix-tls/src/accept/mod.rs | 2 +- .../accept/{nativetls.rs => native_tls.rs} | 0 actix-tls/src/connect/ssl/mod.rs | 3 + actix-tls/src/connect/ssl/native_tls.rs | 88 +++++++++++++++++++ 9 files changed, 105 insertions(+), 9 deletions(-) rename actix-tls/src/accept/{nativetls.rs => native_tls.rs} (100%) create mode 100644 actix-tls/src/connect/ssl/native_tls.rs diff --git a/actix-router/src/url.rs b/actix-router/src/url.rs index d2dd7a19..f669da99 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 { - // Unsafe: we get data from http::Uri, which does utf-8 checks already + cloned.map(|data| { + // SAFETY: 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/CHANGES.md b/actix-server/CHANGES.md index 5eca1f91..aaa38911 100644 --- a/actix-server/CHANGES.md +++ b/actix-server/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2021-xx-xx +* Prevent panic when shutdown_timeout is very large. [f9262db] + +[f9262db]: https://github.com/actix/actix-net/commit/f9262db ## 2.0.0-beta.3 - 2021-02-06 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/CHANGES.md b/actix-tls/CHANGES.md index d78663d9..400b1763 100644 --- a/actix-tls/CHANGES.md +++ b/actix-tls/CHANGES.md @@ -5,10 +5,14 @@ generation failed instead of panic. [#296] * Remove `connect::ssl::openssl::OpensslConnectServiceFactory`. [#297] * Remove `connect::ssl::openssl::OpensslConnectService`. [#297] +* Add `connect::ssl::native_tls` module for native tls support. [#295] +* Rename `accept::{nativetls => native_tls}`. [#295] +[#295]: https://github.com/actix/actix-net/pull/295 [#296]: https://github.com/actix/actix-net/pull/296 [#297]: https://github.com/actix/actix-net/pull/297 + ## 3.0.0-beta.4 - 2021-02-24 * Rename `accept::openssl::{SslStream => TlsStream}`. * Add `connect::Connect::set_local_addr` to attach local `IpAddr`. [#282] diff --git a/actix-tls/src/accept/mod.rs b/actix-tls/src/accept/mod.rs index 8b1fe47c..dd939e4a 100644 --- a/actix-tls/src/accept/mod.rs +++ b/actix-tls/src/accept/mod.rs @@ -16,7 +16,7 @@ pub mod openssl; pub mod rustls; #[cfg(feature = "native-tls")] -pub mod nativetls; +pub mod native_tls; pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256); diff --git a/actix-tls/src/accept/nativetls.rs b/actix-tls/src/accept/native_tls.rs similarity index 100% rename from actix-tls/src/accept/nativetls.rs rename to actix-tls/src/accept/native_tls.rs diff --git a/actix-tls/src/connect/ssl/mod.rs b/actix-tls/src/connect/ssl/mod.rs index 8ace5ef1..6e0e8aac 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 native_tls; diff --git a/actix-tls/src/connect/ssl/native_tls.rs b/actix-tls/src/connect/ssl/native_tls.rs new file mode 100644 index 00000000..de08ea2a --- /dev/null +++ b/actix-tls/src/connect/ssl/native_tls.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 + 'static, +{ + 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 + 'static, +{ + 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)) + }) + }) + } +}