From 1eefce4f1ceef431f69ecafaae450510ff4e4c13 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sun, 17 May 2020 15:20:16 +0100 Subject: [PATCH] Create a channel on incoming messages We don't yet emit signals, but we're getting closer. This commit also partially implements the deprecated ListChannels method on the Connection interface. --- src/padfoot/channel.rs | 5 +- src/padfoot/connection.rs | 42 +++++++++++--- src/padfoot/connection/connection.rs | 87 +++++++++++++++++----------- 3 files changed, 92 insertions(+), 42 deletions(-) diff --git a/src/padfoot/channel.rs b/src/padfoot/channel.rs index b19992d..56c5ce9 100644 --- a/src/padfoot/channel.rs +++ b/src/padfoot/channel.rs @@ -37,9 +37,10 @@ impl Channel { let messages_iface = telepathy::channel_interface_messages_server(&f, (), move |_| c_rc2.clone()); - let type_text_iface = telepathy::channel_type_text_server(&f, (), move |_| channel.clone()); + let c_rc3 = channel.clone(); + let type_text_iface = telepathy::channel_type_text_server(&f, (), move |_| c_rc3.clone()); - f.object_path("", ()) + f.object_path(channel.path.clone(), ()) .introspectable() .add(chan_iface) .add(messages_iface) diff --git a/src/padfoot/connection.rs b/src/padfoot/connection.rs index cf2dd2b..b3753c1 100644 --- a/src/padfoot/connection.rs +++ b/src/padfoot/connection.rs @@ -292,7 +292,12 @@ impl Connection { }; // Spend a bit of time sending any outgoing messages - signals, mostly - while let Some(act) = actq.lock().unwrap().pop_front() { + while let Some(act) = { + let mut q = actq.lock().unwrap(); + let r = q.pop_front(); + drop(q); // Only hold the mutex for the pop operation + r + } { match act { DbusAction::Signal(msg) => { print!("Connection<{}>: Sending message...", id); @@ -303,13 +308,15 @@ impl Connection { } } DbusAction::NewChannel(channel) => { - let path = channel.path.clone(); + let chan_path = channel.path.clone(); let rc_channel = Arc::new(channel); + println!("*** Creating channel {}", chan_path); + Arc::clone(&chans) .write() .unwrap() - .insert(path.clone(), rc_channel.clone()); + .insert(chan_path.clone(), rc_channel.clone()); let t2 = tree.clone(); let op = Channel::build_object_path(rc_channel); @@ -320,14 +327,35 @@ impl Connection { DbusAction::CloseChannel(path) => { let _chan = Arc::clone(&chans).write().unwrap().remove(&path); let t2 = tree.clone(); - t2.lock().unwrap().remove(&path); // TODO: emit signals } - DbusAction::IncomingMessage(_chat_id, _msg_id) => { + DbusAction::IncomingMessage(chat_id, msg_id) => { // TODO: check if we have a channel for the chat - // If not, create one - // If we do, send the message down it + let chan_path = dbus::strings::Path::new(format!( + "{}/{}", + path.clone(), + chat_id.to_u32() + )) + .unwrap(); + let c2 = Arc::clone(&chans); + let chans = c2.read().unwrap(); + + // Autocreate channel if it doesn't already exist + // FIXME: unknown contacts need more care than this + if chans.contains_key(&chan_path) { + println!( + "Message {} received for {}, passing it on is TODO!", + msg_id, chan_path + ); + } else { + println!("Channel for {} doesn't exist yet, re-enqueuing", chat_id); + let chan = Channel { path: chan_path }; + let mut q = actq.lock().unwrap(); + q.push_back(DbusAction::NewChannel(chan)); + q.push_back(act); + drop(q); + } } } } diff --git a/src/padfoot/connection/connection.rs b/src/padfoot/connection/connection.rs index 8e19574..8a33e8d 100644 --- a/src/padfoot/connection/connection.rs +++ b/src/padfoot/connection/connection.rs @@ -1,4 +1,5 @@ use crate::telepathy; +use crate::telepathy::ConnectionInterfaceRequests; // Non-deprecated channel methods use dbus::message::SignalArgs; use dbus::tree::MethodErr; @@ -14,6 +15,16 @@ pub enum ConnState { Disconnected, } +type Result = std::result::Result; + +// Deprecated channel information. Replaced by Requests.ChannelSpec +type ChannelInfo = ( + dbus::Path<'static>, // Object path + String, // Channel type + u32, // Handle type + u32, // Handle +); + pub fn connection_interfaces() -> Vec { vec![ "org.freedesktop.Telepathy.Connection".to_string(), @@ -33,7 +44,7 @@ impl AsRef for std::rc::Rc { impl telepathy::Connection for Connection { // In connect(), we start the threads that drive the deltachat context - fn connect(&self) -> Result<(), MethodErr> { + fn connect(&self) -> Result<()> { println!("Connection<{}>::connect()", self.id()); let inbox_ctx = self.ctx.clone(); @@ -120,7 +131,7 @@ impl telepathy::Connection for Connection { Ok(()) } - fn disconnect(&self) -> Result<(), MethodErr> { + fn disconnect(&self) -> Result<()> { println!("Connection<{}>::disconnect()", self.id()); let ctx = self.ctx.read().unwrap(); @@ -139,50 +150,51 @@ impl telepathy::Connection for Connection { Ok(()) } - fn interfaces(&self) -> Result, MethodErr> { + fn interfaces(&self) -> Result> { println!("Connection<{}>::interfaces()", self.id()); self.get_interfaces() } - fn get_interfaces(&self) -> Result, MethodErr> { + fn get_interfaces(&self) -> Result> { println!("Connection<{}>::get_interfaces()", self.id()); Ok(connection_interfaces()) } - fn get_protocol(&self) -> Result { + fn get_protocol(&self) -> Result { println!("Connection<{}>::get_protocol()", self.id()); Ok(crate::padfoot::PROTO_NAME.to_string()) } - fn self_handle(&self) -> Result { + fn self_handle(&self) -> Result { println!("Connection<{}>::self_handle()", self.id()); - self.get_self_handle() - } - - fn get_self_handle(&self) -> Result { - println!("Connection<{}>::get_self_handle()", self.id()); - Ok(dc::constants::DC_CONTACT_ID_SELF) } - fn status(&self) -> Result { + // Deprecated in favour of the self_handle DBUS property + fn get_self_handle(&self) -> Result { + println!("Connection<{}>::get_self_handle()", self.id()); + + self.get_self_handle() + } + + fn status(&self) -> Result { println!("Connection<{}>::status()", self.id()); self.get_status() } - fn get_status(&self) -> Result { + fn get_status(&self) -> Result { match *self.state.clone().read().unwrap() { ConnState::Initial | ConnState::Disconnected => Ok(2), ConnState::Connected => Ok(0), } } - fn hold_handles(&self, handle_type: u32, handles: Vec) -> Result<(), MethodErr> { + fn hold_handles(&self, handle_type: u32, handles: Vec) -> Result<()> { println!( "Connection<{}>::hold_handles({}, {:?})", self.id(), @@ -194,11 +206,7 @@ impl telepathy::Connection for Connection { Ok(()) } - fn inspect_handles( - &self, - handle_type: u32, - handles: Vec, - ) -> Result, MethodErr> { + fn inspect_handles(&self, handle_type: u32, handles: Vec) -> Result> { println!( "Connection<{}>::inspect_handles({}, {:?})", self.id(), @@ -208,12 +216,27 @@ impl telepathy::Connection for Connection { Err(MethodErr::no_arg()) // FIXME: should be NotImplemented? } - fn list_channels(&self) -> Result, String, u32, u32)>, MethodErr> { + // Deprecated in favour of Requests.Channels + fn list_channels(&self) -> Result> { println!("Connection<{}>::list_channels()", self.id()); - Err(MethodErr::no_arg()) // FIXME: should be NotImplemented? + + let data = self.channels()?; + let mut out = Vec::::new(); + + for (path, _props) in data { + // FIXME: pull correct details from the properties hash + out.push(( + path, + "org.freedesktop.Telepathy.Channel.Type.Text".to_string(), + 0, + 0, + )) + } + + Ok(out) } - fn release_handles(&self, handle_type: u32, handles: Vec) -> Result<(), MethodErr> { + fn release_handles(&self, handle_type: u32, handles: Vec) -> Result<()> { println!( "Connection<{}>::release_handles({}, {:?})", self.id(), @@ -232,7 +255,7 @@ impl telepathy::Connection for Connection { handle_type: u32, handle: u32, suppress_handler: bool, - ) -> Result, MethodErr> { + ) -> Result> { println!( "Connection<{}>::request_channel({}, {}, {}, {})", self.id(), @@ -241,24 +264,22 @@ impl telepathy::Connection for Connection { handle, suppress_handler ); + Err(MethodErr::no_arg()) // FIXME: should be NotImplemented? } - fn request_handles( - &self, - handle_type: u32, - identifiers: Vec<&str>, - ) -> Result, MethodErr> { + fn request_handles(&self, handle_type: u32, identifiers: Vec<&str>) -> Result> { println!( "Connection<{}>::request_handles({}, {:?})", self.id(), handle_type, identifiers ); + Err(MethodErr::no_arg()) // FIXME: should be NotImplemented? } - fn add_client_interest(&self, tokens: Vec<&str>) -> Result<(), MethodErr> { + fn add_client_interest(&self, tokens: Vec<&str>) -> Result<()> { println!( "Connection<{}>::add_client_interest({:?})", self.id(), @@ -267,7 +288,7 @@ impl telepathy::Connection for Connection { Err(MethodErr::no_arg()) // FIXME: should be NotImplemented? } - fn remove_client_interest(&self, tokens: Vec<&str>) -> Result<(), MethodErr> { + fn remove_client_interest(&self, tokens: Vec<&str>) -> Result<()> { println!( "Connection<{}>::remove_client_interest({:?})", self.id(), @@ -276,7 +297,7 @@ impl telepathy::Connection for Connection { Err(MethodErr::no_arg()) // FIXME: should be NotImplemented? } - fn self_id(&self) -> Result { + fn self_id(&self) -> Result { println!("Connection<{}>::self_id()", self.id()); let contact = match dc::contact::Contact::get_by_id( @@ -293,7 +314,7 @@ impl telepathy::Connection for Connection { Ok(contact.get_addr().to_string()) } - fn has_immortal_handles(&self) -> Result { + fn has_immortal_handles(&self) -> Result { println!("Connection<{}>::has_immortal_handles()", self.id()); Ok(true)