webrtc_dtls/handshake/
handshake_random.rs

1use std::io::{self, Read, Write};
2use std::time::{Duration, SystemTime};
3
4use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
5use rand::Rng;
6
7pub const RANDOM_BYTES_LENGTH: usize = 28;
8pub const HANDSHAKE_RANDOM_LENGTH: usize = RANDOM_BYTES_LENGTH + 4;
9
10/// ## Specifications
11///
12/// * [RFC 4346 §7.4.1.2]
13///
14/// [RFC 4346 §7.4.1.2]: https://tools.ietf.org/html/rfc4346#section-7.4.1.2
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct HandshakeRandom {
17    pub gmt_unix_time: SystemTime,
18    pub random_bytes: [u8; RANDOM_BYTES_LENGTH],
19}
20
21impl Default for HandshakeRandom {
22    fn default() -> Self {
23        HandshakeRandom {
24            gmt_unix_time: SystemTime::UNIX_EPOCH,
25            random_bytes: [0u8; RANDOM_BYTES_LENGTH],
26        }
27    }
28}
29
30impl HandshakeRandom {
31    pub fn size(&self) -> usize {
32        4 + RANDOM_BYTES_LENGTH
33    }
34
35    pub fn marshal<W: Write>(&self, writer: &mut W) -> io::Result<()> {
36        let secs = match self.gmt_unix_time.duration_since(SystemTime::UNIX_EPOCH) {
37            Ok(d) => d.as_secs() as u32,
38            Err(_) => 0,
39        };
40        writer.write_u32::<BigEndian>(secs)?;
41        writer.write_all(&self.random_bytes)?;
42
43        writer.flush()
44    }
45
46    pub fn unmarshal<R: Read>(reader: &mut R) -> io::Result<Self> {
47        let secs = reader.read_u32::<BigEndian>()?;
48        let gmt_unix_time = if let Some(unix_time) =
49            SystemTime::UNIX_EPOCH.checked_add(Duration::new(secs as u64, 0))
50        {
51            unix_time
52        } else {
53            SystemTime::UNIX_EPOCH
54        };
55
56        let mut random_bytes = [0u8; RANDOM_BYTES_LENGTH];
57        reader.read_exact(&mut random_bytes)?;
58
59        Ok(HandshakeRandom {
60            gmt_unix_time,
61            random_bytes,
62        })
63    }
64
65    // populate fills the HandshakeRandom with random values
66    // may be called multiple times
67    pub fn populate(&mut self) {
68        self.gmt_unix_time = SystemTime::now();
69        rand::thread_rng().fill(&mut self.random_bytes);
70    }
71}