webrtc_dtls/handshake/
handshake_message_server_hello.rs

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