Rework to get a map of connections in ConnectionManager
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2647,6 +2647,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"dbus",
|
||||
"deltachat",
|
||||
"rand 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@@ -9,8 +9,9 @@ license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
dbus = "0.8.2"
|
||||
dbus = "0.8"
|
||||
deltachat = { git = "https://github.com/deltachat/deltachat-core-rust", tag="1.31.0" }
|
||||
rand = "0.7"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
61
src/main.rs
61
src/main.rs
@@ -6,22 +6,50 @@ use dbus::{
|
||||
blocking::{stdintf::org_freedesktop_dbus::RequestNameReply, LocalConnection},
|
||||
tree::Factory,
|
||||
};
|
||||
use padfoot::{ConnectionManager, Protocol};
|
||||
use padfoot::{
|
||||
Connection, ConnectionManager, Protocol, CM_BUS_NAME, CM_CONN_BUS_NAME, CM_OBJECT_PATH,
|
||||
CONN_BUS_NAME, PROTO_BUS_NAME, PROTO_OBJECT_PATH,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
const CM_BUS_NAME: &'static str = "org.freedesktop.Telepathy.ConnectionManager.padfoot";
|
||||
const CM_OBJECT_PATH: &'static str = "/org/freedesktop/Telepathy/ConnectionManager/padfoot";
|
||||
const PROTO_OBJECT_PATH: &'static str =
|
||||
"/org/freedesktop/Telepathy/ConnectionManager/padfoot/delta";
|
||||
#[derive(Debug, Default)]
|
||||
struct TData {
|
||||
cm: ConnectionManager,
|
||||
p: Protocol,
|
||||
}
|
||||
|
||||
impl dbus::tree::DataType for TData {
|
||||
type Interface = Arc<TData>;
|
||||
type Tree = ();
|
||||
type Property = ();
|
||||
type ObjectPath = ();
|
||||
|
||||
type Method = ();
|
||||
type Signal = ();
|
||||
}
|
||||
|
||||
fn run() -> Result<()> {
|
||||
let f = Factory::new_fn::<()>();
|
||||
let cm = ConnectionManager::new();
|
||||
let proto = Protocol {};
|
||||
let data = Arc::new(TData { cm: cm, p: proto });
|
||||
|
||||
let f = Factory::new_fn::<TData>();
|
||||
let mut tree = f.tree(());
|
||||
|
||||
let proto: &'static Protocol = &Protocol {};
|
||||
let cm: &'static ConnectionManager = &ConnectionManager {};
|
||||
let cm_iface = telepathy::connection_manager_server(&f, (), move |_m| cm);
|
||||
let proto_iface = telepathy::protocol_server(&f, (), move |_m| proto);
|
||||
let cm_iface = telepathy::connection_manager_server(&f, Arc::clone(&data), |m| {
|
||||
let a: &Arc<TData> = &m.iface.get_data();
|
||||
let b: &TData = &a;
|
||||
|
||||
&b.cm
|
||||
});
|
||||
|
||||
let proto_iface = telepathy::protocol_server(&f, Arc::clone(&data), |m| {
|
||||
let a: &Arc<TData> = &m.iface.get_data();
|
||||
let b: &TData = &a;
|
||||
|
||||
&b.p
|
||||
});
|
||||
|
||||
tree = tree.add(
|
||||
f.object_path(CM_OBJECT_PATH, ())
|
||||
@@ -40,16 +68,15 @@ fn run() -> Result<()> {
|
||||
let mut c = LocalConnection::new_session()?;
|
||||
tree.start_receive(&c);
|
||||
|
||||
let result = c.request_name(CM_BUS_NAME, false, false, true)?;
|
||||
for name in vec![CM_BUS_NAME, PROTO_BUS_NAME, CM_CONN_BUS_NAME, CONN_BUS_NAME] {
|
||||
let result = c.request_name(name, false, false, true)?;
|
||||
match result {
|
||||
RequestNameReply::Exists => {
|
||||
return Err(anyhow!(
|
||||
"Another process is already registered on {}",
|
||||
CM_BUS_NAME
|
||||
))
|
||||
return Err(anyhow!("Another process is already registered on {}", name))
|
||||
}
|
||||
_ => println!("{} listening on {}", c.unique_name(), name), // All other responses we can get are a success
|
||||
}
|
||||
}
|
||||
_ => println!("{} listening on {}", c.unique_name(), CM_BUS_NAME), // All other responses we can get are a success
|
||||
};
|
||||
|
||||
loop {
|
||||
c.process(Duration::from_secs(1))?;
|
||||
|
@@ -1,3 +1,6 @@
|
||||
mod connection;
|
||||
pub use self::connection::*;
|
||||
|
||||
mod connection_manager;
|
||||
pub use self::connection_manager::*;
|
||||
|
||||
|
53
src/padfoot/connection.rs
Normal file
53
src/padfoot/connection.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use rand::Rng;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub const CONN_BUS_NAME: &'static str = "org.freedesktop.Telepathy.Connection.padfoot.delta";
|
||||
pub const CONN_OBJECT_PATH: &'static str = "org/freedesktop/Telepathy/Connection/padfoot/delta";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Connection {
|
||||
path: String,
|
||||
account: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
pub fn new(params: HashMap<&str, super::Variant>) -> Result<Self, dbus::tree::MethodErr> {
|
||||
let err = Err(dbus::tree::MethodErr::no_arg());
|
||||
|
||||
// Generate a unique identifier for this connection
|
||||
let id = rand::thread_rng()
|
||||
.sample_iter(&rand::distributions::Alphanumeric)
|
||||
.take(16)
|
||||
.collect::<String>();
|
||||
|
||||
let path = super::CONN_OBJECT_PATH.to_owned() + "/" + &id;
|
||||
|
||||
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 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 {
|
||||
path: path,
|
||||
account: acct,
|
||||
password: password,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn path(&self) -> String {
|
||||
return self.path.to_owned();
|
||||
}
|
||||
}
|
@@ -1,19 +1,61 @@
|
||||
use crate::telepathy;
|
||||
|
||||
use dbus::{arg, tree};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Mutex;
|
||||
|
||||
// FIXME: CM should take an opaque set of protocols to advertise
|
||||
use super::protocol;
|
||||
pub const CM_BUS_NAME: &'static str = "org.freedesktop.Telepathy.ConnectionManager.padfoot";
|
||||
pub const CM_CONN_BUS_NAME: &'static str = "org.freedesktop.Telepathy.Connection.padfoot";
|
||||
pub const CM_OBJECT_PATH: &'static str = "/org/freedesktop/Telepathy/ConnectionManager/padfoot";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConnectionManager {}
|
||||
pub struct ConnectionManager {
|
||||
conns: Mutex<HashMap<String, super::Connection>>, // FIXME: remove mutex if we can
|
||||
}
|
||||
|
||||
impl Default for ConnectionManager {
|
||||
fn default() -> Self {
|
||||
ConnectionManager {
|
||||
conns: Mutex::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectionManager {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn new_connection(
|
||||
&self,
|
||||
params: HashMap<&str, super::Variant>,
|
||||
) -> Result<(String, dbus::Path<'static>), tree::MethodErr> {
|
||||
let conn = super::Connection::new(params)?;
|
||||
let path = conn.path();
|
||||
|
||||
let mut conns = self.conns.lock().expect("mutex should be lockable");
|
||||
|
||||
conns.insert(path.to_owned(), conn);
|
||||
|
||||
// TODO: register new object path + bus name
|
||||
// Will this be easier if I give each one its own dbus connection?
|
||||
|
||||
// FIXME: does the bus name matter? Is it used for client recovery?
|
||||
// Maybe it should be org.freedesktop.Telepathy.Connection.padfoot.delta.<id>?
|
||||
Ok((
|
||||
CM_CONN_BUS_NAME.to_string(),
|
||||
dbus::strings::Path::new(path).expect("Object path should meet DBUS requirements"),
|
||||
))
|
||||
// Err(tree::MethodErr::no_arg())
|
||||
}
|
||||
}
|
||||
|
||||
impl telepathy::ConnectionManager for ConnectionManager {
|
||||
fn get_parameters(&self, protocol: &str) -> Result<Vec<protocol::ParamSpec>, tree::MethodErr> {
|
||||
fn get_parameters(&self, protocol: &str) -> Result<Vec<super::ParamSpec>, tree::MethodErr> {
|
||||
println!("CM::get_parameters({})", protocol);
|
||||
|
||||
match protocol {
|
||||
protocol::NAME => Ok(protocol::parameters()),
|
||||
super::PROTO_NAME => Ok(super::parameters()),
|
||||
_ => Err(tree::MethodErr::no_arg()), // FIXME: should be NotImplemented?
|
||||
}
|
||||
}
|
||||
@@ -21,27 +63,31 @@ impl telepathy::ConnectionManager for ConnectionManager {
|
||||
fn list_protocols(&self) -> Result<Vec<String>, tree::MethodErr> {
|
||||
println!("CM::list_protocols()");
|
||||
|
||||
Ok(vec![protocol::NAME.to_string()])
|
||||
Ok(vec![super::PROTO_NAME.to_string()])
|
||||
}
|
||||
|
||||
fn request_connection(
|
||||
&self,
|
||||
protocol: &str,
|
||||
parameters: HashMap<&str, protocol::Variant>,
|
||||
params: HashMap<&str, super::Variant>,
|
||||
) -> Result<(String, dbus::Path<'static>), tree::MethodErr> {
|
||||
println!("CM::request_connection({}, {:?})", protocol, parameters);
|
||||
println!("CM::request_connection({}, {:?})", protocol, params);
|
||||
|
||||
Err(tree::MethodErr::no_arg())
|
||||
match protocol {
|
||||
super::PROTO_NAME => self.new_connection(params),
|
||||
_ => Err(tree::MethodErr::no_arg()), // FIXME: should be NotImplemented?
|
||||
}
|
||||
}
|
||||
|
||||
fn protocols(
|
||||
&self,
|
||||
) -> Result<HashMap<String, HashMap<String, protocol::Variant>>, tree::MethodErr> {
|
||||
) -> Result<HashMap<String, HashMap<String, super::Variant>>, tree::MethodErr> {
|
||||
println!("CM::protocols()");
|
||||
|
||||
// FIXME: so much duplication
|
||||
let mut out = HashMap::<String, HashMap<String, protocol::Variant>>::new();
|
||||
let mut props = HashMap::<String, protocol::Variant>::new();
|
||||
// FIXME: so much duplication. It would be good if we could get the
|
||||
// properties from the Protocol instead
|
||||
let mut out = HashMap::<String, HashMap<String, super::Variant>>::new();
|
||||
let mut props = HashMap::<String, super::Variant>::new();
|
||||
|
||||
props.insert(
|
||||
"org.freedesktop.Telepathy.Protocol.AuthenticationTypes".to_string(),
|
||||
@@ -71,18 +117,18 @@ impl telepathy::ConnectionManager for ConnectionManager {
|
||||
);
|
||||
props.insert(
|
||||
"org.freedesktop.Telepathy.Protocol.Parameters".to_string(),
|
||||
arg::Variant(Box::new(protocol::parameters())),
|
||||
arg::Variant(Box::new(super::parameters())),
|
||||
);
|
||||
props.insert(
|
||||
"org.freedesktop.Telepathy.Protocol.RequestableChannelClasses".to_string(),
|
||||
arg::Variant(Box::new(protocol::requestables())),
|
||||
arg::Variant(Box::new(super::requestables())),
|
||||
);
|
||||
props.insert(
|
||||
"org.freedesktop.Telepathy.Protocol.VCardField".to_string(),
|
||||
arg::Variant(Box::new("email".to_string())),
|
||||
);
|
||||
|
||||
out.insert(protocol::NAME.to_string(), props);
|
||||
out.insert(super::PROTO_NAME.to_string(), props);
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
@@ -2,7 +2,13 @@ use crate::telepathy;
|
||||
use dbus::{arg, tree};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub const PROTO_OBJECT_PATH: &'static str =
|
||||
"/org/freedesktop/Telepathy/ConnectionManager/padfoot/delta";
|
||||
pub const PROTO_BUS_NAME: &'static str =
|
||||
"org.freedesktop.Telepathy.ConnectionManager.padfoot.delta";
|
||||
|
||||
pub const PROTO_NAME: &'static str = "delta";
|
||||
#[derive(Clone, Copy, Default, Debug)]
|
||||
pub struct Protocol {}
|
||||
|
||||
pub type Variant = arg::Variant<Box<dyn arg::RefArg + 'static>>;
|
||||
@@ -14,14 +20,12 @@ pub type ParamSpec = (
|
||||
Variant, // Default
|
||||
);
|
||||
|
||||
// Requestable_Channel_Class
|
||||
pub type RequestableChannelSpec = (
|
||||
// Requestable_Channel_Class
|
||||
HashMap<String, Variant>, // Fixed properties
|
||||
Vec<String>, // Allowed properties
|
||||
);
|
||||
|
||||
pub const NAME: &'static str = "delta";
|
||||
|
||||
// FIXME: these should come from codegen
|
||||
//const FLAG_NONE: u32 = 0;
|
||||
const FLAG_REQUIRED: u32 = 1;
|
||||
|
Reference in New Issue
Block a user