Merge branch 'std-future' of github.com:actix/actix-net into std-future

This commit is contained in:
Nikolay Kim 2019-11-14 05:16:06 +06:00
commit 210f183aa0
5 changed files with 100 additions and 183 deletions

View File

@ -14,26 +14,14 @@ name = "actix_server_config"
path = "src/lib.rs" path = "src/lib.rs"
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["ssl", "rust-tls", "uds"] features = ["openssl", "rustls"]
[features] [features]
default = ["ssl", "rustls" ] default = []
openssl = ["tokio-openssl"]
# openssl rustls = ["tokio-rustls"]
ssl = ["tokio-openssl"]
# rustls
rust-tls = ["rustls", "tokio-rustls"]
# unix domain sockets
# TODO: FIXME
uds = [] # ["tokio-uds"]
[dependencies] [dependencies]
futures = { package = "futures-preview", version = "0.3.0-alpha.18" } tokio = "0.2.0-alpha.6"
tokio = "0.2.0-alpha.4" tokio-openssl = { version = "0.4.0-alpha.6", optional = true }
tokio-rustls = { version = "0.12.0-alpha.8", optional = true }
tokio-openssl = { version="0.4.0-alpha.4", optional = true }
rustls = { version = "0.16.0", optional = true }
tokio-rustls = { version = "0.12.0-alpha.2", optional = true }
#tokio-uds = { version="0.3.0-alpha.1", optional = true }

View File

@ -1,10 +1,12 @@
//! Actix server config utils.
use std::cell::Cell; use std::cell::Cell;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::rc::Rc; use std::rc::Rc;
use std::{fmt, io, net, time}; use std::{fmt, io, net, ops, time};
use tokio::io::{AsyncRead, AsyncWrite}; use tokio::io::{AsyncRead, AsyncWrite};
use tokio::net::tcp::TcpStream; use tokio::net::TcpStream;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ServerConfig { pub struct ServerConfig {
@ -13,6 +15,7 @@ pub struct ServerConfig {
} }
impl ServerConfig { impl ServerConfig {
#[inline]
pub fn new(addr: SocketAddr) -> Self { pub fn new(addr: SocketAddr) -> Self {
ServerConfig { ServerConfig {
addr, addr,
@ -21,16 +24,19 @@ impl ServerConfig {
} }
/// Returns the address of the local half of this TCP server socket /// Returns the address of the local half of this TCP server socket
#[inline]
pub fn local_addr(&self) -> SocketAddr { pub fn local_addr(&self) -> SocketAddr {
self.addr self.addr
} }
/// Returns true if connection is secure (tls enabled) /// Returns true if connection is secure (tls enabled)
#[inline]
pub fn secure(&self) -> bool { pub fn secure(&self) -> bool {
self.secure.as_ref().get() self.secure.as_ref().get()
} }
/// Set secure flag /// Set secure flag
#[inline]
pub fn set_secure(&self) { pub fn set_secure(&self) {
self.secure.as_ref().set(true) self.secure.as_ref().set(true)
} }
@ -114,7 +120,7 @@ impl<T, P> Io<T, P> {
} }
} }
impl<T, P> std::ops::Deref for Io<T, P> { impl<T, P> ops::Deref for Io<T, P> {
type Target = T; type Target = T;
fn deref(&self) -> &T { fn deref(&self) -> &T {
@ -122,14 +128,14 @@ impl<T, P> std::ops::Deref for Io<T, P> {
} }
} }
impl<T, P> std::ops::DerefMut for Io<T, P> { impl<T, P> ops::DerefMut for Io<T, P> {
fn deref_mut(&mut self) -> &mut T { fn deref_mut(&mut self) -> &mut T {
&mut self.io &mut self.io
} }
} }
impl<T: fmt::Debug, P> fmt::Debug for Io<T, P> { impl<T: fmt::Debug, P> fmt::Debug for Io<T, P> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Io {{{:?}}}", self.io) write!(f, "Io {{{:?}}}", self.io)
} }
} }
@ -171,7 +177,7 @@ impl IoStream for TcpStream {
} }
} }
#[cfg(any(feature = "ssl"))] #[cfg(feature = "openssl")]
impl<T: IoStream + Unpin> IoStream for tokio_openssl::SslStream<T> { impl<T: IoStream + Unpin> IoStream for tokio_openssl::SslStream<T> {
#[inline] #[inline]
fn peer_addr(&self) -> Option<net::SocketAddr> { fn peer_addr(&self) -> Option<net::SocketAddr> {
@ -194,8 +200,8 @@ impl<T: IoStream + Unpin> IoStream for tokio_openssl::SslStream<T> {
} }
} }
#[cfg(any(feature = "rust-tls"))] #[cfg(feature = "rustls")]
impl<T: IoStream> IoStream for tokio_rustls::server::TlsStream<T> { impl<T: IoStream + Unpin> IoStream for tokio_rustls::server::TlsStream<T> {
#[inline] #[inline]
fn peer_addr(&self) -> Option<net::SocketAddr> { fn peer_addr(&self) -> Option<net::SocketAddr> {
self.get_ref().0.peer_addr() self.get_ref().0.peer_addr()
@ -217,8 +223,8 @@ impl<T: IoStream> IoStream for tokio_rustls::server::TlsStream<T> {
} }
} }
#[cfg(all(unix, feature = "uds"))] #[cfg(unix)]
impl IoStream for t::UnixStream { impl IoStream for tokio::net::UnixStream {
#[inline] #[inline]
fn peer_addr(&self) -> Option<net::SocketAddr> { fn peer_addr(&self) -> Option<net::SocketAddr> {
None None

View File

@ -14,7 +14,7 @@ edition = "2018"
workspace = ".." workspace = ".."
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["ssl", "tls", "rust-tls", "uds"] features = ["nativetls", "openssl", "rustls", "uds"]
[lib] [lib]
name = "actix_server" name = "actix_server"
@ -22,15 +22,9 @@ path = "src/lib.rs"
[features] [features]
default = [] default = []
nativetls = ["native-tls", "tokio-tls"]
# tls openssl = ["open-ssl", "tokio-openssl", "actix-server-config/openssl"]
tls = ["native-tls"] rustls = ["rust-tls", "tokio-rustls", "webpki", "webpki-roots", "actix-server-config/rustls"]
# openssl
ssl = ["openssl", "tokio-openssl", "actix-server-config/ssl"]
# rustls
rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots", "actix-server-config/rust-tls"]
# uds # uds
# uds = ["mio-uds", "tokio-uds", "actix-server-config/uds"] # uds = ["mio-uds", "tokio-uds", "actix-server-config/uds"]
@ -54,18 +48,19 @@ tokio-net = { version = "0.2.0-alpha.6", features = ["signal"] }
tokio-timer = "0.3.0-alpha.6" tokio-timer = "0.3.0-alpha.6"
# unix domain sockets # unix domain sockets
mio-uds = { version="0.6.7", optional = true } mio-uds = { version = "0.6.7", optional = true }
#tokio-uds = { version="0.2.5", optional = true } #tokio-uds = { version="0.2.5", optional = true }
# native-tls # nativetls
native-tls = { version="0.2", optional = true } native-tls = { version = "0.2", optional = true }
tokio-tls = { version = "0.3.0-alpha.6", optional = true }
# openssl # openssl
openssl = { version="0.10", optional = true } open-ssl = { version = "0.10", package = "openssl", optional = true }
tokio-openssl = { version="0.4.0-alpha.6", optional = true } tokio-openssl = { version = "0.4.0-alpha.6", optional = true }
# rustls # rustls
rustls = { version = "0.16.0", optional = true } rust-tls = { version = "0.16.0", package = "rustls", optional = true }
tokio-rustls = { version = "0.12.0-alpha.2", optional = true } tokio-rustls = { version = "0.12.0-alpha.2", optional = true }
webpki = { version = "0.21", optional = true } webpki = { version = "0.21", optional = true }
webpki-roots = { version = "0.17", optional = true } webpki-roots = { version = "0.17", optional = true }

View File

@ -3,19 +3,19 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use crate::counter::Counter; use crate::counter::Counter;
#[cfg(feature = "ssl")] #[cfg(feature = "openssl")]
mod openssl; mod openssl;
#[cfg(feature = "ssl")] #[cfg(feature = "openssl")]
pub use self::openssl::OpensslAcceptor; pub use self::openssl::OpensslAcceptor;
#[cfg(feature = "tls")] #[cfg(feature = "nativetls")]
mod nativetls; mod nativetls;
#[cfg(feature = "tls")] #[cfg(feature = "nativetls")]
pub use self::nativetls::{NativeTlsAcceptor, TlsStream}; pub use self::nativetls::NativeTlsAcceptor;
#[cfg(feature = "rust-tls")] #[cfg(feature = "rustls")]
mod rustls; mod rustls;
#[cfg(feature = "rust-tls")] #[cfg(feature = "rustls")]
pub use self::rustls::RustlsAcceptor; pub use self::rustls::RustlsAcceptor;
/// Sets the maximum per-worker concurrent ssl connection establish process. /// Sets the maximum per-worker concurrent ssl connection establish process.

View File

@ -1,16 +1,19 @@
use std::io; use std::convert::Infallible;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::task::{Context, Poll};
use actix_service::{NewService, Service}; use actix_service::{Service, ServiceFactory};
use futures::{future::ok, future::FutureResult, Async, Future, Poll}; use futures::{
use native_tls::{self, Error, HandshakeError, TlsAcceptor}; future::{self, LocalBoxFuture},
use tokio_io::{AsyncRead, AsyncWrite}; FutureExt as _, TryFutureExt as _,
};
use native_tls::Error;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio_tls::{TlsAcceptor, TlsStream};
use crate::counter::{Counter, CounterGuard}; use crate::counter::Counter;
use crate::ssl::MAX_CONN_COUNTER; use crate::ssl::MAX_CONN_COUNTER;
use crate::{Io, Protocol, ServerConfig}; use crate::{Io, ServerConfig};
use std::pin::Pin;
use std::task::Context;
/// Support `SSL` connections via native-tls package /// Support `SSL` connections via native-tls package
/// ///
@ -20,8 +23,12 @@ pub struct NativeTlsAcceptor<T, P = ()> {
io: PhantomData<(T, P)>, io: PhantomData<(T, P)>,
} }
impl<T: AsyncRead + AsyncWrite, P> NativeTlsAcceptor<T, P> { impl<T, P> NativeTlsAcceptor<T, P>
where
T: AsyncRead + AsyncWrite + Unpin,
{
/// Create `NativeTlsAcceptor` instance /// Create `NativeTlsAcceptor` instance
#[inline]
pub fn new(acceptor: TlsAcceptor) -> Self { pub fn new(acceptor: TlsAcceptor) -> Self {
NativeTlsAcceptor { NativeTlsAcceptor {
acceptor, acceptor,
@ -30,7 +37,8 @@ impl<T: AsyncRead + AsyncWrite, P> NativeTlsAcceptor<T, P> {
} }
} }
impl<T: AsyncRead + AsyncWrite, P> Clone for NativeTlsAcceptor<T, P> { impl<T, P> Clone for NativeTlsAcceptor<T, P> {
#[inline]
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
acceptor: self.acceptor.clone(), acceptor: self.acceptor.clone(),
@ -39,21 +47,25 @@ impl<T: AsyncRead + AsyncWrite, P> Clone for NativeTlsAcceptor<T, P> {
} }
} }
impl<T: AsyncRead + AsyncWrite, P> NewService for NativeTlsAcceptor<T, P> { impl<T, P> ServiceFactory for NativeTlsAcceptor<T, P>
where
T: AsyncRead + AsyncWrite + Unpin + 'static,
P: 'static,
{
type Request = Io<T, P>; type Request = Io<T, P>;
type Response = Io<TlsStream<T>, P>; type Response = Io<TlsStream<T>, P>;
type Error = Error; type Error = Error;
type Config = ServerConfig; type Config = ServerConfig;
type Service = NativeTlsAcceptorService<T, P>; type Service = NativeTlsAcceptorService<T, P>;
type InitError = (); type InitError = Infallible;
type Future = FutureResult<Self::Service, Self::InitError>; type Future = future::Ready<Result<Self::Service, Self::InitError>>;
fn new_service(&self, cfg: &ServerConfig) -> Self::Future { fn new_service(&self, cfg: &ServerConfig) -> Self::Future {
cfg.set_secure(); cfg.set_secure();
MAX_CONN_COUNTER.with(|conns| { MAX_CONN_COUNTER.with(|conns| {
ok(NativeTlsAcceptorService { future::ok(NativeTlsAcceptorService {
acceptor: self.acceptor.clone(), acceptor: self.acceptor.clone(),
conns: conns.clone(), conns: conns.clone(),
io: PhantomData, io: PhantomData,
@ -68,130 +80,46 @@ pub struct NativeTlsAcceptorService<T, P> {
conns: Counter, conns: Counter,
} }
impl<T: AsyncRead + AsyncWrite, P> Service for NativeTlsAcceptorService<T, P> { impl<T, P> Clone for NativeTlsAcceptorService<T, P> {
fn clone(&self) -> Self {
Self {
acceptor: self.acceptor.clone(),
io: PhantomData,
conns: self.conns.clone(),
}
}
}
impl<T, P> Service for NativeTlsAcceptorService<T, P>
where
T: AsyncRead + AsyncWrite + Unpin + 'static,
P: 'static,
{
type Request = Io<T, P>; type Request = Io<T, P>;
type Response = Io<TlsStream<T>, P>; type Response = Io<TlsStream<T>, P>;
type Error = Error; type Error = Error;
type Future = Accept<T, P>; type Future = LocalBoxFuture<'static, Result<Io<TlsStream<T>, P>, Error>>;
fn poll_ready( fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self: Pin<&mut Self>, if self.conns.available(cx) {
ctx: &mut Context<'_>, Poll::Ready(Ok(()))
) -> Poll<Result<(), Self::Error>> {
if self.conns.available(ctx) {
Ok(Async::Ready(()))
} else { } else {
Ok(Async::NotReady) Poll::Pending
} }
} }
/*
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
if self.conns.available() {
Ok(Async::Ready(()))
} else {
Ok(Async::NotReady)
}
}
*/
fn call(&mut self, req: Self::Request) -> Self::Future { fn call(&mut self, req: Self::Request) -> Self::Future {
let (io, params, _) = req.into_parts(); let guard = self.conns.get();
Accept { let this = self.clone();
_guard: self.conns.get(), let (io, params, proto) = req.into_parts();
inner: Some(self.acceptor.accept(io)), async move { this.acceptor.accept(io).await }
params: Some(params), .map_ok(move |stream| Io::from_parts(stream, params, proto))
} .map_ok(move |io| {
} // Required to preserve `CounterGuard` until `Self::Future`
} // is completely resolved.
let _ = guard;
/// A wrapper around an underlying raw stream which implements the TLS or SSL io
/// protocol. })
/// .boxed_local()
/// A `TlsStream<S>` represents a handshake that has been completed successfully
/// and both the server and the client are ready for receiving and sending
/// data. Bytes read from a `TlsStream` are decrypted from `S` and bytes written
/// to a `TlsStream` are encrypted when passing through to `S`.
#[derive(Debug)]
pub struct TlsStream<S> {
inner: native_tls::TlsStream<S>,
}
/// Future returned from `NativeTlsAcceptor::accept` which will resolve
/// once the accept handshake has finished.
pub struct Accept<S, P> {
inner: Option<Result<native_tls::TlsStream<S>, HandshakeError<S>>>,
params: Option<P>,
_guard: CounterGuard,
}
impl<T: AsyncRead + AsyncWrite, P> Future for Accept<T, P> {
type Item = Io<TlsStream<T>, P>;
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match self.inner.take().expect("cannot poll MidHandshake twice") {
Ok(stream) => Ok(Async::Ready(Io::from_parts(
TlsStream { inner: stream },
self.params.take().unwrap(),
Protocol::Unknown,
))),
Err(HandshakeError::Failure(e)) => Err(e),
Err(HandshakeError::WouldBlock(s)) => match s.handshake() {
Ok(stream) => Ok(Async::Ready(Io::from_parts(
TlsStream { inner: stream },
self.params.take().unwrap(),
Protocol::Unknown,
))),
Err(HandshakeError::Failure(e)) => Err(e),
Err(HandshakeError::WouldBlock(s)) => {
self.inner = Some(Err(HandshakeError::WouldBlock(s)));
Ok(Async::NotReady)
}
},
}
}
}
impl<S> TlsStream<S> {
/// Get access to the internal `native_tls::TlsStream` stream which also
/// transitively allows access to `S`.
pub fn get_ref(&self) -> &native_tls::TlsStream<S> {
&self.inner
}
/// Get mutable access to the internal `native_tls::TlsStream` stream which
/// also transitively allows mutable access to `S`.
pub fn get_mut(&mut self) -> &mut native_tls::TlsStream<S> {
&mut self.inner
}
}
impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}
impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}
impl<S: AsyncRead + AsyncWrite> AsyncRead for TlsStream<S> {}
impl<S: AsyncRead + AsyncWrite> AsyncWrite for TlsStream<S> {
fn shutdown(&mut self) -> Poll<(), io::Error> {
match self.inner.shutdown() {
Ok(_) => (),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => (),
Err(e) => return Err(e),
}
self.inner.get_mut().shutdown()
} }
} }