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
use super::*;

/// A `tokio` connector that uses `tokio-native-tls` (a `native-tls` wrapper). This uses TLS.

///

/// To use this type, ensure you set up the 'TLS Domain' in the configuration.

///

/// The crate provides the 'TLS domain' for Twitch in the root of this crate.

#[derive(Debug, Clone, PartialEq)]
pub struct ConnectorNativeTls {
    addrs: Vec<std::net::SocketAddr>,
    tls_domain: String,
}

impl ConnectorNativeTls {
    connector_ctor!(tls:
        /// [`tokio`](https://docs.rs/tokio/0.2/tokio/) (using [`tokio-native-tls`](https://docs.rs/tokio-native-tls/latest/tokio_native_tls/))

    );
}

type CloneStream<T> = async_dup::Mutex<tokio_util::compat::Compat<T>>;
type Stream = tokio_native_tls::TlsStream<tokio::net::TcpStream>;

impl crate::connector::Connector for ConnectorNativeTls {
    type Output = CloneStream<Stream>;

    fn connect(&mut self) -> BoxedFuture<std::io::Result<Self::Output>> {
        let this = self.clone();

        let fut = async move {
            use tokio_util::compat::Tokio02AsyncReadCompatExt as _;

            let connector: tokio_native_tls::TlsConnector = ::native_tls::TlsConnector::new()
                .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?
                .into();

            let stream = tokio::net::TcpStream::connect(&*this.addrs).await?;
            let stream = connector
                .connect(&this.tls_domain, stream)
                .await
                .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?;

            Ok(async_dup::Mutex::new(stream.compat()))
        };
        Box::pin(fut)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn assert_connector_trait_is_fulfilled() {
        use crate::connector::testing::*;
        use crate::connector::Connector as C;

        assert_connector::<ConnectorNativeTls>();
        assert_type_is_read_write::<<ConnectorNativeTls as C>::Output>();
        assert_obj_is_sane(ConnectorNativeTls::twitch().unwrap());
    }
}