Deltachat connects on connection startup

This commit is contained in:
2020-05-12 01:25:48 +01:00
parent 9151f64a6d
commit 2a565b3ee7
7 changed files with 228 additions and 44 deletions

View File

@@ -23,8 +23,8 @@ fn run() -> Result<()> {
let f = Factory::new_fn::<()>();
let mut tree = f.tree(());
let cm_iface = telepathy::connection_manager_server(&f, (), move |_| cm_rc.clone() );
let proto_iface = telepathy::protocol_server(&f, (), move |_| proto_rc.clone() );
let cm_iface = telepathy::connection_manager_server(&f, (), move |_| cm_rc.clone());
let proto_iface = telepathy::protocol_server(&f, (), move |_| proto_rc.clone());
tree = tree.add(
f.object_path(CM_OBJECT_PATH, ())

View File

@@ -1,7 +1,15 @@
use crate::telepathy;
use dbus::blocking::{stdintf::org_freedesktop_dbus::RequestNameReply, LocalConnection};
use dbus::tree;
use dc::config::Config;
use dc::context::Context;
use dc::Event;
use deltachat as dc;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::thread;
use std::time::Duration;
pub const CONN_BUS_NAME: &'static str = "org.freedesktop.Telepathy.Connection.padfoot.delta";
@@ -10,8 +18,7 @@ pub const CONN_OBJECT_PATH: &'static str = "/org/freedesktop/Telepathy/Connectio
#[derive(Debug)]
pub struct Connection {
id: String,
account: String,
password: String,
ctx: Arc<RwLock<Context>>,
}
fn escape_one(b: u8) -> String {
@@ -68,6 +75,70 @@ mod tests {
}
impl Connection {
pub fn new(params: HashMap<&str, super::Variant>) -> Result<Self, dbus::tree::MethodErr> {
let err = Err(dbus::tree::MethodErr::no_arg());
let acct = match params.get("account") {
Some(variant) => match variant.0.as_str() {
Some(str) => str.to_string(),
None => return err,
},
None => return err,
};
let id = escape(acct.to_owned());
let password = match params.get("password") {
Some(variant) => match variant.0.as_str() {
Some(str) => str.to_string(),
None => return err,
},
None => return err,
};
let mut dbfile = directories::ProjectDirs::from("gs", "ur", "telepathy-padfoot")
.ok_or_else(|| tree::MethodErr::no_arg())
.and_then(|p| Ok(p.data_local_dir().to_path_buf()))?;
dbfile.push(&id);
dbfile.push("db.sqlite3");
// FIXME: how to give it access to the connection (initialized later)?
let id2 = id.clone();
let f = move |_c: &Context, e: Event| {
match e {
Event::Info(msg) => println!("Connection<{}>: INFO: {}", id2, msg),
Event::Warning(msg) => println!("Connection<{}>: WARN : {}", id2, msg),
Event::Error(msg) | Event::ErrorNetwork(msg) | Event::ErrorSelfNotInGroup(msg) => {
println!("Connection<{}>: ERR : {}", id2, msg)
}
_ => println!("Connection<{}>: unhandled event received: {:?}", id2, e),
};
};
let ctx =
Context::new(Box::new(f), "telepathy-padfoot".to_string(), dbfile).map_err(|e| {
println!("Connection<{}>: couldn't get delta context: {}", id, e);
tree::MethodErr::no_arg() // FIXME: better error handling
})?;
ctx.set_config(Config::Addr, Some(&acct))
.map_err(|_e| tree::MethodErr::no_arg())?;
ctx.set_config(Config::MailPw, Some(&password))
.map_err(|_e| tree::MethodErr::no_arg())?;
ctx.set_config(Config::SentboxWatch, Some(&"Sent"))
.map_err(|_e| tree::MethodErr::no_arg())?;
if !ctx.is_configured() {
ctx.configure();
};
Ok(Connection {
id: id,
ctx: Arc::new(RwLock::new(ctx)),
})
}
// This is run inside its own thread
//
// FIXME: running several +process+ loops sure is convenient, but it also
@@ -75,6 +146,7 @@ impl Connection {
pub fn run(self) {
let bus = self.bus();
let path = self.path();
let ctx = self.ctx.clone();
let c_rc = std::rc::Rc::new(self);
let f = tree::Factory::new_fn::<()>();
@@ -108,7 +180,60 @@ impl Connection {
_ => println!("{} listening on {}", c.unique_name(), bus), // All other responses we can get are a success
};
loop {
// Set up delta jobs last in case registering to DBUS fails
// "Borrowed" from https://github.com/deltachat/deltachat-core-rust/blob/master/examples/simple.rs
let running = Arc::new(RwLock::new(true));
let inbox_ctx = ctx.clone();
let r1 = running.clone();
let _t1 = thread::spawn(move || {
while *r1.read().unwrap() {
dc::job::perform_inbox_jobs(&inbox_ctx.read().unwrap());
if *r1.read().unwrap() {
dc::job::perform_inbox_fetch(&inbox_ctx.read().unwrap());
if *r1.read().unwrap() {
dc::job::perform_inbox_idle(&inbox_ctx.read().unwrap());
}
}
}
});
let smtp_ctx = ctx.clone();
let r1 = running.clone();
let _t2 = thread::spawn(move || {
while *r1.read().unwrap() {
dc::job::perform_smtp_jobs(&smtp_ctx.read().unwrap());
if *r1.read().unwrap() {
dc::job::perform_smtp_idle(&smtp_ctx.read().unwrap());
}
}
});
let mvbox_ctx = ctx.clone();
let r1 = running.clone();
let _t3 = thread::spawn(move || {
while *r1.read().unwrap() {
dc::job::perform_mvbox_fetch(&mvbox_ctx.read().unwrap());
if *r1.read().unwrap() {
dc::job::perform_mvbox_idle(&mvbox_ctx.read().unwrap());
}
}
});
let sentbox_ctx = ctx.clone();
let r1 = running.clone();
let _t4 = thread::spawn(move || {
while *r1.read().unwrap() {
dc::job::perform_sentbox_fetch(&sentbox_ctx.read().unwrap());
if *r1.read().unwrap() {
dc::job::perform_sentbox_idle(&sentbox_ctx.read().unwrap());
}
}
});
let r1 = running.clone();
while *r1.read().unwrap() {
match c.process(Duration::from_millis(100)) {
Err(e) => {
println!("Error processing: {}", e);
@@ -121,34 +246,6 @@ impl Connection {
}
}
pub fn new(params: HashMap<&str, super::Variant>) -> Result<Self, dbus::tree::MethodErr> {
let err = Err(dbus::tree::MethodErr::no_arg());
let acct = match params.get("account") {
Some(variant) => match variant.0.as_str() {
Some(str) => str.to_string(),
None => return err,
},
None => return err,
};
let id = escape(acct.to_owned());
let password = match params.get("password") {
Some(variant) => match variant.0.as_str() {
Some(str) => str.to_string(),
None => return err,
},
None => return err,
};
Ok(Connection {
id: id,
account: acct,
password: password,
})
}
pub fn bus(&self) -> String {
CONN_BUS_NAME.to_owned() + "." + &self.id
}
@@ -159,7 +256,9 @@ impl Connection {
}
impl AsRef<dyn telepathy::Connection + 'static> for std::rc::Rc<Connection> {
fn as_ref(&self) -> &(dyn telepathy::Connection + 'static) { &**self }
fn as_ref(&self) -> &(dyn telepathy::Connection + 'static) {
&**self
}
}
impl telepathy::Connection for Connection {

View File

@@ -15,17 +15,22 @@ pub struct ConnectionManager {
}
impl AsRef<dyn telepathy::ConnectionManager + 'static> for std::rc::Rc<ConnectionManager> {
fn as_ref(&self) -> &(dyn telepathy::ConnectionManager + 'static) { &**self }
fn as_ref(&self) -> &(dyn telepathy::ConnectionManager + 'static) {
&**self
}
}
impl ConnectionManager {
pub fn new() -> (Self, mpsc::Receiver<dbus::Message>) {
let (msg_s, msg_r) = std::sync::mpsc::channel::<dbus::Message>();
(ConnectionManager {
conns: std::sync::Mutex::new(HashSet::<String>::new()),
sender: msg_s,
}, msg_r)
(
ConnectionManager {
conns: std::sync::Mutex::new(HashSet::<String>::new()),
sender: msg_s,
},
msg_r,
)
}
fn create_connection(
@@ -64,7 +69,9 @@ impl ConnectionManager {
let dbus_cm_path = dbus::strings::Path::new(CM_OBJECT_PATH.to_string())
.expect("Object path should meet DBUS requirements");
self.sender.send(sig.to_emit_message(&dbus_cm_path)).expect("send signal");
self.sender
.send(sig.to_emit_message(&dbus_cm_path))
.expect("send signal");
// The bus name *must* be org.freedesktop.Telepathy.Connection.padfoot.delta.<name>
Ok((bus, dbus_conn_path))
@@ -92,7 +99,7 @@ impl telepathy::ConnectionManager for ConnectionManager {
protocol: &str,
params: HashMap<&str, super::Variant>,
) -> Result<(String, dbus::Path<'static>), tree::MethodErr> {
println!("CM::request_connection({}, {:?})", protocol, params);
println!("CM::request_connection({}, ...)", protocol);
match protocol {
super::PROTO_NAME => self.create_connection(params),

View File

@@ -76,7 +76,9 @@ pub fn requestables() -> Vec<RequestableChannelSpec> {
}
impl AsRef<dyn telepathy::Protocol + 'static> for std::rc::Rc<Protocol> {
fn as_ref(&self) -> &(dyn telepathy::Protocol + 'static) { &**self }
fn as_ref(&self) -> &(dyn telepathy::Protocol + 'static) {
&**self
}
}
impl telepathy::Protocol for Protocol {