use bytes::Bytes;
#[derive(Debug, Clone)]
pub struct TlsClientHello {
pub record_version: TlsVersion,
pub legacy_version: TlsVersion,
pub random: [u8; 32],
pub session_id: Bytes,
pub cipher_suites: Vec<u16>,
pub compression: Vec<u8>,
pub sni: Option<String>,
pub alpn: Vec<String>,
pub supported_versions: Vec<TlsVersion>,
pub supported_groups: Vec<u16>,
pub extension_types: Vec<u16>,
}
#[derive(Debug, Clone)]
pub struct TlsServerHello {
pub record_version: TlsVersion,
pub legacy_version: TlsVersion,
pub random: [u8; 32],
pub session_id: Bytes,
pub cipher_suite: u16,
pub compression: u8,
pub alpn: Option<String>,
pub supported_version: Option<TlsVersion>,
}
#[derive(Debug, Clone, Copy)]
pub struct TlsAlert {
pub level: TlsAlertLevel,
pub description: u8,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TlsAlertLevel {
Warning,
Fatal,
Other(u8),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TlsVersion {
Ssl3_0,
Tls1_0,
Tls1_1,
Tls1_2,
Tls1_3,
Other(u16),
}
impl TlsVersion {
pub fn from_raw(v: u16) -> Self {
match v {
0x0300 => TlsVersion::Ssl3_0,
0x0301 => TlsVersion::Tls1_0,
0x0302 => TlsVersion::Tls1_1,
0x0303 => TlsVersion::Tls1_2,
0x0304 => TlsVersion::Tls1_3,
other => TlsVersion::Other(other),
}
}
pub fn to_raw(self) -> u16 {
match self {
TlsVersion::Ssl3_0 => 0x0300,
TlsVersion::Tls1_0 => 0x0301,
TlsVersion::Tls1_1 => 0x0302,
TlsVersion::Tls1_2 => 0x0303,
TlsVersion::Tls1_3 => 0x0304,
TlsVersion::Other(v) => v,
}
}
}
pub trait TlsHandler: Send + Sync + 'static {
fn on_client_hello(&self, _hello: &TlsClientHello) {}
fn on_server_hello(&self, _hello: &TlsServerHello) {}
fn on_alert(&self, _alert: &TlsAlert) {}
#[cfg(feature = "ja3")]
fn on_ja3(&self, _hash_md5: &str, _canonical: &str) {}
}
#[derive(Debug, Clone)]
pub struct TlsConfig {
pub ja3: bool,
pub max_buffer: usize,
}
impl Default for TlsConfig {
fn default() -> Self {
Self {
ja3: false,
max_buffer: 64 * 1024,
}
}
}