Skip to main content

net_wire/tls/extensions/
versions.rs

1use super::layout::{len, v8};
2use crate::tls::{error::TlsParseError, types::TlsProtocolVersion};
3
4/// Ordered protocol versions from a ClientHello supported_versions extension.
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub struct ClientSupportedVersions<'a> {
7    bytes: &'a [u8],
8}
9impl<'a> ClientSupportedVersions<'a> {
10    pub(super) fn parse(b: &'a [u8]) -> Result<Self, TlsParseError> {
11        let bytes = v8(b, 2)?;
12        if !bytes.len().is_multiple_of(2) {
13            return Err(TlsParseError::InvalidValue);
14        }
15        Ok(Self { bytes })
16    }
17    /// Returns versions in their original wire order.
18    pub fn iter(&self) -> impl Iterator<Item = TlsProtocolVersion> + 'a {
19        self.bytes
20            .chunks_exact(2)
21            .map(|x| TlsProtocolVersion::new(u16::from_be_bytes([x[0], x[1]])))
22    }
23    /// Returns the numerically highest non-GREASE offered version.
24    pub fn highest(&self) -> Option<TlsProtocolVersion> {
25        self.iter().filter(|x| !x.is_grease()).max()
26    }
27}
28/// A protocol version selected by a server or HelloRetryRequest.
29#[derive(Clone, Copy, Debug, Eq, PartialEq)]
30pub struct ServerSupportedVersion(TlsProtocolVersion);
31impl ServerSupportedVersion {
32    pub(super) fn parse(b: &[u8]) -> Result<Self, TlsParseError> {
33        if b.len() != 2 {
34            return Err(len(2, b.len()));
35        }
36        Ok(Self(TlsProtocolVersion::new(u16::from_be_bytes([
37            b[0], b[1],
38        ]))))
39    }
40    /// Returns the selected raw-preserving version.
41    pub const fn version(self) -> TlsProtocolVersion {
42        self.0
43    }
44}