rtc_dtls/handshake/
handshake_message_client_hello.rs1#[cfg(test)]
2mod handshake_message_client_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#[derive(Clone)]
23pub struct HandshakeMessageClientHello {
25 pub(crate) version: ProtocolVersion,
26 pub(crate) random: HandshakeRandom,
27 pub(crate) cookie: Vec<u8>,
28
29 pub(crate) cipher_suites: Vec<CipherSuiteId>,
30 pub(crate) compression_methods: CompressionMethods,
31 pub(crate) extensions: Vec<Extension>,
32}
33
34impl PartialEq for HandshakeMessageClientHello {
35 fn eq(&self, other: &Self) -> bool {
36 if !(self.version == other.version
37 && self.random == other.random
38 && self.cookie == other.cookie
39 && self.compression_methods == other.compression_methods
40 && self.extensions == other.extensions
41 && self.cipher_suites.len() == other.cipher_suites.len())
42 {
43 return false;
44 }
45
46 for i in 0..self.cipher_suites.len() {
47 if self.cipher_suites[i] != other.cipher_suites[i] {
48 return false;
49 }
50 }
51
52 true
53 }
54}
55
56impl fmt::Debug for HandshakeMessageClientHello {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 let mut cipher_suites_str = String::new();
59 for cipher_suite in &self.cipher_suites {
60 cipher_suites_str += &cipher_suite.to_string();
61 cipher_suites_str += " ";
62 }
63 let s = [
64 format!("version: {:?} random: {:?}", self.version, self.random),
65 format!("cookie: {:?}", self.cookie),
66 format!("cipher_suites: {cipher_suites_str:?}"),
67 format!("compression_methods: {:?}", self.compression_methods),
68 format!("extensions: {:?}", self.extensions),
69 ];
70 write!(f, "{}", s.join(" "))
71 }
72}
73
74const HANDSHAKE_MESSAGE_CLIENT_HELLO_VARIABLE_WIDTH_START: usize = 34;
75
76impl HandshakeMessageClientHello {
77 pub fn handshake_type(&self) -> HandshakeType {
79 HandshakeType::ClientHello
80 }
81
82 pub fn size(&self) -> usize {
84 let mut len = 0;
85
86 len += 2; len += self.random.size();
88
89 len += 1;
91
92 len += 1 + self.cookie.len();
93
94 len += 2 + 2 * self.cipher_suites.len();
95
96 len += self.compression_methods.size();
97
98 len += 2;
99 for extension in &self.extensions {
100 len += extension.size();
101 }
102
103 len
104 }
105
106 pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
112 if self.cookie.len() > 255 {
113 return Err(Error::ErrCookieTooLong);
114 }
115
116 writer.write_u8(self.version.major)?;
117 writer.write_u8(self.version.minor)?;
118 self.random.marshal(writer)?;
119
120 writer.write_u8(0x00)?;
122
123 writer.write_u8(self.cookie.len() as u8)?;
124 writer.write_all(&self.cookie)?;
125
126 writer.write_u16::<BigEndian>(2 * self.cipher_suites.len() as u16)?;
127 for cipher_suite in &self.cipher_suites {
128 writer.write_u16::<BigEndian>(*cipher_suite as u16)?;
129 }
130
131 self.compression_methods.marshal(writer)?;
132
133 let mut extension_buffer = vec![];
134 {
135 let mut extension_writer = BufWriter::<&mut Vec<u8>>::new(extension_buffer.as_mut());
136 for extension in &self.extensions {
137 extension.marshal(&mut extension_writer)?;
138 }
139 }
140
141 writer.write_u16::<BigEndian>(extension_buffer.len() as u16)?;
142 writer.write_all(&extension_buffer)?;
143
144 Ok(writer.flush()?)
145 }
146
147 pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self> {
153 let major = reader.read_u8()?;
154 let minor = reader.read_u8()?;
155 let random = HandshakeRandom::unmarshal(reader)?;
156
157 reader.read_u8()?;
159
160 let cookie_len = reader.read_u8()? as usize;
161 let mut cookie = vec![0; cookie_len];
162 reader.read_exact(&mut cookie)?;
163
164 let cipher_suites_len = reader.read_u16::<BigEndian>()? as usize / 2;
165 let mut cipher_suites = vec![];
166 for _ in 0..cipher_suites_len {
167 let id: CipherSuiteId = reader.read_u16::<BigEndian>()?.into();
168 cipher_suites.push(id);
170 }
171
172 let compression_methods = CompressionMethods::unmarshal(reader)?;
173 let mut extensions = vec![];
174
175 let extension_buffer_len = reader.read_u16::<BigEndian>()? as usize;
176 let mut extension_buffer = vec![0u8; extension_buffer_len];
177 reader.read_exact(&mut extension_buffer)?;
178
179 let mut offset = 0;
180 while offset < extension_buffer_len {
181 if offset + 4 > extension_buffer_len {
182 return Err(Error::ErrBufferTooSmall);
183 }
184
185 let mut extension_reader = BufReader::new(&extension_buffer[offset..]);
186 if let Ok(extension) = Extension::unmarshal(&mut extension_reader) {
187 extensions.push(extension);
188 } else {
189 log::warn!(
190 "Unsupported Extension Type {} {}",
191 extension_buffer[offset],
192 extension_buffer[offset + 1]
193 );
194 }
195
196 let extension_len =
197 u16::from_be_bytes([extension_buffer[offset + 2], extension_buffer[offset + 3]])
198 as usize;
199 offset += 4 + extension_len;
200 }
201
202 Ok(HandshakeMessageClientHello {
203 version: ProtocolVersion { major, minor },
204 random,
205 cookie,
206
207 cipher_suites,
208 compression_methods,
209 extensions,
210 })
211 }
212}