webrtc_dtls/handshake/
handshake_message_server_hello.rs1#[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#[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 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 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 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}