use std::future::Future; use std::io; use std::marker::PhantomData; use std::pin::Pin; use std::sync::Arc; use std::task::{Context, Poll}; use actix_service::{Service, ServiceFactory}; use futures::future::{ok, Ready}; use rust_tls::ServerConfig; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_rustls::{server::TlsStream, Accept, TlsAcceptor}; use crate::counter::{Counter, CounterGuard}; use crate::ssl::MAX_CONN_COUNTER; use crate::{Io, Protocol, ServerConfig as SrvConfig}; /// Support `SSL` connections via rustls package /// /// `rust-tls` feature enables `RustlsAcceptor` type pub struct RustlsAcceptor { config: Arc, io: PhantomData<(T, P)>, } impl RustlsAcceptor { /// Create `RustlsAcceptor` new service pub fn new(config: ServerConfig) -> Self { RustlsAcceptor { config: Arc::new(config), io: PhantomData, } } } impl Clone for RustlsAcceptor { fn clone(&self) -> Self { Self { config: self.config.clone(), io: PhantomData, } } } impl ServiceFactory for RustlsAcceptor { type Request = Io; type Response = Io, P>; type Error = io::Error; type Config = SrvConfig; type Service = RustlsAcceptorService; type InitError = (); type Future = Ready>; fn new_service(&self, cfg: &SrvConfig) -> Self::Future { cfg.set_secure(); MAX_CONN_COUNTER.with(|conns| { ok(RustlsAcceptorService { acceptor: self.config.clone().into(), conns: conns.clone(), io: PhantomData, }) }) } } pub struct RustlsAcceptorService { acceptor: TlsAcceptor, io: PhantomData<(T, P)>, conns: Counter, } impl Service for RustlsAcceptorService { type Request = Io; type Response = Io, P>; type Error = io::Error; type Future = RustlsAcceptorServiceFut; fn poll_ready(&mut self, cx: &mut Context) -> Poll> { if self.conns.available(cx) { Poll::Ready(Ok(())) } else { Poll::Pending } } fn call(&mut self, req: Self::Request) -> Self::Future { let (io, params, _) = req.into_parts(); RustlsAcceptorServiceFut { _guard: self.conns.get(), fut: self.acceptor.accept(io), params: Some(params), } } } pub struct RustlsAcceptorServiceFut where T: AsyncRead + AsyncWrite + Unpin, { fut: Accept, params: Option

, _guard: CounterGuard, } impl Unpin for RustlsAcceptorServiceFut {} impl Future for RustlsAcceptorServiceFut { type Output = Result, P>, io::Error>; fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { let this = self.get_mut(); let res = futures::ready!(Pin::new(&mut this.fut).poll(cx)); match res { Ok(io) => { let params = this.params.take().unwrap(); Poll::Ready(Ok(Io::from_parts(io, params, Protocol::Unknown))) } Err(e) => Poll::Ready(Err(e)), } } }