Skip to main content

net_wire/tls/extensions/
alpn.rs

1use super::layout::v16;
2use crate::tls::error::TlsParseError;
3
4/// One opaque ALPN protocol identification sequence.
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub struct AlpnProtocol<'a>(&'a [u8]);
7impl<'a> AlpnProtocol<'a> {
8    /// Returns the opaque protocol-name bytes.
9    pub const fn as_bytes(self) -> &'a [u8] {
10        self.0
11    }
12    /// Returns whether this is the RFC 8701 two-byte GREASE ALPN value.
13    pub const fn is_grease(self) -> bool {
14        self.0.len() == 2 && self.0[0] == self.0[1] && self.0[0] & 15 == 10
15    }
16}
17/// An ordered ALPN protocol-name list.
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
19pub struct AlpnProtocolList<'a> {
20    bytes: &'a [u8],
21}
22impl<'a> AlpnProtocolList<'a> {
23    pub(super) fn parse(b: &'a [u8]) -> Result<Self, TlsParseError> {
24        let x = v16(b, 1, false)?;
25        protocols_ok(x)?;
26        Ok(Self { bytes: x })
27    }
28    /// Returns ALPN protocols in their original wire order.
29    pub fn iter(&self) -> AlpnProtocolIter<'a> {
30        AlpnProtocolIter { bytes: self.bytes }
31    }
32}
33/// A fallible iterator over ALPN protocol names.
34#[derive(Clone, Debug)]
35pub struct AlpnProtocolIter<'a> {
36    bytes: &'a [u8],
37}
38impl<'a> Iterator for AlpnProtocolIter<'a> {
39    type Item = Result<AlpnProtocol<'a>, TlsParseError>;
40    fn next(&mut self) -> Option<Self::Item> {
41        if self.bytes.is_empty() {
42            return None;
43        }
44        let n = usize::from(self.bytes[0]);
45        if n == 0 {
46            self.bytes = &[];
47            return Some(Err(TlsParseError::InvalidValue));
48        }
49        if self.bytes.len() < n + 1 {
50            let a = self.bytes.len();
51            self.bytes = &[];
52            return Some(Err(TlsParseError::Incomplete {
53                required: n + 1,
54                available: a,
55            }));
56        }
57        let x = AlpnProtocol(&self.bytes[1..n + 1]);
58        self.bytes = &self.bytes[n + 1..];
59        Some(Ok(x))
60    }
61}
62fn protocols_ok(mut b: &[u8]) -> Result<(), TlsParseError> {
63    while !b.is_empty() {
64        let n = usize::from(b[0]);
65        if n == 0 {
66            return Err(TlsParseError::InvalidValue);
67        }
68        if b.len() < n + 1 {
69            return Err(TlsParseError::Incomplete {
70                required: n + 1,
71                available: b.len(),
72            });
73        }
74        b = &b[n + 1..]
75    }
76    Ok(())
77}
78/// The single ALPN protocol selected by a server.
79#[derive(Clone, Copy, Debug, Eq, PartialEq)]
80pub struct ServerSelectedAlpn<'a>(AlpnProtocol<'a>);
81impl<'a> ServerSelectedAlpn<'a> {
82    pub(super) fn parse(b: &'a [u8]) -> Result<Self, TlsParseError> {
83        let x = AlpnProtocolList::parse(b)?;
84        let mut i = x.iter();
85        let p = i.next().expect("nonempty")?;
86        if i.next().is_some() {
87            return Err(TlsParseError::TrailingBytes);
88        }
89        Ok(Self(p))
90    }
91    /// Returns the selected opaque protocol name.
92    pub const fn protocol(self) -> AlpnProtocol<'a> {
93        self.0
94    }
95}