openmls/framing/
message_in.rs1use super::*;
18use crate::{
19 key_packages::KeyPackageIn, messages::group_info::VerifiableGroupInfo,
20 versions::ProtocolVersion,
21};
22
23#[derive(PartialEq, Debug, Clone, TlsSize)]
38#[cfg_attr(feature = "test-utils", derive(TlsSerialize))]
39pub struct MlsMessageIn {
40 pub(crate) version: ProtocolVersion,
41 pub(crate) body: MlsMessageBodyIn,
42}
43
44#[derive(Debug, PartialEq, Clone, TlsDeserialize, TlsDeserializeBytes, TlsSize)]
72#[cfg_attr(feature = "test-utils", derive(TlsSerialize))]
73#[repr(u16)]
74pub enum MlsMessageBodyIn {
75 #[tls_codec(discriminant = 1)]
77 PublicMessage(PublicMessageIn),
78
79 #[tls_codec(discriminant = 2)]
81 PrivateMessage(PrivateMessageIn),
82
83 #[tls_codec(discriminant = 3)]
85 Welcome(Welcome),
86
87 #[tls_codec(discriminant = 4)]
89 GroupInfo(VerifiableGroupInfo),
90
91 #[tls_codec(discriminant = 5)]
93 KeyPackage(KeyPackageIn),
94}
95
96impl MlsMessageIn {
97 pub fn wire_format(&self) -> WireFormat {
99 match self.body {
100 MlsMessageBodyIn::PrivateMessage(_) => WireFormat::PrivateMessage,
101 MlsMessageBodyIn::PublicMessage(_) => WireFormat::PublicMessage,
102 MlsMessageBodyIn::Welcome(_) => WireFormat::Welcome,
103 MlsMessageBodyIn::GroupInfo(_) => WireFormat::GroupInfo,
104 MlsMessageBodyIn::KeyPackage(_) => WireFormat::KeyPackage,
105 }
106 }
107
108 pub fn extract(self) -> MlsMessageBodyIn {
111 self.body
112 }
113
114 pub fn try_into_protocol_message(self) -> Result<ProtocolMessage, ProtocolMessageError> {
116 self.try_into()
117 }
118
119 #[cfg(any(test, feature = "test-utils"))]
120 pub fn into_keypackage(self) -> Option<crate::key_packages::KeyPackage> {
121 match self.body {
122 MlsMessageBodyIn::KeyPackage(key_package) => {
123 debug_assert!(key_package.version_is_supported(self.version));
124 Some(key_package.into())
125 }
126 _ => None,
127 }
128 }
129
130 #[cfg(test)]
131 pub(crate) fn into_plaintext(self) -> Option<PublicMessage> {
132 match self.body {
133 MlsMessageBodyIn::PublicMessage(m) => Some(m.into()),
134 _ => None,
135 }
136 }
137
138 #[cfg(test)]
139 pub(crate) fn into_ciphertext(self) -> Option<PrivateMessageIn> {
140 match self.body {
141 MlsMessageBodyIn::PrivateMessage(m) => Some(m),
142 _ => None,
143 }
144 }
145
146 #[cfg(any(feature = "test-utils", test))]
150 pub fn into_welcome(self) -> Option<Welcome> {
151 match self.body {
152 MlsMessageBodyIn::Welcome(w) => Some(w),
153 _ => None,
154 }
155 }
156
157 #[cfg(any(feature = "test-utils", test))]
158 pub fn into_protocol_message(self) -> Option<ProtocolMessage> {
159 match self.body {
160 MlsMessageBodyIn::PublicMessage(m) => Some(m.into()),
161 MlsMessageBodyIn::PrivateMessage(m) => Some(m.into()),
162 _ => None,
163 }
164 }
165
166 #[cfg(any(feature = "test-utils", test))]
167 pub fn into_verifiable_group_info(self) -> Option<VerifiableGroupInfo> {
168 match self.body {
169 MlsMessageBodyIn::GroupInfo(group_info) => Some(group_info),
170 _ => None,
171 }
172 }
173}
174
175#[derive(Debug, Clone)]
179pub enum ProtocolMessage {
180 PrivateMessage(PrivateMessageIn),
182 PublicMessage(Box<PublicMessageIn>),
184}
185
186impl ProtocolMessage {
187 pub fn wire_format(&self) -> WireFormat {
189 match self {
190 ProtocolMessage::PrivateMessage(_) => WireFormat::PrivateMessage,
191 ProtocolMessage::PublicMessage(_) => WireFormat::PublicMessage,
192 }
193 }
194
195 pub fn group_id(&self) -> &GroupId {
197 match self {
198 ProtocolMessage::PrivateMessage(ref m) => m.group_id(),
199 ProtocolMessage::PublicMessage(ref m) => m.group_id(),
200 }
201 }
202
203 pub fn epoch(&self) -> GroupEpoch {
205 match self {
206 ProtocolMessage::PrivateMessage(ref m) => m.epoch(),
207 ProtocolMessage::PublicMessage(ref m) => m.epoch(),
208 }
209 }
210
211 pub fn content_type(&self) -> ContentType {
213 match self {
214 ProtocolMessage::PrivateMessage(ref m) => m.content_type(),
215 ProtocolMessage::PublicMessage(ref m) => m.content_type(),
216 }
217 }
218
219 pub fn is_external(&self) -> bool {
221 match &self {
222 ProtocolMessage::PublicMessage(p) => {
223 matches!(
224 p.sender(),
225 Sender::NewMemberProposal | Sender::NewMemberCommit | Sender::External(_)
226 )
227 }
228 ProtocolMessage::PrivateMessage(_) => false,
230 }
231 }
232
233 pub fn is_handshake_message(&self) -> bool {
235 self.content_type().is_handshake_message()
236 }
237}
238
239impl From<PrivateMessageIn> for ProtocolMessage {
240 fn from(private_message: PrivateMessageIn) -> Self {
241 ProtocolMessage::PrivateMessage(private_message)
242 }
243}
244
245impl From<PublicMessageIn> for ProtocolMessage {
246 fn from(public_message: PublicMessageIn) -> Self {
247 ProtocolMessage::PublicMessage(Box::new(public_message))
248 }
249}
250
251impl TryFrom<MlsMessageIn> for ProtocolMessage {
252 type Error = ProtocolMessageError;
253
254 fn try_from(msg: MlsMessageIn) -> Result<Self, Self::Error> {
255 match msg.body {
256 MlsMessageBodyIn::PublicMessage(m) => Ok(m.into()),
257 MlsMessageBodyIn::PrivateMessage(m) => Ok(ProtocolMessage::PrivateMessage(m)),
258 _ => Err(ProtocolMessageError::WrongWireFormat),
259 }
260 }
261}
262
263#[cfg(any(feature = "test-utils", test))]
264impl From<PublicMessage> for ProtocolMessage {
265 fn from(msg: PublicMessage) -> Self {
266 PublicMessageIn::from(msg).into()
267 }
268}