ytls_record/record/handshake/
server_hello.rs1use ytls_traits::ServerHelloProcessor;
4use ytls_traits::ServerRecordProcessor;
5
6use super::CipherSuites;
7use super::Extensions;
8use crate::error::{RecordError, ServerHelloError};
9
10use zerocopy::byteorder::network_endian::U16 as N16;
11use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes, Unaligned};
12
13#[derive(TryFromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)]
14#[repr(C)]
15#[derive(Debug, PartialEq)]
16pub struct ServerHelloHdr {
17 pub(crate) legacy_version: [u8; 2],
18 pub(crate) server_random: [u8; 32],
19 pub(crate) ses_id_len: u8,
20}
21
22#[derive(Debug, PartialEq)]
23pub struct ServerHello<'r> {
24 pub(crate) hdr: &'r ServerHelloHdr,
25}
26
27impl<'r> ServerHello<'r> {
28 pub fn parse<P: ServerRecordProcessor>(
29 prc: &mut P,
30 bytes: &'r [u8],
31 ) -> Result<(Self, &'r [u8]), RecordError> {
32 let (hello_hdr, mut rest) = ServerHelloHdr::try_ref_from_prefix(bytes)
33 .map_err(|e| RecordError::from_zero_copy(e))?;
34
35 let sh = prc.server_hello();
36
37 sh.handle_server_random(&hello_hdr.server_random);
38
39 let ses_id_len: usize = hello_hdr.ses_id_len.into();
40
41 if ses_id_len > 32 {
42 return Err(RecordError::OverflowLength);
43 }
44
45 let ses_id = rest.split_off(..ses_id_len).ok_or(RecordError::Size)?;
46 sh.handle_session_id(&ses_id);
47
48 let cipher_suite = rest.split_off(..2).ok_or(RecordError::Size)?;
49 sh.handle_selected_cipher_suite([cipher_suite[0], cipher_suite[1]]);
50
51 let _compress_method = rest.split_off(..1).ok_or(RecordError::Size)?;
52
53 let ext_len_s = rest.split_off(..2).ok_or(RecordError::Size)?;
54 let extensions_length = u16::from_be_bytes([ext_len_s[0], ext_len_s[1]]);
55
56 let extensions = rest
57 .split_off(..extensions_length as usize)
58 .ok_or(RecordError::Size)?;
59
60 Extensions::parse_server_extensions(prc, extensions)
61 .map_err(|e| RecordError::ServerHello(ServerHelloError::Extensions(e)))?;
62
63 Ok((ServerHello { hdr: hello_hdr }, rest))
64 }
65}