1use super::message::{Message, Payload};
2use super::version::Version;
3use crate::error::RlsResult;
4use crate::{Alert, CipherSuite, RlsError, WriteExt, ALPN};
5
6#[derive(Debug, Copy, Clone)]
7pub enum RecordType {
8 CipherSpec = 0x14,
9 Alert = 0x15,
10 HandShake = 0x16,
11 ApplicationData = 0x17,
12
13}
14
15impl RecordType {
16 pub fn from_byte(byte: u8) -> Option<RecordType> {
17 match byte {
18 0x14 => Some(RecordType::CipherSpec),
19 0x15 => Some(RecordType::Alert),
20 0x16 => Some(RecordType::HandShake),
21 0x17 => Some(RecordType::ApplicationData),
22 _ => None
23 }
24 }
25
26 pub fn as_u8(&self) -> u8 {
27 *self as u8
28 }
29}
30
31
32#[derive(Debug)]
33pub struct RecordLayer<'a> {
34 pub context_type: RecordType,
35 pub version: Version,
36 pub len: u16,
37 pub messages: Vec<Message<'a>>,
38}
39
40impl<'a> RecordLayer<'a> {
41 pub fn new(rt: RecordType) -> RecordLayer<'a> {
42 RecordLayer {
43 context_type: rt,
44 version: Version::TLS_1_2,
45 len: 0,
46 messages: vec![],
47 }
48 }
49
50 pub fn handshake() -> RecordLayer<'a> {
51 RecordLayer::new(RecordType::HandShake)
52 }
53
54 pub fn from_bytes(bytes: &'a mut [u8], payload: bool, suite: Option<&CipherSuite>) -> RlsResult<RecordLayer<'a>> {
55 if bytes.len() < 5 { return Err(RlsError::MessageTooShort); }
56 let (head, messages) = bytes.split_at_mut(5);
57 let mut res = RecordLayer::new(RecordType::from_byte(head[0]).ok_or("LayerType Unknown")?);
58 res.version = Version::new(u16::from_be_bytes([head[1], head[2]]));
59 res.len = u16::from_be_bytes([head[3], head[4]]);
60 if messages.len() < res.len as usize { return Err("record body not enough".into()); }
61 let (mut messages, _) = messages.split_at_mut(res.len as usize);
62 let mut index = 0;
63 let total_len = messages.len();
64
65 while index < total_len {
66 match res.context_type {
67 RecordType::HandShake => {
68 if !payload {
69 let msg_len = u32::from_be_bytes([0, messages[1], messages[2], messages[3]]) as usize;
70 let (message, reset) = messages.split_at_mut(msg_len + 4);
71 messages = reset;
72 index = index + 4 + msg_len;
73 res.messages.push(Message::from_bytes(message, payload, suite)?)
74 } else {
75 res.messages.push(Message::Payload(Payload::from_slice(messages)));
76 break;
77 }
78 }
79 RecordType::ApplicationData => {
80 res.messages.push(Message::Payload(Payload::from_slice(messages)));
81 break;
82 }
83 RecordType::Alert => if payload {
84 res.messages.push(Message::Payload(Payload::from_slice(messages)));
85 break;
86 } else {
87 res.messages.push(Message::Alert(Alert::from_bytes(messages)?));
88 break;
89 }
90 RecordType::CipherSpec => {
91 index += 1;
92 res.messages.push(Message::CipherSpec)
93 }
94 };
95 }
96
97 Ok(res)
98 }
99
100 pub fn write_to<W: WriteExt>(self, writer: &mut W, key_size: u8) -> RlsResult<usize> {
101 let offset = writer.offset().end;
102 let sni = self.messages[0].client().map(|x| x.server_name().unwrap_or("")).unwrap_or("").to_string();
103 let h2 = self.messages[0].client().map(|x| x.alps().map(|x| x.values().iter().any(|x| x == &ALPN::Http20)).unwrap_or(false)).unwrap_or(false);
104 writer.write_u8(self.context_type as u8);
105 writer.write_u16(self.version.into_inner());
106 let len = self.messages.iter().map(|x| x.len(key_size)).sum::<usize>();
107 writer.write_u16(len as u16);
108 for message in self.messages {
109 message.write_to(writer, key_size);
110 }
111 writer.flush(offset, sni, h2)
112 }
113}
114