From 7cca28be586a32c153833b95eed48e0a2182751e Mon Sep 17 00:00:00 2001 From: Krisztian Litkey Date: Fri, 6 Apr 2012 14:41:20 +0300 Subject: [PATCH] plugins: added dbus core plugin. --- configure.ac | 1 + src/Makefile.am | 18 +++ src/plugins/plugin-dbus.c | 350 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 369 insertions(+) create mode 100644 src/plugins/plugin-dbus.c diff --git a/configure.ac b/configure.ac index 969eb1f..0557436 100644 --- a/configure.ac +++ b/configure.ac @@ -152,6 +152,7 @@ function check_if_internal() { } AM_CONDITIONAL(BUILTIN_PLUGIN_TEST, [check_if_internal test]) +AM_CONDITIONAL(BUILTIN_PLUGIN_DBUS, [check_if_internal dbus]) #AM_CONDITIONAL(BUILTIN_PLUGIN_STORAGE, [check_if_internal storage]) #AM_CONDITIONAL(BUILTIN_PLUGIN_SYSFS, [check_if_internal sysfs ]) #AM_CONDITIONAL(BUILTIN_PLUGIN_DISPLAY, [check_if_internal display]) diff --git a/src/Makefile.am b/src/Makefile.am index a554487..dbf0f94 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -124,6 +124,24 @@ plugin_test_la_LIBADD = $(TEST_PLUGIN_LIBS) plugin_LTLIBRARIES += plugin-test.la endif +# dbus plugin +DBUS_PLUGIN_SOURCES = plugins/plugin-dbus.c +DBUS_PLUGIN_CFLAGS = $(DBUS_CFLAGS) +DBUS_PLUGIN_LIBS = $(DBUS_LIBS) + +if BUILTIN_PLUGIN_DBUS +BUILTIN_PLUGINS += $(DBUS_PLUGIN_SOURCES) +BUILTIN_CFLAGS += $(DBUS_PLUGIN_CFLAGS) +BUILTIN_LIBS += $(DBUS_PLUGIN_LIBS) +else +plugin_dbus_la_SOURCES = $(DBUS_PLUGIN_SOURCES) +plugin_dbus_la_CFLAGS = $(DBUS_PLUGIN_CFLAGS) $(MURPHY_CFLAGS) $(AM_CFLAGS) +plugin_dbus_la_LDFLAGS = -module -avoid-version +plugin_dbus_la_LIBADD = $(DBUS_PLUGIN_LIBS) + +plugin_LTLIBRARIES += plugin-dbus.la +endif + ################################### # murphy daemon diff --git a/src/plugins/plugin-dbus.c b/src/plugins/plugin-dbus.c new file mode 100644 index 0000000..9836c19 --- /dev/null +++ b/src/plugins/plugin-dbus.c @@ -0,0 +1,350 @@ +#include + +#include +#include +#include +#include +#include +#include + +typedef struct dbus_glue_s dbus_glue_t; + +typedef struct { + dbus_glue_t *glue; + mrp_io_watch_t *mw; + DBusWatch *dw; + mrp_list_hook_t hook; +} watch_t; + + +typedef struct { + dbus_glue_t *glue; + mrp_timer_t *mt; + DBusTimeout *dt; + mrp_list_hook_t hook; +} timeout_t; + + +struct dbus_glue_s { + DBusConnection *conn; + mrp_mainloop_t *ml; + mrp_list_hook_t watches; + mrp_list_hook_t timers; + mrp_deferred_t *pump; +}; + + +static dbus_int32_t data_slot = -1; + +static void dispatch_watch(mrp_mainloop_t *ml, mrp_io_watch_t *mw, int fd, + mrp_io_event_t events, void *user_data) +{ + watch_t *watch = (watch_t *)user_data; + DBusConnection *conn = watch->glue->conn; + unsigned int mask = 0; + + MRP_UNUSED(ml); + MRP_UNUSED(mw); + MRP_UNUSED(fd); + + if (events & MRP_IO_EVENT_IN) + mask |= DBUS_WATCH_READABLE; + if (events & MRP_IO_EVENT_OUT) + mask |= DBUS_WATCH_WRITABLE; + if (events & MRP_IO_EVENT_HUP) + mask |= DBUS_WATCH_HANGUP; + if (events & MRP_IO_EVENT_ERR) + mask |= DBUS_WATCH_ERROR; + + dbus_connection_ref(conn); + dbus_watch_handle(watch->dw, mask); + dbus_connection_unref(conn); +} + + +static void watch_freed_cb(void *data) +{ + watch_t *watch = (watch_t *)data; + + if (watch != NULL) { + mrp_list_delete(&watch->hook); + mrp_del_io_watch(watch->mw); + mrp_free(watch); + } +} + + +static dbus_bool_t add_watch(DBusWatch *dw, void *data) +{ + dbus_glue_t *glue = (dbus_glue_t *)data; + watch_t *watch; + mrp_io_watch_t *mw; + mrp_io_event_t mask; + int fd; + unsigned int flags; + + if (!dbus_watch_get_enabled(dw)) + return TRUE; + + fd = dbus_watch_get_unix_fd(dw); + flags = dbus_watch_get_flags(dw); + mask = MRP_IO_EVENT_HUP | MRP_IO_EVENT_ERR; + + if (flags & DBUS_WATCH_READABLE) + mask |= MRP_IO_EVENT_IN; + if (flags & DBUS_WATCH_WRITABLE) + mask |= MRP_IO_EVENT_OUT; + + if ((watch = mrp_allocz(sizeof(*watch))) != NULL) { + mrp_list_init(&watch->hook); + mw = mrp_add_io_watch(glue->ml, fd, mask, dispatch_watch, watch); + + if (mw != NULL) { + watch->glue = glue; + watch->mw = mw; + watch->dw = dw; + dbus_watch_set_data(dw, watch, watch_freed_cb); + mrp_list_append(&glue->watches, &watch->hook); + + return TRUE; + } + else + mrp_free(watch); + } + + return FALSE; +} + + +static void del_watch(DBusWatch *dw, void *data) +{ + watch_t *watch = (watch_t *)dbus_watch_get_data(dw); + + MRP_UNUSED(data); + + if (watch != NULL) { + mrp_del_io_watch(watch->mw); + watch->mw = NULL; + } +} + + +static void toggle_watch(DBusWatch *dw, void *data) +{ + if (dbus_watch_get_enabled(dw)) + add_watch(dw, data); + else + del_watch(dw, data); +} + + +static void dispatch_timeout(mrp_mainloop_t *ml, mrp_timer_t *mt, + void *user_data) +{ + timeout_t *timer = (timeout_t *)user_data; + + MRP_UNUSED(ml); + MRP_UNUSED(mt); + + dbus_timeout_handle(timer->dt); +} + + +static void timeout_freed_cb(void *data) +{ + timeout_t *timer = (timeout_t *)data; + + if (timer != NULL) { + mrp_list_delete(&timer->hook); + mrp_del_timer(timer->mt); + + mrp_free(timer); + } +} + + +static dbus_bool_t add_timeout(DBusTimeout *dt, void *data) +{ + dbus_glue_t *glue = (dbus_glue_t *)data; + timeout_t *timer; + mrp_timer_t *mt; + unsigned int msecs; + + if ((timer = mrp_allocz(sizeof(*timer))) != NULL) { + mrp_list_init(&timer->hook); + msecs = dbus_timeout_get_interval(dt); + mt = mrp_add_timer(glue->ml, msecs, dispatch_timeout, timer); + + if (mt != NULL) { + timer->glue = glue; + timer->mt = mt; + timer->dt = dt; + dbus_timeout_set_data(dt, timer, timeout_freed_cb); + mrp_list_append(&glue->timers, &timer->hook); + + return TRUE; + } + else + mrp_free(timer); + } + + return FALSE; +} + + +static void del_timeout(DBusTimeout *dt, void *data) +{ + timeout_t *timer = (timeout_t *)dbus_timeout_get_data(dt); + + MRP_UNUSED(data); + + if (timer != NULL) { + mrp_del_timer(timer->mt); + timer->mt = NULL; + } +} + + +static void toggle_timeout(DBusTimeout *dt, void *data) +{ + if (dbus_timeout_get_enabled(dt)) + add_timeout(dt, data); + else + del_timeout(dt, data); +} + + +static void wakeup_mainloop(void *data) +{ + dbus_glue_t *glue = (dbus_glue_t *)data; + + mrp_enable_deferred(glue->pump); +} + + +static void glue_free_cb(void *data) +{ + dbus_glue_t *glue = (dbus_glue_t *)data; + mrp_list_hook_t *p, *n; + watch_t *watch; + timeout_t *timer; + + mrp_list_foreach(&glue->watches, p, n) { + watch = mrp_list_entry(p, typeof(*watch), hook); + + mrp_list_delete(&watch->hook); + mrp_del_io_watch(watch->mw); + + mrp_free(watch); + } + + mrp_list_foreach(&glue->timers, p, n) { + timer = mrp_list_entry(p, typeof(*timer), hook); + + mrp_list_delete(&timer->hook); + mrp_del_timer(timer->mt); + + mrp_free(timer); + } + + mrp_free(glue); +} + + +static void pump_cb(mrp_mainloop_t *ml, mrp_deferred_t *d, void *user_data) +{ + dbus_glue_t *glue = (dbus_glue_t *)user_data; + + MRP_UNUSED(ml); + + if (dbus_connection_dispatch(glue->conn) == DBUS_DISPATCH_COMPLETE) + mrp_disable_deferred(d); +} + + +static void dispatch_status_cb(DBusConnection *conn, DBusDispatchStatus status, + void *user_data) +{ + dbus_glue_t *glue = (dbus_glue_t *)user_data; + + MRP_UNUSED(conn); + + switch (status) { + case DBUS_DISPATCH_COMPLETE: + mrp_disable_deferred(glue->pump); + break; + + case DBUS_DISPATCH_DATA_REMAINS: + case DBUS_DISPATCH_NEED_MEMORY: + default: + mrp_enable_deferred(glue->pump); + break; + } +} + + +int mrp_setup_dbus_connection(mrp_mainloop_t *ml, DBusConnection *conn) +{ + dbus_glue_t *glue; + + if (!dbus_connection_allocate_data_slot(&data_slot)) + return FALSE; + + if (dbus_connection_get_data(conn, data_slot) != NULL) + return FALSE; + + if ((glue = mrp_allocz(sizeof(*glue))) != NULL) { + mrp_list_init(&glue->watches); + mrp_list_init(&glue->timers); + glue->pump = mrp_add_deferred(ml, pump_cb, glue); + + if (glue->pump == NULL) { + mrp_free(glue); + return FALSE; + } + + glue->ml = ml; + glue->conn = conn; + } + else + return FALSE; + + if (!dbus_connection_set_data(conn, data_slot, glue, glue_free_cb)) + return FALSE; + + dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb, + glue, NULL); + + dbus_connection_set_wakeup_main_function(conn, wakeup_mainloop, + glue, NULL); + + return + dbus_connection_set_watch_functions(conn, add_watch, del_watch, + toggle_watch, glue, NULL) && + dbus_connection_set_timeout_functions(conn, add_timeout, del_timeout, + toggle_timeout, glue, NULL); +} + + + +static int dbus_init(mrp_plugin_t *plugin) +{ + MRP_UNUSED(plugin); + + mrp_log_info("%s() called...", __FUNCTION__); + + return TRUE; +} + + +static void dbus_exit(mrp_plugin_t *plugin) +{ + MRP_UNUSED(plugin); + + mrp_log_info("%s() called...", __FUNCTION__); +} + + +#define DBUS_HELP "DBUS pump plugin (DBUS-mainloop integration)." + +MURPHY_REGISTER_CORE_PLUGIN("dbus", DBUS_HELP, dbus_init, dbus_exit); -- 2.7.4