use std::marker::PhantomData; use actix_service::{NewService, Service}; use futures::{future::ok, future::FutureResult, Async, Future, Poll}; use openssl::ssl::{HandshakeError, SslAcceptor}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_openssl::{AcceptAsync, SslAcceptorExt, SslStream}; use super::MAX_CONN_COUNTER; use crate::counter::{Counter, CounterGuard}; /// Support `SSL` connections via openssl package /// /// `ssl` feature enables `OpensslAcceptor` type pub struct OpensslAcceptor { acceptor: SslAcceptor, io: PhantomData, } impl OpensslAcceptor { /// Create default `OpensslAcceptor` pub fn new(acceptor: SslAcceptor) -> Self { OpensslAcceptor { acceptor, io: PhantomData, } } } impl Clone for OpensslAcceptor { fn clone(&self) -> Self { Self { acceptor: self.acceptor.clone(), io: PhantomData, } } } impl NewService for OpensslAcceptor { type Request = T; type Response = SslStream; type Error = HandshakeError; type Service = OpensslAcceptorService; type InitError = (); type Future = FutureResult; fn new_service(&self, _: &()) -> Self::Future { MAX_CONN_COUNTER.with(|conns| { ok(OpensslAcceptorService { acceptor: self.acceptor.clone(), conns: conns.clone(), io: PhantomData, }) }) } } pub struct OpensslAcceptorService { acceptor: SslAcceptor, io: PhantomData, conns: Counter, } impl Service for OpensslAcceptorService { type Request = T; type Response = SslStream; type Error = HandshakeError; type Future = OpensslAcceptorServiceFut; fn poll_ready(&mut self) -> Poll<(), Self::Error> { if self.conns.available() { Ok(Async::Ready(())) } else { Ok(Async::NotReady) } } fn call(&mut self, req: T) -> Self::Future { OpensslAcceptorServiceFut { _guard: self.conns.get(), fut: SslAcceptorExt::accept_async(&self.acceptor, req), } } } pub struct OpensslAcceptorServiceFut where T: AsyncRead + AsyncWrite, { fut: AcceptAsync, _guard: CounterGuard, } impl Future for OpensslAcceptorServiceFut { type Item = SslStream; type Error = HandshakeError; fn poll(&mut self) -> Poll { self.fut.poll() } }