Skip to main content

rtc_dtls/handshake/
handshake_message_server_hello.rs

1#[cfg(test)]
2mod handshake_message_server_hello_test;
3
4use super::handshake_random::*;
5use super::*;
6use crate::cipher_suite::*;
7use crate::compression_methods::*;
8use crate::extension::*;
9use crate::record_layer::record_layer_header::*;
10
11use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
12use std::fmt;
13use std::io::{BufReader, BufWriter};
14
15/*
16The server will send this message in response to a ClientHello
17message when it was able to find an acceptable set of algorithms.
18If it cannot find such a match, it will respond with a handshake
19failure alert.
20https://tools.ietf.org/html/rfc5246#section-7.4.1.3
21*/
22#[derive(Clone)]
23pub struct HandshakeMessageServerHello {
24    pub(crate) version: ProtocolVersion,
25    pub(crate) random: HandshakeRandom,
26
27    pub(crate) cipher_suite: CipherSuiteId,
28    pub(crate) compression_method: CompressionMethodId,
29    pub(crate) extensions: Vec<Extension>,
30}
31
32impl PartialEq for HandshakeMessageServerHello {
33    fn eq(&self, other: &Self) -> bool {
34        self.version == other.version
35            && self.random == other.random
36            && self.compression_method == other.compression_method
37            && self.extensions == other.extensions
38            && self.cipher_suite == other.cipher_suite
39    }
40}
41
42impl fmt::Debug for HandshakeMessageServerHello {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        let s = [
45            format!("version: {:?} random: {:?}", self.version, self.random),
46            format!("cipher_suites: {:?}", self.cipher_suite),
47            format!("compression_method: {:?}", self.compression_method),
48            format!("extensions: {:?}", self.extensions),
49        ];
50        write!(f, "{}", s.join(" "))
51    }
52}
53
54impl HandshakeMessageServerHello {
55    pub fn handshake_type(&self) -> HandshakeType {
56        HandshakeType::ServerHello
57    }
58
59    pub fn size(&self) -> usize {
60        let mut len = 2 + self.random.size();
61
62        // SessionID
63        len += 1;
64
65        len += 2;
66
67        len += 1;
68
69        len += 2;
70        for extension in &self.extensions {
71            len += extension.size();
72        }
73
74        len
75    }
76
77    pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
78        writer.write_u8(self.version.major)?;
79        writer.write_u8(self.version.minor)?;
80        self.random.marshal(writer)?;
81
82        // SessionID
83        writer.write_u8(0x00)?;
84
85        writer.write_u16::<BigEndian>(self.cipher_suite as u16)?;
86
87        writer.write_u8(self.compression_method as u8)?;
88
89        let mut extension_buffer = vec![];
90        {
91            let mut extension_writer = BufWriter::<&mut Vec<u8>>::new(extension_buffer.as_mut());
92            for extension in &self.extensions {
93                extension.marshal(&mut extension_writer)?;
94            }
95        }
96
97        writer.write_u16::<BigEndian>(extension_buffer.len() as u16)?;
98        writer.write_all(&extension_buffer)?;
99
100        Ok(writer.flush()?)
101    }
102
103    pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self> {
104        let major = reader.read_u8()?;
105        let minor = reader.read_u8()?;
106        let random = HandshakeRandom::unmarshal(reader)?;
107
108        // Session ID
109        let session_id_len = reader.read_u8()? as usize;
110        let mut session_id_buffer = vec![0u8; session_id_len];
111        reader.read_exact(&mut session_id_buffer)?;
112
113        let cipher_suite: CipherSuiteId = reader.read_u16::<BigEndian>()?.into();
114
115        let compression_method = reader.read_u8()?.into();
116        let mut extensions = vec![];
117
118        let extension_buffer_len = reader.read_u16::<BigEndian>()? as usize;
119        let mut extension_buffer = vec![0u8; extension_buffer_len];
120        reader.read_exact(&mut extension_buffer)?;
121
122        let mut offset = 0;
123        while offset < extension_buffer_len {
124            let mut extension_reader = BufReader::new(&extension_buffer[offset..]);
125            if let Ok(extension) = Extension::unmarshal(&mut extension_reader) {
126                extensions.push(extension);
127            } else {
128                log::warn!(
129                    "Unsupported Extension Type {} {}",
130                    extension_buffer[offset],
131                    extension_buffer[offset + 1]
132                );
133            }
134
135            let extension_len =
136                u16::from_be_bytes([extension_buffer[offset + 2], extension_buffer[offset + 3]])
137                    as usize;
138            offset += 4 + extension_len;
139        }
140
141        Ok(HandshakeMessageServerHello {
142            version: ProtocolVersion { major, minor },
143            random,
144
145            cipher_suite,
146            compression_method,
147            extensions,
148        })
149    }
150}