1
0
mirror of https://github.com/actix/actix-extras.git synced 2025-06-29 19:24:58 +02:00

add rustls

This commit is contained in:
Marat Safin
2018-07-29 09:43:04 +03:00
parent b4ed564e5d
commit 196da6d570
9 changed files with 413 additions and 47 deletions

View File

@ -310,3 +310,46 @@ impl IoStream for TlsStream<TcpStream> {
self.get_mut().get_mut().set_linger(dur)
}
}
#[cfg(feature = "rust-tls")]
use rustls::{ClientSession, ServerSession};
#[cfg(feature = "rust-tls")]
use tokio_rustls::TlsStream;
#[cfg(feature = "rust-tls")]
impl IoStream for TlsStream<TcpStream, ClientSession> {
#[inline]
fn shutdown(&mut self, _how: Shutdown) -> io::Result<()> {
let _ = <Self as AsyncWrite>::shutdown(self);
Ok(())
}
#[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)
}
}
#[cfg(feature = "rust-tls")]
impl IoStream for TlsStream<TcpStream, ServerSession> {
#[inline]
fn shutdown(&mut self, _how: Shutdown) -> io::Result<()> {
let _ = <Self as AsyncWrite>::shutdown(self);
Ok(())
}
#[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)
}
}

View File

@ -22,6 +22,9 @@ use native_tls::TlsAcceptor;
#[cfg(feature = "alpn")]
use openssl::ssl::{AlpnError, SslAcceptorBuilder};
#[cfg(feature = "rust-tls")]
use rustls::ServerConfig;
use super::channel::{HttpChannel, WrapperStream};
use super::settings::{ServerSettings, WorkerSettings};
use super::worker::{Conn, SocketInfo, StopWorker, StreamHandlerType, Worker};
@ -42,6 +45,14 @@ fn configure_alpn(builder: &mut SslAcceptorBuilder) -> io::Result<()> {
Ok(())
}
#[cfg(all(feature = "rust-tls", not(feature = "alpn")))]
fn configure_alpn(builder: &mut Arc<ServerConfig>) -> io::Result<()> {
Arc::<ServerConfig>::get_mut(builder)
.unwrap()
.set_protocols(&vec!["h2".to_string(), "http/1.1".to_string()]);
Ok(())
}
/// An HTTP Server
pub struct HttpServer<H>
where
@ -265,6 +276,26 @@ where
Ok(self)
}
#[cfg(all(feature = "rust-tls", not(feature = "alpn")))]
/// Use listener for accepting incoming tls connection requests
///
/// This method sets alpn protocols to "h2" and "http/1.1"
pub fn listen_ssl(
mut self, lst: net::TcpListener, mut builder: Arc<ServerConfig>,
) -> io::Result<Self> {
// alpn support
if !self.no_http2 {
configure_alpn(&mut builder)?;
}
let addr = lst.local_addr().unwrap();
self.sockets.push(Socket {
addr,
lst,
tp: StreamHandlerType::Rustls(builder.clone()),
});
Ok(self)
}
fn bind2<S: net::ToSocketAddrs>(&mut self, addr: S) -> io::Result<Vec<Socket>> {
let mut err = None;
let mut succ = false;
@ -343,6 +374,26 @@ where
Ok(self)
}
#[cfg(all(feature = "rust-tls", not(feature = "alpn")))]
/// Start listening for incoming tls connections.
///
/// This method sets alpn protocols to "h2" and "http/1.1"
pub fn bind_ssl<S: net::ToSocketAddrs>(
mut self, addr: S, mut builder: Arc<ServerConfig>,
) -> io::Result<Self> {
// alpn support
if !self.no_http2 {
configure_alpn(&mut builder)?;
}
let sockets = self.bind2(addr)?;
self.sockets.extend(sockets.into_iter().map(|mut s| {
s.tp = StreamHandlerType::Rustls(builder.clone());
s
}));
Ok(self)
}
fn start_workers(
&mut self, settings: &ServerSettings, sockets: &Slab<SocketInfo>,
) -> Vec<(usize, mpsc::UnboundedSender<Conn<net::TcpStream>>)> {

View File

@ -8,7 +8,7 @@ use tokio::executor::current_thread;
use tokio_reactor::Handle;
use tokio_tcp::TcpStream;
#[cfg(any(feature = "tls", feature = "alpn"))]
#[cfg(any(feature = "tls", feature = "alpn", feature = "rust-tls"))]
use futures::future;
#[cfg(feature = "tls")]
@ -21,6 +21,13 @@ use openssl::ssl::SslAcceptor;
#[cfg(feature = "alpn")]
use tokio_openssl::SslAcceptorExt;
#[cfg(feature = "rust-tls")]
use rustls::{ServerConfig, Session};
#[cfg(feature = "rust-tls")]
use std::sync::Arc;
#[cfg(feature = "rust-tls")]
use tokio_rustls::ServerConfigExt;
use actix::msgs::StopArbiter;
use actix::{Actor, Arbiter, AsyncContext, Context, Handler, Message, Response};
@ -170,6 +177,8 @@ pub(crate) enum StreamHandlerType {
Tls(TlsAcceptor),
#[cfg(feature = "alpn")]
Alpn(SslAcceptor),
#[cfg(feature = "rust-tls")]
Rustls(Arc<ServerConfig>),
}
impl StreamHandlerType {
@ -237,6 +246,36 @@ impl StreamHandlerType {
},
));
}
#[cfg(feature = "rust-tls")]
StreamHandlerType::Rustls(ref acceptor) => {
let Conn { io, peer, .. } = msg;
let _ = io.set_nodelay(true);
let io = TcpStream::from_std(io, &Handle::default())
.expect("failed to associate TCP stream");
current_thread::spawn(ServerConfigExt::accept_async(acceptor, io).then(
move |res| {
match res {
Ok(io) => {
let http2 = if let Some(p) =
io.get_ref().1.get_alpn_protocol()
{
p.len() == 2 && &p == &"h2"
} else {
false
};
current_thread::spawn(HttpChannel::new(
h, io, peer, http2,
));
}
Err(err) => {
trace!("Error during handling tls connection: {}", err)
}
};
future::result(Ok(()))
},
));
}
}
}
@ -247,6 +286,8 @@ impl StreamHandlerType {
StreamHandlerType::Tls(_) => "https",
#[cfg(feature = "alpn")]
StreamHandlerType::Alpn(_) => "https",
#[cfg(feature = "rust-tls")]
StreamHandlerType::Rustls(_) => "https",
}
}
}