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 {
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 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 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 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}