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)]
23/// The server's reply: its random, and the cipher suite and extensions it selected.
24pub struct HandshakeMessageServerHello {
25    pub(crate) version: ProtocolVersion,
26    pub(crate) random: HandshakeRandom,
27
28    pub(crate) cipher_suite: CipherSuiteId,
29    pub(crate) compression_method: CompressionMethodId,
30    pub(crate) extensions: Vec<Extension>,
31}
32
33impl PartialEq for HandshakeMessageServerHello {
34    fn eq(&self, other: &Self) -> bool {
35        self.version == other.version
36            && self.random == other.random
37            && self.compression_method == other.compression_method
38            && self.extensions == other.extensions
39            && self.cipher_suite == other.cipher_suite
40    }
41}
42
43impl fmt::Debug for HandshakeMessageServerHello {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        let s = [
46            format!("version: {:?} random: {:?}", self.version, self.random),
47            format!("cipher_suites: {:?}", self.cipher_suite),
48            format!("compression_method: {:?}", self.compression_method),
49            format!("extensions: {:?}", self.extensions),
50        ];
51        write!(f, "{}", s.join(" "))
52    }
53}
54
55impl HandshakeMessageServerHello {
56    /// The handshake type that identifies this message on the wire.
57    pub fn handshake_type(&self) -> HandshakeType {
58        HandshakeType::ServerHello
59    }
60
61    /// The encoded size of this message in bytes.
62    pub fn size(&self) -> usize {
63        let mut len = 2 + self.random.size();
64
65        // SessionID
66        len += 1;
67
68        len += 2;
69
70        len += 1;
71
72        len += 2;
73        for extension in &self.extensions {
74            len += extension.size();
75        }
76
77        len
78    }
79
80    /// Encodes this message to `writer`.
81    ///
82    /// # Errors
83    ///
84    /// Fails on a write error, or if a field exceeds the length its wire format allows.
85    pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
86        writer.write_u8(self.version.major)?;
87        writer.write_u8(self.version.minor)?;
88        self.random.marshal(writer)?;
89
90        // SessionID
91        writer.write_u8(0x00)?;
92
93        writer.write_u16::<BigEndian>(self.cipher_suite as u16)?;
94
95        writer.write_u8(self.compression_method as u8)?;
96
97        let mut extension_buffer = vec![];
98        {
99            let mut extension_writer = BufWriter::<&mut Vec<u8>>::new(extension_buffer.as_mut());
100            for extension in &self.extensions {
101                extension.marshal(&mut extension_writer)?;
102            }
103        }
104
105        writer.write_u16::<BigEndian>(extension_buffer.len() as u16)?;
106        writer.write_all(&extension_buffer)?;
107
108        Ok(writer.flush()?)
109    }
110
111    /// Decodes one of these messages from `reader`.
112    ///
113    /// # Errors
114    ///
115    /// Fails if `reader` is truncated or its contents are not a valid encoding.
116    pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self> {
117        let major = reader.read_u8()?;
118        let minor = reader.read_u8()?;
119        let random = HandshakeRandom::unmarshal(reader)?;
120
121        // Session ID
122        let session_id_len = reader.read_u8()? as usize;
123        let mut session_id_buffer = vec![0u8; session_id_len];
124        reader.read_exact(&mut session_id_buffer)?;
125
126        let cipher_suite: CipherSuiteId = reader.read_u16::<BigEndian>()?.into();
127
128        let compression_method = reader.read_u8()?.into();
129        let mut extensions = vec![];
130
131        let extension_buffer_len = reader.read_u16::<BigEndian>()? as usize;
132        let mut extension_buffer = vec![0u8; extension_buffer_len];
133        reader.read_exact(&mut extension_buffer)?;
134
135        let mut offset = 0;
136        while offset < extension_buffer_len {
137            if offset + 4 > extension_buffer_len {
138                return Err(Error::ErrBufferTooSmall);
139            }
140
141            let mut extension_reader = BufReader::new(&extension_buffer[offset..]);
142            if let Ok(extension) = Extension::unmarshal(&mut extension_reader) {
143                extensions.push(extension);
144            } else {
145                log::warn!(
146                    "Unsupported Extension Type {} {}",
147                    extension_buffer[offset],
148                    extension_buffer[offset + 1]
149                );
150            }
151
152            let extension_len =
153                u16::from_be_bytes([extension_buffer[offset + 2], extension_buffer[offset + 3]])
154                    as usize;
155            offset += 4 + extension_len;
156        }
157
158        Ok(HandshakeMessageServerHello {
159            version: ProtocolVersion { major, minor },
160            random,
161
162            cipher_suite,
163            compression_method,
164            extensions,
165        })
166    }
167}