webrtc_dtls/
content.rs

1use std::io::{Read, Write};
2
3use super::alert::*;
4use super::application_data::*;
5use super::change_cipher_spec::*;
6use super::handshake::*;
7use crate::error::*;
8
9/// ## Specifications
10///
11/// * [RFC 4346 §6.2.1]
12///
13/// [RFC 4346 §6.2.1]: https://tools.ietf.org/html/rfc4346#section-6.2.1
14#[derive(Default, Copy, Clone, PartialEq, Eq, Debug)]
15pub enum ContentType {
16    ChangeCipherSpec = 20,
17    Alert = 21,
18    Handshake = 22,
19    ApplicationData = 23,
20    #[default]
21    Invalid,
22}
23
24impl From<u8> for ContentType {
25    fn from(val: u8) -> Self {
26        match val {
27            20 => ContentType::ChangeCipherSpec,
28            21 => ContentType::Alert,
29            22 => ContentType::Handshake,
30            23 => ContentType::ApplicationData,
31            _ => ContentType::Invalid,
32        }
33    }
34}
35
36#[derive(PartialEq, Debug, Clone)]
37pub enum Content {
38    ChangeCipherSpec(ChangeCipherSpec),
39    Alert(Alert),
40    Handshake(Handshake),
41    ApplicationData(ApplicationData),
42}
43
44impl Content {
45    pub fn content_type(&self) -> ContentType {
46        match self {
47            Content::ChangeCipherSpec(c) => c.content_type(),
48            Content::Alert(c) => c.content_type(),
49            Content::Handshake(c) => c.content_type(),
50            Content::ApplicationData(c) => c.content_type(),
51        }
52    }
53
54    pub fn size(&self) -> usize {
55        match self {
56            Content::ChangeCipherSpec(c) => c.size(),
57            Content::Alert(c) => c.size(),
58            Content::Handshake(c) => c.size(),
59            Content::ApplicationData(c) => c.size(),
60        }
61    }
62
63    pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
64        match self {
65            Content::ChangeCipherSpec(c) => c.marshal(writer),
66            Content::Alert(c) => c.marshal(writer),
67            Content::Handshake(c) => c.marshal(writer),
68            Content::ApplicationData(c) => c.marshal(writer),
69        }
70    }
71
72    pub fn unmarshal<R: Read>(content_type: ContentType, reader: &mut R) -> Result<Self> {
73        match content_type {
74            ContentType::ChangeCipherSpec => Ok(Content::ChangeCipherSpec(
75                ChangeCipherSpec::unmarshal(reader)?,
76            )),
77            ContentType::Alert => Ok(Content::Alert(Alert::unmarshal(reader)?)),
78            ContentType::Handshake => Ok(Content::Handshake(Handshake::unmarshal(reader)?)),
79            ContentType::ApplicationData => Ok(Content::ApplicationData(
80                ApplicationData::unmarshal(reader)?,
81            )),
82            _ => Err(Error::ErrInvalidContentType),
83        }
84    }
85}