• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 // Copyright by contributors to this project.
3 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
4 
5 use alloc::vec;
6 use alloc::vec::Vec;
7 use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
8 
9 use crate::{
10     crypto::CipherSuite,
11     extension::{ExtensionList, ExtensionType},
12     identity::{CredentialType, SigningIdentity},
13     protocol_version::ProtocolVersion,
14 };
15 
16 use super::ProposalType;
17 
18 #[derive(Clone, PartialEq, Eq, Debug, MlsSize, MlsEncode, MlsDecode)]
19 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
20 #[cfg_attr(
21     all(feature = "ffi", not(test)),
22     safer_ffi_gen::ffi_type(clone, opaque)
23 )]
24 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25 ///  Capabilities of a MLS client
26 pub struct Capabilities {
27     pub protocol_versions: Vec<ProtocolVersion>,
28     pub cipher_suites: Vec<CipherSuite>,
29     pub extensions: Vec<ExtensionType>,
30     pub proposals: Vec<ProposalType>,
31     pub credentials: Vec<CredentialType>,
32 }
33 
34 #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen)]
35 impl Capabilities {
36     /// Supported protocol versions
37     #[cfg(feature = "ffi")]
protocol_versions(&self) -> &[ProtocolVersion]38     pub fn protocol_versions(&self) -> &[ProtocolVersion] {
39         &self.protocol_versions
40     }
41 
42     /// Supported ciphersuites
43     #[cfg(feature = "ffi")]
cipher_suites(&self) -> &[CipherSuite]44     pub fn cipher_suites(&self) -> &[CipherSuite] {
45         &self.cipher_suites
46     }
47 
48     /// Supported extensions
49     #[cfg(feature = "ffi")]
extensions(&self) -> &[ExtensionType]50     pub fn extensions(&self) -> &[ExtensionType] {
51         &self.extensions
52     }
53 
54     /// Supported proposals
55     #[cfg(feature = "ffi")]
proposals(&self) -> &[ProposalType]56     pub fn proposals(&self) -> &[ProposalType] {
57         &self.proposals
58     }
59 
60     /// Supported credentials
61     #[cfg(feature = "ffi")]
credentials(&self) -> &[CredentialType]62     pub fn credentials(&self) -> &[CredentialType] {
63         &self.credentials
64     }
65 
66     /// Canonical form
sorted(mut self) -> Self67     pub fn sorted(mut self) -> Self {
68         self.protocol_versions.sort();
69         self.cipher_suites.sort();
70         self.extensions.sort();
71         self.proposals.sort();
72         self.credentials.sort();
73 
74         self
75     }
76 }
77 
78 impl Default for Capabilities {
default() -> Self79     fn default() -> Self {
80         use crate::identity::BasicCredential;
81 
82         Self {
83             protocol_versions: vec![ProtocolVersion::MLS_10],
84             cipher_suites: CipherSuite::all().collect(),
85             extensions: Default::default(),
86             proposals: Default::default(),
87             credentials: vec![BasicCredential::credential_type()],
88         }
89     }
90 }
91 
92 /// A member of a MLS group.
93 #[cfg_attr(
94     all(feature = "ffi", not(test)),
95     safer_ffi_gen::ffi_type(clone, opaque)
96 )]
97 #[derive(Debug, Clone, PartialEq, Eq)]
98 #[non_exhaustive]
99 pub struct Member {
100     /// The index of this member within a group.
101     ///
102     /// This value is consistent for all clients and will not change as the
103     /// group evolves.
104     pub index: u32,
105     /// Current identity public key and credential of this member.
106     pub signing_identity: SigningIdentity,
107     /// Current client [Capabilities] of this member.
108     pub capabilities: Capabilities,
109     /// Current leaf node extensions in use by this member.
110     pub extensions: ExtensionList,
111 }
112 
113 #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen)]
114 impl Member {
new( index: u32, signing_identity: SigningIdentity, capabilities: Capabilities, extensions: ExtensionList, ) -> Self115     pub fn new(
116         index: u32,
117         signing_identity: SigningIdentity,
118         capabilities: Capabilities,
119         extensions: ExtensionList,
120     ) -> Self {
121         Self {
122             index,
123             signing_identity,
124             capabilities,
125             extensions,
126         }
127     }
128 
129     /// The index of this member within a group.
130     ///
131     /// This value is consistent for all clients and will not change as the
132     /// group evolves.
133     #[cfg(feature = "ffi")]
index(&self) -> u32134     pub fn index(&self) -> u32 {
135         self.index
136     }
137 
138     /// Current identity public key and credential of this member.
139     #[cfg(feature = "ffi")]
signing_identity(&self) -> &SigningIdentity140     pub fn signing_identity(&self) -> &SigningIdentity {
141         &self.signing_identity
142     }
143 
144     /// Current client [Capabilities] of this member.
145     #[cfg(feature = "ffi")]
capabilities(&self) -> &Capabilities146     pub fn capabilities(&self) -> &Capabilities {
147         &self.capabilities
148     }
149 
150     /// Current leaf node extensions in use by this member.
151     #[cfg(feature = "ffi")]
extensions(&self) -> &ExtensionList152     pub fn extensions(&self) -> &ExtensionList {
153         &self.extensions
154     }
155 }
156 
157 #[derive(Clone, Debug, PartialEq)]
158 #[non_exhaustive]
159 #[cfg_attr(
160     all(feature = "ffi", not(test)),
161     safer_ffi_gen::ffi_type(clone, opaque)
162 )]
163 /// Update of a member due to a commit.
164 pub struct MemberUpdate {
165     pub prior: Member,
166     pub new: Member,
167 }
168 
169 #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen)]
170 impl MemberUpdate {
171     /// Create a new member update.
new(prior: Member, new: Member) -> MemberUpdate172     pub fn new(prior: Member, new: Member) -> MemberUpdate {
173         MemberUpdate { prior, new }
174     }
175 
176     /// The index that was updated.
index(&self) -> u32177     pub fn index(&self) -> u32 {
178         self.new.index
179     }
180 
181     /// Member state before the update.
182     #[cfg(feature = "ffi")]
before_update(&self) -> &Member183     pub fn before_update(&self) -> &Member {
184         &self.prior
185     }
186 
187     /// Member state after the update.
188     #[cfg(feature = "ffi")]
after_update(&self) -> &Member189     pub fn after_update(&self) -> &Member {
190         &self.new
191     }
192 }
193 
194 /// A set of roster updates due to a commit.
195 #[derive(Clone, Debug, PartialEq)]
196 #[non_exhaustive]
197 pub struct RosterUpdate {
198     pub(crate) added: Vec<Member>,
199     pub(crate) removed: Vec<Member>,
200     pub(crate) updated: Vec<MemberUpdate>,
201 }
202 
203 impl RosterUpdate {
204     /// Create a new roster update.
new( mut added: Vec<Member>, mut removed: Vec<Member>, mut updated: Vec<MemberUpdate>, ) -> RosterUpdate205     pub fn new(
206         mut added: Vec<Member>,
207         mut removed: Vec<Member>,
208         mut updated: Vec<MemberUpdate>,
209     ) -> RosterUpdate {
210         added.sort_by_key(|m| m.index);
211         removed.sort_by_key(|m| m.index);
212         updated.sort_by_key(|u| u.index());
213 
214         RosterUpdate {
215             added,
216             removed,
217             updated,
218         }
219     }
220     /// Members added via this update.
added(&self) -> &[Member]221     pub fn added(&self) -> &[Member] {
222         &self.added
223     }
224 
225     /// Members removed via this update.
removed(&self) -> &[Member]226     pub fn removed(&self) -> &[Member] {
227         &self.removed
228     }
229 
230     /// Members updated via this update.
updated(&self) -> &[MemberUpdate]231     pub fn updated(&self) -> &[MemberUpdate] {
232         &self.updated
233     }
234 }
235