pub(crate) mod conn;
mod keylog;
mod options;
mod x509;
#[cfg(feature = "boring")]
pub(crate) mod boring;
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
pub(crate) mod rustls;
#[cfg(feature = "boring")]
pub use ::boring::ssl::{CertificateCompressionAlgorithm, ExtensionType};
use bytes::Bytes;
pub use self::{
keylog::KeyLog,
options::{TlsOptions, TlsOptionsBuilder},
x509::{CertStore, CertStoreBuilder, Certificate, Identity},
};
#[derive(Debug, Clone)]
pub struct TlsInfo {
pub(crate) peer_certificate: Option<Bytes>,
pub(crate) peer_certificate_chain: Option<Vec<Bytes>>,
}
impl TlsInfo {
pub fn peer_certificate(&self) -> Option<&[u8]> {
self.peer_certificate.as_deref()
}
pub fn peer_certificate_chain(&self) -> Option<impl Iterator<Item = &[u8]>> {
self.peer_certificate_chain
.as_ref()
.map(|v| v.iter().map(|b| b.as_ref()))
}
}
#[allow(unused_imports)]
use std::hash::{Hash, Hasher};
#[cfg(feature = "boring")]
use ::boring::ssl;
use bytes::{BufMut, BytesMut};
#[cfg(feature = "boring")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TlsVersion(ssl::SslVersion);
#[cfg(feature = "boring")]
impl Hash for TlsVersion {
fn hash<H: Hasher>(&self, state: &mut H) {
format!("{:?}", self.0).hash(state);
}
}
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct TlsVersion(u16);
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct TlsVersion(u16);
impl TlsVersion {
#[cfg(feature = "boring")]
pub const TLS_1_0: TlsVersion = TlsVersion(ssl::SslVersion::TLS1);
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
pub const TLS_1_0: TlsVersion = TlsVersion(0x0301);
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
pub const TLS_1_0: TlsVersion = TlsVersion(0x0301);
#[cfg(feature = "boring")]
pub const TLS_1_1: TlsVersion = TlsVersion(ssl::SslVersion::TLS1_1);
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
pub const TLS_1_1: TlsVersion = TlsVersion(0x0302);
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
pub const TLS_1_1: TlsVersion = TlsVersion(0x0302);
#[cfg(feature = "boring")]
pub const TLS_1_2: TlsVersion = TlsVersion(ssl::SslVersion::TLS1_2);
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
pub const TLS_1_2: TlsVersion = TlsVersion(0x0303);
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
pub const TLS_1_2: TlsVersion = TlsVersion(0x0303);
#[cfg(feature = "boring")]
pub const TLS_1_3: TlsVersion = TlsVersion(ssl::SslVersion::TLS1_3);
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
pub const TLS_1_3: TlsVersion = TlsVersion(0x0304);
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
pub const TLS_1_3: TlsVersion = TlsVersion(0x0304);
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct AlpnProtocol(&'static [u8]);
impl AlpnProtocol {
pub const HTTP1: AlpnProtocol = AlpnProtocol(b"http/1.1");
pub const HTTP2: AlpnProtocol = AlpnProtocol(b"h2");
pub const HTTP3: AlpnProtocol = AlpnProtocol(b"h3");
#[inline]
pub const fn new(value: &'static [u8]) -> Self {
AlpnProtocol(value)
}
#[inline]
pub fn as_wire_bytes(&self) -> &'static [u8] {
self.0
}
#[inline]
fn encode(self) -> Bytes {
Self::encode_sequence(std::iter::once(&self))
}
fn encode_sequence<'a, I>(items: I) -> Bytes
where
I: IntoIterator<Item = &'a AlpnProtocol>,
{
let mut buf = BytesMut::new();
for item in items {
buf.put_u8(item.0.len() as u8);
buf.extend_from_slice(item.0);
}
buf.freeze()
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct AlpsProtocol(&'static [u8]);
impl AlpsProtocol {
pub const HTTP1: AlpsProtocol = AlpsProtocol(b"http/1.1");
pub const HTTP2: AlpsProtocol = AlpsProtocol(b"h2");
pub const HTTP3: AlpsProtocol = AlpsProtocol(b"h3");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn alpn_protocol_encode() {
let alpn = AlpnProtocol::encode_sequence(&[AlpnProtocol::HTTP1, AlpnProtocol::HTTP2]);
assert_eq!(alpn, Bytes::from_static(b"\x08http/1.1\x02h2"));
let alpn = AlpnProtocol::encode_sequence(&[AlpnProtocol::HTTP3]);
assert_eq!(alpn, Bytes::from_static(b"\x02h3"));
let alpn = AlpnProtocol::encode_sequence(&[AlpnProtocol::HTTP1, AlpnProtocol::HTTP3]);
assert_eq!(alpn, Bytes::from_static(b"\x08http/1.1\x02h3"));
let alpn = AlpnProtocol::encode_sequence(&[AlpnProtocol::HTTP2, AlpnProtocol::HTTP3]);
assert_eq!(alpn, Bytes::from_static(b"\x02h2\x02h3"));
let alpn = AlpnProtocol::encode_sequence(&[
AlpnProtocol::HTTP1,
AlpnProtocol::HTTP2,
AlpnProtocol::HTTP3,
]);
assert_eq!(alpn, Bytes::from_static(b"\x08http/1.1\x02h2\x02h3"));
}
#[test]
fn alpn_protocol_encode_single() {
let alpn = AlpnProtocol::HTTP1.encode();
assert_eq!(alpn, b"\x08http/1.1".as_ref());
let alpn = AlpnProtocol::HTTP2.encode();
assert_eq!(alpn, b"\x02h2".as_ref());
let alpn = AlpnProtocol::HTTP3.encode();
assert_eq!(alpn, b"\x02h3".as_ref());
}
}