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