1use crate::TlsExtError;
5use ytls_typed::Alpn;
6
7pub trait ExtAlpnProcessor {
9 fn alpn<'r>(&mut self, _: Alpn<'r>) -> bool;
10}
11
12pub struct TlsExtAlpn {}
14
15impl TlsExtAlpn {
16 #[inline]
17 pub fn client_alpn_cb<P: ExtAlpnProcessor>(
18 p: &mut P,
19 alpn_raw: &[u8],
20 ) -> Result<(), TlsExtError> {
21 if alpn_raw.len() < 2 {
22 return Err(TlsExtError::InvalidLength);
23 }
24
25 let alpns_expected_len = u16::from_be_bytes([alpn_raw[0], alpn_raw[1]]);
26
27 let alpns_raw_len_remaining = alpn_raw.len() - 2;
28
29 if alpns_raw_len_remaining == 0 {
30 return Err(TlsExtError::NoData);
31 }
32
33 if alpns_expected_len as usize != alpns_raw_len_remaining {
34 return Err(TlsExtError::InvalidLength);
35 }
36
37 let mut remaining = &alpn_raw[2..];
38
39 let expected_len: usize = remaining.len();
40
41 let mut processed: usize = 0;
42
43 loop {
44 if remaining.len() < 2 {
45 return Err(TlsExtError::InvalidLength);
46 }
47 let alpn_len = remaining[0] as usize;
48
49 remaining = &remaining[1..];
50 processed += 1;
51
52 if alpn_len > remaining.len() {
53 return Err(TlsExtError::EntryOverflow);
54 }
55
56 let (alpn, remaining_next) = remaining.split_at(alpn_len as usize);
57 processed += alpn_len as usize;
58
59 p.alpn(alpn.into());
60
61 remaining = remaining_next;
62
63 if processed > expected_len {
64 return Err(TlsExtError::EntryOverflow);
65 }
66
67 if remaining.len() == 0 {
68 break;
69 }
70 }
71
72 Ok(())
73 }
74}