openmls/framing/
sender.rs

1//! # The sender of a message.
2
3use crate::{binary_tree::array_representation::LeafNodeIndex, extensions::SenderExtensionIndex};
4
5use super::*;
6use tls_codec::{TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize};
7
8/// All possible sender types according to the MLS protocol spec.
9///
10/// ```c
11/// // draft-ietf-mls-protocol-16
12/// enum {
13///     reserved(0),
14///     member(1),
15///     external(2),
16///     new_member_proposal(3),
17///     new_member_commit(4),
18///     (255)
19/// } SenderType;
20///
21/// // draft-ietf-mls-protocol-16
22/// struct {
23///     SenderType sender_type;
24///     select (Sender.sender_type) {
25///         case member:
26///             uint32 leaf_index;
27///         case external:
28///             uint32 sender_index;
29///         case new_member_commit:
30///         case new_member_proposal:
31///             struct{};
32///     }
33/// } Sender;
34/// ```
35#[derive(
36    Debug,
37    PartialEq,
38    Eq,
39    Clone,
40    Serialize,
41    Deserialize,
42    TlsSerialize,
43    TlsDeserialize,
44    TlsDeserializeBytes,
45    TlsSize,
46)]
47#[repr(u8)]
48pub enum Sender {
49    /// The sender is a member of the group
50    #[tls_codec(discriminant = 1)]
51    Member(LeafNodeIndex),
52    /// The sender is not a member of the group and has an external value instead
53    /// The index refers to the [crate::extensions::ExternalSendersExtension] and is 0 indexed
54    External(SenderExtensionIndex),
55    /// The sender is a new member of the group that joins itself through
56    /// an [External Add proposal](crate::messages::external_proposals::JoinProposal)
57    NewMemberProposal,
58    /// The sender is a new member of the group that joins itself through
59    /// an [External Commit](crate::group::mls_group::MlsGroup::join_by_external_commit)
60    NewMemberCommit,
61}
62
63impl Sender {
64    /// Build a [`Sender`] from [`MlsSenderData`].
65    pub(crate) fn from_sender_data(sender_data: MlsSenderData) -> Self {
66        Self::Member(sender_data.leaf_index)
67    }
68
69    /// Create a member sender.
70    pub(crate) fn build_member(leaf_index: LeafNodeIndex) -> Self {
71        Self::Member(leaf_index)
72    }
73
74    /// Returns true if this [`Sender`] has [`SenderType::Member`].
75    pub(crate) fn is_member(&self) -> bool {
76        matches!(self, Sender::Member(_))
77    }
78
79    /// Returns the leaf index of the [`Sender`] or [`None`] if this
80    /// is not a [`Sender::Member`].
81    pub(crate) fn as_member(&self) -> Option<LeafNodeIndex> {
82        match self {
83            Sender::Member(leaf_index) => Some(*leaf_index),
84            _ => None,
85        }
86    }
87}
88
89#[derive(Clone, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize)]
90#[cfg_attr(test, derive(Debug))]
91pub(crate) struct MlsSenderData {
92    pub(crate) leaf_index: LeafNodeIndex,
93    pub(crate) generation: u32,
94    pub(crate) reuse_guard: ReuseGuard,
95}
96
97impl MlsSenderData {
98    /// Build new [`MlsSenderData`] for a [`Sender`].
99    pub(crate) fn from_sender(
100        leaf_index: LeafNodeIndex,
101        generation: u32,
102        reuse_guard: ReuseGuard,
103    ) -> Self {
104        MlsSenderData {
105            leaf_index,
106            generation,
107            reuse_guard,
108        }
109    }
110}
111
112#[derive(Clone, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize)]
113pub(crate) struct MlsSenderDataAad {
114    pub(crate) group_id: GroupId,
115    pub(crate) epoch: GroupEpoch,
116    pub(crate) content_type: ContentType,
117}
118
119impl MlsSenderDataAad {
120    pub(crate) fn new(group_id: GroupId, epoch: GroupEpoch, content_type: ContentType) -> Self {
121        Self {
122            group_id,
123            epoch,
124            content_type,
125        }
126    }
127
128    #[cfg(test)]
129    pub fn test_new(group_id: GroupId, epoch: GroupEpoch, content_type: ContentType) -> Self {
130        Self::new(group_id, epoch, content_type)
131    }
132}