rtc_dtls/record_layer/
record_layer_header.rs

1use crate::content::*;
2
3use shared::error::*;
4
5use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6use std::io::{Read, Write};
7
8pub const RECORD_LAYER_HEADER_SIZE: usize = 13;
9pub const MAX_SEQUENCE_NUMBER: u64 = 0x0000FFFFFFFFFFFF;
10
11pub const DTLS1_2MAJOR: u8 = 0xfe;
12pub const DTLS1_2MINOR: u8 = 0xfd;
13
14pub const DTLS1_0MAJOR: u8 = 0xfe;
15pub const DTLS1_0MINOR: u8 = 0xff;
16
17// VERSION_DTLS12 is the DTLS version in the same style as
18// VersionTLSXX from crypto/tls
19pub const VERSION_DTLS12: u16 = 0xfefd;
20
21pub const PROTOCOL_VERSION1_0: ProtocolVersion = ProtocolVersion {
22    major: DTLS1_0MAJOR,
23    minor: DTLS1_0MINOR,
24};
25pub const PROTOCOL_VERSION1_2: ProtocolVersion = ProtocolVersion {
26    major: DTLS1_2MAJOR,
27    minor: DTLS1_2MINOR,
28};
29
30/// ## Specifications
31///
32/// * [RFC 4346 §6.2.1]
33///
34/// [RFC 4346 §6.2.1]: https://tools.ietf.org/html/rfc4346#section-6.2.1
35#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
36pub struct ProtocolVersion {
37    pub major: u8,
38    pub minor: u8,
39}
40
41#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
42pub struct RecordLayerHeader {
43    pub content_type: ContentType,
44    pub protocol_version: ProtocolVersion,
45    pub epoch: u16,
46    pub sequence_number: u64, // uint48 in spec
47    pub content_len: u16,
48}
49
50impl RecordLayerHeader {
51    pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
52        if self.sequence_number > MAX_SEQUENCE_NUMBER {
53            return Err(Error::ErrSequenceNumberOverflow);
54        }
55
56        writer.write_u8(self.content_type as u8)?;
57        writer.write_u8(self.protocol_version.major)?;
58        writer.write_u8(self.protocol_version.minor)?;
59        writer.write_u16::<BigEndian>(self.epoch)?;
60
61        let be: [u8; 8] = self.sequence_number.to_be_bytes();
62        writer.write_all(&be[2..])?; // uint48 in spec
63
64        writer.write_u16::<BigEndian>(self.content_len)?;
65
66        Ok(writer.flush()?)
67    }
68
69    pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self> {
70        let content_type = reader.read_u8()?.into();
71        let major = reader.read_u8()?;
72        let minor = reader.read_u8()?;
73        let epoch = reader.read_u16::<BigEndian>()?;
74
75        // SequenceNumber is stored as uint48, make into uint64
76        let mut be: [u8; 8] = [0u8; 8];
77        reader.read_exact(&mut be[2..])?;
78        let sequence_number = u64::from_be_bytes(be);
79
80        let protocol_version = ProtocolVersion { major, minor };
81        if protocol_version != PROTOCOL_VERSION1_0 && protocol_version != PROTOCOL_VERSION1_2 {
82            return Err(Error::ErrUnsupportedProtocolVersion);
83        }
84        let content_len = reader.read_u16::<BigEndian>()?;
85
86        Ok(RecordLayerHeader {
87            content_type,
88            protocol_version,
89            epoch,
90            sequence_number,
91            content_len,
92        })
93    }
94}