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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! # One TLS API to rule them all
//!
//! Support both:
//! * `tokio`
//! * `async-std`
//!
//! and four TLS implementations:
//! * `tls-api-openssl`, wraps `openssl` crate
//! * `tls-api-rustls`, wraps `rustls` crate
//! * `tls-api-native-tls`, wraps `native-tls` crate
//! * `tls-api-security-framework`, wraps `security-framework` crate
//!
//! The idea is that code can be written without the knowledge of the TLS implementation used,
//! like this:
//!
//! ```
//! # { #![cfg(feature = "runtime-tokio")]
//! use tls_api_2::{TlsConnector, TlsConnectorBuilder};
//! // or async_std::net::TcpStream;
//! use tokio::net::TcpStream;
//! # use tls_api_2::runtime::AsyncWriteExt;
//! # use tls_api_2::runtime::AsyncReadExt;
//!
//! async fn download_rust_lang_org<C: TlsConnector>() -> anyhow::Result<Vec<u8>> {
//! let stream = TcpStream::connect(("rust-lang.org", 443)).await?;
//! let mut stream = C::builder()?.build()?.connect("rust-lang.org", stream).await?;
//! stream.write_all(b"GET / HTTP/1.1\r\nHost: rust-lang.org\r\n\r\n").await?;
//! let mut buf = Vec::new();
//! stream.read_to_end(&mut buf).await?;
//! Ok(buf)
//! }
//! # }
//! ```
//!
//! or the same code with dynamic connector:
//!
//! ```
//! # { #![cfg(feature = "runtime-tokio")]
//! use tls_api_2::TlsConnectorType;
//! // or async_std::net::TcpStream;
//! use tokio::net::TcpStream;
//! # use tls_api_2::runtime::AsyncWriteExt;
//! # use tls_api_2::runtime::AsyncReadExt;
//!
//! async fn download_rust_lang_org(connector_type: &dyn TlsConnectorType) -> anyhow::Result<Vec<u8>> {
//! let stream = TcpStream::connect(("rust-lang.org", 443)).await?;
//! let mut stream = connector_type.builder()?.build()?.connect("rust-lang.org", stream).await?;
//! stream.write_all(b"GET / HTTP/1.1\r\nHost: rust-lang.org\r\n\r\n").await?;
//! let mut buf = Vec::new();
//! stream.read_to_end(&mut buf).await?;
//! Ok(buf)
//! }
//! # }
//! ```
//!
//! Have a look at working example invoking all implementation
//! [on GitHub](https://github.com/edgedb/rust-tls-api/blob/master/examples/examples/download-rust-lang-org.rs#L66).
//!
//! There are also two fake implementations:
//! * `tls-api-stub` crate which returns an error on any operations, useful to check code compiles
//! * `tls-api-no-tls` fake implementation which returns plain sockets without TLS
//!
//! The API is provided to be compatible with both tokio and async-std.
//! Crate features:
//! * `runtime-tokio` enables the implementation over tokio
//! * `runtime-async-std` enables the implementation over async-std
//!
//! Currently the features are mutually exclusive.
pub use TlsAcceptor;
pub use TlsAcceptorBuilder;
pub use TlsAcceptorBox;
pub use TlsAcceptorBuilderBox;
pub use TlsAcceptorType;
pub use TlsConnector;
pub use TlsConnectorBuilder;
pub use TlsConnectorBox;
pub use TlsConnectorBuilderBox;
pub use TlsConnectorType;
pub use BoxFuture;
pub use ImplInfo;
pub use AsyncSocket;
pub use AsyncSocketBox;
pub use TlsStream;
pub use TlsStreamDyn;
pub use TlsStreamWithSocketDyn;
pub use TlsStreamWithSocket;
pub use crateassert_send;
pub use crateassert_send_value;
pub use crateassert_sync;
pub use CommonError;
/// Interfaces needed by API implementor (like `tls-api-rustls`),
/// and not needed by the users of API.