tls_api/
lib.rs

1//! # One TLS API to rule them all
2//!
3//! Support both:
4//! * `tokio`
5//! * `async-std`
6//!
7//! and four TLS implementations:
8//! * `tls-api-openssl`, wraps `openssl` crate
9//! * `tls-api-rustls`, wraps `rustls` crate
10//! * `tls-api-native-tls`, wraps `native-tls` crate
11//! * `tls-api-security-framework`, wraps `security-framework` crate
12//!
13//! The idea is that code can be written without the knowledge of the TLS implementation used,
14//! like this:
15//!
16//! ```
17//! # { #![cfg(feature = "runtime-tokio")]
18//! use tls_api_2::{TlsConnector, TlsConnectorBuilder};
19//! // or async_std::net::TcpStream;
20//! use tokio::net::TcpStream;
21//! # use tls_api_2::runtime::AsyncWriteExt;
22//! # use tls_api_2::runtime::AsyncReadExt;
23//!
24//! async fn download_rust_lang_org<C: TlsConnector>() -> anyhow::Result<Vec<u8>> {
25//!     let stream = TcpStream::connect(("rust-lang.org", 443)).await?;
26//!     let mut  stream = C::builder()?.build()?.connect("rust-lang.org", stream).await?;
27//!     stream.write_all(b"GET / HTTP/1.1\r\nHost: rust-lang.org\r\n\r\n").await?;
28//!     let mut buf = Vec::new();
29//!     stream.read_to_end(&mut buf).await?;
30//!     Ok(buf)
31//! }
32//! # }
33//! ```
34//!
35//! or the same code with dynamic connector:
36//!
37//! ```
38//! # { #![cfg(feature = "runtime-tokio")]
39//! use tls_api_2::TlsConnectorType;
40//! // or async_std::net::TcpStream;
41//! use tokio::net::TcpStream;
42//! # use tls_api_2::runtime::AsyncWriteExt;
43//! # use tls_api_2::runtime::AsyncReadExt;
44//!
45//! async fn download_rust_lang_org(connector_type: &dyn TlsConnectorType) -> anyhow::Result<Vec<u8>> {
46//!     let stream = TcpStream::connect(("rust-lang.org", 443)).await?;
47//!     let mut  stream = connector_type.builder()?.build()?.connect("rust-lang.org", stream).await?;
48//!     stream.write_all(b"GET / HTTP/1.1\r\nHost: rust-lang.org\r\n\r\n").await?;
49//!     let mut buf = Vec::new();
50//!     stream.read_to_end(&mut buf).await?;
51//!     Ok(buf)
52//! }
53//! # }
54//! ```
55//!
56//! Have a look at working example invoking all implementation
57//! [on GitHub](https://github.com/edgedb/rust-tls-api/blob/master/examples/examples/download-rust-lang-org.rs#L66).
58//!
59//! There are also two fake implementations:
60//! * `tls-api-stub` crate which returns an error on any operations, useful to check code compiles
61//! * `tls-api-no-tls` fake implementation which returns plain sockets without TLS
62//!
63//! The API is provided to be compatible with both tokio and async-std.
64//! Crate features:
65//! * `runtime-tokio` enables the implementation over tokio
66//! * `runtime-async-std` enables the implementation over async-std
67//!
68//! Currently the features are mutually exclusive.
69
70#![deny(rustdoc::broken_intra_doc_links)]
71#![deny(missing_docs)]
72
73pub use acceptor::TlsAcceptor;
74pub use acceptor::TlsAcceptorBuilder;
75pub use acceptor_box::TlsAcceptorBox;
76pub use acceptor_box::TlsAcceptorBuilderBox;
77pub use acceptor_box::TlsAcceptorType;
78pub use connector::TlsConnector;
79pub use connector::TlsConnectorBuilder;
80pub use connector_box::TlsConnectorBox;
81pub use connector_box::TlsConnectorBuilderBox;
82pub use connector_box::TlsConnectorType;
83pub use future::BoxFuture;
84pub use info::ImplInfo;
85pub use socket::AsyncSocket;
86pub use socket_box::AsyncSocketBox;
87pub use stream::TlsStream;
88pub use stream_dyn::TlsStreamDyn;
89pub use stream_dyn::TlsStreamWithSocketDyn;
90pub use stream_with_socket::TlsStreamWithSocket;
91
92pub(crate) use crate::assert_kinds::assert_send;
93pub(crate) use crate::assert_kinds::assert_send_value;
94pub(crate) use crate::assert_kinds::assert_sync;
95pub(crate) use error::CommonError;
96
97pub mod runtime;
98
99/// Interfaces needed by API implementor (like `tls-api-rustls`),
100/// and not needed by the users of API.
101pub mod spi {
102    pub use crate::stream_dyn::TlsStreamWithUpcastDyn;
103    pub use crate::thread_local_context::restore_context;
104    pub use crate::thread_local_context::save_context;
105}
106
107mod acceptor;
108mod acceptor_box;
109mod assert_kinds;
110pub mod async_as_sync;
111mod connector;
112mod connector_box;
113mod error;
114mod future;
115mod info;
116mod openssl;
117mod socket;
118mod socket_box;
119mod stream;
120mod stream_dyn;
121mod stream_with_socket;
122mod thread_local_context;
123
124fn _assert_kinds() {
125    fn connect_future_is_send<C, S>(c: &C, s: S)
126    where
127        C: TlsConnector,
128        S: AsyncSocket,
129    {
130        let f = c.connect_with_socket("dom", s);
131        assert_send_value(f);
132    }
133
134    fn accept_future_is_send<A, S>(a: &A, s: S)
135    where
136        A: TlsAcceptor,
137        S: AsyncSocket,
138    {
139        let f = a.accept_with_socket(s);
140        assert_send_value(f);
141    }
142}