chore: use inbound and outbound for session

This commit is contained in:
kaichaosun 2026-02-03 13:01:26 +08:00
parent 6c54bbd79d
commit 2a9fe1c8e5
No known key found for this signature in database
GPG Key ID: 223E0F992F4F03BF
4 changed files with 61 additions and 57 deletions

View File

@ -2,7 +2,7 @@ use std::{collections::HashMap, rc::Rc, sync::Arc};
use crate::{ use crate::{
// conversation::{ConversationStore, Convo, Id}, // conversation::{ConversationStore, Convo, Id},
conversation::common::{ConversationStore, Convo, HasConversationId}, conversation::common::{HasConversationId, OutboundSession, SessionRegistry},
errors::ChatError, errors::ChatError,
identity::Identity, identity::Identity,
inbox::Inbox, inbox::Inbox,
@ -21,7 +21,7 @@ pub type ConvoHandle = u32;
// Ctx manages lifetimes of objects to process and generate payloads. // Ctx manages lifetimes of objects to process and generate payloads.
pub struct Context { pub struct Context {
_identity: Rc<Identity>, _identity: Rc<Identity>,
store: ConversationStore, store: SessionRegistry,
inbox: Inbox, inbox: Inbox,
buf_size: usize, buf_size: usize,
convo_handle_map: HashMap<u32, Arc<str>>, convo_handle_map: HashMap<u32, Arc<str>>,
@ -34,7 +34,7 @@ impl Context {
let inbox = Inbox::new(Rc::clone(&identity)); // let inbox = Inbox::new(Rc::clone(&identity)); //
Self { Self {
_identity: identity, _identity: identity,
store: ConversationStore::new(), store: SessionRegistry::new(),
inbox, inbox,
buf_size: 0, buf_size: 0,
convo_handle_map: HashMap::new(), convo_handle_map: HashMap::new(),
@ -100,17 +100,23 @@ impl Context {
Ok(Introduction::from(pkb).into()) Ok(Introduction::from(pkb).into())
} }
fn add_convo(&mut self, convo: impl Convo + HasConversationId + 'static) -> ConvoHandle { fn add_convo(
&mut self,
convo: impl OutboundSession + HasConversationId + 'static,
) -> ConvoHandle {
let handle = self.next_convo_handle; let handle = self.next_convo_handle;
self.next_convo_handle += 1; self.next_convo_handle += 1;
let convo_id = self.store.insert_convo(convo); let convo_id = self.store.insert_session(convo);
self.convo_handle_map.insert(handle, convo_id); self.convo_handle_map.insert(handle, convo_id);
handle handle
} }
// Returns a mutable reference to a Convo for a given ConvoHandle // Returns a mutable reference to a Convo for a given ConvoHandle
fn get_convo_mut(&mut self, handle: ConvoHandle) -> Result<&mut dyn Convo, ChatError> { fn get_convo_mut(
&mut self,
handle: ConvoHandle,
) -> Result<&mut dyn OutboundSession, ChatError> {
let convo_id = self let convo_id = self
.convo_handle_map .convo_handle_map
.get(&handle) .get(&handle)
@ -118,7 +124,7 @@ impl Context {
.clone(); .clone();
self.store self.store
.get_mut(&convo_id) .get_mut_session(&convo_id)
.ok_or_else(|| ChatError::NoConvo(handle)) .ok_or_else(|| ChatError::NoConvo(handle))
} }
} }
@ -132,12 +138,12 @@ mod tests {
#[test] #[test]
fn convo_store_get() { fn convo_store_get() {
let mut store: ConversationStore = ConversationStore::new(); let mut store: SessionRegistry = SessionRegistry::new();
let new_convo = PrivateV1Convo::new([0; 32].into()); let new_convo = PrivateV1Convo::new([0; 32].into());
let convo_id = store.insert_convo(new_convo); let convo_id = store.insert_session(new_convo);
let convo = store.get_mut(&convo_id).ok_or_else(|| 0); let convo = store.get_mut_session(&convo_id).ok_or_else(|| 0);
convo.unwrap(); convo.unwrap();
} }
} }

View File

@ -5,76 +5,78 @@ use std::sync::Arc;
pub use crate::errors::ChatError; pub use crate::errors::ChatError;
use crate::types::{AddressedEncryptedPayload, ContentData}; use crate::types::{AddressedEncryptedPayload, ContentData};
pub type ConversationId<'a> = &'a str; pub type SessionId<'a> = &'a str;
pub type ConversationIdOwned = Arc<str>; pub type SessionIdOwned = Arc<str>;
pub trait HasConversationId: Debug { pub trait HasConversationId: Debug {
fn id(&self) -> ConversationId; fn id(&self) -> SessionId<'_>;
} }
pub trait ConvoFactory: HasConversationId + Debug { #[allow(dead_code)]
pub trait InboundSessionHandler: HasConversationId + Debug {
fn handle_frame( fn handle_frame(
&mut self, &mut self,
encoded_payload: &[u8], encoded_payload: &[u8],
) -> Result<(Box<dyn Convo>, Vec<ContentData>), ChatError>; ) -> Result<(Box<dyn OutboundSession>, Vec<ContentData>), ChatError>;
} }
pub trait Convo: HasConversationId + Debug { pub trait OutboundSession: HasConversationId + Debug {
fn send_message(&mut self, content: &[u8]) fn send_message(&mut self, content: &[u8])
-> Result<Vec<AddressedEncryptedPayload>, ChatError>; -> Result<Vec<AddressedEncryptedPayload>, ChatError>;
fn remote_id(&self) -> String; fn remote_id(&self) -> String;
} }
pub struct ConversationStore { #[allow(dead_code)]
conversations: HashMap<Arc<str>, Box<dyn Convo>>, pub struct SessionRegistry {
factories: HashMap<Arc<str>, Box<dyn ConvoFactory>>, sessions: HashMap<Arc<str>, Box<dyn OutboundSession>>,
handlers: HashMap<Arc<str>, Box<dyn InboundSessionHandler>>,
} }
impl ConversationStore { #[allow(dead_code)]
impl SessionRegistry {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
conversations: HashMap::new(), sessions: HashMap::new(),
factories: HashMap::new(), handlers: HashMap::new(),
} }
} }
pub fn insert_convo( pub fn insert_session(
&mut self, &mut self,
conversation: impl Convo + HasConversationId + 'static, conversation: impl OutboundSession + HasConversationId + 'static,
) -> ConversationIdOwned { ) -> SessionIdOwned {
let key: ConversationIdOwned = Arc::from(conversation.id()); let key: SessionIdOwned = Arc::from(conversation.id());
self.conversations self.sessions.insert(key.clone(), Box::new(conversation));
.insert(key.clone(), Box::new(conversation));
key key
} }
pub fn register_factory( pub fn register_handler(
&mut self, &mut self,
handler: impl ConvoFactory + HasConversationId + 'static, handler: impl InboundSessionHandler + HasConversationId + 'static,
) -> ConversationIdOwned { ) -> SessionIdOwned {
let key: ConversationIdOwned = Arc::from(handler.id()); let key: SessionIdOwned = Arc::from(handler.id());
self.factories.insert(key.clone(), Box::new(handler)); self.handlers.insert(key.clone(), Box::new(handler));
key key
} }
pub fn get(&self, id: ConversationId) -> Option<&(dyn Convo + '_)> { pub fn get_session(&self, id: SessionId) -> Option<&(dyn OutboundSession + '_)> {
self.conversations.get(id).map(|c| c.as_ref()) self.sessions.get(id).map(|c| c.as_ref())
} }
pub fn get_mut(&mut self, id: &str) -> Option<&mut (dyn Convo + '_)> { pub fn get_mut_session(&mut self, id: &str) -> Option<&mut (dyn OutboundSession + '_)> {
Some(self.conversations.get_mut(id)?.as_mut()) Some(self.sessions.get_mut(id)?.as_mut())
} }
pub fn get_factory(&mut self, id: ConversationId) -> Option<&mut (dyn ConvoFactory + '_)> { pub fn get_handler(&mut self, id: SessionId) -> Option<&mut (dyn InboundSessionHandler + '_)> {
Some(self.factories.get_mut(id)?.as_mut()) Some(self.handlers.get_mut(id)?.as_mut())
} }
pub fn conversation_ids(&self) -> impl Iterator<Item = ConversationIdOwned> + '_ { pub fn session_ids(&self) -> impl Iterator<Item = SessionIdOwned> + '_ {
self.conversations.keys().cloned() self.sessions.keys().cloned()
} }
pub fn factory_ids(&self) -> impl Iterator<Item = ConversationIdOwned> + '_ { pub fn handler_ids(&self) -> impl Iterator<Item = SessionIdOwned> + '_ {
self.factories.keys().cloned() self.handlers.keys().cloned()
} }
} }

View File

@ -6,7 +6,7 @@ use crypto::SecretKey;
use prost::{Message, bytes::Bytes}; use prost::{Message, bytes::Bytes};
use crate::{ use crate::{
conversation::common::{ConversationId, Convo, HasConversationId}, conversation::common::{HasConversationId, OutboundSession, SessionId},
errors::ChatError, errors::ChatError,
types::AddressedEncryptedPayload, types::AddressedEncryptedPayload,
utils::timestamp_millis, utils::timestamp_millis,
@ -36,13 +36,13 @@ impl PrivateV1Convo {
} }
impl HasConversationId for PrivateV1Convo { impl HasConversationId for PrivateV1Convo {
fn id(&self) -> ConversationId { fn id(&self) -> SessionId<'_> {
// TODO: implementation // TODO: implementation
"private_v1_convo_id" "private_v1_convo_id"
} }
} }
impl Convo for PrivateV1Convo { impl OutboundSession for PrivateV1Convo {
fn send_message( fn send_message(
&mut self, &mut self,
content: &[u8], content: &[u8],

View File

@ -8,10 +8,11 @@ use std::rc::Rc;
use crypto::{PrekeyBundle, SecretKey}; use crypto::{PrekeyBundle, SecretKey};
use crate::context::Introduction; use crate::context::Introduction;
use crate::conversation::common::{ConversationId, Convo, ConvoFactory, HasConversationId}; use crate::conversation::common::{
HasConversationId, InboundSessionHandler, OutboundSession, SessionId,
};
use crate::conversation::privatev1::PrivateV1Convo; use crate::conversation::privatev1::PrivateV1Convo;
// use crate::conversation::{ChatError, ConversationId, Convo, ConvoFactory, Id, PrivateV1Convo}; use crate::crypto::{CopyBytes, PublicKey, StaticSecret};
use crate::crypto::{Blake2b128, CopyBytes, Digest, PublicKey, StaticSecret};
use crate::errors::ChatError; use crate::errors::ChatError;
use crate::identity::Identity; use crate::identity::Identity;
use crate::inbox::handshake::InboxHandshake; use crate::inbox::handshake::InboxHandshake;
@ -53,11 +54,6 @@ impl Inbox {
} }
} }
fn compute_local_convo_id(addr: &str) -> String {
let hash = Blake2b128::digest(format!("{}:{}:{}", "logoschat", "inboxV1", addr));
hex::encode(hash)
}
pub fn create_bundle(&mut self) -> PrekeyBundle { pub fn create_bundle(&mut self) -> PrekeyBundle {
let ephemeral = StaticSecret::random(); let ephemeral = StaticSecret::random();
@ -204,16 +200,16 @@ impl Inbox {
} }
impl HasConversationId for Inbox { impl HasConversationId for Inbox {
fn id(&self) -> ConversationId { fn id(&self) -> SessionId<'_> {
&self.local_convo_id &self.local_convo_id
} }
} }
impl ConvoFactory for Inbox { impl InboundSessionHandler for Inbox {
fn handle_frame( fn handle_frame(
&mut self, &mut self,
message: &[u8], message: &[u8],
) -> Result<(Box<dyn Convo>, Vec<ContentData>), ChatError> { ) -> Result<(Box<dyn OutboundSession>, Vec<ContentData>), ChatError> {
if message.len() == 0 { if message.len() == 0 {
return Err(ChatError::Protocol("Example error".into())); return Err(ChatError::Protocol("Example error".into()));
} }