From 9fbe6a1f6d0ee5d08d7939c332549ce5490c7951 Mon Sep 17 00:00:00 2001
From: Nikolay Kim <fafhrd91@gmail.com>
Date: Mon, 2 Dec 2019 11:30:27 +0600
Subject: [PATCH] refactor server configuration and tls support

---
 Cargo.toml                                    |   4 +-
 actix-rt/Cargo.toml                           |   9 +-
 actix-rt/src/lib.rs                           |  34 ++-
 actix-server-config/Cargo.toml                |  29 --
 actix-server-config/changes.md                |  21 --
 actix-server-config/src/lib.rs                | 249 ------------------
 actix-server/Cargo.toml                       |  28 +-
 actix-server/src/builder.rs                   |  19 +-
 actix-server/src/config.rs                    |  19 +-
 actix-server/src/lib.rs                       |   3 -
 actix-server/src/service.rs                   |  13 +-
 actix-server/src/signals.rs                   |   8 +-
 actix-server/src/socket.rs                    |   7 +-
 actix-server/src/ssl/openssl.rs               | 138 ----------
 actix-tls/CHANGES.md                          |  90 +++++++
 actix-tls/Cargo.toml                          |  57 ++++
 .../LICENSE-APACHE                            |   0
 .../LICENSE-MIT                               |   0
 actix-tls/src/lib.rs                          |  51 ++++
 actix-tls/src/openssl.rs                      | 111 ++++++++
 actix-utils/src/counter.rs                    |   2 +
 21 files changed, 366 insertions(+), 526 deletions(-)
 delete mode 100644 actix-server-config/Cargo.toml
 delete mode 100644 actix-server-config/changes.md
 delete mode 100644 actix-server-config/src/lib.rs
 delete mode 100644 actix-server/src/ssl/openssl.rs
 create mode 100644 actix-tls/CHANGES.md
 create mode 100644 actix-tls/Cargo.toml
 rename {actix-server-config => actix-tls}/LICENSE-APACHE (100%)
 rename {actix-server-config => actix-tls}/LICENSE-MIT (100%)
 create mode 100644 actix-tls/src/lib.rs
 create mode 100644 actix-tls/src/openssl.rs

diff --git a/Cargo.toml b/Cargo.toml
index b7646adb..ced73d14 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,9 +7,9 @@ members = [
   "actix-macros",
   "actix-service",
   "actix-server",
-  "actix-server-config",
   "actix-testing",
   "actix-threadpool",
+  "actix-tls",
   "actix-utils",
   "router",
 ]
@@ -21,9 +21,9 @@ actix-ioframe = { path = "actix-ioframe" }
 actix-rt = { path = "actix-rt" }
 actix-macros = { path = "actix-macros" }
 actix-server = { path = "actix-server" }
-actix-server-config = { path = "actix-server-config" }
 actix-service = { path = "actix-service" }
 actix-testing = { path = "actix-testing" }
 actix-threadpool = { path = "actix-threadpool" }
+actix-tls = { path = "actix-tls" }
 actix-utils = { path = "actix-utils" }
 actix-router = { path = "router" }
diff --git a/actix-rt/Cargo.toml b/actix-rt/Cargo.toml
index 340ac4c4..5f7910bd 100644
--- a/actix-rt/Cargo.toml
+++ b/actix-rt/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "actix-rt"
-version = "1.0.0-alpha.1"
+version = "1.0.0-alpha.2"
 authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
 description = "Actix runtime"
 keywords = ["network", "framework", "async", "futures"]
@@ -21,10 +21,9 @@ path = "src/lib.rs"
 actix-macros = "0.1.0-alpha.1"
 actix-threadpool = "0.2"
 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-net = "=0.2.0-alpha.6"
-tokio-timer = "=0.3.0-alpha.6"
-
-copyless = "0.1.4"
+tokio-timer = "=0.3.0-alpha.6"
\ No newline at end of file
diff --git a/actix-rt/src/lib.rs b/actix-rt/src/lib.rs
index cf1c359c..7a75f95a 100644
--- a/actix-rt/src/lib.rs
+++ b/actix-rt/src/lib.rs
@@ -32,6 +32,28 @@ where
     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.
 pub mod time {
     use std::time::{Duration, Instant};
@@ -52,15 +74,3 @@ pub mod time {
         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::*;
-}
diff --git a/actix-server-config/Cargo.toml b/actix-server-config/Cargo.toml
deleted file mode 100644
index f7b1afdb..00000000
--- a/actix-server-config/Cargo.toml
+++ /dev/null
@@ -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 }
diff --git a/actix-server-config/changes.md b/actix-server-config/changes.md
deleted file mode 100644
index 9af452a5..00000000
--- a/actix-server-config/changes.md
+++ /dev/null
@@ -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
diff --git a/actix-server-config/src/lib.rs b/actix-server-config/src/lib.rs
deleted file mode 100644
index 5b9a7dbe..00000000
--- a/actix-server-config/src/lib.rs
+++ /dev/null
@@ -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(())
-    }
-}
diff --git a/actix-server/Cargo.toml b/actix-server/Cargo.toml
index 8e4b2fcc..5ff60e13 100644
--- a/actix-server/Cargo.toml
+++ b/actix-server/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "actix-server"
-version = "0.8.0-alpha.1"
+version = "0.8.0-alpha.2"
 authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
 description = "Actix server - General purpose tcp server"
 keywords = ["network", "framework", "async", "futures"]
@@ -13,23 +13,16 @@ exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
 edition = "2018"
 workspace = ".."
 
-[package.metadata.docs.rs]
-features = ["nativetls", "openssl", "rustls", "uds"]
-
 [lib]
 name = "actix_server"
 path = "src/lib.rs"
 
 [features]
 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]
 actix-service = "1.0.0-alpha.1"
-actix-server-config = "0.3.0-alpha.1"
-actix-rt = "1.0.0-alpha.1"
+actix-rt = "1.0.0-alpha.2"
 actix-codec = "0.2.0-alpha.1"
 
 log = "0.4"
@@ -38,28 +31,13 @@ mio = "0.6.19"
 net2 = "0.2"
 futures = "0.3.1"
 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"
 
 # unix domain sockets
 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]
 bytes = "0.4"
 actix-codec = "0.2.0-alpha.1"
diff --git a/actix-server/src/builder.rs b/actix-server/src/builder.rs
index 0004cdcc..02f94533 100644
--- a/actix-server/src/builder.rs
+++ b/actix-server/src/builder.rs
@@ -3,6 +3,7 @@ use std::task::{Context, Poll};
 use std::time::{Duration, Instant};
 use std::{io, mem, net};
 
+use actix_rt::net::TcpStream;
 use actix_rt::{spawn, time::delay, Arbiter, System};
 use futures::channel::mpsc::{unbounded, UnboundedReceiver};
 use futures::channel::oneshot;
@@ -12,7 +13,6 @@ use futures::{ready, Future, FutureExt, Stream, StreamExt};
 use log::{error, info};
 use net2::TcpBuilder;
 use num_cpus;
-use tokio_net::tcp::TcpStream;
 
 use crate::accept::{AcceptLoop, AcceptNotify, Command};
 use crate::config::{ConfiguredService, ServiceConfig};
@@ -21,7 +21,7 @@ use crate::service::{InternalServiceFactory, ServiceFactory, StreamNewService};
 use crate::signals::{Signal, Signals};
 use crate::socket::StdListener;
 use crate::worker::{self, Worker, WorkerAvailability, WorkerClient};
-use crate::{ssl, Token};
+use crate::Token;
 
 /// Server builder
 pub struct ServerBuilder {
@@ -104,17 +104,6 @@ impl ServerBuilder {
         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.
     pub fn system_exit(mut self) -> Self {
         self.exit = true;
@@ -191,7 +180,7 @@ impl ServerBuilder {
     /// 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>
     where
-        F: ServiceFactory<tokio_net::uds::UnixStream>,
+        F: ServiceFactory<actix_rt::net::UnixStream>,
         N: AsRef<str>,
         U: AsRef<std::path::Path>,
     {
@@ -221,7 +210,7 @@ impl ServerBuilder {
         factory: F,
     ) -> io::Result<Self>
     where
-        F: ServiceFactory<tokio_net::uds::UnixStream>,
+        F: ServiceFactory<actix_rt::net::UnixStream>,
     {
         use std::net::{IpAddr, Ipv4Addr, SocketAddr};
         let token = self.token.next();
diff --git a/actix-server/src/config.rs b/actix-server/src/config.rs
index 36e94a37..1ab6b9da 100644
--- a/actix-server/src/config.rs
+++ b/actix-server/src/config.rs
@@ -1,11 +1,10 @@
 use std::collections::HashMap;
 use std::{fmt, io, net};
 
-use actix_server_config::{Io, ServerConfig};
+use actix_rt::net::TcpStream;
 use actix_service as actix;
 use futures::future::{Future, FutureExt, LocalBoxFuture};
 use log::error;
-use tokio_net::tcp::TcpStream;
 
 use super::builder::bind_addr;
 use super::service::{
@@ -113,8 +112,6 @@ impl InternalServiceFactory for ConfiguredService {
         self.rt.configure(&mut rt);
         rt.validate();
 
-        let names = self.names.clone();
-
         // construct services
         async move {
             let services = rt.services;
@@ -124,9 +121,7 @@ impl InternalServiceFactory for ConfiguredService {
             }
             let mut res = vec![];
             for (token, ns) in services.into_iter() {
-                let config = ServerConfig::new(names[&token].1);
-
-                let newserv = ns.new_service(&config);
+                let newserv = ns.new_service(&());
                 match newserv.await {
                     Ok(serv) => {
                         res.push((token, serv));
@@ -196,7 +191,7 @@ impl ServiceRuntime {
     pub fn service<T, F>(&mut self, name: &str, service: F)
     where
         F: actix::IntoServiceFactory<T>,
-        T: actix::ServiceFactory<Config = ServerConfig, Request = Io<TcpStream>> + 'static,
+        T: actix::ServiceFactory<Config = (), Request = TcpStream> + 'static,
         T::Future: 'static,
         T::Service: 'static,
         T::InitError: fmt::Debug,
@@ -229,7 +224,7 @@ type BoxedNewService = Box<
         Response = (),
         Error = (),
         InitError = (),
-        Config = ServerConfig,
+        Config = (),
         Service = BoxedServerService,
         Future = LocalBoxFuture<'static, Result<BoxedServerService, ()>>,
     >,
@@ -241,7 +236,7 @@ struct ServiceFactory<T> {
 
 impl<T> actix::ServiceFactory for ServiceFactory<T>
 where
-    T: actix::ServiceFactory<Config = ServerConfig, Request = Io<TcpStream>>,
+    T: actix::ServiceFactory<Config = (), Request = TcpStream>,
     T::Future: 'static,
     T::Service: 'static,
     T::Error: 'static,
@@ -251,11 +246,11 @@ where
     type Response = ();
     type Error = ();
     type InitError = ();
-    type Config = ServerConfig;
+    type Config = ();
     type Service = 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);
         async move {
             return match fut.await {
diff --git a/actix-server/src/lib.rs b/actix-server/src/lib.rs
index 97687c2f..4e9b5f71 100644
--- a/actix-server/src/lib.rs
+++ b/actix-server/src/lib.rs
@@ -8,11 +8,8 @@ mod server;
 mod service;
 mod signals;
 mod socket;
-pub mod ssl;
 mod worker;
 
-pub use actix_server_config::{Io, IoStream, Protocol, ServerConfig};
-
 pub use self::builder::ServerBuilder;
 pub use self::config::{ServiceConfig, ServiceRuntime};
 pub use self::server::Server;
diff --git a/actix-server/src/service.rs b/actix-server/src/service.rs
index 2bf7a570..e883c375 100644
--- a/actix-server/src/service.rs
+++ b/actix-server/src/service.rs
@@ -4,7 +4,6 @@ use std::task::{Context, Poll};
 use std::time::Duration;
 
 use actix_rt::spawn;
-use actix_server_config::{Io, ServerConfig};
 use actix_service::{self as actix, Service, ServiceFactory as ActixServiceFactory};
 use futures::future::{err, ok, LocalBoxFuture, Ready};
 use futures::{FutureExt, TryFutureExt};
@@ -25,7 +24,7 @@ pub(crate) enum ServerMessage {
 }
 
 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;
 }
@@ -59,7 +58,7 @@ impl<T> StreamService<T> {
 
 impl<T, I> Service for StreamService<T>
 where
-    T: Service<Request = Io<I>>,
+    T: Service<Request = I>,
     T::Future: 'static,
     T::Error: 'static,
     I: FromStream,
@@ -81,7 +80,7 @@ where
                 });
 
                 if let Ok(stream) = stream {
-                    let f = self.service.call(Io::new(stream));
+                    let f = self.service.call(stream);
                     spawn(
                         async move {
                             let _ = f.await;
@@ -149,11 +148,9 @@ where
 
     fn create(&self) -> LocalBoxFuture<'static, Result<Vec<(Token, BoxedServerService)>, ()>> {
         let token = self.token;
-        let config = ServerConfig::new(self.addr);
-
         self.inner
             .create()
-            .new_service(&config)
+            .new_service(&())
             .map_err(|_| ())
             .map_ok(move |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
 where
     F: Fn() -> T + Send + Clone + 'static,
-    T: actix::ServiceFactory<Config = ServerConfig, Request = Io<I>>,
+    T: actix::ServiceFactory<Config = (), Request = I>,
     I: FromStream,
 {
     type Factory = T;
diff --git a/actix-server/src/signals.rs b/actix-server/src/signals.rs
index 6194f2f1..55f23b8f 100644
--- a/actix-server/src/signals.rs
+++ b/actix-server/src/signals.rs
@@ -23,9 +23,9 @@ pub(crate) enum Signal {
 pub(crate) struct Signals {
     srv: Server,
     #[cfg(not(unix))]
-    stream: tokio_net::signal::CtrlC,
+    stream: actix_rt::signal::CtrlC,
     #[cfg(unix)]
-    streams: Vec<(Signal, tokio_net::signal::unix::Signal)>,
+    streams: Vec<(Signal, actix_rt::signal::unix::Signal)>,
 }
 
 impl Signals {
@@ -33,13 +33,13 @@ impl Signals {
         actix_rt::spawn({
             #[cfg(not(unix))]
             {
-                let stream = tokio_net::signal::ctrl_c()?;
+                let stream = actix_rt::signal::ctrl_c()?;
                 Signals { srv, stream }
             }
 
             #[cfg(unix)]
             {
-                use tokio_net::signal::unix;
+                use actix_rt::signal::unix;
 
                 let mut streams = Vec::new();
 
diff --git a/actix-server/src/socket.rs b/actix-server/src/socket.rs
index 9030310a..743ba462 100644
--- a/actix-server/src/socket.rs
+++ b/actix-server/src/socket.rs
@@ -1,8 +1,9 @@
 use std::{fmt, io, net};
 
 use actix_codec::{AsyncRead, AsyncWrite};
+use actix_rt::net::TcpStream;
+
 use tokio_net::driver::Handle;
-use tokio_net::tcp::TcpStream;
 
 pub(crate) enum StdListener {
     Tcp(net::TcpListener),
@@ -161,12 +162,12 @@ impl FromStream for TcpStream {
 }
 
 #[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> {
         match sock {
             StdStream::Tcp(_) => panic!("Should not happen, bug in server impl"),
             StdStream::Uds(stream) => {
-                tokio_net::uds::UnixStream::from_std(stream, &Handle::default())
+                actix_rt::net::UnixStream::from_std(stream, &Handle::default())
             }
         }
     }
diff --git a/actix-server/src/ssl/openssl.rs b/actix-server/src/ssl/openssl.rs
deleted file mode 100644
index ebd05397..00000000
--- a/actix-server/src/ssl/openssl.rs
+++ /dev/null
@@ -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)))
-    }
-}
diff --git a/actix-tls/CHANGES.md b/actix-tls/CHANGES.md
new file mode 100644
index 00000000..baea3d30
--- /dev/null
+++ b/actix-tls/CHANGES.md
@@ -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
diff --git a/actix-tls/Cargo.toml b/actix-tls/Cargo.toml
new file mode 100644
index 00000000..ebcbd867
--- /dev/null
+++ b/actix-tls/Cargo.toml
@@ -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" }
diff --git a/actix-server-config/LICENSE-APACHE b/actix-tls/LICENSE-APACHE
similarity index 100%
rename from actix-server-config/LICENSE-APACHE
rename to actix-tls/LICENSE-APACHE
diff --git a/actix-server-config/LICENSE-MIT b/actix-tls/LICENSE-MIT
similarity index 100%
rename from actix-server-config/LICENSE-MIT
rename to actix-tls/LICENSE-MIT
diff --git a/actix-tls/src/lib.rs b/actix-tls/src/lib.rs
new file mode 100644
index 00000000..53b850d4
--- /dev/null
+++ b/actix-tls/src/lib.rs
@@ -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 {}
diff --git a/actix-tls/src/openssl.rs b/actix-tls/src/openssl.rs
new file mode 100644
index 00000000..8e6641fd
--- /dev/null
+++ b/actix-tls/src/openssl.rs
@@ -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))
+    }
+}
diff --git a/actix-utils/src/counter.rs b/actix-utils/src/counter.rs
index 07d62454..cffa9541 100644
--- a/actix-utils/src/counter.rs
+++ b/actix-utils/src/counter.rs
@@ -52,6 +52,8 @@ impl CounterGuard {
     }
 }
 
+impl Unpin for CounterGuard {}
+
 impl Drop for CounterGuard {
     fn drop(&mut self) {
         self.0.dec();