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
use crate::smtp::net::tls::TlsCapable;
use crate::smtp::net::tls::TlsProvider;
use crate::smtp::net::Connector;
use crate::smtp::net::TlsMode;
use crate::{smtp::net::ConnectionConfiguration, SyncFuture};
use async_std::io;
use async_std::os::unix::net::UnixStream;
use samotop_core::common::Pin;
use samotop_core::io::tls::MayBeTls;

#[derive(Debug)]
pub struct UnixConnector<TLS> {
    pub tls_mode: TlsMode,
    pub provider: TLS,
}

impl<TLS: Default> Default for UnixConnector<TLS> {
    fn default() -> Self {
        Self {
            tls_mode: TlsMode::StartTls,
            provider: TLS::default(),
        }
    }
}

impl<TLS> Connector for UnixConnector<TLS>
where
    TLS: TlsProvider + Sync + Send + 'static,
{
    type Stream = TlsCapable;
    /// This provider of connectivity takes care of resolving
    /// given address (which could be an IP, FQDN, URL...),
    /// establishing a connection and enabling (or not) TLS upgrade.
    fn connect<'s, 'c, 'a, C: ConnectionConfiguration + Sync>(
        &'s self,
        configuration: &'c C,
    ) -> SyncFuture<'a, io::Result<Self::Stream>>
    where
        's: 'a,
        'c: 'a,
    {
        Box::pin(async move {
            let to = configuration.address();
            let timeout = configuration.timeout();

            let stream = io::timeout(timeout, UnixStream::connect(&to)).await?;
            let stream = Box::new(stream);
            let mut stream = match self.provider.get_tls_upgrade() {
                Some(u) => TlsCapable::enabled(stream, u, String::default()),
                None => TlsCapable::plaintext(stream),
            };

            match self.tls_mode {
                TlsMode::Tls => Pin::new(&mut stream).encrypt(),
                TlsMode::StartTls => { /* ready! */ }
            }
            Ok(stream)
        })
    }
}