Initial protocol implementation
Empathy needs this patch before it will display the settings: https://gitlab.gnome.org/GNOME/telepathy-account-widgets/-/merge_requests/1
This commit is contained in:
@@ -2,11 +2,10 @@
|
|||||||
Name=padfoot
|
Name=padfoot
|
||||||
BusName=org.freedesktop.Telepathy.ConnectionManager.padfoot
|
BusName=org.freedesktop.Telepathy.ConnectionManager.padfoot
|
||||||
ObjectPath=/org/freedesktop/Telepathy/ConnectionManager/padfoot
|
ObjectPath=/org/freedesktop/Telepathy/ConnectionManager/padfoot
|
||||||
Interfaces=
|
|
||||||
|
|
||||||
[Protocol delta]
|
[Protocol delta]
|
||||||
param-account=s required
|
param-account=s required
|
||||||
param-password=s required secret
|
param-password=s required secret
|
||||||
Interfaces=
|
|
||||||
EnglishName=Delta Chat
|
EnglishName=Delta Chat
|
||||||
|
VCardField=email
|
||||||
Icon=im-delta
|
Icon=im-delta
|
||||||
|
63
src/main.rs
63
src/main.rs
@@ -1,49 +1,44 @@
|
|||||||
mod padfoot;
|
mod padfoot;
|
||||||
mod telepathy;
|
mod telepathy;
|
||||||
|
|
||||||
//use dbus::tree::{Interface, MTFn, MethodErr};
|
use anyhow::{anyhow, Result};
|
||||||
use dbus::{
|
use dbus::{
|
||||||
blocking::{stdintf::org_freedesktop_dbus::RequestNameReply, LocalConnection},
|
blocking::{stdintf::org_freedesktop_dbus::RequestNameReply, LocalConnection},
|
||||||
tree::{Factory, MTFn, Tree},
|
tree::Factory,
|
||||||
};
|
};
|
||||||
|
use padfoot::{ConnectionManager, Protocol};
|
||||||
use padfoot::{CMData, ConnectionManager};
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
|
||||||
|
|
||||||
const CM_BUS_NAME: &'static str = "org.freedesktop.Telepathy.ConnectionManager.padfoot";
|
const CM_BUS_NAME: &'static str = "org.freedesktop.Telepathy.ConnectionManager.padfoot";
|
||||||
const CM_OBJECT_PATH: &'static str = "/org/freedesktop/Telepathy/ConnectionManager/padfoot";
|
const CM_OBJECT_PATH: &'static str = "/org/freedesktop/Telepathy/ConnectionManager/padfoot";
|
||||||
|
const PROTO_OBJECT_PATH: &'static str =
|
||||||
fn create_tree(cm: &Arc<ConnectionManager>) -> Tree<MTFn<CMData>, CMData> {
|
"/org/freedesktop/Telepathy/ConnectionManager/padfoot/delta";
|
||||||
let f = Factory::new_fn();
|
|
||||||
let mut tree = f.tree(());
|
|
||||||
|
|
||||||
let iface = telepathy::connection_manager_server(&f, (), |m| {
|
|
||||||
let a: &Arc<ConnectionManager> = m.path.get_data();
|
|
||||||
let b: &ConnectionManager = &a;
|
|
||||||
|
|
||||||
b
|
|
||||||
});
|
|
||||||
|
|
||||||
tree = tree.add(
|
|
||||||
f.object_path(CM_OBJECT_PATH, cm.clone())
|
|
||||||
.introspectable()
|
|
||||||
.add(iface),
|
|
||||||
);
|
|
||||||
tree = tree.add(f.object_path("/", cm.clone()).introspectable());
|
|
||||||
|
|
||||||
tree
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<()> {
|
fn run() -> Result<()> {
|
||||||
let cm: ConnectionManager = ConnectionManager {};
|
let f = Factory::new_fn::<()>();
|
||||||
let tree = create_tree(&Arc::new(cm));
|
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);
|
||||||
|
|
||||||
|
tree = tree.add(
|
||||||
|
f.object_path(CM_OBJECT_PATH, ())
|
||||||
|
.introspectable()
|
||||||
|
.add(cm_iface),
|
||||||
|
);
|
||||||
|
tree = tree.add(
|
||||||
|
f.object_path(PROTO_OBJECT_PATH, ())
|
||||||
|
.introspectable()
|
||||||
|
.add(proto_iface),
|
||||||
|
);
|
||||||
|
|
||||||
|
tree = tree.add(f.object_path("/", ()).introspectable());
|
||||||
|
|
||||||
// Setup DBus connection
|
// Setup DBus connection
|
||||||
let mut c = LocalConnection::new_session()?;
|
let mut c = LocalConnection::new_session()?;
|
||||||
|
tree.start_receive(&c);
|
||||||
|
|
||||||
let result = c.request_name(CM_BUS_NAME, false, false, true)?;
|
let result = c.request_name(CM_BUS_NAME, false, false, true)?;
|
||||||
match result {
|
match result {
|
||||||
@@ -53,15 +48,11 @@ fn run() -> Result<()> {
|
|||||||
CM_BUS_NAME
|
CM_BUS_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
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("Bus registered: {}", CM_BUS_NAME);
|
|
||||||
tree.start_receive(&c);
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
c.process(Duration::from_secs(1))?;
|
c.process(Duration::from_secs(1))?;
|
||||||
println!("Tick");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,89 +2,89 @@ use crate::telepathy;
|
|||||||
use dbus::{arg, tree};
|
use dbus::{arg, tree};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
// FIXME: CM should take an opaque set of protocols to advertise
|
||||||
|
use super::protocol;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ConnectionManager {}
|
pub struct ConnectionManager {}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Debug)]
|
|
||||||
pub struct CMData;
|
|
||||||
|
|
||||||
impl dbus::tree::DataType for CMData {
|
|
||||||
type Tree = ();
|
|
||||||
type Property = ();
|
|
||||||
type Interface = ();
|
|
||||||
type Method = ();
|
|
||||||
type Signal = ();
|
|
||||||
type ObjectPath = std::sync::Arc<ConnectionManager>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PROTO: &'static str = "delta";
|
|
||||||
|
|
||||||
pub type ParamSpec = (
|
|
||||||
String, // Name
|
|
||||||
u32, // Flags (Conn_Mgr_Param_Flags)
|
|
||||||
String, // Signature
|
|
||||||
arg::Variant<Box<dyn arg::RefArg + 'static>>, // Default
|
|
||||||
);
|
|
||||||
|
|
||||||
pub type Dict = HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>;
|
|
||||||
|
|
||||||
// FIXME: these should come from codegen
|
|
||||||
const FLAG_REQUIRED: u32 = 1;
|
|
||||||
//const FLAG_REGISTER: u32 = 2;
|
|
||||||
//const FLAG_HAS_DEFAULT: u32 = 4;
|
|
||||||
const FLAG_SECRET: u32 = 8;
|
|
||||||
//const FLAG_DBUS_PROP: u32 = 16;
|
|
||||||
|
|
||||||
impl telepathy::ConnectionManager for ConnectionManager {
|
impl telepathy::ConnectionManager for ConnectionManager {
|
||||||
fn get_parameters(&self, protocol: &str) -> Result<Vec<ParamSpec>, tree::MethodErr> {
|
fn get_parameters(&self, protocol: &str) -> Result<Vec<protocol::ParamSpec>, tree::MethodErr> {
|
||||||
println!("CM::get_parameters({})", protocol);
|
println!("CM::get_parameters({})", protocol);
|
||||||
|
|
||||||
if protocol != PROTO {
|
match protocol {
|
||||||
return Err(tree::MethodErr::no_arg()); // FIXME: should be NotImplemented?
|
protocol::NAME => Ok(protocol::parameters()),
|
||||||
|
_ => Err(tree::MethodErr::no_arg()), // FIXME: should be NotImplemented?
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: query the protocol for these?
|
|
||||||
Ok(vec![
|
|
||||||
(
|
|
||||||
"account".to_string(),
|
|
||||||
FLAG_REQUIRED,
|
|
||||||
"s".to_string(),
|
|
||||||
arg::Variant(Box::new("".to_string())),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"password".to_string(),
|
|
||||||
FLAG_REQUIRED | FLAG_SECRET,
|
|
||||||
"s".to_string(),
|
|
||||||
arg::Variant(Box::new("".to_string())),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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![PROTO.to_string()])
|
Ok(vec![protocol::NAME.to_string()])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_connection(
|
fn request_connection(
|
||||||
&self,
|
&self,
|
||||||
protocol: &str,
|
protocol: &str,
|
||||||
parameters: HashMap<&str, arg::Variant<Box<dyn arg::RefArg>>>,
|
parameters: HashMap<&str, protocol::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, parameters);
|
||||||
|
|
||||||
Err(tree::MethodErr::no_arg())
|
Err(tree::MethodErr::no_arg())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn protocols(&self) -> Result<HashMap<String, Dict>, tree::MethodErr> {
|
fn protocols(
|
||||||
|
&self,
|
||||||
|
) -> Result<HashMap<String, HashMap<String, protocol::Variant>>, tree::MethodErr> {
|
||||||
println!("CM::protocols()");
|
println!("CM::protocols()");
|
||||||
|
|
||||||
// If this map is empty or missing, clients SHOULD fall back to
|
// FIXME: so much duplication
|
||||||
// calling ListProtocols and GetParameters
|
let mut out = HashMap::<String, HashMap<String, protocol::Variant>>::new();
|
||||||
Err(tree::MethodErr::no_arg())
|
let mut props = HashMap::<String, protocol::Variant>::new();
|
||||||
|
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Protocol.AuthenticationTypes".to_string(),
|
||||||
|
arg::Variant(Box::new(Vec::<String>::new())),
|
||||||
|
);
|
||||||
|
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Protocol.ConnectionInterfaces".to_string(),
|
||||||
|
arg::Variant(Box::new(Vec::<String>::new())),
|
||||||
|
);
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Protocol.EnglishName".to_string(),
|
||||||
|
arg::Variant(Box::new("Delta Chat".to_string())),
|
||||||
|
);
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Protocol.Icon".to_string(),
|
||||||
|
arg::Variant(Box::new("im-delta".to_string())),
|
||||||
|
);
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Protocol.Interfaces".to_string(),
|
||||||
|
arg::Variant(Box::new(Vec::<String>::new())),
|
||||||
|
);
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Protocol.Parameters".to_string(),
|
||||||
|
arg::Variant(Box::new(protocol::parameters())),
|
||||||
|
);
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Protocol.RequestableChannelClasses".to_string(),
|
||||||
|
arg::Variant(Box::new(Vec::<String>::new())),
|
||||||
|
);
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Protocol.VCardField".to_string(),
|
||||||
|
arg::Variant(Box::new("email".to_string())),
|
||||||
|
);
|
||||||
|
|
||||||
|
out.insert(protocol::NAME.to_string(), props);
|
||||||
|
|
||||||
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interfaces(&self) -> Result<Vec<String>, tree::MethodErr> {
|
fn interfaces(&self) -> Result<Vec<String>, tree::MethodErr> {
|
||||||
|
println!("CM::interfaces()");
|
||||||
|
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1 +1,106 @@
|
|||||||
|
use crate::telepathy;
|
||||||
|
use dbus::{arg, tree};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Protocol {}
|
pub struct Protocol {}
|
||||||
|
|
||||||
|
pub type ParamSpec = (
|
||||||
|
String, // Name
|
||||||
|
u32, // Flags (Conn_Mgr_Param_Flags)
|
||||||
|
String, // Signature
|
||||||
|
arg::Variant<Box<dyn arg::RefArg + 'static>>, // Default
|
||||||
|
);
|
||||||
|
|
||||||
|
pub type Variant = arg::Variant<Box<dyn arg::RefArg + 'static>>;
|
||||||
|
|
||||||
|
pub const NAME: &'static str = "delta";
|
||||||
|
|
||||||
|
// FIXME: these should come from codegen
|
||||||
|
//const FLAG_NONE: u32 = 0;
|
||||||
|
const FLAG_REQUIRED: u32 = 1;
|
||||||
|
//const FLAG_REGISTER: u32 = 2;
|
||||||
|
//const FLAG_HAS_DEFAULT: u32 = 4;
|
||||||
|
const FLAG_SECRET: u32 = 8;
|
||||||
|
//const FLAG_DBUS_PROP: u32 = 16;
|
||||||
|
|
||||||
|
pub fn parameters() -> Vec<ParamSpec> {
|
||||||
|
vec![
|
||||||
|
(
|
||||||
|
"account".to_string(),
|
||||||
|
FLAG_REQUIRED,
|
||||||
|
"s".to_string(),
|
||||||
|
arg::Variant(Box::new("".to_string())),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"password".to_string(),
|
||||||
|
FLAG_REQUIRED | FLAG_SECRET,
|
||||||
|
"s".to_string(),
|
||||||
|
arg::Variant(Box::new("".to_string())),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl telepathy::Protocol for Protocol {
|
||||||
|
fn identify_account(&self, params: HashMap<&str, Variant>) -> Result<String, tree::MethodErr> {
|
||||||
|
println!("Protocol::identify_account({:?})", params);
|
||||||
|
|
||||||
|
Err(tree::MethodErr::no_arg())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalize_contact(&self, contact_id: &str) -> Result<String, tree::MethodErr> {
|
||||||
|
println!("Protocol::normalize_contact({})", contact_id);
|
||||||
|
|
||||||
|
Err(tree::MethodErr::no_arg())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interfaces(&self) -> Result<Vec<String>, tree::MethodErr> {
|
||||||
|
println!("Protocol::interfaces()");
|
||||||
|
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
fn parameters(&self) -> Result<Vec<ParamSpec>, tree::MethodErr> {
|
||||||
|
println!("Protocol::parameters()");
|
||||||
|
|
||||||
|
Ok(parameters())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connection_interfaces(&self) -> Result<Vec<String>, tree::MethodErr> {
|
||||||
|
println!("Protocol::connection_interfaces()");
|
||||||
|
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
fn requestable_channel_classes(
|
||||||
|
&self,
|
||||||
|
) -> Result<
|
||||||
|
Vec<(
|
||||||
|
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
|
||||||
|
Vec<String>,
|
||||||
|
)>,
|
||||||
|
tree::MethodErr,
|
||||||
|
> {
|
||||||
|
println!("Protocol::requestable_channel_classes()");
|
||||||
|
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
fn vcard_field(&self) -> Result<String, tree::MethodErr> {
|
||||||
|
println!("Protocol::vcard_field()");
|
||||||
|
|
||||||
|
Ok("email".to_string())
|
||||||
|
}
|
||||||
|
fn english_name(&self) -> Result<String, tree::MethodErr> {
|
||||||
|
println!("Protocol::english_name()");
|
||||||
|
|
||||||
|
Ok("Delta Chat".to_string())
|
||||||
|
}
|
||||||
|
fn icon(&self) -> Result<String, tree::MethodErr> {
|
||||||
|
println!("Protocol::icon()");
|
||||||
|
|
||||||
|
Ok("im-delta".to_string())
|
||||||
|
}
|
||||||
|
fn authentication_types(&self) -> Result<Vec<String>, tree::MethodErr> {
|
||||||
|
println!("Protocol::authentication_types()");
|
||||||
|
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user