mirror of
https://github.com/fafhrd91/actix-net
synced 2024-11-27 15:42:57 +01:00
refactor server configuration and tls support
This commit is contained in:
parent
16ff283fb2
commit
9fbe6a1f6d
@ -7,9 +7,9 @@ members = [
|
|||||||
"actix-macros",
|
"actix-macros",
|
||||||
"actix-service",
|
"actix-service",
|
||||||
"actix-server",
|
"actix-server",
|
||||||
"actix-server-config",
|
|
||||||
"actix-testing",
|
"actix-testing",
|
||||||
"actix-threadpool",
|
"actix-threadpool",
|
||||||
|
"actix-tls",
|
||||||
"actix-utils",
|
"actix-utils",
|
||||||
"router",
|
"router",
|
||||||
]
|
]
|
||||||
@ -21,9 +21,9 @@ actix-ioframe = { path = "actix-ioframe" }
|
|||||||
actix-rt = { path = "actix-rt" }
|
actix-rt = { path = "actix-rt" }
|
||||||
actix-macros = { path = "actix-macros" }
|
actix-macros = { path = "actix-macros" }
|
||||||
actix-server = { path = "actix-server" }
|
actix-server = { path = "actix-server" }
|
||||||
actix-server-config = { path = "actix-server-config" }
|
|
||||||
actix-service = { path = "actix-service" }
|
actix-service = { path = "actix-service" }
|
||||||
actix-testing = { path = "actix-testing" }
|
actix-testing = { path = "actix-testing" }
|
||||||
actix-threadpool = { path = "actix-threadpool" }
|
actix-threadpool = { path = "actix-threadpool" }
|
||||||
|
actix-tls = { path = "actix-tls" }
|
||||||
actix-utils = { path = "actix-utils" }
|
actix-utils = { path = "actix-utils" }
|
||||||
actix-router = { path = "router" }
|
actix-router = { path = "router" }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-rt"
|
name = "actix-rt"
|
||||||
version = "1.0.0-alpha.1"
|
version = "1.0.0-alpha.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix runtime"
|
description = "Actix runtime"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
@ -21,10 +21,9 @@ path = "src/lib.rs"
|
|||||||
actix-macros = "0.1.0-alpha.1"
|
actix-macros = "0.1.0-alpha.1"
|
||||||
actix-threadpool = "0.2"
|
actix-threadpool = "0.2"
|
||||||
futures = "0.3.1"
|
futures = "0.3.1"
|
||||||
|
copyless = "0.1.4"
|
||||||
|
|
||||||
tokio = { version = "=0.2.0-alpha.6", features=["rt-current-thread","tcp","uds","udp","timer"] }
|
tokio = { version = "=0.2.0-alpha.6", features=["rt-current-thread","tcp","uds","udp","timer","signal"] }
|
||||||
tokio-executor = "=0.2.0-alpha.6"
|
tokio-executor = "=0.2.0-alpha.6"
|
||||||
tokio-net = "=0.2.0-alpha.6"
|
tokio-net = "=0.2.0-alpha.6"
|
||||||
tokio-timer = "=0.3.0-alpha.6"
|
tokio-timer = "=0.3.0-alpha.6"
|
||||||
|
|
||||||
copyless = "0.1.4"
|
|
||||||
|
@ -32,6 +32,28 @@ where
|
|||||||
Arbiter::spawn(f);
|
Arbiter::spawn(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Asynchronous signal handling
|
||||||
|
pub mod signal {
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub mod unix {
|
||||||
|
pub use tokio_net::signal::unix::*;
|
||||||
|
}
|
||||||
|
pub use tokio_net::signal::{ctrl_c, CtrlC};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TCP/UDP/Unix bindings
|
||||||
|
pub mod net {
|
||||||
|
pub use tokio::net::UdpSocket;
|
||||||
|
pub use tokio::net::{TcpListener, TcpStream};
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
mod unix {
|
||||||
|
pub use tokio::net::{UnixDatagram, UnixListener, UnixStream};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::unix::*;
|
||||||
|
}
|
||||||
|
|
||||||
/// Utilities for tracking time.
|
/// Utilities for tracking time.
|
||||||
pub mod time {
|
pub mod time {
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@ -52,15 +74,3 @@ pub mod time {
|
|||||||
Interval::new(start, duration)
|
Interval::new(start, duration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod net {
|
|
||||||
pub use tokio::net::UdpSocket;
|
|
||||||
pub use tokio::net::{TcpListener, TcpStream};
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
mod unix {
|
|
||||||
pub use tokio::net::{UnixDatagram, UnixListener, UnixStream};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use self::unix::*;
|
|
||||||
}
|
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "actix-server-config"
|
|
||||||
version = "0.3.0-alpha.1"
|
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
|
||||||
description = "Actix server config utils"
|
|
||||||
homepage = "https://actix.rs"
|
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
|
||||||
license = "MIT/Apache-2.0"
|
|
||||||
edition = "2018"
|
|
||||||
workspace = ".."
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "actix_server_config"
|
|
||||||
path = "src/lib.rs"
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
features = ["openssl"] #, "rustls"]
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = []
|
|
||||||
openssl = ["tokio-openssl"]
|
|
||||||
# rustls = ["tokio-rustls"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
actix-codec = "0.2.0-alpha.1"
|
|
||||||
tokio-net = { version = "=0.2.0-alpha.6", features = ["tcp", "uds"] }
|
|
||||||
tokio-openssl = { version = "0.4.0-alpha.6", optional = true }
|
|
||||||
# tokio-rustls = { version = "0.12.0-alpha.8", optional = true }
|
|
||||||
# tokio-rustls = { git = "https://github.com/quininer/tokio-rustls.git", branch = "tokio-0.2", optional = true }
|
|
@ -1,21 +0,0 @@
|
|||||||
# Changes
|
|
||||||
|
|
||||||
## [0.2.0] - 2019-10-03
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
* Update `rustls` to 0.16
|
|
||||||
* Minimum required Rust version upped to 1.37.0
|
|
||||||
|
|
||||||
## [0.1.2] - 2019-07-18
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
* Add unix domnain sockets support
|
|
||||||
|
|
||||||
|
|
||||||
## [0.1.1] - 2019-04-16
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
* `IoStream` trait and impls for TcpStream, SslStream and TlsStream
|
|
@ -1,249 +0,0 @@
|
|||||||
//! Actix server config utils.
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::{fmt, io, net, ops, time};
|
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite};
|
|
||||||
use tokio_net::tcp::TcpStream;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ServerConfig {
|
|
||||||
addr: SocketAddr,
|
|
||||||
secure: Rc<Cell<bool>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ServerConfig {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(addr: SocketAddr) -> Self {
|
|
||||||
ServerConfig {
|
|
||||||
addr,
|
|
||||||
secure: Rc::new(Cell::new(false)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the address of the local half of this TCP server socket
|
|
||||||
#[inline]
|
|
||||||
pub fn local_addr(&self) -> SocketAddr {
|
|
||||||
self.addr
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if connection is secure (tls enabled)
|
|
||||||
#[inline]
|
|
||||||
pub fn secure(&self) -> bool {
|
|
||||||
self.secure.as_ref().get()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set secure flag
|
|
||||||
#[inline]
|
|
||||||
pub fn set_secure(&self) {
|
|
||||||
self.secure.as_ref().set(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
|
||||||
pub enum Protocol {
|
|
||||||
Unknown,
|
|
||||||
Http10,
|
|
||||||
Http11,
|
|
||||||
Http2,
|
|
||||||
Proto1,
|
|
||||||
Proto2,
|
|
||||||
Proto3,
|
|
||||||
Proto4,
|
|
||||||
Proto5,
|
|
||||||
Proto6,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Io<T, P = ()> {
|
|
||||||
io: T,
|
|
||||||
proto: Protocol,
|
|
||||||
params: P,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Unpin> Unpin for Io<T> {}
|
|
||||||
|
|
||||||
impl<T> Io<T, ()> {
|
|
||||||
pub fn new(io: T) -> Self {
|
|
||||||
Self {
|
|
||||||
io,
|
|
||||||
proto: Protocol::Unknown,
|
|
||||||
params: (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, P> Io<T, P> {
|
|
||||||
/// Reconstruct from a parts.
|
|
||||||
pub fn from_parts(io: T, params: P, proto: Protocol) -> Self {
|
|
||||||
Self { io, params, proto }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deconstruct into a parts.
|
|
||||||
pub fn into_parts(self) -> (T, P, Protocol) {
|
|
||||||
(self.io, self.params, self.proto)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a shared reference to the underlying stream.
|
|
||||||
pub fn get_ref(&self) -> &T {
|
|
||||||
&self.io
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a mutable reference to the underlying stream.
|
|
||||||
pub fn get_mut(&mut self) -> &mut T {
|
|
||||||
&mut self.io
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get selected protocol
|
|
||||||
pub fn protocol(&self) -> Protocol {
|
|
||||||
self.proto
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return new Io object with new parameter.
|
|
||||||
pub fn set<U>(self, params: U) -> Io<T, U> {
|
|
||||||
Io {
|
|
||||||
params,
|
|
||||||
io: self.io,
|
|
||||||
proto: self.proto,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Maps an Io<_, P> to Io<_, U> by applying a function to a contained value.
|
|
||||||
pub fn map<U, F>(self, op: F) -> Io<T, U>
|
|
||||||
where
|
|
||||||
F: FnOnce(P) -> U,
|
|
||||||
{
|
|
||||||
Io {
|
|
||||||
io: self.io,
|
|
||||||
proto: self.proto,
|
|
||||||
params: op(self.params),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, P> ops::Deref for Io<T, P> {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
fn deref(&self) -> &T {
|
|
||||||
&self.io
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, P> ops::DerefMut for Io<T, P> {
|
|
||||||
fn deref_mut(&mut self) -> &mut T {
|
|
||||||
&mut self.io
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Debug, P> fmt::Debug for Io<T, P> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "Io {{{:?}}}", self.io)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Low-level io stream operations
|
|
||||||
pub trait IoStream: AsyncRead + AsyncWrite + Unpin {
|
|
||||||
/// Returns the socket address of the remote peer of this TCP connection.
|
|
||||||
fn peer_addr(&self) -> Option<SocketAddr> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the value of the TCP_NODELAY option on this socket.
|
|
||||||
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()>;
|
|
||||||
|
|
||||||
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()>;
|
|
||||||
|
|
||||||
fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IoStream for TcpStream {
|
|
||||||
#[inline]
|
|
||||||
fn peer_addr(&self) -> Option<net::SocketAddr> {
|
|
||||||
TcpStream::peer_addr(self).ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
|
|
||||||
TcpStream::set_nodelay(self, nodelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
|
|
||||||
TcpStream::set_linger(self, dur)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
|
|
||||||
TcpStream::set_keepalive(self, dur)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "openssl")]
|
|
||||||
impl<T: IoStream + Unpin> IoStream for tokio_openssl::SslStream<T> {
|
|
||||||
#[inline]
|
|
||||||
fn peer_addr(&self) -> Option<net::SocketAddr> {
|
|
||||||
self.get_ref().peer_addr()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
|
|
||||||
self.get_mut().set_nodelay(nodelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
|
|
||||||
self.get_mut().set_linger(dur)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
|
|
||||||
self.get_mut().set_keepalive(dur)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "rustls")]
|
|
||||||
impl<T: IoStream + Unpin> IoStream for tokio_rustls::server::TlsStream<T> {
|
|
||||||
#[inline]
|
|
||||||
fn peer_addr(&self) -> Option<net::SocketAddr> {
|
|
||||||
self.get_ref().0.peer_addr()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
|
|
||||||
self.get_mut().0.set_nodelay(nodelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
|
|
||||||
self.get_mut().0.set_linger(dur)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
|
|
||||||
self.get_mut().0.set_keepalive(dur)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
impl IoStream for tokio_net::uds::UnixStream {
|
|
||||||
#[inline]
|
|
||||||
fn peer_addr(&self) -> Option<net::SocketAddr> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_nodelay(&mut self, _: bool) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_linger(&mut self, _: Option<time::Duration>) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_keepalive(&mut self, _: Option<time::Duration>) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-server"
|
name = "actix-server"
|
||||||
version = "0.8.0-alpha.1"
|
version = "0.8.0-alpha.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix server - General purpose tcp server"
|
description = "Actix server - General purpose tcp server"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
@ -13,23 +13,16 @@ exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
workspace = ".."
|
workspace = ".."
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
features = ["nativetls", "openssl", "rustls", "uds"]
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "actix_server"
|
name = "actix_server"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
nativetls = ["native-tls", "tokio-tls"]
|
|
||||||
openssl = ["open-ssl", "tokio-openssl", "actix-server-config/openssl"]
|
|
||||||
# rustls = ["rust-tls", "tokio-rustls", "webpki", "webpki-roots", "actix-server-config/rustls"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-service = "1.0.0-alpha.1"
|
actix-service = "1.0.0-alpha.1"
|
||||||
actix-server-config = "0.3.0-alpha.1"
|
actix-rt = "1.0.0-alpha.2"
|
||||||
actix-rt = "1.0.0-alpha.1"
|
|
||||||
actix-codec = "0.2.0-alpha.1"
|
actix-codec = "0.2.0-alpha.1"
|
||||||
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
@ -38,28 +31,13 @@ mio = "0.6.19"
|
|||||||
net2 = "0.2"
|
net2 = "0.2"
|
||||||
futures = "0.3.1"
|
futures = "0.3.1"
|
||||||
slab = "0.4"
|
slab = "0.4"
|
||||||
tokio-net = { version = "0.2.0-alpha.6", features = ["signal", "tcp", "uds"] }
|
|
||||||
|
|
||||||
|
tokio-net = { version = "0.2.0-alpha.6", features = ["signal", "tcp", "uds"] }
|
||||||
futures-core-preview = "0.3.0-alpha.19"
|
futures-core-preview = "0.3.0-alpha.19"
|
||||||
|
|
||||||
# unix domain sockets
|
# unix domain sockets
|
||||||
mio-uds = { version = "0.6.7" }
|
mio-uds = { version = "0.6.7" }
|
||||||
|
|
||||||
# nativetls
|
|
||||||
native-tls = { version = "0.2", optional = true }
|
|
||||||
tokio-tls = { version = "0.3.0-alpha.6", optional = true }
|
|
||||||
|
|
||||||
# openssl
|
|
||||||
open-ssl = { version = "0.10", package = "openssl", optional = true }
|
|
||||||
tokio-openssl = { version = "0.4.0-alpha.6", optional = true }
|
|
||||||
|
|
||||||
# rustls
|
|
||||||
rust-tls = { version = "0.16.0", package = "rustls", optional = true }
|
|
||||||
# tokio-rustls = { version = "0.12.0-alpha.2", optional = true }
|
|
||||||
# tokio-rustls = { git = "https://github.com/quininer/tokio-rustls.git", branch = "tokio-0.2", optional = true }
|
|
||||||
webpki = { version = "0.21", optional = true }
|
|
||||||
webpki-roots = { version = "0.17", optional = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
actix-codec = "0.2.0-alpha.1"
|
actix-codec = "0.2.0-alpha.1"
|
||||||
|
@ -3,6 +3,7 @@ use std::task::{Context, Poll};
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::{io, mem, net};
|
use std::{io, mem, net};
|
||||||
|
|
||||||
|
use actix_rt::net::TcpStream;
|
||||||
use actix_rt::{spawn, time::delay, Arbiter, System};
|
use actix_rt::{spawn, time::delay, Arbiter, System};
|
||||||
use futures::channel::mpsc::{unbounded, UnboundedReceiver};
|
use futures::channel::mpsc::{unbounded, UnboundedReceiver};
|
||||||
use futures::channel::oneshot;
|
use futures::channel::oneshot;
|
||||||
@ -12,7 +13,6 @@ use futures::{ready, Future, FutureExt, Stream, StreamExt};
|
|||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use net2::TcpBuilder;
|
use net2::TcpBuilder;
|
||||||
use num_cpus;
|
use num_cpus;
|
||||||
use tokio_net::tcp::TcpStream;
|
|
||||||
|
|
||||||
use crate::accept::{AcceptLoop, AcceptNotify, Command};
|
use crate::accept::{AcceptLoop, AcceptNotify, Command};
|
||||||
use crate::config::{ConfiguredService, ServiceConfig};
|
use crate::config::{ConfiguredService, ServiceConfig};
|
||||||
@ -21,7 +21,7 @@ use crate::service::{InternalServiceFactory, ServiceFactory, StreamNewService};
|
|||||||
use crate::signals::{Signal, Signals};
|
use crate::signals::{Signal, Signals};
|
||||||
use crate::socket::StdListener;
|
use crate::socket::StdListener;
|
||||||
use crate::worker::{self, Worker, WorkerAvailability, WorkerClient};
|
use crate::worker::{self, Worker, WorkerAvailability, WorkerClient};
|
||||||
use crate::{ssl, Token};
|
use crate::Token;
|
||||||
|
|
||||||
/// Server builder
|
/// Server builder
|
||||||
pub struct ServerBuilder {
|
pub struct ServerBuilder {
|
||||||
@ -104,17 +104,6 @@ impl ServerBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the maximum per-worker concurrent connection establish process.
|
|
||||||
///
|
|
||||||
/// All listeners will stop accepting connections when this limit is reached. It
|
|
||||||
/// can be used to limit the global SSL CPU usage.
|
|
||||||
///
|
|
||||||
/// By default max connections is set to a 256.
|
|
||||||
pub fn maxconnrate(self, num: usize) -> Self {
|
|
||||||
ssl::max_concurrent_ssl_connect(num);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stop actix system.
|
/// Stop actix system.
|
||||||
pub fn system_exit(mut self) -> Self {
|
pub fn system_exit(mut self) -> Self {
|
||||||
self.exit = true;
|
self.exit = true;
|
||||||
@ -191,7 +180,7 @@ impl ServerBuilder {
|
|||||||
/// Add new unix domain service to the server.
|
/// Add new unix domain service to the server.
|
||||||
pub fn bind_uds<F, U, N>(self, name: N, addr: U, factory: F) -> io::Result<Self>
|
pub fn bind_uds<F, U, N>(self, name: N, addr: U, factory: F) -> io::Result<Self>
|
||||||
where
|
where
|
||||||
F: ServiceFactory<tokio_net::uds::UnixStream>,
|
F: ServiceFactory<actix_rt::net::UnixStream>,
|
||||||
N: AsRef<str>,
|
N: AsRef<str>,
|
||||||
U: AsRef<std::path::Path>,
|
U: AsRef<std::path::Path>,
|
||||||
{
|
{
|
||||||
@ -221,7 +210,7 @@ impl ServerBuilder {
|
|||||||
factory: F,
|
factory: F,
|
||||||
) -> io::Result<Self>
|
) -> io::Result<Self>
|
||||||
where
|
where
|
||||||
F: ServiceFactory<tokio_net::uds::UnixStream>,
|
F: ServiceFactory<actix_rt::net::UnixStream>,
|
||||||
{
|
{
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
let token = self.token.next();
|
let token = self.token.next();
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::{fmt, io, net};
|
use std::{fmt, io, net};
|
||||||
|
|
||||||
use actix_server_config::{Io, ServerConfig};
|
use actix_rt::net::TcpStream;
|
||||||
use actix_service as actix;
|
use actix_service as actix;
|
||||||
use futures::future::{Future, FutureExt, LocalBoxFuture};
|
use futures::future::{Future, FutureExt, LocalBoxFuture};
|
||||||
use log::error;
|
use log::error;
|
||||||
use tokio_net::tcp::TcpStream;
|
|
||||||
|
|
||||||
use super::builder::bind_addr;
|
use super::builder::bind_addr;
|
||||||
use super::service::{
|
use super::service::{
|
||||||
@ -113,8 +112,6 @@ impl InternalServiceFactory for ConfiguredService {
|
|||||||
self.rt.configure(&mut rt);
|
self.rt.configure(&mut rt);
|
||||||
rt.validate();
|
rt.validate();
|
||||||
|
|
||||||
let names = self.names.clone();
|
|
||||||
|
|
||||||
// construct services
|
// construct services
|
||||||
async move {
|
async move {
|
||||||
let services = rt.services;
|
let services = rt.services;
|
||||||
@ -124,9 +121,7 @@ impl InternalServiceFactory for ConfiguredService {
|
|||||||
}
|
}
|
||||||
let mut res = vec![];
|
let mut res = vec![];
|
||||||
for (token, ns) in services.into_iter() {
|
for (token, ns) in services.into_iter() {
|
||||||
let config = ServerConfig::new(names[&token].1);
|
let newserv = ns.new_service(&());
|
||||||
|
|
||||||
let newserv = ns.new_service(&config);
|
|
||||||
match newserv.await {
|
match newserv.await {
|
||||||
Ok(serv) => {
|
Ok(serv) => {
|
||||||
res.push((token, serv));
|
res.push((token, serv));
|
||||||
@ -196,7 +191,7 @@ impl ServiceRuntime {
|
|||||||
pub fn service<T, F>(&mut self, name: &str, service: F)
|
pub fn service<T, F>(&mut self, name: &str, service: F)
|
||||||
where
|
where
|
||||||
F: actix::IntoServiceFactory<T>,
|
F: actix::IntoServiceFactory<T>,
|
||||||
T: actix::ServiceFactory<Config = ServerConfig, Request = Io<TcpStream>> + 'static,
|
T: actix::ServiceFactory<Config = (), Request = TcpStream> + 'static,
|
||||||
T::Future: 'static,
|
T::Future: 'static,
|
||||||
T::Service: 'static,
|
T::Service: 'static,
|
||||||
T::InitError: fmt::Debug,
|
T::InitError: fmt::Debug,
|
||||||
@ -229,7 +224,7 @@ type BoxedNewService = Box<
|
|||||||
Response = (),
|
Response = (),
|
||||||
Error = (),
|
Error = (),
|
||||||
InitError = (),
|
InitError = (),
|
||||||
Config = ServerConfig,
|
Config = (),
|
||||||
Service = BoxedServerService,
|
Service = BoxedServerService,
|
||||||
Future = LocalBoxFuture<'static, Result<BoxedServerService, ()>>,
|
Future = LocalBoxFuture<'static, Result<BoxedServerService, ()>>,
|
||||||
>,
|
>,
|
||||||
@ -241,7 +236,7 @@ struct ServiceFactory<T> {
|
|||||||
|
|
||||||
impl<T> actix::ServiceFactory for ServiceFactory<T>
|
impl<T> actix::ServiceFactory for ServiceFactory<T>
|
||||||
where
|
where
|
||||||
T: actix::ServiceFactory<Config = ServerConfig, Request = Io<TcpStream>>,
|
T: actix::ServiceFactory<Config = (), Request = TcpStream>,
|
||||||
T::Future: 'static,
|
T::Future: 'static,
|
||||||
T::Service: 'static,
|
T::Service: 'static,
|
||||||
T::Error: 'static,
|
T::Error: 'static,
|
||||||
@ -251,11 +246,11 @@ where
|
|||||||
type Response = ();
|
type Response = ();
|
||||||
type Error = ();
|
type Error = ();
|
||||||
type InitError = ();
|
type InitError = ();
|
||||||
type Config = ServerConfig;
|
type Config = ();
|
||||||
type Service = BoxedServerService;
|
type Service = BoxedServerService;
|
||||||
type Future = LocalBoxFuture<'static, Result<BoxedServerService, ()>>;
|
type Future = LocalBoxFuture<'static, Result<BoxedServerService, ()>>;
|
||||||
|
|
||||||
fn new_service(&self, cfg: &ServerConfig) -> Self::Future {
|
fn new_service(&self, cfg: &()) -> Self::Future {
|
||||||
let fut = self.inner.new_service(cfg);
|
let fut = self.inner.new_service(cfg);
|
||||||
async move {
|
async move {
|
||||||
return match fut.await {
|
return match fut.await {
|
||||||
|
@ -8,11 +8,8 @@ mod server;
|
|||||||
mod service;
|
mod service;
|
||||||
mod signals;
|
mod signals;
|
||||||
mod socket;
|
mod socket;
|
||||||
pub mod ssl;
|
|
||||||
mod worker;
|
mod worker;
|
||||||
|
|
||||||
pub use actix_server_config::{Io, IoStream, Protocol, ServerConfig};
|
|
||||||
|
|
||||||
pub use self::builder::ServerBuilder;
|
pub use self::builder::ServerBuilder;
|
||||||
pub use self::config::{ServiceConfig, ServiceRuntime};
|
pub use self::config::{ServiceConfig, ServiceRuntime};
|
||||||
pub use self::server::Server;
|
pub use self::server::Server;
|
||||||
|
@ -4,7 +4,6 @@ use std::task::{Context, Poll};
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use actix_rt::spawn;
|
use actix_rt::spawn;
|
||||||
use actix_server_config::{Io, ServerConfig};
|
|
||||||
use actix_service::{self as actix, Service, ServiceFactory as ActixServiceFactory};
|
use actix_service::{self as actix, Service, ServiceFactory as ActixServiceFactory};
|
||||||
use futures::future::{err, ok, LocalBoxFuture, Ready};
|
use futures::future::{err, ok, LocalBoxFuture, Ready};
|
||||||
use futures::{FutureExt, TryFutureExt};
|
use futures::{FutureExt, TryFutureExt};
|
||||||
@ -25,7 +24,7 @@ pub(crate) enum ServerMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait ServiceFactory<Stream: FromStream>: Send + Clone + 'static {
|
pub trait ServiceFactory<Stream: FromStream>: Send + Clone + 'static {
|
||||||
type Factory: actix::ServiceFactory<Config = ServerConfig, Request = Io<Stream>>;
|
type Factory: actix::ServiceFactory<Config = (), Request = Stream>;
|
||||||
|
|
||||||
fn create(&self) -> Self::Factory;
|
fn create(&self) -> Self::Factory;
|
||||||
}
|
}
|
||||||
@ -59,7 +58,7 @@ impl<T> StreamService<T> {
|
|||||||
|
|
||||||
impl<T, I> Service for StreamService<T>
|
impl<T, I> Service for StreamService<T>
|
||||||
where
|
where
|
||||||
T: Service<Request = Io<I>>,
|
T: Service<Request = I>,
|
||||||
T::Future: 'static,
|
T::Future: 'static,
|
||||||
T::Error: 'static,
|
T::Error: 'static,
|
||||||
I: FromStream,
|
I: FromStream,
|
||||||
@ -81,7 +80,7 @@ where
|
|||||||
});
|
});
|
||||||
|
|
||||||
if let Ok(stream) = stream {
|
if let Ok(stream) = stream {
|
||||||
let f = self.service.call(Io::new(stream));
|
let f = self.service.call(stream);
|
||||||
spawn(
|
spawn(
|
||||||
async move {
|
async move {
|
||||||
let _ = f.await;
|
let _ = f.await;
|
||||||
@ -149,11 +148,9 @@ where
|
|||||||
|
|
||||||
fn create(&self) -> LocalBoxFuture<'static, Result<Vec<(Token, BoxedServerService)>, ()>> {
|
fn create(&self) -> LocalBoxFuture<'static, Result<Vec<(Token, BoxedServerService)>, ()>> {
|
||||||
let token = self.token;
|
let token = self.token;
|
||||||
let config = ServerConfig::new(self.addr);
|
|
||||||
|
|
||||||
self.inner
|
self.inner
|
||||||
.create()
|
.create()
|
||||||
.new_service(&config)
|
.new_service(&())
|
||||||
.map_err(|_| ())
|
.map_err(|_| ())
|
||||||
.map_ok(move |inner| {
|
.map_ok(move |inner| {
|
||||||
let service: BoxedServerService = Box::new(StreamService::new(inner));
|
let service: BoxedServerService = Box::new(StreamService::new(inner));
|
||||||
@ -180,7 +177,7 @@ impl InternalServiceFactory for Box<dyn InternalServiceFactory> {
|
|||||||
impl<F, T, I> ServiceFactory<I> for F
|
impl<F, T, I> ServiceFactory<I> for F
|
||||||
where
|
where
|
||||||
F: Fn() -> T + Send + Clone + 'static,
|
F: Fn() -> T + Send + Clone + 'static,
|
||||||
T: actix::ServiceFactory<Config = ServerConfig, Request = Io<I>>,
|
T: actix::ServiceFactory<Config = (), Request = I>,
|
||||||
I: FromStream,
|
I: FromStream,
|
||||||
{
|
{
|
||||||
type Factory = T;
|
type Factory = T;
|
||||||
|
@ -23,9 +23,9 @@ pub(crate) enum Signal {
|
|||||||
pub(crate) struct Signals {
|
pub(crate) struct Signals {
|
||||||
srv: Server,
|
srv: Server,
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
stream: tokio_net::signal::CtrlC,
|
stream: actix_rt::signal::CtrlC,
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
streams: Vec<(Signal, tokio_net::signal::unix::Signal)>,
|
streams: Vec<(Signal, actix_rt::signal::unix::Signal)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Signals {
|
impl Signals {
|
||||||
@ -33,13 +33,13 @@ impl Signals {
|
|||||||
actix_rt::spawn({
|
actix_rt::spawn({
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
{
|
{
|
||||||
let stream = tokio_net::signal::ctrl_c()?;
|
let stream = actix_rt::signal::ctrl_c()?;
|
||||||
Signals { srv, stream }
|
Signals { srv, stream }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
use tokio_net::signal::unix;
|
use actix_rt::signal::unix;
|
||||||
|
|
||||||
let mut streams = Vec::new();
|
let mut streams = Vec::new();
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use std::{fmt, io, net};
|
use std::{fmt, io, net};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite};
|
use actix_codec::{AsyncRead, AsyncWrite};
|
||||||
|
use actix_rt::net::TcpStream;
|
||||||
|
|
||||||
use tokio_net::driver::Handle;
|
use tokio_net::driver::Handle;
|
||||||
use tokio_net::tcp::TcpStream;
|
|
||||||
|
|
||||||
pub(crate) enum StdListener {
|
pub(crate) enum StdListener {
|
||||||
Tcp(net::TcpListener),
|
Tcp(net::TcpListener),
|
||||||
@ -161,12 +162,12 @@ impl FromStream for TcpStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(unix))]
|
#[cfg(all(unix))]
|
||||||
impl FromStream for tokio_net::uds::UnixStream {
|
impl FromStream for actix_rt::net::UnixStream {
|
||||||
fn from_stdstream(sock: StdStream) -> io::Result<Self> {
|
fn from_stdstream(sock: StdStream) -> io::Result<Self> {
|
||||||
match sock {
|
match sock {
|
||||||
StdStream::Tcp(_) => panic!("Should not happen, bug in server impl"),
|
StdStream::Tcp(_) => panic!("Should not happen, bug in server impl"),
|
||||||
StdStream::Uds(stream) => {
|
StdStream::Uds(stream) => {
|
||||||
tokio_net::uds::UnixStream::from_std(stream, &Handle::default())
|
actix_rt::net::UnixStream::from_std(stream, &Handle::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,138 +0,0 @@
|
|||||||
use std::future::Future;
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::pin::Pin;
|
|
||||||
use std::task::{Context, Poll};
|
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite};
|
|
||||||
use actix_service::{Service, ServiceFactory};
|
|
||||||
use futures::future::{ok, FutureExt, LocalBoxFuture, Ready};
|
|
||||||
use open_ssl::ssl::SslAcceptor;
|
|
||||||
use tokio_openssl::{HandshakeError, SslStream};
|
|
||||||
|
|
||||||
use crate::counter::{Counter, CounterGuard};
|
|
||||||
use crate::ssl::MAX_CONN_COUNTER;
|
|
||||||
use crate::{Io, Protocol, ServerConfig};
|
|
||||||
|
|
||||||
/// Support `SSL` connections via openssl package
|
|
||||||
///
|
|
||||||
/// `ssl` feature enables `OpensslAcceptor` type
|
|
||||||
pub struct OpensslAcceptor<T: AsyncRead + AsyncWrite, P = ()> {
|
|
||||||
acceptor: SslAcceptor,
|
|
||||||
io: PhantomData<(T, P)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: AsyncRead + AsyncWrite, P> OpensslAcceptor<T, P> {
|
|
||||||
/// Create default `OpensslAcceptor`
|
|
||||||
pub fn new(acceptor: SslAcceptor) -> Self {
|
|
||||||
OpensslAcceptor {
|
|
||||||
acceptor,
|
|
||||||
io: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: AsyncRead + AsyncWrite, P> Clone for OpensslAcceptor<T, P> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Self {
|
|
||||||
acceptor: self.acceptor.clone(),
|
|
||||||
io: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: AsyncRead + AsyncWrite + Unpin + 'static, P> ServiceFactory for OpensslAcceptor<T, P> {
|
|
||||||
type Request = Io<T, P>;
|
|
||||||
type Response = Io<SslStream<T>, P>;
|
|
||||||
type Error = HandshakeError<T>;
|
|
||||||
type Config = ServerConfig;
|
|
||||||
type Service = OpensslAcceptorService<T, P>;
|
|
||||||
type InitError = ();
|
|
||||||
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
|
||||||
|
|
||||||
fn new_service(&self, cfg: &ServerConfig) -> Self::Future {
|
|
||||||
cfg.set_secure();
|
|
||||||
|
|
||||||
MAX_CONN_COUNTER.with(|conns| {
|
|
||||||
ok(OpensslAcceptorService {
|
|
||||||
acceptor: self.acceptor.clone(),
|
|
||||||
conns: conns.clone(),
|
|
||||||
io: PhantomData,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct OpensslAcceptorService<T, P> {
|
|
||||||
acceptor: SslAcceptor,
|
|
||||||
conns: Counter,
|
|
||||||
io: PhantomData<(T, P)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: AsyncRead + AsyncWrite + Unpin + 'static, P> Service for OpensslAcceptorService<T, P> {
|
|
||||||
type Request = Io<T, P>;
|
|
||||||
type Response = Io<SslStream<T>, P>;
|
|
||||||
type Error = HandshakeError<T>;
|
|
||||||
type Future = OpensslAcceptorServiceFut<T, P>;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
||||||
if self.conns.available(ctx) {
|
|
||||||
Poll::Ready(Ok(()))
|
|
||||||
} else {
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
|
||||||
let (io, params, _) = req.into_parts();
|
|
||||||
let acc = self.acceptor.clone();
|
|
||||||
OpensslAcceptorServiceFut {
|
|
||||||
_guard: self.conns.get(),
|
|
||||||
fut: async move {
|
|
||||||
let acc = acc;
|
|
||||||
tokio_openssl::accept(&acc, io).await
|
|
||||||
}
|
|
||||||
.boxed_local(),
|
|
||||||
params: Some(params),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct OpensslAcceptorServiceFut<T, P>
|
|
||||||
where
|
|
||||||
T: AsyncRead + AsyncWrite,
|
|
||||||
{
|
|
||||||
fut: LocalBoxFuture<'static, Result<SslStream<T>, HandshakeError<T>>>,
|
|
||||||
params: Option<P>,
|
|
||||||
_guard: CounterGuard,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: AsyncRead + AsyncWrite + Unpin, P> Unpin for OpensslAcceptorServiceFut<T, P> {}
|
|
||||||
|
|
||||||
impl<T: AsyncRead + AsyncWrite + Unpin, P> Future for OpensslAcceptorServiceFut<T, P> {
|
|
||||||
type Output = Result<Io<SslStream<T>, P>, HandshakeError<T>>;
|
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
||||||
let this = self.get_mut();
|
|
||||||
|
|
||||||
let io = futures::ready!(Pin::new(&mut this.fut).poll(cx))?;
|
|
||||||
let proto = if let Some(protos) = io.ssl().selected_alpn_protocol() {
|
|
||||||
const H2: &[u8] = b"\x02h2";
|
|
||||||
const HTTP10: &[u8] = b"\x08http/1.0";
|
|
||||||
const HTTP11: &[u8] = b"\x08http/1.1";
|
|
||||||
|
|
||||||
if protos.windows(3).any(|window| window == H2) {
|
|
||||||
Protocol::Http2
|
|
||||||
} else if protos.windows(9).any(|window| window == HTTP11) {
|
|
||||||
Protocol::Http11
|
|
||||||
} else if protos.windows(9).any(|window| window == HTTP10) {
|
|
||||||
Protocol::Http10
|
|
||||||
} else {
|
|
||||||
Protocol::Unknown
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Protocol::Unknown
|
|
||||||
};
|
|
||||||
|
|
||||||
Poll::Ready(Ok(Io::from_parts(io, this.params.take().unwrap(), proto)))
|
|
||||||
}
|
|
||||||
}
|
|
90
actix-tls/CHANGES.md
Normal file
90
actix-tls/CHANGES.md
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# Changes
|
||||||
|
|
||||||
|
## [0.3.0] - 2019-10-03
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Update `rustls` to 0.16
|
||||||
|
* Minimum required Rust version upped to 1.37.0
|
||||||
|
|
||||||
|
## [0.2.5] - 2019-09-05
|
||||||
|
|
||||||
|
* Add `TcpConnectService`
|
||||||
|
|
||||||
|
## [0.2.4] - 2019-09-02
|
||||||
|
|
||||||
|
* Use arbiter's storage for default async resolver
|
||||||
|
|
||||||
|
## [0.2.3] - 2019-08-05
|
||||||
|
|
||||||
|
* Add `ConnectService` and `OpensslConnectService`
|
||||||
|
|
||||||
|
## [0.2.2] - 2019-07-24
|
||||||
|
|
||||||
|
* Add `rustls` support
|
||||||
|
|
||||||
|
## [0.2.1] - 2019-07-17
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Expose Connect addrs #30
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Update `derive_more` to 0.15
|
||||||
|
|
||||||
|
|
||||||
|
## [0.2.0] - 2019-05-12
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Upgrade to actix-service 0.4
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.5] - 2019-04-19
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `Connect::set_addr()`
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Use trust-dns-resolver 0.11.0
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.4] - 2019-04-12
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Do not start default resolver immediately for default connector.
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.3] - 2019-04-11
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Start trust-dns default resolver on first use
|
||||||
|
|
||||||
|
## [0.1.2] - 2019-04-04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Log error if dns system config could not be loaded.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Rename connect Connector to TcpConnector #10
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.1] - 2019-03-15
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix error handling for single address
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.0] - 2019-03-14
|
||||||
|
|
||||||
|
* Refactor resolver and connector services
|
||||||
|
|
||||||
|
* Rename crate
|
57
actix-tls/Cargo.toml
Normal file
57
actix-tls/Cargo.toml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
[package]
|
||||||
|
name = "actix-tls"
|
||||||
|
version = "1.0.0-alpha.1"
|
||||||
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
|
description = "Actix tls services"
|
||||||
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
|
homepage = "https://actix.rs"
|
||||||
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
|
documentation = "https://docs.rs/actix-tls/"
|
||||||
|
categories = ["network-programming", "asynchronous"]
|
||||||
|
license = "MIT/Apache-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
workspace = ".."
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
features = ["server", "openssl", "rustls"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "actix_tls"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
|
||||||
|
# openssl
|
||||||
|
openssl = ["open-ssl", "tokio-openssl"]
|
||||||
|
|
||||||
|
# rustls
|
||||||
|
rustls = ["rust-tls", "webpki"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-service = "1.0.0-alpha.1"
|
||||||
|
actix-codec = "0.2.0-alpha.1"
|
||||||
|
actix-utils = "0.5.0-alpha.1"
|
||||||
|
actix-rt = "1.0.0-alpha.1"
|
||||||
|
derive_more = "0.99"
|
||||||
|
either = "1.5.2"
|
||||||
|
futures = "0.3.1"
|
||||||
|
log = "0.4"
|
||||||
|
|
||||||
|
# server feature
|
||||||
|
actix-server = { version = "0.8.0-alpha.1", optional=true }
|
||||||
|
|
||||||
|
# openssl
|
||||||
|
open-ssl = { version="0.10", package = "openssl", optional = true }
|
||||||
|
tokio-openssl = { version = "=0.4.0-alpha.6", optional = true }
|
||||||
|
|
||||||
|
# rustls
|
||||||
|
rust-tls = { version = "0.16.0", package = "rustls", optional = true }
|
||||||
|
webpki = { version = "0.21", optional = true }
|
||||||
|
webpki-roots = { version = "0.17", optional = true }
|
||||||
|
# tokio-rustls = { version = "0.12.0-alpha.2", optional = true }
|
||||||
|
# tokio-rustls = { git = "https://github.com/quininer/tokio-rustls.git", branch = "tokio-0.2", optional = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
bytes = "0.4"
|
||||||
|
actix-testing = { version="0.3.0-alpha.1" }
|
51
actix-tls/src/lib.rs
Normal file
51
actix-tls/src/lib.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
//! SSL Services
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
use actix_utils::counter::Counter;
|
||||||
|
|
||||||
|
#[cfg(feature = "openssl")]
|
||||||
|
pub mod openssl;
|
||||||
|
|
||||||
|
//#[cfg(feature = "rustls")]
|
||||||
|
//mod rustls;
|
||||||
|
//#[cfg(feature = "rustls")]
|
||||||
|
//pub use self::rustls::RustlsAcceptor;
|
||||||
|
|
||||||
|
/// Sets the maximum per-worker concurrent ssl connection establish process.
|
||||||
|
///
|
||||||
|
/// All listeners will stop accepting connections when this limit is
|
||||||
|
/// reached. It can be used to limit the global SSL CPU usage.
|
||||||
|
///
|
||||||
|
/// By default max connections is set to a 256.
|
||||||
|
pub fn max_concurrent_ssl_connect(num: usize) {
|
||||||
|
MAX_CONN.store(num, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256);
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static MAX_CONN_COUNTER: Counter = Counter::new(MAX_CONN.load(Ordering::Relaxed));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ssl error combinded with service error.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SslError<E1, E2> {
|
||||||
|
Ssl(E1),
|
||||||
|
Service(E2),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ServerBuilderExt: Sized {
|
||||||
|
/// Sets the maximum per-worker concurrent connection establish process.
|
||||||
|
///
|
||||||
|
/// All listeners will stop accepting connections when this limit is reached. It
|
||||||
|
/// can be used to limit the global SSL CPU usage.
|
||||||
|
///
|
||||||
|
/// By default max connections is set to a 256.
|
||||||
|
fn maxconnrate(self, num: usize) -> Self {
|
||||||
|
max_concurrent_ssl_connect(num);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
impl ServerBuilderExt for actix_server::ServerBuilder {}
|
111
actix-tls/src/openssl.rs
Normal file
111
actix-tls/src/openssl.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
use std::future::Future;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
|
pub use tokio_openssl::{HandshakeError, SslStream};
|
||||||
|
|
||||||
|
use actix_codec::{AsyncRead, AsyncWrite};
|
||||||
|
use actix_service::{Service, ServiceFactory};
|
||||||
|
use actix_utils::counter::{Counter, CounterGuard};
|
||||||
|
use futures::future::{ok, FutureExt, LocalBoxFuture, Ready};
|
||||||
|
use open_ssl::ssl::SslAcceptor;
|
||||||
|
|
||||||
|
use crate::MAX_CONN_COUNTER;
|
||||||
|
|
||||||
|
/// Support `TLS` server connections via openssl package
|
||||||
|
///
|
||||||
|
/// `openssl` feature enables `Acceptor` type
|
||||||
|
pub struct Acceptor<T: AsyncRead + AsyncWrite> {
|
||||||
|
acceptor: SslAcceptor,
|
||||||
|
io: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsyncRead + AsyncWrite> Acceptor<T> {
|
||||||
|
/// Create default `OpensslAcceptor`
|
||||||
|
pub fn new(acceptor: SslAcceptor) -> Self {
|
||||||
|
Acceptor {
|
||||||
|
acceptor,
|
||||||
|
io: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsyncRead + AsyncWrite> Clone for Acceptor<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
acceptor: self.acceptor.clone(),
|
||||||
|
io: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsyncRead + AsyncWrite + Unpin + 'static> ServiceFactory for Acceptor<T> {
|
||||||
|
type Request = T;
|
||||||
|
type Response = SslStream<T>;
|
||||||
|
type Error = HandshakeError<T>;
|
||||||
|
type Config = ();
|
||||||
|
type Service = AcceptorService<T>;
|
||||||
|
type InitError = ();
|
||||||
|
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: &()) -> Self::Future {
|
||||||
|
MAX_CONN_COUNTER.with(|conns| {
|
||||||
|
ok(AcceptorService {
|
||||||
|
acceptor: self.acceptor.clone(),
|
||||||
|
conns: conns.clone(),
|
||||||
|
io: PhantomData,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AcceptorService<T> {
|
||||||
|
acceptor: SslAcceptor,
|
||||||
|
conns: Counter,
|
||||||
|
io: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsyncRead + AsyncWrite + Unpin + 'static> Service for AcceptorService<T> {
|
||||||
|
type Request = T;
|
||||||
|
type Response = SslStream<T>;
|
||||||
|
type Error = HandshakeError<T>;
|
||||||
|
type Future = AcceptorServiceResponse<T>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
if self.conns.available(ctx) {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||||
|
let acc = self.acceptor.clone();
|
||||||
|
AcceptorServiceResponse {
|
||||||
|
_guard: self.conns.get(),
|
||||||
|
fut: async move {
|
||||||
|
let acc = acc;
|
||||||
|
tokio_openssl::accept(&acc, req).await
|
||||||
|
}
|
||||||
|
.boxed_local(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AcceptorServiceResponse<T>
|
||||||
|
where
|
||||||
|
T: AsyncRead + AsyncWrite,
|
||||||
|
{
|
||||||
|
fut: LocalBoxFuture<'static, Result<SslStream<T>, HandshakeError<T>>>,
|
||||||
|
_guard: CounterGuard,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsyncRead + AsyncWrite + Unpin> Future for AcceptorServiceResponse<T> {
|
||||||
|
type Output = Result<SslStream<T>, HandshakeError<T>>;
|
||||||
|
|
||||||
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let io = futures::ready!(Pin::new(&mut self.fut).poll(cx))?;
|
||||||
|
Poll::Ready(Ok(io))
|
||||||
|
}
|
||||||
|
}
|
@ -52,6 +52,8 @@ impl CounterGuard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Unpin for CounterGuard {}
|
||||||
|
|
||||||
impl Drop for CounterGuard {
|
impl Drop for CounterGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.0.dec();
|
self.0.dec();
|
||||||
|
Loading…
Reference in New Issue
Block a user