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",
|
"anyhow",
|
||||||
"dbus",
|
"dbus",
|
||||||
"deltachat",
|
"deltachat",
|
||||||
|
"rand 0.7.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@@ -9,8 +9,9 @@ license = "MIT"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
dbus = "0.8.2"
|
dbus = "0.8"
|
||||||
deltachat = { git = "https://github.com/deltachat/deltachat-core-rust", tag="1.31.0" }
|
deltachat = { git = "https://github.com/deltachat/deltachat-core-rust", tag="1.31.0" }
|
||||||
|
rand = "0.7"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
65
src/main.rs
65
src/main.rs
@@ -6,22 +6,50 @@ use dbus::{
|
|||||||
blocking::{stdintf::org_freedesktop_dbus::RequestNameReply, LocalConnection},
|
blocking::{stdintf::org_freedesktop_dbus::RequestNameReply, LocalConnection},
|
||||||
tree::Factory,
|
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;
|
use std::time::Duration;
|
||||||
|
|
||||||
const CM_BUS_NAME: &'static str = "org.freedesktop.Telepathy.ConnectionManager.padfoot";
|
#[derive(Debug, Default)]
|
||||||
const CM_OBJECT_PATH: &'static str = "/org/freedesktop/Telepathy/ConnectionManager/padfoot";
|
struct TData {
|
||||||
const PROTO_OBJECT_PATH: &'static str =
|
cm: ConnectionManager,
|
||||||
"/org/freedesktop/Telepathy/ConnectionManager/padfoot/delta";
|
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<()> {
|
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 mut tree = f.tree(());
|
||||||
|
|
||||||
let proto: &'static Protocol = &Protocol {};
|
let cm_iface = telepathy::connection_manager_server(&f, Arc::clone(&data), |m| {
|
||||||
let cm: &'static ConnectionManager = &ConnectionManager {};
|
let a: &Arc<TData> = &m.iface.get_data();
|
||||||
let cm_iface = telepathy::connection_manager_server(&f, (), move |_m| cm);
|
let b: &TData = &a;
|
||||||
let proto_iface = telepathy::protocol_server(&f, (), move |_m| proto);
|
|
||||||
|
&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(
|
tree = tree.add(
|
||||||
f.object_path(CM_OBJECT_PATH, ())
|
f.object_path(CM_OBJECT_PATH, ())
|
||||||
@@ -40,16 +68,15 @@ fn run() -> Result<()> {
|
|||||||
let mut c = LocalConnection::new_session()?;
|
let mut c = LocalConnection::new_session()?;
|
||||||
tree.start_receive(&c);
|
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] {
|
||||||
match result {
|
let result = c.request_name(name, false, false, true)?;
|
||||||
RequestNameReply::Exists => {
|
match result {
|
||||||
return Err(anyhow!(
|
RequestNameReply::Exists => {
|
||||||
"Another process is already registered on {}",
|
return Err(anyhow!("Another process is already registered on {}", name))
|
||||||
CM_BUS_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 {
|
loop {
|
||||||
c.process(Duration::from_secs(1))?;
|
c.process(Duration::from_secs(1))?;
|
||||||
|
@@ -1,3 +1,6 @@
|
|||||||
|
mod connection;
|
||||||
|
pub use self::connection::*;
|
||||||
|
|
||||||
mod connection_manager;
|
mod connection_manager;
|
||||||
pub use self::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 crate::telepathy;
|
||||||
|
|
||||||
use dbus::{arg, tree};
|
use dbus::{arg, tree};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
// FIXME: CM should take an opaque set of protocols to advertise
|
pub const CM_BUS_NAME: &'static str = "org.freedesktop.Telepathy.ConnectionManager.padfoot";
|
||||||
use super::protocol;
|
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)]
|
#[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 {
|
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);
|
println!("CM::get_parameters({})", protocol);
|
||||||
|
|
||||||
match protocol {
|
match protocol {
|
||||||
protocol::NAME => Ok(protocol::parameters()),
|
super::PROTO_NAME => Ok(super::parameters()),
|
||||||
_ => Err(tree::MethodErr::no_arg()), // FIXME: should be NotImplemented?
|
_ => 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> {
|
fn list_protocols(&self) -> Result<Vec<String>, tree::MethodErr> {
|
||||||
println!("CM::list_protocols()");
|
println!("CM::list_protocols()");
|
||||||
|
|
||||||
Ok(vec![protocol::NAME.to_string()])
|
Ok(vec![super::PROTO_NAME.to_string()])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_connection(
|
fn request_connection(
|
||||||
&self,
|
&self,
|
||||||
protocol: &str,
|
protocol: &str,
|
||||||
parameters: HashMap<&str, protocol::Variant>,
|
params: HashMap<&str, super::Variant>,
|
||||||
) -> Result<(String, dbus::Path<'static>), tree::MethodErr> {
|
) -> 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(
|
fn protocols(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<HashMap<String, HashMap<String, protocol::Variant>>, tree::MethodErr> {
|
) -> Result<HashMap<String, HashMap<String, super::Variant>>, tree::MethodErr> {
|
||||||
println!("CM::protocols()");
|
println!("CM::protocols()");
|
||||||
|
|
||||||
// FIXME: so much duplication
|
// FIXME: so much duplication. It would be good if we could get the
|
||||||
let mut out = HashMap::<String, HashMap<String, protocol::Variant>>::new();
|
// properties from the Protocol instead
|
||||||
let mut props = HashMap::<String, protocol::Variant>::new();
|
let mut out = HashMap::<String, HashMap<String, super::Variant>>::new();
|
||||||
|
let mut props = HashMap::<String, super::Variant>::new();
|
||||||
|
|
||||||
props.insert(
|
props.insert(
|
||||||
"org.freedesktop.Telepathy.Protocol.AuthenticationTypes".to_string(),
|
"org.freedesktop.Telepathy.Protocol.AuthenticationTypes".to_string(),
|
||||||
@@ -71,18 +117,18 @@ impl telepathy::ConnectionManager for ConnectionManager {
|
|||||||
);
|
);
|
||||||
props.insert(
|
props.insert(
|
||||||
"org.freedesktop.Telepathy.Protocol.Parameters".to_string(),
|
"org.freedesktop.Telepathy.Protocol.Parameters".to_string(),
|
||||||
arg::Variant(Box::new(protocol::parameters())),
|
arg::Variant(Box::new(super::parameters())),
|
||||||
);
|
);
|
||||||
props.insert(
|
props.insert(
|
||||||
"org.freedesktop.Telepathy.Protocol.RequestableChannelClasses".to_string(),
|
"org.freedesktop.Telepathy.Protocol.RequestableChannelClasses".to_string(),
|
||||||
arg::Variant(Box::new(protocol::requestables())),
|
arg::Variant(Box::new(super::requestables())),
|
||||||
);
|
);
|
||||||
props.insert(
|
props.insert(
|
||||||
"org.freedesktop.Telepathy.Protocol.VCardField".to_string(),
|
"org.freedesktop.Telepathy.Protocol.VCardField".to_string(),
|
||||||
arg::Variant(Box::new("email".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)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,13 @@ use crate::telepathy;
|
|||||||
use dbus::{arg, tree};
|
use dbus::{arg, tree};
|
||||||
use std::collections::HashMap;
|
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 struct Protocol {}
|
||||||
|
|
||||||
pub type Variant = arg::Variant<Box<dyn arg::RefArg + 'static>>;
|
pub type Variant = arg::Variant<Box<dyn arg::RefArg + 'static>>;
|
||||||
@@ -14,14 +20,12 @@ pub type ParamSpec = (
|
|||||||
Variant, // Default
|
Variant, // Default
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Requestable_Channel_Class
|
||||||
pub type RequestableChannelSpec = (
|
pub type RequestableChannelSpec = (
|
||||||
// Requestable_Channel_Class
|
|
||||||
HashMap<String, Variant>, // Fixed properties
|
HashMap<String, Variant>, // Fixed properties
|
||||||
Vec<String>, // Allowed properties
|
Vec<String>, // Allowed properties
|
||||||
);
|
);
|
||||||
|
|
||||||
pub const NAME: &'static str = "delta";
|
|
||||||
|
|
||||||
// FIXME: these should come from codegen
|
// FIXME: these should come from codegen
|
||||||
//const FLAG_NONE: u32 = 0;
|
//const FLAG_NONE: u32 = 0;
|
||||||
const FLAG_REQUIRED: u32 = 1;
|
const FLAG_REQUIRED: u32 = 1;
|
||||||
|
Reference in New Issue
Block a user