1use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
2use crate::error::{Error, InvalidMessage};
3use crate::msgs::alert::AlertMessagePayload;
4use crate::msgs::base::Payload;
5use crate::msgs::ccs::ChangeCipherSpecPayload;
6use crate::msgs::codec::{Codec, Reader};
7use crate::msgs::enums::{AlertLevel, KeyUpdateRequest};
8use crate::msgs::handshake::{HandshakeMessagePayload, HandshakePayload};
9
10mod inbound;
11pub use inbound::{BorrowedPayload, InboundOpaqueMessage, InboundPlainMessage};
12
13mod outbound;
14use alloc::vec::Vec;
15
16pub(crate) use outbound::read_opaque_message_header;
17pub use outbound::{OutboundChunks, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload};
18
19#[derive(Debug)]
20pub enum MessagePayload<'a> {
21 Alert(AlertMessagePayload),
22 Handshake {
24 parsed: HandshakeMessagePayload<'a>,
25 encoded: Payload<'a>,
26 },
27 HandshakeFlight(Payload<'a>),
29 ChangeCipherSpec(ChangeCipherSpecPayload),
30 ApplicationData(Payload<'a>),
31}
32
33impl<'a> MessagePayload<'a> {
34 pub fn encode(&self, bytes: &mut Vec<u8>) {
35 match self {
36 Self::Alert(x) => x.encode(bytes),
37 Self::Handshake { encoded, .. } => bytes.extend(encoded.bytes()),
38 Self::HandshakeFlight(x) => bytes.extend(x.bytes()),
39 Self::ChangeCipherSpec(x) => x.encode(bytes),
40 Self::ApplicationData(x) => x.encode(bytes),
41 }
42 }
43
44 pub fn handshake(parsed: HandshakeMessagePayload<'a>) -> Self {
45 Self::Handshake {
46 encoded: Payload::new(parsed.get_encoding()),
47 parsed,
48 }
49 }
50
51 pub fn new(
52 typ: ContentType,
53 vers: ProtocolVersion,
54 payload: &'a [u8],
55 ) -> Result<Self, InvalidMessage> {
56 let mut r = Reader::init(payload);
57 match typ {
58 ContentType::ApplicationData => Ok(Self::ApplicationData(Payload::Borrowed(payload))),
59 ContentType::Alert => AlertMessagePayload::read(&mut r).map(MessagePayload::Alert),
60 ContentType::Handshake => {
61 HandshakeMessagePayload::read_version(&mut r, vers).map(|parsed| Self::Handshake {
62 parsed,
63 encoded: Payload::Borrowed(payload),
64 })
65 }
66 ContentType::ChangeCipherSpec => {
67 ChangeCipherSpecPayload::read(&mut r).map(MessagePayload::ChangeCipherSpec)
68 }
69 _ => Err(InvalidMessage::InvalidContentType),
70 }
71 }
72
73 pub fn content_type(&self) -> ContentType {
74 match self {
75 Self::Alert(_) => ContentType::Alert,
76 Self::Handshake { .. } | Self::HandshakeFlight(_) => ContentType::Handshake,
77 Self::ChangeCipherSpec(_) => ContentType::ChangeCipherSpec,
78 Self::ApplicationData(_) => ContentType::ApplicationData,
79 }
80 }
81
82 pub(crate) fn into_owned(self) -> MessagePayload<'static> {
83 use MessagePayload::*;
84 match self {
85 Alert(x) => Alert(x),
86 Handshake { parsed, encoded } => Handshake {
87 parsed: parsed.into_owned(),
88 encoded: encoded.into_owned(),
89 },
90 HandshakeFlight(x) => HandshakeFlight(x.into_owned()),
91 ChangeCipherSpec(x) => ChangeCipherSpec(x),
92 ApplicationData(x) => ApplicationData(x.into_owned()),
93 }
94 }
95}
96
97impl From<Message<'_>> for PlainMessage {
98 fn from(msg: Message<'_>) -> Self {
99 let typ = msg.payload.content_type();
100 let payload = match msg.payload {
101 MessagePayload::ApplicationData(payload) => payload.into_owned(),
102 _ => {
103 let mut buf = Vec::new();
104 msg.payload.encode(&mut buf);
105 Payload::Owned(buf)
106 }
107 };
108
109 Self {
110 typ,
111 version: msg.version,
112 payload,
113 }
114 }
115}
116
117#[derive(Clone, Debug)]
122pub struct PlainMessage {
123 pub typ: ContentType,
124 pub version: ProtocolVersion,
125 pub payload: Payload<'static>,
126}
127
128impl PlainMessage {
129 pub fn into_unencrypted_opaque(self) -> OutboundOpaqueMessage {
130 OutboundOpaqueMessage {
131 version: self.version,
132 typ: self.typ,
133 payload: PrefixedPayload::from(self.payload.bytes()),
134 }
135 }
136
137 pub fn borrow_inbound(&self) -> InboundPlainMessage<'_> {
138 InboundPlainMessage {
139 version: self.version,
140 typ: self.typ,
141 payload: self.payload.bytes(),
142 }
143 }
144
145 pub fn borrow_outbound(&self) -> OutboundPlainMessage<'_> {
146 OutboundPlainMessage {
147 version: self.version,
148 typ: self.typ,
149 payload: self.payload.bytes().into(),
150 }
151 }
152}
153
154#[derive(Debug)]
156pub struct Message<'a> {
157 pub version: ProtocolVersion,
158 pub payload: MessagePayload<'a>,
159}
160
161impl Message<'_> {
162 pub fn is_handshake_type(&self, hstyp: HandshakeType) -> bool {
163 if let MessagePayload::Handshake { parsed, .. } = &self.payload {
165 parsed.typ == hstyp
166 } else {
167 false
168 }
169 }
170
171 pub fn build_alert(level: AlertLevel, desc: AlertDescription) -> Self {
172 Self {
173 version: ProtocolVersion::TLSv1_2,
174 payload: MessagePayload::Alert(AlertMessagePayload {
175 level,
176 description: desc,
177 }),
178 }
179 }
180
181 pub fn build_key_update_notify() -> Self {
182 Self {
183 version: ProtocolVersion::TLSv1_3,
184 payload: MessagePayload::handshake(HandshakeMessagePayload {
185 typ: HandshakeType::KeyUpdate,
186 payload: HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateNotRequested),
187 }),
188 }
189 }
190
191 pub fn build_key_update_request() -> Self {
192 Self {
193 version: ProtocolVersion::TLSv1_3,
194 payload: MessagePayload::handshake(HandshakeMessagePayload {
195 typ: HandshakeType::KeyUpdate,
196 payload: HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateRequested),
197 }),
198 }
199 }
200
201 #[cfg(feature = "std")]
202 pub(crate) fn into_owned(self) -> Message<'static> {
203 let Self { version, payload } = self;
204 Message {
205 version,
206 payload: payload.into_owned(),
207 }
208 }
209}
210
211impl TryFrom<PlainMessage> for Message<'static> {
212 type Error = Error;
213
214 fn try_from(plain: PlainMessage) -> Result<Self, Self::Error> {
215 Ok(Self {
216 version: plain.version,
217 payload: MessagePayload::new(plain.typ, plain.version, plain.payload.bytes())?
218 .into_owned(),
219 })
220 }
221}
222
223impl<'a> TryFrom<InboundPlainMessage<'a>> for Message<'a> {
228 type Error = Error;
229
230 fn try_from(plain: InboundPlainMessage<'a>) -> Result<Self, Self::Error> {
231 Ok(Self {
232 version: plain.version,
233 payload: MessagePayload::new(plain.typ, plain.version, plain.payload)?,
234 })
235 }
236}
237
238#[derive(Debug)]
239pub enum MessageError {
240 TooShortForHeader,
241 TooShortForLength,
242 InvalidEmptyPayload,
243 MessageTooLarge,
244 InvalidContentType,
245 UnknownProtocolVersion,
246}
247
248pub(crate) const HEADER_SIZE: usize = 1 + 2 + 2;
250
251const MAX_PAYLOAD: u16 = 16_384 + 2048;
254
255#[cfg(feature = "std")]
257pub(crate) const MAX_WIRE_SIZE: usize = MAX_PAYLOAD as usize + HEADER_SIZE;