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