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.
This commit is contained in:
2020-05-17 15:20:16 +01:00
parent b814a9aab0
commit 1eefce4f1c
3 changed files with 92 additions and 42 deletions

View File

@@ -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)

View File

@@ -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);
}
}
}
}

View File

@@ -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<T> = std::result::Result<T, dbus::tree::MethodErr>;
// 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<String> {
vec![
"org.freedesktop.Telepathy.Connection".to_string(),
@@ -33,7 +44,7 @@ impl AsRef<dyn telepathy::Connection + 'static> for std::rc::Rc<Connection> {
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<Vec<String>, MethodErr> {
fn interfaces(&self) -> Result<Vec<String>> {
println!("Connection<{}>::interfaces()", self.id());
self.get_interfaces()
}
fn get_interfaces(&self) -> Result<Vec<String>, MethodErr> {
fn get_interfaces(&self) -> Result<Vec<String>> {
println!("Connection<{}>::get_interfaces()", self.id());
Ok(connection_interfaces())
}
fn get_protocol(&self) -> Result<String, MethodErr> {
fn get_protocol(&self) -> Result<String> {
println!("Connection<{}>::get_protocol()", self.id());
Ok(crate::padfoot::PROTO_NAME.to_string())
}
fn self_handle(&self) -> Result<u32, MethodErr> {
fn self_handle(&self) -> Result<u32> {
println!("Connection<{}>::self_handle()", self.id());
self.get_self_handle()
}
fn get_self_handle(&self) -> Result<u32, MethodErr> {
println!("Connection<{}>::get_self_handle()", self.id());
Ok(dc::constants::DC_CONTACT_ID_SELF)
}
fn status(&self) -> Result<u32, MethodErr> {
// Deprecated in favour of the self_handle DBUS property
fn get_self_handle(&self) -> Result<u32> {
println!("Connection<{}>::get_self_handle()", self.id());
self.get_self_handle()
}
fn status(&self) -> Result<u32> {
println!("Connection<{}>::status()", self.id());
self.get_status()
}
fn get_status(&self) -> Result<u32, MethodErr> {
fn get_status(&self) -> Result<u32> {
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<u32>) -> Result<(), MethodErr> {
fn hold_handles(&self, handle_type: u32, handles: Vec<u32>) -> 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<u32>,
) -> Result<Vec<String>, MethodErr> {
fn inspect_handles(&self, handle_type: u32, handles: Vec<u32>) -> Result<Vec<String>> {
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<Vec<(dbus::Path<'static>, String, u32, u32)>, MethodErr> {
// Deprecated in favour of Requests.Channels
fn list_channels(&self) -> Result<Vec<ChannelInfo>> {
println!("Connection<{}>::list_channels()", self.id());
Err(MethodErr::no_arg()) // FIXME: should be NotImplemented?
let data = self.channels()?;
let mut out = Vec::<ChannelInfo>::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<u32>) -> Result<(), MethodErr> {
fn release_handles(&self, handle_type: u32, handles: Vec<u32>) -> 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<dbus::Path<'static>, MethodErr> {
) -> Result<dbus::Path<'static>> {
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<Vec<u32>, MethodErr> {
fn request_handles(&self, handle_type: u32, identifiers: Vec<&str>) -> Result<Vec<u32>> {
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<String, MethodErr> {
fn self_id(&self) -> Result<String> {
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<bool, MethodErr> {
fn has_immortal_handles(&self) -> Result<bool> {
println!("Connection<{}>::has_immortal_handles()", self.id());
Ok(true)