1use crate::enums::{AlertDescription, ContentType, HandshakeType, ProtocolVersion};
2use crate::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.0.handshake_type() == 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 HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateNotRequested),
186 )),
187 }
188 }
189
190 pub fn build_key_update_request() -> Self {
191 Self {
192 version: ProtocolVersion::TLSv1_3,
193 payload: MessagePayload::handshake(HandshakeMessagePayload(
194 HandshakePayload::KeyUpdate(KeyUpdateRequest::UpdateRequested),
195 )),
196 }
197 }
198
199 #[cfg(feature = "std")]
200 pub(crate) fn into_owned(self) -> Message<'static> {
201 let Self { version, payload } = self;
202 Message {
203 version,
204 payload: payload.into_owned(),
205 }
206 }
207
208 #[cfg(test)]
209 pub(crate) fn into_wire_bytes(self) -> Vec<u8> {
210 PlainMessage::from(self)
211 .into_unencrypted_opaque()
212 .encode()
213 }
214}
215
216impl TryFrom<PlainMessage> for Message<'static> {
217 type Error = InvalidMessage;
218
219 fn try_from(plain: PlainMessage) -> Result<Self, Self::Error> {
220 Ok(Self {
221 version: plain.version,
222 payload: MessagePayload::new(plain.typ, plain.version, plain.payload.bytes())?
223 .into_owned(),
224 })
225 }
226}
227
228impl<'a> TryFrom<InboundPlainMessage<'a>> for Message<'a> {
233 type Error = InvalidMessage;
234
235 fn try_from(plain: InboundPlainMessage<'a>) -> Result<Self, Self::Error> {
236 Ok(Self {
237 version: plain.version,
238 payload: MessagePayload::new(plain.typ, plain.version, plain.payload)?,
239 })
240 }
241}
242
243#[derive(Debug)]
244pub enum MessageError {
245 TooShortForHeader,
246 TooShortForLength,
247 InvalidEmptyPayload,
248 MessageTooLarge,
249 InvalidContentType,
250 UnknownProtocolVersion,
251}
252
253pub(crate) const HEADER_SIZE: usize = 1 + 2 + 2;
255
256const MAX_PAYLOAD: u16 = 16_384 + 2048;
259
260#[cfg(feature = "std")]
262pub(crate) const MAX_WIRE_SIZE: usize = MAX_PAYLOAD as usize + HEADER_SIZE;