rtc_dtls/handshake/
handshake_message_server_hello.rs1#[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#[derive(Clone)]
23pub 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 {
58 HandshakeType::ServerHello
59 }
60
61 pub fn size(&self) -> usize {
63 let mut len = 2 + self.random.size();
64
65 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 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 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 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 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}