ytls_record/record/handshake/
server_hello.rs

1//! ServerHello
2
3use 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}