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