use crate::net::alert::TlsError;
pub trait Extension {
fn server_parse(buf: &[u8]) -> Result<Self, TlsError>
where
Self: Sized;
fn client_parse(buf: &[u8]) -> Result<Self, TlsError>
where
Self: Sized,
{
Extension::server_parse(buf)
}
fn server_as_bytes(&self) -> Vec<u8>;
fn client_as_bytes(&self) -> Vec<u8> {
self.server_as_bytes()
}
}
pub trait ExtensionWrapper {
#[allow(clippy::redundant_allocation)]
fn get_extension(&self) -> Box<&dyn Extension>;
}
pub struct Extensions<T: ExtensionWrapper> {
extensions: Vec<T>,
is_client: bool,
}
impl<T: ExtensionWrapper> Extensions<T> {
pub fn new() -> Self {
Self {
extensions: vec![],
is_client: false,
}
}
pub fn as_vec(&self) -> &Vec<T> {
&self.extensions
}
pub fn push(&mut self, ext: T) {
self.extensions.push(ext)
}
pub fn set_is_client(&mut self) {
self.is_client = true;
}
pub fn as_bytes(&self) -> Vec<u8> {
let mut out = vec![0x00, 0x00];
if self.extensions.is_empty() {
return out; }
for ext in self.extensions.iter() {
if self.is_client {
out.extend_from_slice(&ext.get_extension().client_as_bytes());
} else {
out.extend_from_slice(&ext.get_extension().server_as_bytes());
}
}
let extension_len = out.len() - 2;
out[0] = (extension_len >> 8) as u8;
out[1] = extension_len as u8;
out
}
}
impl<T: ExtensionWrapper> Default for Extensions<T> {
fn default() -> Self {
Self::new()
}
}
#[derive(PartialEq, Debug)]
pub enum ExtensionType {
ServerName = 0x00,
SupportedGroups = 0x0a,
SignatureAlgorithms = 0x0d,
SupportedVersions = 0x2b,
KeyShare = 0x33,
}
impl ExtensionType {
pub fn new(val: u16) -> Option<ExtensionType> {
Some(match val {
0x00 => ExtensionType::ServerName,
0x2b => ExtensionType::SupportedVersions,
0x33 => ExtensionType::KeyShare,
_ => return None,
})
}
}