1 #include "eldbus_private.h"
2 #include "eldbus_private_types.h"
3 #include <dbus/dbus.h>
4 
5 /* TODO: mempool of Eldbus_Object, Eldbus_Object_Context_Event_Cb and
6  * Eldbus_Object_Context_Event
7  */
8 
9 #define ELDBUS_OBJECT_CHECK(obj)                        \
10   do                                                   \
11     {                                                  \
12        EINA_SAFETY_ON_NULL_RETURN(obj);                \
13        if (!EINA_MAGIC_CHECK(obj, ELDBUS_OBJECT_MAGIC)) \
14          {                                             \
15             EINA_MAGIC_FAIL(obj, ELDBUS_OBJECT_MAGIC);  \
16             return;                                    \
17          }                                             \
18        EINA_SAFETY_ON_TRUE_RETURN(obj->refcount <= 0); \
19     }                                                  \
20   while (0)
21 
22 #define ELDBUS_OBJECT_CHECK_RETVAL(obj, retval)                     \
23   do                                                               \
24     {                                                              \
25        EINA_SAFETY_ON_NULL_RETURN_VAL(obj, retval);                \
26        if (!EINA_MAGIC_CHECK(obj, ELDBUS_OBJECT_MAGIC))             \
27          {                                                         \
28             EINA_MAGIC_FAIL(obj, ELDBUS_OBJECT_MAGIC);              \
29             return retval;                                         \
30          }                                                         \
31        EINA_SAFETY_ON_TRUE_RETURN_VAL(obj->refcount <= 0, retval); \
32     }                                                              \
33   while (0)
34 
35 #define ELDBUS_OBJECT_CHECK_GOTO(obj, label)                 \
36   do                                                        \
37     {                                                       \
38        EINA_SAFETY_ON_NULL_GOTO(obj, label);                \
39        if (!EINA_MAGIC_CHECK(obj, ELDBUS_OBJECT_MAGIC))      \
40          {                                                  \
41             EINA_MAGIC_FAIL(obj, ELDBUS_OBJECT_MAGIC);       \
42             goto label;                                     \
43          }                                                  \
44        EINA_SAFETY_ON_TRUE_GOTO(obj->refcount <= 0, label); \
45     }                                                       \
46   while (0)
47 
48 Eina_Bool
eldbus_object_init(void)49 eldbus_object_init(void)
50 {
51    return EINA_TRUE;
52 }
53 
54 void
eldbus_object_shutdown(void)55 eldbus_object_shutdown(void)
56 {
57 }
58 
59 static void _eldbus_object_event_callback_call(Eldbus_Object *obj, Eldbus_Object_Event_Type type, const void *event_info);
60 static void _eldbus_object_context_event_cb_del(Eldbus_Object_Context_Event *ce, Eldbus_Object_Context_Event_Cb *ctx);
61 static void _on_connection_free(void *data, const void *dead_pointer);
62 static void _on_signal_handler_free(void *data, const void *dead_pointer);
63 
64 static void
_eldbus_object_call_del(Eldbus_Object * obj)65 _eldbus_object_call_del(Eldbus_Object *obj)
66 {
67    Eldbus_Object_Context_Event *ce;
68 
69    _eldbus_object_event_callback_call(obj, ELDBUS_OBJECT_EVENT_DEL, NULL);
70 
71    /* clear all del callbacks so we don't call them twice at
72     * _eldbus_object_clear()
73     */
74    ce = obj->event_handlers + ELDBUS_OBJECT_EVENT_DEL;
75    while (ce->list)
76      {
77         Eldbus_Object_Context_Event_Cb *ctx;
78 
79         ctx = EINA_INLIST_CONTAINER_GET(ce->list,
80                                         Eldbus_Object_Context_Event_Cb);
81         _eldbus_object_context_event_cb_del(ce, ctx);
82      }
83 }
84 
85 static void
_eldbus_object_clear(Eldbus_Object * obj)86 _eldbus_object_clear(Eldbus_Object *obj)
87 {
88    Eldbus_Signal_Handler *h;
89    Eldbus_Pending *p;
90    Eina_List *iter, *iter_next;
91    Eina_Inlist *in_l;
92    DBG("obj=%p, refcount=%d, name=%s, path=%s",
93        obj, obj->refcount, obj->name, obj->path);
94 
95    obj->refcount = 1;
96    _eldbus_object_call_del(obj);
97    eldbus_connection_name_object_del(obj->conn, obj);
98 
99    /* NOTE: obj->proxies is deleted from obj->cbs_free. */
100 
101    EINA_LIST_FOREACH_SAFE(obj->signal_handlers, iter, iter_next, h)
102      {
103         DBG("obj=%p delete owned signal handler %p %s",
104             obj, h, eldbus_signal_handler_match_get(h));
105         eldbus_signal_handler_del(h);
106      }
107    EINA_INLIST_FOREACH_SAFE(obj->pendings, in_l, p)
108      {
109         DBG("obj=%p delete owned pending call=%p dest=%s path=%s %s.%s()",
110             obj, p,
111             eldbus_pending_destination_get(p),
112             eldbus_pending_path_get(p),
113             eldbus_pending_interface_get(p),
114             eldbus_pending_method_get(p));
115         eldbus_pending_cancel(p);
116      }
117 
118    eldbus_cbs_free_dispatch(&(obj->cbs_free), obj);
119    obj->refcount = 0;
120 }
121 
122 static void
_eldbus_object_free(Eldbus_Object * obj)123 _eldbus_object_free(Eldbus_Object *obj)
124 {
125    unsigned int i;
126    Eldbus_Signal_Handler *h;
127 
128    if (obj->proxies)
129      {
130         Eina_Iterator *iterator = eina_hash_iterator_data_new(obj->proxies);
131         Eldbus_Proxy *proxy;
132         EINA_ITERATOR_FOREACH(iterator, proxy)
133           ERR("obj=%p alive proxy=%p %s", obj, proxy,
134               eldbus_proxy_interface_get(proxy));
135         eina_iterator_free(iterator);
136         eina_hash_free(obj->proxies);
137      }
138 
139    EINA_LIST_FREE(obj->signal_handlers, h)
140      {
141         if (h->dangling)
142           eldbus_signal_handler_free_cb_del(h, _on_signal_handler_free, obj);
143         else
144           ERR("obj=%p alive handler=%p %s", obj, h,
145               eldbus_signal_handler_match_get(h));
146      }
147 
148    if (obj->pendings)
149      CRI("Object %p released with live pending calls!", obj);
150 
151    for (i = 0; i < ELDBUS_OBJECT_EVENT_LAST; i++)
152      {
153         Eldbus_Object_Context_Event *ce = obj->event_handlers + i;
154         while (ce->list)
155           {
156              Eldbus_Object_Context_Event_Cb *ctx;
157 
158              ctx = EINA_INLIST_CONTAINER_GET(ce->list,
159                                              Eldbus_Object_Context_Event_Cb);
160              _eldbus_object_context_event_cb_del(ce, ctx);
161           }
162         eina_list_free(ce->to_delete);
163      }
164 
165    if (obj->interfaces_added)
166      eldbus_signal_handler_del(obj->interfaces_added);
167    if (obj->interfaces_removed)
168      eldbus_signal_handler_del(obj->interfaces_removed);
169    if (obj->properties_changed)
170      eldbus_signal_handler_del(obj->properties_changed);
171    eina_stringshare_del(obj->name);
172    eina_stringshare_del(obj->path);
173    EINA_MAGIC_SET(obj, EINA_MAGIC_NONE);
174 
175    free(obj);
176 }
177 
178 static void
_on_connection_free(void * data,const void * dead_pointer EINA_UNUSED)179 _on_connection_free(void *data, const void *dead_pointer EINA_UNUSED)
180 {
181    Eldbus_Object *obj = data;
182    ELDBUS_OBJECT_CHECK(obj);
183    _eldbus_object_clear(obj);
184    _eldbus_object_free(obj);
185 }
186 
187 EAPI Eldbus_Object *
eldbus_object_get(Eldbus_Connection * conn,const char * bus,const char * path)188 eldbus_object_get(Eldbus_Connection *conn, const char *bus, const char *path)
189 {
190    Eldbus_Object *obj;
191 
192    EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
193    EINA_SAFETY_ON_NULL_RETURN_VAL(bus, NULL);
194    EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
195 
196    obj = eldbus_connection_name_object_get(conn, bus, path);
197    if (obj)
198      return eldbus_object_ref(obj);
199 
200    obj = calloc(1, sizeof(Eldbus_Object));
201    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
202 
203    obj->conn = conn;
204    obj->refcount = 1;
205    obj->path = eina_stringshare_add(path);
206    obj->name = eina_stringshare_add(bus);
207    obj->proxies = eina_hash_string_small_new(NULL);
208    EINA_SAFETY_ON_NULL_GOTO(obj->proxies, cleanup);
209    EINA_MAGIC_SET(obj, ELDBUS_OBJECT_MAGIC);
210 
211    eldbus_connection_name_object_set(conn, obj);
212    eldbus_connection_free_cb_add(obj->conn, _on_connection_free, obj);
213 
214    obj->properties = eldbus_proxy_get(obj, ELDBUS_FDO_INTERFACE_PROPERTIES);
215 
216    return obj;
217 
218 cleanup:
219    eina_stringshare_del(obj->path);
220    eina_stringshare_del(obj->name);
221    free(obj);
222 
223    return NULL;
224 }
225 
226 static void _on_signal_handler_free(void *data, const void *dead_pointer);
227 
228 static void
_eldbus_object_unref(Eldbus_Object * obj)229 _eldbus_object_unref(Eldbus_Object *obj)
230 {
231    obj->refcount--;
232    if (obj->refcount > 0) return;
233 
234    eldbus_connection_free_cb_del(obj->conn, _on_connection_free, obj);
235    _eldbus_object_clear(obj);
236    _eldbus_object_free(obj);
237 }
238 
239 EAPI Eldbus_Object *
eldbus_object_ref(Eldbus_Object * obj)240 eldbus_object_ref(Eldbus_Object *obj)
241 {
242    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
243    DBG("obj=%p, pre-refcount=%d, name=%s, path=%s",
244        obj, obj->refcount, obj->name, obj->path);
245    obj->refcount++;
246    return obj;
247 }
248 
249 EAPI void
eldbus_object_unref(Eldbus_Object * obj)250 eldbus_object_unref(Eldbus_Object *obj)
251 {
252    ELDBUS_OBJECT_CHECK(obj);
253    DBG("obj=%p, pre-refcount=%d, name=%s, path=%s",
254        obj, obj->refcount, obj->name, obj->path);
255    _eldbus_object_unref(obj);
256 }
257 
258 EAPI void
eldbus_object_free_cb_add(Eldbus_Object * obj,Eldbus_Free_Cb cb,const void * data)259 eldbus_object_free_cb_add(Eldbus_Object *obj, Eldbus_Free_Cb cb, const void *data)
260 {
261    ELDBUS_OBJECT_CHECK(obj);
262    EINA_SAFETY_ON_NULL_RETURN(cb);
263    obj->cbs_free = eldbus_cbs_free_add(obj->cbs_free, cb, data);
264 }
265 
266 EAPI void
eldbus_object_free_cb_del(Eldbus_Object * obj,Eldbus_Free_Cb cb,const void * data)267 eldbus_object_free_cb_del(Eldbus_Object *obj, Eldbus_Free_Cb cb, const void *data)
268 {
269    ELDBUS_OBJECT_CHECK(obj);
270    EINA_SAFETY_ON_NULL_RETURN(cb);
271    obj->cbs_free = eldbus_cbs_free_del(obj->cbs_free, cb, data);
272 }
273 
274 static void
_cb_interfaces_added(void * data,const Eldbus_Message * msg)275 _cb_interfaces_added(void *data, const Eldbus_Message *msg)
276 {
277    Eldbus_Object *obj = data;
278    const char *obj_path;
279    Eldbus_Message_Iter *array_ifaces, *entry_iface;
280 
281    if (!eldbus_message_arguments_get(msg, "oa{sa{sv}}", &obj_path, &array_ifaces))
282      return;
283 
284    while (eldbus_message_iter_get_and_next(array_ifaces, 'e', &entry_iface))
285      {
286         const char *iface_name;
287         Eldbus_Object_Event_Interface_Added event;
288 
289         eldbus_message_iter_basic_get(entry_iface, &iface_name);
290         event.proxy = eldbus_proxy_get(obj, iface_name);
291         EINA_SAFETY_ON_NULL_RETURN(event.proxy);
292         event.interface = iface_name;
293         _eldbus_object_event_callback_call(obj, ELDBUS_OBJECT_EVENT_IFACE_ADDED,
294                                           &event);
295         eldbus_proxy_unref(event.proxy);
296      }
297 }
298 
299 static void
_cb_interfaces_removed(void * data,const Eldbus_Message * msg)300 _cb_interfaces_removed(void *data, const Eldbus_Message *msg)
301 {
302    Eldbus_Object *obj = data;
303    const char *obj_path, *iface;
304    Eldbus_Message_Iter *array_ifaces;
305 
306    if (!eldbus_message_arguments_get(msg, "oas", &obj_path, &array_ifaces))
307      return;
308 
309    while (eldbus_message_iter_get_and_next(array_ifaces, 's', &iface))
310      {
311         Eldbus_Object_Event_Interface_Removed event;
312         event.interface = iface;
313         _eldbus_object_event_callback_call(obj, ELDBUS_OBJECT_EVENT_IFACE_REMOVED,
314                                           &event);
315      }
316 }
317 
318 static void
_property_changed_iter(void * data,const void * key,Eldbus_Message_Iter * var)319 _property_changed_iter(void *data, const void *key, Eldbus_Message_Iter *var)
320 {
321    Eldbus_Proxy *proxy = data;
322    const char *skey = key;
323    Eina_Value *st_value, stack_value;
324    Eldbus_Object_Event_Property_Changed event;
325 
326    st_value = _message_iter_struct_to_eina_value(var);
327    eina_value_struct_value_get(st_value, "arg0", &stack_value);
328 
329    event.interface = eldbus_proxy_interface_get(proxy);
330    event.proxy = proxy;
331    event.name = skey;
332    event.value = &stack_value;
333    _eldbus_object_event_callback_call(eldbus_proxy_object_get(proxy),
334                                      ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED,
335                                      &event);
336    eina_value_free(st_value);
337    eina_value_flush(&stack_value);
338 }
339 
340 static void
_cb_properties_changed(void * data,const Eldbus_Message * msg)341 _cb_properties_changed(void *data, const Eldbus_Message *msg)
342 {
343    Eldbus_Object *obj = data;
344    Eldbus_Proxy *proxy;
345    Eldbus_Message_Iter *array, *invalidate;
346    const char *iface;
347    const char *invalidate_prop;
348 
349    if (!eldbus_message_arguments_get(msg, "sa{sv}as", &iface, &array, &invalidate))
350      {
351         ERR("Error getting data from properties changed signal.");
352         return;
353      }
354 
355    proxy = eldbus_proxy_get(obj, iface);
356    EINA_SAFETY_ON_NULL_RETURN(proxy);
357 
358    if (obj->event_handlers[ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED].list)
359      eldbus_message_iter_dict_iterate(array, "sv", _property_changed_iter,
360                                      proxy);
361 
362    if (!obj->event_handlers[ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED].list)
363      goto end;
364 
365    while (eldbus_message_iter_get_and_next(invalidate, 's', &invalidate_prop))
366      {
367         Eldbus_Object_Event_Property_Removed event;
368         event.interface = iface;
369         event.name = invalidate_prop;
370         event.proxy = proxy;
371         _eldbus_object_event_callback_call(obj,
372                                           ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED,
373                                           &event);
374      }
375 end:
376    eldbus_proxy_unref(proxy);
377 }
378 
379 EAPI void
eldbus_object_event_callback_add(Eldbus_Object * obj,Eldbus_Object_Event_Type type,Eldbus_Object_Event_Cb cb,const void * cb_data)380 eldbus_object_event_callback_add(Eldbus_Object *obj, Eldbus_Object_Event_Type type, Eldbus_Object_Event_Cb cb, const void *cb_data)
381 {
382    Eldbus_Object_Context_Event *ce;
383    Eldbus_Object_Context_Event_Cb *ctx;
384 
385    ELDBUS_OBJECT_CHECK(obj);
386    EINA_SAFETY_ON_NULL_RETURN(cb);
387    EINA_SAFETY_ON_TRUE_RETURN(type >= ELDBUS_OBJECT_EVENT_LAST);
388 
389    ce = obj->event_handlers + type;
390 
391    ctx = calloc(1, sizeof(Eldbus_Object_Context_Event_Cb));
392    EINA_SAFETY_ON_NULL_RETURN(ctx);
393 
394    ctx->cb = cb;
395    ctx->cb_data = cb_data;
396 
397    ce->list = eina_inlist_append(ce->list, EINA_INLIST_GET(ctx));
398 
399    switch (type)
400      {
401       case ELDBUS_OBJECT_EVENT_IFACE_ADDED:
402          {
403             if (obj->interfaces_added)
404               break;
405             obj->interfaces_added =
406                      _eldbus_signal_handler_add(obj->conn, obj->name, NULL,
407                                                ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
408                                                "InterfacesAdded",
409                                                _cb_interfaces_added, obj);
410             EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_added);
411             eldbus_signal_handler_match_extra_set(obj->interfaces_added, "arg0",
412                                                  obj->path, NULL);
413             break;
414          }
415       case ELDBUS_OBJECT_EVENT_IFACE_REMOVED:
416         {
417            if (obj->interfaces_removed)
418              break;
419            obj->interfaces_removed =
420                     _eldbus_signal_handler_add(obj->conn, obj->name, NULL,
421                                               ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
422                                               "InterfacesRemoved",
423                                               _cb_interfaces_removed, obj);
424            EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_removed);
425            eldbus_signal_handler_match_extra_set(obj->interfaces_removed,
426                                                 "arg0", obj->path, NULL);
427            break;
428         }
429       case ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED:
430       case ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED:
431         {
432            if (obj->properties_changed)
433              break;
434            obj->properties_changed =
435                     eldbus_object_signal_handler_add(obj,
436                                                     ELDBUS_FDO_INTERFACE_PROPERTIES,
437                                                     "PropertiesChanged",
438                                                     _cb_properties_changed, obj);
439            EINA_SAFETY_ON_NULL_RETURN(obj->properties_changed);
440            break;
441         }
442       default:
443         break;
444      }
445 }
446 
447 static void
_eldbus_object_context_event_cb_del(Eldbus_Object_Context_Event * ce,Eldbus_Object_Context_Event_Cb * ctx)448 _eldbus_object_context_event_cb_del(Eldbus_Object_Context_Event *ce, Eldbus_Object_Context_Event_Cb *ctx)
449 {
450    ce->list = eina_inlist_remove(ce->list, EINA_INLIST_GET(ctx));
451    free(ctx);
452 }
453 
454 EAPI void
eldbus_object_event_callback_del(Eldbus_Object * obj,Eldbus_Object_Event_Type type,Eldbus_Object_Event_Cb cb,const void * cb_data)455 eldbus_object_event_callback_del(Eldbus_Object *obj, Eldbus_Object_Event_Type type, Eldbus_Object_Event_Cb cb, const void *cb_data)
456 {
457    Eldbus_Object_Context_Event *ce;
458    Eldbus_Object_Context_Event_Cb *iter, *found = NULL;
459 
460    ELDBUS_OBJECT_CHECK(obj);
461    EINA_SAFETY_ON_NULL_RETURN(cb);
462    EINA_SAFETY_ON_TRUE_RETURN(type >= ELDBUS_OBJECT_EVENT_LAST);
463 
464    ce = obj->event_handlers + type;
465 
466    EINA_INLIST_FOREACH(ce->list, iter)
467      {
468         if (cb != iter->cb) continue;
469         if ((cb_data) && (cb_data != iter->cb_data)) continue;
470 
471         found = iter;
472         break;
473      }
474 
475    EINA_SAFETY_ON_NULL_RETURN(found);
476    EINA_SAFETY_ON_TRUE_RETURN(found->deleted);
477 
478    if (ce->walking)
479      {
480         found->deleted = EINA_TRUE;
481         ce->to_delete = eina_list_append(ce->to_delete, found);
482         return;
483      }
484 
485    _eldbus_object_context_event_cb_del(ce, found);
486 
487    switch (type)
488      {
489       case ELDBUS_OBJECT_EVENT_IFACE_ADDED:
490          {
491             if (obj->event_handlers[ELDBUS_OBJECT_EVENT_IFACE_ADDED].list)
492               break;
493             eldbus_signal_handler_del(obj->interfaces_added);
494             obj->interfaces_added = NULL;
495             break;
496          }
497       case ELDBUS_OBJECT_EVENT_IFACE_REMOVED:
498         {
499            if (obj->event_handlers[ELDBUS_OBJECT_EVENT_IFACE_REMOVED].list)
500              break;
501            eldbus_signal_handler_del(obj->interfaces_removed);
502            obj->interfaces_removed = NULL;
503            break;
504         }
505       case ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED:
506       case ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED:
507         {
508            if (obj->event_handlers[ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED].list ||
509                obj->event_handlers[ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED].list)
510              break;
511            eldbus_signal_handler_del(obj->properties_changed);
512            obj->properties_changed = NULL;
513            break;
514         }
515       default:
516         break;
517      }
518 }
519 
520 static void
_eldbus_object_event_callback_call(Eldbus_Object * obj,Eldbus_Object_Event_Type type,const void * event_info)521 _eldbus_object_event_callback_call(Eldbus_Object *obj, Eldbus_Object_Event_Type type, const void *event_info)
522 {
523    Eldbus_Object_Context_Event *ce;
524    Eldbus_Object_Context_Event_Cb *iter;
525 
526    ce = obj->event_handlers + type;
527 
528    ce->walking++;
529    EINA_INLIST_FOREACH(ce->list, iter)
530      {
531         if (iter->deleted) continue;
532         iter->cb((void *)iter->cb_data, obj, (void *)event_info);
533      }
534    ce->walking--;
535    if (ce->walking > 0) return;
536 
537    EINA_LIST_FREE(ce->to_delete, iter)
538      _eldbus_object_context_event_cb_del(ce, iter);
539 }
540 
541 EAPI Eldbus_Connection *
eldbus_object_connection_get(const Eldbus_Object * obj)542 eldbus_object_connection_get(const Eldbus_Object *obj)
543 {
544    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
545    return obj->conn;
546 }
547 
548 EAPI const char *
eldbus_object_bus_name_get(const Eldbus_Object * obj)549 eldbus_object_bus_name_get(const Eldbus_Object *obj)
550 {
551    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
552    return obj->name;
553 }
554 
555 EAPI const char *
eldbus_object_path_get(const Eldbus_Object * obj)556 eldbus_object_path_get(const Eldbus_Object *obj)
557 {
558    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
559    return obj->path;
560 }
561 
562 static void
_on_object_message_cb(void * data,const Eldbus_Message * msg,Eldbus_Pending * pending)563 _on_object_message_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
564 {
565    Eldbus_Message_Cb cb = eldbus_pending_data_del(pending, "__user_cb");
566    Eldbus_Object *obj = eldbus_pending_data_del(pending, "__object");
567 
568    ELDBUS_OBJECT_CHECK(obj);
569    obj->pendings = eina_inlist_remove(obj->pendings, EINA_INLIST_GET(pending));
570 
571    cb(data, msg, pending);
572 }
573 
574 EAPI Eldbus_Pending *
eldbus_object_send(Eldbus_Object * obj,Eldbus_Message * msg,Eldbus_Message_Cb cb,const void * cb_data,double timeout)575 eldbus_object_send(Eldbus_Object *obj, Eldbus_Message *msg, Eldbus_Message_Cb cb, const void *cb_data, double timeout)
576 {
577    Eldbus_Pending *pending;
578 
579    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
580    EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
581 
582    if (!cb)
583      {
584         _eldbus_connection_send(obj->conn, msg, NULL, NULL, timeout);
585         return NULL;
586      }
587    pending = _eldbus_connection_send(obj->conn, msg, _on_object_message_cb,
588                                      cb_data, timeout);
589    EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
590 
591    eldbus_pending_data_set(pending, "__user_cb", cb);
592    eldbus_pending_data_set(pending, "__object", obj);
593    obj->pendings = eina_inlist_append(obj->pendings, EINA_INLIST_GET(pending));
594 
595    return pending;
596 }
597 
598 static void
_on_signal_handler_free(void * data,const void * dead_pointer)599 _on_signal_handler_free(void *data, const void *dead_pointer)
600 {
601    Eldbus_Object *obj = data;
602    ELDBUS_OBJECT_CHECK(obj);
603    obj->signal_handlers = eina_list_remove(obj->signal_handlers, dead_pointer);
604 }
605 
606 EAPI Eldbus_Signal_Handler *
eldbus_object_signal_handler_add(Eldbus_Object * obj,const char * interface,const char * member,Eldbus_Signal_Cb cb,const void * cb_data)607 eldbus_object_signal_handler_add(Eldbus_Object *obj, const char *interface, const char *member, Eldbus_Signal_Cb cb, const void *cb_data)
608 {
609    Eldbus_Signal_Handler *handler;
610 
611    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
612    EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
613 
614    handler = _eldbus_signal_handler_add(obj->conn, obj->name, obj->path,
615                                        interface, member, cb, cb_data);
616    EINA_SAFETY_ON_NULL_RETURN_VAL(handler, NULL);
617 
618    eldbus_signal_handler_free_cb_add(handler, _on_signal_handler_free, obj);
619    obj->signal_handlers = eina_list_append(obj->signal_handlers, handler);
620 
621    return handler;
622 }
623 
624 EAPI Eldbus_Message *
eldbus_object_method_call_new(Eldbus_Object * obj,const char * interface,const char * member)625 eldbus_object_method_call_new(Eldbus_Object *obj, const char *interface, const char *member)
626 {
627    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
628    EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
629    EINA_SAFETY_ON_NULL_RETURN_VAL(member, NULL);
630 
631    return eldbus_message_method_call_new(obj->name, obj->path, interface, member);
632 }
633 
634 Eina_Bool
eldbus_object_proxy_add(Eldbus_Object * obj,Eldbus_Proxy * proxy)635 eldbus_object_proxy_add(Eldbus_Object *obj, Eldbus_Proxy *proxy)
636 {
637    return eina_hash_add(obj->proxies, eldbus_proxy_interface_get(proxy), proxy);
638 }
639 
640 Eldbus_Proxy *
eldbus_object_proxy_get(Eldbus_Object * obj,const char * interface)641 eldbus_object_proxy_get(Eldbus_Object *obj, const char *interface)
642 {
643    return eina_hash_find(obj->proxies, interface);
644 }
645 
646 Eina_Bool
eldbus_object_proxy_del(Eldbus_Object * obj,Eldbus_Proxy * proxy,const char * interface)647 eldbus_object_proxy_del(Eldbus_Object *obj, Eldbus_Proxy *proxy, const char *interface)
648 {
649    return eina_hash_del(obj->proxies, interface, proxy);
650 }
651 
652 EAPI Eldbus_Pending *
eldbus_object_peer_ping(Eldbus_Object * obj,Eldbus_Message_Cb cb,const void * data)653 eldbus_object_peer_ping(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
654 {
655    Eldbus_Message *msg;
656    Eldbus_Pending *p;
657    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
658    msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTEFACE_PEER, "Ping");
659    p = eldbus_object_send(obj, msg, cb, data, -1);
660    return p;
661 }
662 
663 EAPI Eldbus_Pending *
eldbus_object_peer_machine_id_get(Eldbus_Object * obj,Eldbus_Message_Cb cb,const void * data)664 eldbus_object_peer_machine_id_get(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
665 {
666    Eldbus_Message *msg;
667    Eldbus_Pending *p;
668    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
669    msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTEFACE_PEER,
670                                       "GetMachineId");
671    p = eldbus_object_send(obj, msg, cb, data, -1);
672    return p;
673 }
674 
675 EAPI Eldbus_Pending *
eldbus_object_introspect(Eldbus_Object * obj,Eldbus_Message_Cb cb,const void * data)676 eldbus_object_introspect(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
677 {
678    Eldbus_Message *msg;
679    Eldbus_Pending *p;
680    ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
681    msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTERFACE_INTROSPECTABLE,
682                                       "Introspect");
683    p = eldbus_object_send(obj, msg, cb, data, -1);
684    return p;
685 }
686