diff --git a/core/core_client/src/conversation.rs b/core/core_client/src/conversation.rs index 58aa4f1..e257c6b 100644 --- a/core/core_client/src/conversation.rs +++ b/core/core_client/src/conversation.rs @@ -12,40 +12,56 @@ pub use group_v1::GroupV1Convo; pub type ConversationIdRef<'a> = &'a str; pub type ConversationId = String; -pub struct ServiceContext { - pub identity_provider: IP, - pub ds: DS, - pub rs: RS, +/// A trait which bundles all the external service traits into a single scope. +/// This allows for a single bound to be used internally, and cuts down on +/// the clutter +pub trait ExternalServices: Debug { + type IP: IdentityProvider; + type DS: DeliveryService; + type RS: RegistrationService; +} + +#[derive(Debug)] +pub struct ServiceContext { + pub(crate) identity_provider: S::IP, + pub(crate) ds: S::DS, + pub(crate) rs: S::RS, +} + +impl ServiceContext { + pub fn new(identity_provider: S::IP, ds: S::DS, rs: S::RS) -> Self { + ServiceContext { + identity_provider, + ds, + rs, + } + } } pub trait Id: Debug { fn id(&self) -> ConversationIdRef<'_>; } -pub trait BaseConvo: - Id + Debug -{ - fn init(&self, service_ctx: &mut ServiceContext) -> Result<(), ChatError>; +pub trait BaseConvo: Id + Debug { + fn init(&self, service_ctx: &mut ServiceContext) -> Result<(), ChatError>; fn send_content( &mut self, - service_ctx: &mut ServiceContext, + service_ctx: &mut ServiceContext, content: &[u8], ) -> Result<(), ChatError>; fn handle_frame( &mut self, - service_ctx: &mut ServiceContext, + service_ctx: &mut ServiceContext, enc_payload: EncryptedPayload, ) -> Result, ChatError>; } -pub trait BaseGroupConvo: - BaseConvo -{ +pub trait BaseGroupConvo: BaseConvo { fn add_member( &mut self, - service_ctx: &mut ServiceContext, + service_ctx: &mut ServiceContext, members: &[&AccountId], ) -> Result<(), ChatError>; } diff --git a/core/core_client/src/conversation/group_v1.rs b/core/core_client/src/conversation/group_v1.rs index 91ee1cf..d54a506 100644 --- a/core/core_client/src/conversation/group_v1.rs +++ b/core/core_client/src/conversation/group_v1.rs @@ -11,7 +11,7 @@ use openmls::prelude::tls_codec::Deserialize; use openmls::prelude::*; use crate::AccountId; -use crate::conversation::{ConversationIdRef, ServiceContext}; +use crate::conversation::{ConversationIdRef, ExternalServices, ServiceContext}; use crate::inbox_v2::{MlsIdentityProvider, MlsProvider}; use crate::{ AddressedEncryptedPayload, ContentData, DeliveryService, IdentityProvider, RegistrationService, @@ -128,15 +128,12 @@ where } } -impl BaseConvo for GroupV1Convo +impl BaseConvo for GroupV1Convo where - IP: IdentityProvider, + S: ExternalServices, MP: MlsProvider, - DS: DeliveryService, - RS: RegistrationService, - // KP: RegistrationService, { - fn init(&self, service_ctx: &mut super::ServiceContext) -> Result<(), ChatError> { + fn init(&self, service_ctx: &mut super::ServiceContext) -> Result<(), ChatError> { // Configure the delivery service to listen for the required delivery addresses. service_ctx @@ -153,7 +150,7 @@ where fn send_content( &mut self, - service_ctx: &mut super::ServiceContext, + service_ctx: &mut super::ServiceContext, content: &[u8], ) -> Result<(), ChatError> { let signer = MlsIdentityProvider(&service_ctx.identity_provider); @@ -182,7 +179,7 @@ where fn handle_frame( &mut self, - _service_ctx: &mut super::ServiceContext, + _service_ctx: &mut super::ServiceContext, encoded_payload: EncryptedPayload, ) -> Result, ChatError> { let bytes = match encoded_payload.encryption { @@ -231,12 +228,10 @@ where } } -impl BaseGroupConvo for GroupV1Convo +impl BaseGroupConvo for GroupV1Convo where - IP: IdentityProvider, + S: ExternalServices, MP: MlsProvider, - DS: DeliveryService, - RS: RegistrationService, { // add_members returns: // commit — the Commit message Alice broadcasts to all members @@ -244,7 +239,7 @@ where // _group_info — used for external joins; ignore for now fn add_member( &mut self, - service_ctx: &mut ServiceContext, + service_ctx: &mut ServiceContext, members: &[&AccountId], ) -> Result<(), ChatError> { let mls_provider = &*self.mls_provider.borrow(); @@ -304,19 +299,15 @@ where } impl GroupV1Convo { - fn key_package_for_account< - IP: IdentityProvider, - DS: DeliveryService, - RS: RegistrationService, - >( + fn key_package_for_account( &self, - service_ctx: &mut ServiceContext, + service_ctx: &mut ServiceContext, ident: &AccountId, ) -> Result { let retrieved_bytes = service_ctx .rs .retrieve(ident) - .map_err(|e: RS::Error| ChatError::Generic(e.to_string()))?; + .map_err(|e| ChatError::Generic(e.to_string()))?; // dbg!(ctx.contact_registry()); let Some(keypkg_bytes) = retrieved_bytes else { diff --git a/core/core_client/src/core_client.rs b/core/core_client/src/core_client.rs index ce0f347..b1911dc 100644 --- a/core/core_client/src/core_client.rs +++ b/core/core_client/src/core_client.rs @@ -1,8 +1,11 @@ use std::cell::RefMut; use std::collections::HashMap; +use std::fmt::Debug; use std::{cell::RefCell, rc::Rc}; -use crate::conversation::{BaseGroupConvo, ConversationId, ConversationIdRef, Id, ServiceContext}; +use crate::conversation::{ + BaseGroupConvo, ConversationId, ConversationIdRef, ExternalServices, Id, ServiceContext, +}; use crate::inbox_v2::InboxV2; use crate::{AccountId, errors::ChatError}; @@ -14,16 +17,14 @@ use prost::Message; use storage::ChatStore; #[derive(Debug)] -enum ConvoTypeOwned { - // Pairwise(Box>), - Group(Box>), +enum ConvoTypeOwned { + // Pairwise(Box>), + Group(Box>), } -impl Id for ConvoTypeOwned +impl Id for ConvoTypeOwned where - IP: IdentityProvider, - DS: DeliveryService, - RS: RegistrationService, + S: ExternalServices, { fn id(&self) -> crate::conversation::ConversationIdRef<'_> { match self { @@ -33,21 +34,14 @@ where } } -pub struct GroupConvo< - IP: IdentityProvider, - DS: DeliveryService, - RS: RegistrationService, - CS: ChatStore, -> { - client: Rc>>, +pub struct GroupConvo { + client: Rc>>, convo_id: ConversationId, } -impl GroupConvo +impl GroupConvo where - IP: IdentityProvider + 'static, - DS: DeliveryService + 'static, - RS: RegistrationService + 'static, + S: ExternalServices, CS: ChatStore + 'static, { pub fn send_content(&self, content: &[u8]) -> Result<(), ChatError> { @@ -56,20 +50,34 @@ where } } +// This allows the ExternalServices trait to be converted from a tuple. +// This is used in CoreClient to convert from the explicit impls to a +// ExternalServices bundle, which means it does not have to be exposed externally. +impl ExternalServices for (IP, DS, RS) +where + IP: IdentityProvider + Debug, + DS: DeliveryService + Debug, + RS: RegistrationService + Debug, +{ + type IP = IP; + type DS = DS; + type RS = RS; +} + pub struct CoreClient< IP: IdentityProvider, DS: DeliveryService, RS: RegistrationService, CS: ChatStore, > { - inner: Rc>>, + inner: Rc>>, } impl CoreClient where - IP: IdentityProvider + 'static, - DS: DeliveryService + 'static, - RS: RegistrationService + 'static, + IP: IdentityProvider, + DS: DeliveryService, + RS: RegistrationService, CS: ChatStore + 'static, { pub fn new(account: IP, delivery: DS, registration: RS, store: CS) -> Result { @@ -90,7 +98,7 @@ where pub fn create_group_convo( &self, participants: &[&AccountId], - ) -> Result, ChatError> { + ) -> Result, ChatError> { let convo_id = self.inner.borrow_mut().create_group_convo(participants)?; Ok(GroupConvo { client: self.inner.clone(), @@ -114,7 +122,7 @@ where self.inner.borrow_mut().handle_payload(payload) } - pub fn convo(&self, convo_id: ConversationIdRef) -> Option> { + pub fn convo(&self, convo_id: ConversationIdRef) -> Option> { let client = self.inner.clone(); if !client.borrow().has_conversation(convo_id) { @@ -128,36 +136,32 @@ where } } -struct InnerClient< - IP: IdentityProvider, - DS: DeliveryService, - RS: RegistrationService, - CS: ChatStore, -> { - service_ctx: ServiceContext, +struct InnerClient { + service_ctx: ServiceContext, _store: Rc>, pq_inbox: InboxV2, // Cache of loaded conversations - cached_convos: HashMap>, + cached_convos: HashMap>, } -impl InnerClient +impl InnerClient where - IP: IdentityProvider + 'static, - DS: DeliveryService + 'static, - RS: RegistrationService + 'static, + S: ExternalServices, CS: ChatStore + 'static, { - pub fn new(account: IP, delivery: DS, registration: RS, store: CS) -> Result { + pub fn new( + account: S::IP, + delivery: S::DS, + registration: S::RS, + store: CS, + ) -> Result { // Services for sharing with Converastions/Inboxes - let mut service_ctx = ServiceContext { - identity_provider: account, - ds: delivery, - rs: registration, - }; + // let mut service_ctx: ServiceContext = ServiceContext::new(account, delivery, registration); + let mut service_ctx: ServiceContext = + ServiceContext::new(account, delivery, registration); // let contact_registry = Rc::new(RefCell::new(registration)); let _store = Rc::new(RefCell::new(store)); @@ -179,7 +183,7 @@ where }) } - pub fn ds(&mut self) -> &mut DS { + pub fn ds(&mut self) -> &mut S::DS { &mut self.service_ctx.ds } @@ -190,7 +194,7 @@ where pub fn create_group_convo(&mut self, participants: &[&AccountId]) -> Result { let convo = self.pq_inbox.create_group_v1(&mut self.service_ctx)?; - let mut convo: Box> = Box::new(convo); + let mut convo: Box> = Box::new(convo); convo.init(&mut self.service_ctx)?; convo.add_member(&mut self.service_ctx, participants)?; @@ -242,7 +246,7 @@ where // Dispatch encrypted payload to Inbox, and register the created Conversation fn dispatch_to_inbox2(&mut self, payload: &[u8]) -> Result, ChatError> { if let Some(convo) = self.pq_inbox.handle_frame(&mut self.service_ctx, payload)? { - let convo: Box> = Box::new(convo); + let convo: Box> = Box::new(convo); self.register_convo(ConvoTypeOwned::Group(convo))?; } Ok(None) @@ -267,7 +271,7 @@ where convo.handle_frame(&mut self.service_ctx, enc_payload) } - fn register_convo(&mut self, convo: ConvoTypeOwned) -> Result<(), ChatError> { + fn register_convo(&mut self, convo: ConvoTypeOwned) -> Result<(), ChatError> { let res = self.cached_convos.insert(convo.id().to_string(), convo); match res { diff --git a/core/core_client/src/inbox_v2.rs b/core/core_client/src/inbox_v2.rs index 2e5d00b..7bf4b14 100644 --- a/core/core_client/src/inbox_v2.rs +++ b/core/core_client/src/inbox_v2.rs @@ -20,6 +20,7 @@ use crate::DeliveryService; use crate::IdentityProvider; use crate::RegistrationService; use crate::conversation::BaseConvo; +use crate::conversation::ExternalServices; use crate::conversation::ServiceContext; use crate::conversation::{GroupV1Convo, Id}; use crate::utils::{blake2b_hex, hash_size}; @@ -166,8 +167,8 @@ pub struct InboxV2 { } impl InboxV2 { - pub fn new( - service_ctx: &mut ServiceContext, + pub fn new( + service_ctx: &mut ServiceContext, _store: Rc>, ) -> Self { // Avoid referencing a temporary value by caching it. @@ -193,9 +194,9 @@ impl InboxV2 { } /// Submit MlsKeypackage to registration service - pub fn register( + pub fn register( &self, - service_ctx: &mut ServiceContext, + service_ctx: &mut ServiceContext, ) -> Result<(), ChatError> { let mls_ident = MlsIdentityProvider(&service_ctx.identity_provider); let keypackage_bytes = self @@ -213,9 +214,9 @@ impl InboxV2 { .map_err(ChatError::generic) } - pub fn create_group_v1( + pub fn create_group_v1( &self, - service_ctx: &mut ServiceContext, + service_ctx: &mut ServiceContext, ) -> Result, ChatError> { let mls_ident = MlsIdentityProvider(&service_ctx.identity_provider); GroupV1Convo::new(mls_ident, self.mls_provider.clone()) @@ -247,9 +248,9 @@ impl InboxV2 { } impl InboxV2 { - pub fn handle_frame( + pub fn handle_frame( &self, - service_ctx: &mut ServiceContext, + service_ctx: &mut ServiceContext, payload_bytes: &[u8], ) -> Result>, ChatError> { let inbox_frame = InboxV2Frame::decode(payload_bytes)?; @@ -265,9 +266,9 @@ impl InboxV2 { } } - fn handle_heavy_invite( + fn handle_heavy_invite( &self, - service_ctx: &mut ServiceContext, + service_ctx: &mut ServiceContext, invite: GroupV1HeavyInvite, ) -> Result, ChatError> { let (msg_in, _rest) = MlsMessageIn::tls_deserialize_bytes(invite.welcome_bytes.as_slice())?;