summaryrefslogtreecommitdiff
path: root/src/lib/eldbus/eldbus_signal_handler.c
diff options
context:
space:
mode:
authorLucas De Marchi <lucas.demarchi@profusion.mobi>2013-04-23 11:40:05 -0300
committerLucas De Marchi <lucas.demarchi@profusion.mobi>2013-04-23 12:36:29 -0300
commit4e3804041f8e865e007b2a6a0d45a05f39500c3b (patch)
treea493b9c8f8a610d2667651f3ba81819ed16fbe8c /src/lib/eldbus/eldbus_signal_handler.c
parent4cf68bf728b5a858ce1c0efac25ded1a49ba8d9d (diff)
Rename edbus->eldbus
git grep -l edbus2 | while read f; do sed -i 's/edbus2/eldbus/g' "$f"; done find . -name '*edbus2*' -exec rename edbus2 eldbus {} \; git grep -l "EDBUS" | while read f; do sed -i 's/EDBUS/ELDBUS/g' "$f"; done git grep -l "EDBus" | while read f; do sed -i 's/EDBus/Eldbus/g' "$f"; done git grep -l "edbus (v2)" | while read f; do sed -i 's/edbus (v2)/eldbus/g' "$f"; done git grep -l "Edbus" | while read f; do sed -i 's/Edbus/Eldbus/g' "$f"; done git grep -l "edbus" | while read f; do sed -i 's/edbus/eldbus/g' "$f"; done find . -name '*edbus*' -exec rename edbus eldbus {} \; find . -name '*EDBus*' -exec rename EDBus Eldbus {} \;
Diffstat (limited to 'src/lib/eldbus/eldbus_signal_handler.c')
-rw-r--r--src/lib/eldbus/eldbus_signal_handler.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/src/lib/eldbus/eldbus_signal_handler.c b/src/lib/eldbus/eldbus_signal_handler.c
new file mode 100644
index 0000000000..8fedf21368
--- /dev/null
+++ b/src/lib/eldbus/eldbus_signal_handler.c
@@ -0,0 +1,361 @@
1#include "eldbus_private.h"
2#include "eldbus_private_types.h"
3#include <dbus/dbus.h>
4
5/* TODO: mempool of Eldbus_Signal_Handler */
6
7#define ELDBUS_SIGNAL_HANDLER_CHECK(handler) \
8 do \
9 { \
10 EINA_SAFETY_ON_NULL_RETURN(handler); \
11 if (!EINA_MAGIC_CHECK(handler, ELDBUS_SIGNAL_HANDLER_MAGIC)) \
12 { \
13 EINA_MAGIC_FAIL(handler, ELDBUS_SIGNAL_HANDLER_MAGIC); \
14 return; \
15 } \
16 } \
17 while (0)
18
19#define ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, retval) \
20 do \
21 { \
22 EINA_SAFETY_ON_NULL_RETURN_VAL(handler, retval); \
23 if (!EINA_MAGIC_CHECK(handler, ELDBUS_SIGNAL_HANDLER_MAGIC)) \
24 { \
25 EINA_MAGIC_FAIL(handler, ELDBUS_SIGNAL_HANDLER_MAGIC); \
26 return retval; \
27 } \
28 } \
29 while (0)
30
31static void _eldbus_signal_handler_del(Eldbus_Signal_Handler *handler);
32static void _eldbus_signal_handler_clean(Eldbus_Signal_Handler *handler);
33
34Eina_Bool
35eldbus_signal_handler_init(void)
36{
37 return EINA_TRUE;
38}
39
40void
41eldbus_signal_handler_shutdown(void)
42{
43}
44
45static void
46_match_append(Eina_Strbuf *match, const char *key, const char *value)
47{
48 if (!value) return;
49
50 if ((eina_strbuf_length_get(match) + strlen(",=''") + strlen(key) + strlen(value))
51 >= DBUS_MAXIMUM_MATCH_RULE_LENGTH)
52 {
53 ERR("cannot add match %s='%s' to %s: too long!", key, value,
54 eina_strbuf_string_get(match));
55 return;
56 }
57
58 eina_strbuf_append_printf(match, ",%s='%s'", key, value);
59}
60
61static int
62_sort_arg(const void *d1, const void *d2)
63{
64 const Signal_Argument *arg1, *arg2;
65 arg1 = d1;
66 arg2 = d2;
67 return arg1->index - arg2->index;
68}
69
70#define ARGX "arg"
71EAPI Eina_Bool
72eldbus_signal_handler_match_extra_vset(Eldbus_Signal_Handler *sh, va_list ap)
73{
74 const char *key = NULL, *read;
75 DBusError err;
76
77 ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(sh, EINA_FALSE);
78
79 dbus_error_init(&err);
80 dbus_bus_remove_match(sh->conn->dbus_conn,
81 eina_strbuf_string_get(sh->match), &err);
82 EINA_SAFETY_ON_TRUE_RETURN_VAL(dbus_error_is_set(&err), EINA_FALSE);
83
84 for (read = va_arg(ap, char *); read; read = va_arg(ap, char *))
85 {
86 Signal_Argument *arg;
87
88 if (!key)
89 {
90 key = read;
91 continue;
92 }
93 arg = calloc(1, sizeof(Signal_Argument));
94 EINA_SAFETY_ON_NULL_GOTO(arg, error);
95 if (!strncmp(key, ARGX, strlen(ARGX)))
96 {
97 int id = atoi(key + strlen(ARGX));
98 arg->index = (unsigned short) id;
99 arg->value = eina_stringshare_add(read);
100 sh->args = eina_inlist_sorted_state_insert(sh->args,
101 EINA_INLIST_GET(arg),
102 _sort_arg,
103 sh->state_args);
104 _match_append(sh->match, key, read);
105 }
106 else
107 {
108 ERR("%s not supported", key);
109 free(arg);
110 }
111 key = NULL;
112 }
113
114 dbus_error_init(&err);
115 dbus_bus_add_match(sh->conn->dbus_conn,
116 eina_strbuf_string_get(sh->match), &err);
117 if (!dbus_error_is_set(&err))
118 return EINA_TRUE;
119
120 ERR("Error setting new match.");
121 return EINA_FALSE;
122
123error:
124 dbus_error_init(&err);
125 dbus_bus_add_match(sh->conn->dbus_conn,
126 eina_strbuf_string_get(sh->match), &err);
127 if (dbus_error_is_set(&err))
128 ERR("Error setting partial extra arguments.");
129 return EINA_FALSE;
130}
131
132EAPI Eina_Bool
133eldbus_signal_handler_match_extra_set(Eldbus_Signal_Handler *sh, ...)
134{
135 Eina_Bool ret;
136 va_list ap;
137
138 va_start(ap, sh);
139 ret = eldbus_signal_handler_match_extra_vset(sh, ap);
140 va_end(ap);
141 return ret;
142}
143
144static void _on_handler_of_conn_free(void *data, const void *dead_pointer);
145
146static void
147_on_connection_free(void *data, const void *dead_pointer EINA_UNUSED)
148{
149 Eldbus_Signal_Handler *sh = data;
150 eldbus_signal_handler_free_cb_del(sh, _on_handler_of_conn_free, sh->conn);
151 eldbus_signal_handler_del(sh);
152}
153
154static void
155_on_handler_of_conn_free(void *data, const void *dead_pointer)
156{
157 Eldbus_Connection *conn = data;
158 eldbus_connection_free_cb_del(conn, _on_connection_free, dead_pointer);
159}
160
161EAPI Eldbus_Signal_Handler *
162eldbus_signal_handler_add(Eldbus_Connection *conn, const char *sender, const char *path, const char *interface, const char *member, Eldbus_Signal_Cb cb, const void *cb_data)
163{
164 Eldbus_Signal_Handler *sh;
165 sh = _eldbus_signal_handler_add(conn, sender, path, interface, member, cb, cb_data);
166 EINA_SAFETY_ON_NULL_RETURN_VAL(sh, NULL);
167 eldbus_connection_free_cb_add(conn, _on_connection_free, sh);
168 eldbus_signal_handler_free_cb_add(sh, _on_handler_of_conn_free, conn);
169 return sh;
170}
171
172Eldbus_Signal_Handler *
173_eldbus_signal_handler_add(Eldbus_Connection *conn, const char *sender, const char *path, const char *interface, const char *member, Eldbus_Signal_Cb cb, const void *cb_data)
174{
175 Eldbus_Signal_Handler *sh;
176 Eina_Strbuf *match;
177 DBusError err;
178
179 EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
180 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
181 DBG("conn=%p, sender=%s, path=%s, interface=%s, member=%s, cb=%p %p",
182 conn, sender, path, interface, member, cb, cb_data);
183
184 sh = calloc(1, sizeof(Eldbus_Signal_Handler));
185 EINA_SAFETY_ON_NULL_RETURN_VAL(sh, NULL);
186
187 match = eina_strbuf_new();
188 EINA_SAFETY_ON_NULL_GOTO(match, cleanup_create_strbuf);
189 eina_strbuf_append(match, "type='signal'");
190 _match_append(match, "sender", sender);
191 _match_append(match, "path", path);
192 _match_append(match, "interface", interface);
193 _match_append(match, "member", member);
194
195 dbus_error_init(&err);
196 dbus_bus_add_match(conn->dbus_conn, eina_strbuf_string_get(match), &err);
197 if (dbus_error_is_set(&err)) goto cleanup;
198
199 if (sender)
200 {
201 sh->bus = eldbus_connection_name_get(conn, sender);
202 if (!sh->bus) goto cleanup;
203 eldbus_connection_name_ref(sh->bus);
204 }
205
206 sh->cb = cb;
207 sh->cb_data = cb_data;
208 sh->conn = conn;
209 sh->interface = eina_stringshare_add(interface);
210 sh->member = eina_stringshare_add(member);
211 sh->path = eina_stringshare_add(path);
212 sh->sender = eina_stringshare_add(sender);
213 sh->match = match;
214 sh->refcount = 1;
215 sh->dangling = EINA_FALSE;
216 sh->state_args = eina_inlist_sorted_state_new();
217 EINA_MAGIC_SET(sh, ELDBUS_SIGNAL_HANDLER_MAGIC);
218
219 eldbus_connection_signal_handler_add(conn, sh);
220 return sh;
221
222cleanup:
223 eina_strbuf_free(match);
224cleanup_create_strbuf:
225 free(sh);
226
227 return NULL;
228}
229
230static void
231_eldbus_signal_handler_clean(Eldbus_Signal_Handler *handler)
232{
233 DBusError err;
234
235 if (handler->dangling) return;
236
237 dbus_error_init(&err);
238 dbus_bus_remove_match(handler->conn->dbus_conn,
239 eina_strbuf_string_get(handler->match), &err);
240 handler->dangling = EINA_TRUE;
241}
242
243static void
244_eldbus_signal_handler_del(Eldbus_Signal_Handler *handler)
245{
246 Eina_Inlist *list;
247 Signal_Argument *arg;
248 DBG("handler %p, refcount=%d, conn=%p %s",
249 handler, handler->refcount, handler->conn, handler->sender);
250 eldbus_cbs_free_dispatch(&(handler->cbs_free), handler);
251 eldbus_connection_signal_handler_del(handler->conn, handler);
252 EINA_MAGIC_SET(handler, EINA_MAGIC_NONE);
253
254 /* after cbs_free dispatch these shouldn't exit, error if they do */
255
256 eina_stringshare_del(handler->sender);
257 eina_stringshare_del(handler->path);
258 eina_stringshare_del(handler->interface);
259 eina_stringshare_del(handler->member);
260 eina_strbuf_free(handler->match);
261 EINA_INLIST_FOREACH_SAFE(handler->args, list, arg)
262 {
263 eina_stringshare_del(arg->value);
264 free(arg);
265 }
266 eina_inlist_sorted_state_free(handler->state_args);
267
268 if (handler->bus)
269 eldbus_connection_name_unref(handler->conn, handler->bus);
270 free(handler);
271}
272
273EAPI Eldbus_Signal_Handler *
274eldbus_signal_handler_ref(Eldbus_Signal_Handler *handler)
275{
276 ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
277 DBG("handler=%p, pre-refcount=%d, match=%s",
278 handler, handler->refcount, eina_strbuf_string_get(handler->match));
279 handler->refcount++;
280 return handler;
281}
282
283EAPI void
284eldbus_signal_handler_unref(Eldbus_Signal_Handler *handler)
285{
286 ELDBUS_SIGNAL_HANDLER_CHECK(handler);
287 DBG("handler=%p, pre-refcount=%d, match=%s",
288 handler, handler->refcount, eina_strbuf_string_get(handler->match));
289 handler->refcount--;
290 if (handler->refcount > 0) return;
291
292 _eldbus_signal_handler_clean(handler);
293 _eldbus_signal_handler_del(handler);
294}
295
296EAPI void
297eldbus_signal_handler_del(Eldbus_Signal_Handler *handler)
298{
299 ELDBUS_SIGNAL_HANDLER_CHECK(handler);
300 _eldbus_signal_handler_clean(handler);
301 eldbus_signal_handler_unref(handler);
302}
303
304EAPI void
305eldbus_signal_handler_free_cb_add(Eldbus_Signal_Handler *handler, Eldbus_Free_Cb cb, const void *data)
306{
307 ELDBUS_SIGNAL_HANDLER_CHECK(handler);
308 EINA_SAFETY_ON_NULL_RETURN(cb);
309 handler->cbs_free = eldbus_cbs_free_add(handler->cbs_free, cb, data);
310}
311
312EAPI void
313eldbus_signal_handler_free_cb_del(Eldbus_Signal_Handler *handler, Eldbus_Free_Cb cb, const void *data)
314{
315 ELDBUS_SIGNAL_HANDLER_CHECK(handler);
316 EINA_SAFETY_ON_NULL_RETURN(cb);
317 handler->cbs_free = eldbus_cbs_free_del(handler->cbs_free, cb, data);
318}
319
320EAPI const char *
321eldbus_signal_handler_sender_get(const Eldbus_Signal_Handler *handler)
322{
323 ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
324 return handler->sender;
325}
326
327EAPI const char *
328eldbus_signal_handler_path_get(const Eldbus_Signal_Handler *handler)
329{
330 ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
331 return handler->path;
332}
333
334EAPI const char *
335eldbus_signal_handler_interface_get(const Eldbus_Signal_Handler *handler)
336{
337 ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
338 return handler->interface;
339}
340
341EAPI const char *
342eldbus_signal_handler_member_get(const Eldbus_Signal_Handler *handler)
343{
344 ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
345 return handler->member;
346}
347
348EAPI const char *
349eldbus_signal_handler_match_get(const Eldbus_Signal_Handler *handler)
350{
351 ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
352 return eina_strbuf_string_get(handler->match);
353}
354
355EAPI Eldbus_Connection *
356eldbus_signal_handler_connection_get(const Eldbus_Signal_Handler *handler)
357{
358 ELDBUS_SIGNAL_HANDLER_CHECK_RETVAL(handler, NULL);
359 return handler->conn;
360}
361