diff --git a/mls-rs/src/group/commit.rs b/mls-rs/src/group/commit.rs index f8caa7c8..f01fb31c 100644 --- a/mls-rs/src/group/commit.rs +++ b/mls-rs/src/group/commit.rs @@ -94,6 +94,9 @@ pub struct CommitOutput { /// functionality. This value is set if [`MlsRules::commit_options`] returns /// `allow_external_commit` set to true. pub external_commit_group_info: Option, + /// Proposals that were received in the prior epoch but not included in the following commit. + #[cfg(feature = "by_ref_proposal")] + pub unused_proposals: Vec>, } #[cfg_attr(all(feature = "ffi", not(test)), ::safer_ffi_gen::safer_ffi_gen)] @@ -117,6 +120,20 @@ impl CommitOutput { pub fn ratchet_tree(&self) -> Option<&ExportedTree<'static>> { self.ratchet_tree.as_ref() } + + /// A group info that can be provided to new members in order to enable external commit + /// functionality. This value is set if [`MlsRules::commit_options`] returns + /// `allow_external_commit` set to true. + #[cfg(feature = "ffi")] + pub fn external_commit_group_info(&self) -> Option<&MlsMessage> { + self.external_commit_group_info.as_ref() + } + + /// Proposals that were received in the prior epoch but not included in the following commit. + #[cfg(all(feature = "ffi", feature = "by_ref_proposal"))] + pub fn unused_proposals(&self) -> &[crate::mls_rules::ProposalInfo] { + &self.unused_proposals + } } /// Build a commit with multiple proposals by-value. @@ -722,6 +739,8 @@ where welcome_messages, ratchet_tree, external_commit_group_info, + #[cfg(feature = "by_ref_proposal")] + unused_proposals: provisional_state.rejected_proposals, }) } diff --git a/mls-rs/src/group/framing.rs b/mls-rs/src/group/framing.rs index 31527e5b..891127a4 100644 --- a/mls-rs/src/group/framing.rs +++ b/mls-rs/src/group/framing.rs @@ -36,6 +36,10 @@ impl From<&Content> for ContentType { } } +#[cfg_attr( + all(feature = "ffi", not(test)), + safer_ffi_gen::ffi_type(clone, opaque) +)] #[derive(Clone, Copy, Debug, PartialEq, Eq, MlsSize, MlsEncode, MlsDecode)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[repr(u8)] diff --git a/mls-rs/src/group/message_processor.rs b/mls-rs/src/group/message_processor.rs index ba70ecac..b11c24bc 100644 --- a/mls-rs/src/group/message_processor.rs +++ b/mls-rs/src/group/message_processor.rs @@ -35,10 +35,10 @@ use super::proposal_ref::ProposalRef; #[cfg(not(feature = "by_ref_proposal"))] use crate::group::proposal_cache::resolve_for_commit; -#[cfg(any(feature = "state_update", feature = "by_ref_proposal"))] +#[cfg(feature = "by_ref_proposal")] use super::proposal::Proposal; -#[cfg(all(feature = "state_update", feature = "custom_proposal"))] +#[cfg(feature = "custom_proposal")] use super::proposal_filter::ProposalInfo; #[cfg(feature = "state_update")] @@ -72,7 +72,7 @@ pub(crate) struct ProvisionalState { pub(crate) group_context: GroupContext, pub(crate) external_init_index: Option, pub(crate) indexes_of_added_kpkgs: Vec, - #[cfg(all(feature = "state_update", feature = "by_ref_proposal"))] + #[cfg(feature = "by_ref_proposal")] pub(crate) rejected_proposals: Vec>, } diff --git a/mls-rs/src/group/proposal_filter/bundle.rs b/mls-rs/src/group/proposal_filter/bundle.rs index 69d21f45..e2c7c5d3 100644 --- a/mls-rs/src/group/proposal_filter/bundle.rs +++ b/mls-rs/src/group/proposal_filter/bundle.rs @@ -434,6 +434,10 @@ impl ProposalBundle { } } +#[cfg_attr( + all(feature = "ffi", not(test)), + safer_ffi_gen::ffi_type(clone, opaque) +)] #[derive(Clone, Debug, PartialEq)] pub enum ProposalSource { ByValue, @@ -442,6 +446,7 @@ pub enum ProposalSource { Local, } +#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::ffi_type(opaque))] #[derive(Clone, Debug, PartialEq)] #[non_exhaustive] /// Proposal description used as input to a @@ -455,6 +460,9 @@ pub struct ProposalInfo { pub source: ProposalSource, } +safer_ffi_gen::specialize!(ProposalInfoFfi = crate::group::proposal_filter::ProposalInfo); + +#[cfg_attr(all(feature = "ffi", not(test)), ::safer_ffi_gen::safer_ffi_gen)] impl ProposalInfo { /// Create a new ProposalInfo. /// @@ -464,6 +472,7 @@ impl ProposalInfo { /// /// This function is useful when implementing custom /// [`MlsRules`](crate::MlsRules). + #[safer_ffi_gen::safer_ffi_gen_ignore] pub fn new(proposal: Proposal, sender: Sender, can_transmit: bool) -> ProposalInfo { let source = if can_transmit { ProposalSource::ByValue @@ -477,6 +486,18 @@ impl ProposalInfo { source, } } + + // TODO: Proposal has a lot of cases that we don't have FFI support for yet. + + #[cfg(feature = "ffi")] + pub fn sender(&self) -> &Sender { + &self.sender + } + + #[cfg(feature = "ffi")] + pub fn source(&self) -> &ProposalSource { + &self.source + } } impl ProposalInfo { diff --git a/mls-rs/src/group/proposal_ref.rs b/mls-rs/src/group/proposal_ref.rs index c6b10b23..9e9ec483 100644 --- a/mls-rs/src/group/proposal_ref.rs +++ b/mls-rs/src/group/proposal_ref.rs @@ -5,6 +5,10 @@ use super::*; use crate::hash_reference::HashReference; +#[cfg_attr( + all(feature = "ffi", not(test)), + safer_ffi_gen::ffi_type(clone, opaque) +)] #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, MlsSize, MlsEncode, MlsDecode)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] /// Unique identifier for a proposal message. @@ -18,6 +22,7 @@ impl Deref for ProposalRef { } } +#[cfg_attr(all(feature = "ffi", not(test)), ::safer_ffi_gen::safer_ffi_gen)] impl ProposalRef { #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] pub(crate) async fn from_content( @@ -31,6 +36,10 @@ impl ProposalRef { .await?, )) } + + pub fn as_slice(&self) -> &[u8] { + &self.0 + } } #[cfg(test)]