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