1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::sync::Arc;

use hyper::server::conn::AddrIncoming;
use pki_types::{CertificateDer, PrivateKeyDer};
use rustls::ServerConfig;

use super::TlsAcceptor;

/// Builder for [`TlsAcceptor`]
pub struct AcceptorBuilder<State>(State);

/// State of a builder that needs a TLS client config next
pub struct WantsTlsConfig(());

impl AcceptorBuilder<WantsTlsConfig> {
    /// Creates a new [`AcceptorBuilder`]
    pub fn new() -> Self {
        Self(WantsTlsConfig(()))
    }

    /// Passes a rustls [`ServerConfig`] to configure the TLS connection
    pub fn with_tls_config(self, config: ServerConfig) -> AcceptorBuilder<WantsAlpn> {
        AcceptorBuilder(WantsAlpn(config))
    }

    /// Use rustls default crypto provider and safe defaults without
    /// [client authentication][with_no_client_auth]
    ///
    /// [with_no_client_auth]: rustls::ConfigBuilder::with_no_client_auth
    pub fn with_single_cert(
        self,
        cert_chain: Vec<CertificateDer<'static>>,
        key_der: PrivateKeyDer<'static>,
    ) -> Result<AcceptorBuilder<WantsAlpn>, rustls::Error> {
        Ok(AcceptorBuilder(WantsAlpn(
            ServerConfig::builder()
                .with_no_client_auth()
                .with_single_cert(cert_chain, key_der)?,
        )))
    }
}

impl Default for AcceptorBuilder<WantsTlsConfig> {
    fn default() -> Self {
        Self::new()
    }
}

/// State of a builder that needs a incoming address next
pub struct WantsAlpn(ServerConfig);

impl AcceptorBuilder<WantsAlpn> {
    /// Configure ALPN accept protocols in order
    pub fn with_alpn_protocols(
        mut self,
        alpn_protocols: Vec<Vec<u8>>,
    ) -> AcceptorBuilder<WantsIncoming> {
        self.0 .0.alpn_protocols = alpn_protocols;
        AcceptorBuilder(WantsIncoming(self.0 .0))
    }

    /// Configure ALPN to accept HTTP/2
    pub fn with_http2_alpn(mut self) -> AcceptorBuilder<WantsIncoming> {
        self.0 .0.alpn_protocols = vec![b"h2".to_vec()];
        AcceptorBuilder(WantsIncoming(self.0 .0))
    }

    /// Configure ALPN to accept HTTP/1.0
    pub fn with_http10_alpn(mut self) -> AcceptorBuilder<WantsIncoming> {
        self.0 .0.alpn_protocols = vec![b"http/1.0".to_vec()];
        AcceptorBuilder(WantsIncoming(self.0 .0))
    }

    /// Configure ALPN to accept HTTP/1.1
    pub fn with_http11_alpn(mut self) -> AcceptorBuilder<WantsIncoming> {
        self.0 .0.alpn_protocols = vec![b"http/1.1".to_vec()];
        AcceptorBuilder(WantsIncoming(self.0 .0))
    }

    /// Configure ALPN to accept HTTP/2, HTTP/1.1, HTTP/1.0 in that order.
    pub fn with_all_versions_alpn(mut self) -> AcceptorBuilder<WantsIncoming> {
        self.0 .0.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()];
        AcceptorBuilder(WantsIncoming(self.0 .0))
    }
}

/// State of a builder that needs a incoming address next
pub struct WantsIncoming(ServerConfig);

impl AcceptorBuilder<WantsIncoming> {
    /// Passes a [`AddrIncoming`] to configure the TLS connection and
    /// creates the [`TlsAcceptor`]
    pub fn with_incoming(self, incoming: impl Into<AddrIncoming>) -> TlsAcceptor {
        self.with_acceptor(incoming.into())
    }

    /// Passes an acceptor implementing [`Accept`] to configure the TLS connection and
    /// creates the [`TlsAcceptor`]
    ///
    /// [`Accept`]: hyper::server::accept::Accept
    pub fn with_acceptor<A>(self, acceptor: A) -> TlsAcceptor<A> {
        TlsAcceptor {
            config: Arc::new(self.0 .0),
            acceptor,
        }
    }
}