1use std::pin::Pin;
2use std::sync::Arc;
3use dbus::channel::{Sender, default_reply};
4use std::future::Future;
5use std::marker::PhantomData;
6use crate::{Context, MethodErr, IfaceBuilder, stdimpl};
7use crate::ifacedesc::Registry;
8use std::collections::{BTreeMap, HashSet};
9use std::any::Any;
10use std::fmt;
11use crate::utils::Dbg;
12
13const INTROSPECTABLE: usize = 0;
14const PROPERTIES: usize = 1;
15const OBJECT_MANAGER: usize = 2;
16
17pub struct IfaceToken<T: Send + 'static>(usize, PhantomData<&'static T>);
19
20impl<T: Send + 'static> Clone for IfaceToken<T> {
21 fn clone(&self) -> Self { IfaceToken(self.0, PhantomData) }
22}
23impl<T: Send + 'static> Copy for IfaceToken<T> {}
24impl<T: Send + 'static> Eq for IfaceToken<T> {}
25impl<T: Send + 'static> PartialEq for IfaceToken<T> {
26 fn eq(&self, a: &Self) -> bool { self.0 == a.0 }
27}
28impl<T: Send + 'static> Ord for IfaceToken<T> {
29 fn cmp(&self, a: &Self) -> std::cmp::Ordering { self.0.cmp(&a.0) }
30}
31impl<T: Send + 'static> PartialOrd for IfaceToken<T> {
32 fn partial_cmp(&self, a: &Self) -> Option<std::cmp::Ordering> { Some(self.0.cmp(&a.0)) }
33}
34impl<T: Send + 'static> fmt::Debug for IfaceToken<T> {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 write!(f, "IfaceToken({})", self.0)
37 }
38}
39
40
41#[derive(Debug)]
42struct Object {
43 ifaces: HashSet<usize>,
44 data: Box<dyn Any + Send + 'static>
45}
46
47pub type BoxedSpawn = Box<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send + 'static>>) + Send + 'static>;
48
49struct AsyncSupport {
50 sender: Arc<dyn Sender + Send + Sync + 'static>,
51 spawner: BoxedSpawn,
52}
53
54impl fmt::Debug for AsyncSupport {
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "AsyncSupport") }
56}
57
58#[derive(Debug)]
67pub struct Crossroads {
68 map: BTreeMap<dbus::Path<'static>, Object>,
69 registry: Registry,
70 add_standard_ifaces: bool,
71 async_support: Option<AsyncSupport>,
72 object_manager_support: Option<Dbg<Arc<dyn Sender + Send + Sync + 'static>>>,
73}
74
75impl Crossroads {
76 pub fn new() -> Crossroads {
78 let mut cr = Crossroads {
79 map: Default::default(),
80 registry: Default::default(),
81 add_standard_ifaces: true,
82 async_support: None,
83 object_manager_support: None,
84 };
85 let t0 = stdimpl::introspectable(&mut cr);
86 let t1 = stdimpl::properties(&mut cr);
87 let t2 = stdimpl::object_manager(&mut cr);
88 debug_assert_eq!(t0.0, INTROSPECTABLE);
89 debug_assert_eq!(t1.0, PROPERTIES);
90 debug_assert_eq!(t2.0, OBJECT_MANAGER);
91
92 cr.insert("/", &[], ());
94 cr
95 }
96
97 pub fn set_add_standard_ifaces(&mut self, enable: bool) {
100 self.add_standard_ifaces = enable;
101 }
102
103 pub fn register<T, N, F>(&mut self, name: N, f: F) -> IfaceToken<T>
106 where T: Send + 'static, N: Into<dbus::strings::Interface<'static>>,
107 F: FnOnce(&mut IfaceBuilder<T>)
108 {
109 let iface = IfaceBuilder::build(Some(name.into()), f);
110 let x = self.registry.push(iface);
111 IfaceToken(x, PhantomData)
112 }
113
114 pub fn data_mut<D: Any + Send + 'static>(&mut self, name: &dbus::Path<'static>) -> Option<&mut D> {
118 let obj = self.map.get_mut(name)?;
119 obj.data.downcast_mut()
120 }
121
122 pub fn insert<'z, D, I, N>(&mut self, name: N, ifaces: I, data: D)
126 where D: Any + Send + 'static, N: Into<dbus::Path<'static>>, I: IntoIterator<Item = &'z IfaceToken<D>>
127 {
128 let ifaces = ifaces.into_iter().map(|x| x.0);
129 let mut ifaces: HashSet<usize> = std::iter::FromIterator::from_iter(ifaces);
130 if self.add_standard_ifaces {
131 ifaces.insert(INTROSPECTABLE);
132 if ifaces.iter().any(|u| self.registry().has_props(*u)) {
133 ifaces.insert(PROPERTIES);
134 }
135 }
136 let name = name.into();
137 self.map.insert(name.clone(), Object { ifaces, data: Box::new(data)});
138 if let Some(oms) = self.object_manager_support.as_ref() {
139 stdimpl::object_manager_path_added(oms.0.clone(), &name, self);
140 }
141 }
142
143 pub fn add_interface<'z, D, N>(&mut self, name: N, iface: IfaceToken<D>) -> bool
149 where D: Any + Send + 'static, N: Into<dbus::Path<'static>>
150 {
151 let name = name.into();
152 if let Some(obj) = self.map.get_mut(&name) {
153 if !obj.data.is::<D>() {
154 return false;
156 }
157
158 if obj.ifaces.contains(&iface.0) {
159 return true;
161 }
162
163 obj.ifaces.insert(iface.0);
164 if let Some(oms) = self.object_manager_support.as_ref() {
165 stdimpl::object_manager_interface_added(oms.0.clone(), &name, iface.0, self);
166 }
167
168 return true;
169 }
170 false
171 }
172
173 pub fn remove_interface<'z, D, N>(&mut self, name: N, iface: IfaceToken<D>)
175 where D: Any + Send + 'static, N: Into<dbus::Path<'static>>
176 {
177 let name = name.into();
178 if let Some(obj) = self.map.get_mut(&name) {
179 if !obj.ifaces.contains(&iface.0) {
180 return;
181 }
182
183 obj.ifaces.remove(&iface.0);
184 if let Some(oms) = self.object_manager_support.as_ref() {
185 stdimpl::object_manager_interface_removed(oms.0.clone(), &name, iface.0, self);
186 }
187 }
188 }
189
190 pub fn has_interface<D: Send>(&self, name: &dbus::Path<'static>, token: IfaceToken<D>) -> bool {
192 self.map.get(name).map(|x| x.ifaces.contains(&token.0)).unwrap_or(false)
193 }
194
195 pub fn remove<D>(&mut self, name: &dbus::Path<'static>) -> Option<D>
200 where D: Any + Send + 'static {
201 if let Some(oms) = self.object_manager_support.as_ref() {
202 if self.map.contains_key(name) {
203 stdimpl::object_manager_path_removed(oms.0.clone(), &name, self);
204 }
205 }
206 let x = self.map.remove(name)?;
207 let r: Box<D> = x.data.downcast().ok()?;
208 Some(*r)
209 }
210
211 pub (crate) fn find_iface_token(&self,
212 path: &dbus::Path<'static>,
213 interface: Option<&dbus::strings::Interface<'static>>)
214 -> Result<usize, MethodErr> {
215 let obj = self.map.get(path).ok_or_else(|| MethodErr::no_path(path))?;
216 self.registry.find_token(interface, &obj.ifaces)
217 }
218
219 pub (crate) fn registry(&mut self) -> &mut Registry { &mut self.registry }
220
221 pub (crate) fn registry_and_ifaces(&self, path: &dbus::Path<'static>)
222 -> (&Registry, &HashSet<usize>) {
223 let obj = self.map.get(path).unwrap();
224 (&self.registry, &obj.ifaces)
225 }
226
227 pub (crate) fn get_children(&self, path: &dbus::Path<'static>, direct_only: bool) -> Vec<&str> {
228 use std::ops::Bound;
229 let mut range = self.map.range((Bound::Excluded(path), Bound::Unbounded));
230 let p2 = path.as_bytes();
231 let substart = if &p2 == &b"/" { 0 } else { p2.len() };
232 let mut r: Vec<&str> = vec!();
233 while let Some((c, _)) = range.next() {
234 if !c.as_bytes().starts_with(p2) { break; }
235 let csub: &str = &c[substart..];
236 if csub.len() == 0 || csub.as_bytes()[0] != b'/' { continue; }
237 let csub1 = &csub[1..];
238 if direct_only && r.len() > 0 {
239 let prev = r[r.len()-1].as_bytes();
240 let b = csub1.as_bytes();
241 if b.len() > prev.len() && b.starts_with(prev) && b[prev.len()] == b'/' { continue; }
242 }
243 r.push(csub1);
244 };
245 r
246 }
247
248 pub (crate) fn run_async_method<F, R>(&mut self, f: F)
249 where F: FnOnce(Arc<dyn Sender + Send + Sync + 'static>, &mut Crossroads) -> R,
250 R: Future<Output=()> + Send + 'static
251 {
252 let sender = self.async_support.as_ref().expect("Async support not set").sender.clone();
253 let future = f(sender, self);
254 let spawner = &self.async_support.as_ref().expect("Async support not set").spawner;
255 let boxed = Box::pin(async move { future.await });
256 (spawner)(boxed)
257 }
258
259 fn handle_message_inner(&mut self, mut ctx: Context) -> Option<Context> {
260 let itoken_result = match self.find_iface_token(ctx.path(), ctx.interface()) {
261 Ok(x) => Ok(x),
262 Err(merr) => {
263 if let Some(rmsg) = default_reply(ctx.message()) {
264 ctx.push_msg(rmsg);
265 return Some(ctx)
266 }
267 Err(merr)
268 }
269 };
270
271 let (itoken, mut cb) = match ctx.check(|ctx| {
272 let itoken = itoken_result?;
273 let cb = self.registry.take_method(itoken, ctx.method())?;
274 Ok((itoken, cb))
275 }) {
276 Ok(x) => x,
277 Err(_) => return Some(ctx)
278 };
279 let methodname = ctx.method().clone();
281 let ctx = cb(ctx, self);
282 self.registry.give_method(itoken, &methodname, cb);
283 ctx
284 }
285
286 pub fn handle_message<S: dbus::channel::Sender>(&mut self, message: dbus::Message, conn: &S) -> Result<(), ()> {
290 let ctx = Context::new(message).ok_or(())?;
291 if let Some(mut ctx) = self.handle_message_inner(ctx) {
292 let _ = ctx.flush_messages(conn);
293 }
294 Ok(())
295 }
296
297 pub fn introspectable<T: Send + 'static>(&self) -> IfaceToken<T> { IfaceToken(INTROSPECTABLE, PhantomData) }
299
300 pub fn properties<T: Send + 'static>(&self) -> IfaceToken<T> { IfaceToken(PROPERTIES, PhantomData) }
302
303 pub fn object_manager<T: Send + 'static>(&self) -> IfaceToken<T> { IfaceToken(OBJECT_MANAGER, PhantomData) }
308
309 pub fn set_async_support(&mut self, x: Option<(Arc<dyn Sender + Send + Sync + 'static>, BoxedSpawn)>) -> Option<(Arc<dyn Sender + Send + Sync + 'static>, BoxedSpawn)> {
314 let a = self.async_support.take();
315 self.async_support = x.map(|x| AsyncSupport {
316 sender: x.0,
317 spawner: x.1
318 });
319 a.map(|x| (x.sender, x.spawner))
320 }
321
322 pub fn set_object_manager_support(&mut self, x: Option<Arc<dyn Sender + Send + Sync + 'static>>) -> Option<Arc<dyn Sender + Send + Sync + 'static>> {
326 let x = x.map(|x| Dbg(x));
327 std::mem::replace(&mut self.object_manager_support, x).map(|x| x.0)
328 }
329
330 pub fn serve(mut self, connection: &dbus::blocking::Connection) -> Result<(), dbus::Error> {
335 use dbus::channel::MatchingReceiver;
337 connection.start_receive(dbus::message::MatchRule::new_method_call(), Box::new(move |msg, conn| {
338 self.handle_message(msg, conn).unwrap();
339 true
340 }));
341
342 loop { connection.process(std::time::Duration::from_millis(1000))?; }
344 }
345}