1use crate::error::RecordError;
4
5#[derive(Debug, PartialEq)]
6pub enum WrappedContentType {
7 ChangeCipherSpec,
9 Alert,
11 Handshake,
13 ApplicationData,
15 Unknown(u8),
17}
18
19impl From<u8> for WrappedContentType {
20 fn from(i: u8) -> Self {
21 match i {
22 20 => Self::ChangeCipherSpec,
23 21 => Self::Alert,
24 22 => Self::Handshake,
25 23 => Self::ApplicationData,
26 _ => Self::Unknown(i),
27 }
28 }
29}
30
31#[derive(Debug, PartialEq)]
32pub struct WrappedRecord<'r> {
33 raw_bytes: &'r [u8],
34 msg: WrappedMsgType<'r>,
35}
36
37#[derive(Debug, PartialEq)]
38pub enum WrappedMsgType<'r> {
39 Handshake(HandshakeMsg<'r>),
40 Alert(AlertMsg<'r>),
41}
42
43use crate::AlertMsg;
44use crate::HandshakeMsg;
45
46impl<'r> WrappedRecord<'r> {
47 #[inline]
48 pub fn msg(&self) -> &WrappedMsgType<'r> {
49 &self.msg
50 }
51 #[inline]
52 pub fn parse_client(wrapped_data: &'r [u8]) -> Result<WrappedRecord<'r>, RecordError> {
53 let w_len = wrapped_data.len();
54
55 let rec_type: WrappedContentType = wrapped_data[w_len - 1].into();
56 let raw_bytes = &wrapped_data[0..w_len - 1];
57
58 let msg = match rec_type {
59 WrappedContentType::Handshake => {
60 let msg = HandshakeMsg::client_wrapped_parse(raw_bytes)?;
61 WrappedMsgType::Handshake(msg)
62 }
63 WrappedContentType::Alert => {
64 let (msg, _r_next) = AlertMsg::client_parse(raw_bytes)?;
65 WrappedMsgType::Alert(msg)
66 }
67 WrappedContentType::Unknown(_) => return Err(RecordError::Validity),
68 _ => todo!("Missing {:?}", rec_type),
69 };
70 Ok(WrappedRecord { raw_bytes, msg })
71 }
72}
73
74#[cfg(test)]
75mod test {
76 use super::*;
77 use hex_literal::hex;
78 use rstest::rstest;
79
80 use crate::ClientFinished;
81
82 #[rstest]
83 #[case(
84 &hex!("14000020a0210258e7c4402ab07807a1e61df4cf0ab58f828b26c6adf29654228ac0b66f16"),
85 )]
86 fn wrapped_ok(#[case] in_data: &[u8]) {
87 let r = WrappedRecord::parse_client(in_data);
88 insta::assert_debug_snapshot!(r);
89 }
90
91 #[rstest]
92 #[case(&hex!("7710"))]
93 #[case(&hex!("1410"))]
94 #[case(&hex!("140010"))]
95 #[case(&hex!("14000010"))]
96 fn wrapped_err(#[case] in_data: &[u8]) {
97 assert_eq!(
98 WrappedRecord::parse_client(in_data),
99 Err(RecordError::Validity)
100 );
101 }
102}