summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-09-17 15:39:23 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-09-17 15:39:23 +0200
commit7bdac909466263335c13daa824b17ca3d6f75ef6 (patch)
tree7ad23781d103929be66b3b73faefab00a470657b /lib
parentbb586580bee93c67f2b7b40c99d0a38ea02593c4 (diff)
downloadabrt-7bdac909466263335c13daa824b17ca3d6f75ef6.tar.gz
abrt-7bdac909466263335c13daa824b17ca3d6f75ef6.tar.xz
abrt-7bdac909466263335c13daa824b17ca3d6f75ef6.zip
factored out dbus init from CommLayerServerDBus.cpp to lib/Utils/abrt_dbus.cpp
this will allow me to reuse this code for applet Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/Utils/abrt_dbus.cpp202
-rw-r--r--lib/Utils/abrt_dbus.h10
-rw-r--r--lib/Utils/logging.cpp2
3 files changed, 214 insertions, 0 deletions
diff --git a/lib/Utils/abrt_dbus.cpp b/lib/Utils/abrt_dbus.cpp
index 3d868b9d..37d6d3e6 100644
--- a/lib/Utils/abrt_dbus.cpp
+++ b/lib/Utils/abrt_dbus.cpp
@@ -1,9 +1,11 @@
#include <dbus/dbus.h>
+#include <glib.h>
#include "abrtlib.h"
#include "abrt_dbus.h"
DBusConnection* g_dbus_conn;
+
/*
* Helpers for building DBus messages
*/
@@ -40,6 +42,7 @@ void store_string(DBusMessageIter* iter, const char* val)
die_out_of_memory();
}
+
/*
* Helpers for parsing DBus messages
*/
@@ -110,3 +113,202 @@ int load_charp(DBusMessageIter* iter, const char*& val)
//log("load_charp:'%s'", val);
return dbus_message_iter_next(iter);
}
+
+
+/*
+ * Glib integration machinery
+ */
+
+/* Callback: "glib says dbus fd is active" */
+static gboolean handle_dbus_fd(GIOChannel *gio, GIOCondition condition, gpointer data)
+{
+ DBusWatch *watch = (DBusWatch*)data;
+
+ VERB3 log("%s(gio, condition:%x [bits:IN/PRI/OUT/ERR/HUP...], data)", __func__, int(condition));
+
+ /* Notify the D-Bus library when a previously-added watch
+ * is ready for reading or writing, or has an exception such as a hangup.
+ */
+ int glib_flags = int(condition);
+ int dbus_flags = 0;
+ if (glib_flags & G_IO_IN) dbus_flags |= DBUS_WATCH_READABLE;
+ if (glib_flags & G_IO_OUT) dbus_flags |= DBUS_WATCH_WRITABLE;
+ if (glib_flags & G_IO_ERR) dbus_flags |= DBUS_WATCH_ERROR;
+ if (glib_flags & G_IO_HUP) dbus_flags |= DBUS_WATCH_HANGUP;
+ /*
+ * TODO:
+ * If dbus_watch_handle returns FALSE, then the file descriptor
+ * may still be ready for reading or writing, but more memory
+ * is needed in order to do the reading or writing. If you ignore
+ * the FALSE return, your application may spin in a busy loop
+ * on the file descriptor until memory becomes available,
+ * but nothing more catastrophic should happen.
+ */
+ dbus_watch_handle(watch, dbus_flags);
+
+ while (dbus_connection_dispatch(g_dbus_conn) == DBUS_DISPATCH_DATA_REMAINS)
+ VERB3 log("%s: more data to process, looping", __func__);
+ return TRUE; /* "glib, do not remove this even source!" */
+}
+
+struct watch_app_info_t
+{
+ GIOChannel *channel;
+ guint event_source_id;
+ bool watch_enabled;
+};
+/* Callback: "dbus_watch_get_enabled() may return a different value than it did before" */
+static void toggled_watch(DBusWatch *watch, void* data)
+{
+ VERB3 log("%s(watch:%p, data)", __func__, watch);
+
+ watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch);
+ if (dbus_watch_get_enabled(watch))
+ {
+ if (!app_info->watch_enabled)
+ {
+ app_info->watch_enabled = true;
+ int dbus_flags = dbus_watch_get_flags(watch);
+ int glib_flags = 0;
+ if (dbus_flags & DBUS_WATCH_READABLE)
+ glib_flags |= G_IO_IN;
+ if (dbus_flags & DBUS_WATCH_WRITABLE)
+ glib_flags |= G_IO_OUT;
+ VERB3 log(" adding watch to glib main loop. dbus_flags:%x glib_flags:%x", dbus_flags, glib_flags);
+ app_info->event_source_id = g_io_add_watch(app_info->channel, GIOCondition(glib_flags), handle_dbus_fd, watch);
+ }
+ /* else: it was already enabled */
+ } else {
+ if (app_info->watch_enabled)
+ {
+ app_info->watch_enabled = false;
+ /* does it free the hidden GSource too? */
+ VERB3 log(" removing watch from glib main loop");
+ g_source_remove(app_info->event_source_id);
+ }
+ /* else: it was already disabled */
+ }
+}
+/* Callback: "libdbus needs a new watch to be monitored by the main loop" */
+static dbus_bool_t add_watch(DBusWatch *watch, void* data)
+{
+ VERB3 log("%s(watch:%p, data)", __func__, watch);
+
+ watch_app_info_t* app_info = (watch_app_info_t*)xzalloc(sizeof(*app_info));
+ dbus_watch_set_data(watch, app_info, free);
+
+ int fd = dbus_watch_get_unix_fd(watch);
+ VERB3 log(" dbus_watch_get_unix_fd():%d", fd);
+ app_info->channel = g_io_channel_unix_new(fd);
+ /* _unconditionally_ adding it to event loop would be an error */
+ toggled_watch(watch, data);
+ return TRUE;
+}
+/* Callback: "libdbus no longer needs a watch to be monitored by the main loop" */
+static void remove_watch(DBusWatch *watch, void* data)
+{
+ VERB3 log("%s()", __func__);
+ watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch);
+ if (app_info->watch_enabled)
+ {
+ app_info->watch_enabled = false;
+ g_source_remove(app_info->event_source_id);
+ }
+ g_io_channel_unref(app_info->channel);
+}
+
+/* Callback: "libdbus needs a new timeout to be monitored by the main loop" */
+static dbus_bool_t add_timeout(DBusTimeout *timeout, void* data)
+{
+ VERB3 log("%s()", __func__);
+ return TRUE;
+}
+/* Callback: "libdbus no longer needs a timeout to be monitored by the main loop" */
+static void remove_timeout(DBusTimeout *timeout, void* data)
+{
+ VERB3 log("%s()", __func__);
+}
+/* Callback: "dbus_timeout_get_enabled() may return a different value than it did before" */
+static void timeout_toggled(DBusTimeout *timeout, void* data)
+{
+//seems to be never called, let's make it noisy
+ error_msg_and_die("%s(): FIXME: some dbus machinery is missing here", __func__);
+}
+
+/* Callback: "DBusObjectPathVTable is unregistered (or its connection is freed)" */
+static void unregister_vtable(DBusConnection *conn, void* data)
+{
+ VERB3 log("%s()", __func__);
+}
+
+/*
+ * Initialization works as follows:
+ *
+ * we have a DBusConnection* (say, obtained with dbus_bus_get)
+ * we call dbus_connection_set_watch_functions
+ * libdbus calls back add_watch(watch:0x2341090, data), this watch is for writing
+ * we call toggled_watch, but it finds that watch is not to be enabled yet
+ * libdbus calls back add_watch(watch:0x23410e0, data), this watch is for reading
+ * we call toggled_watch, it adds watch's fd to glib main loop with POLLIN
+ * (note: these watches are different objects, but they have the same fd)
+ * we call dbus_connection_set_timeout_functions
+ * we call dbus_connection_register_object_path
+ *
+ * Note: if user will later call dbus_bus_request_name(conn, ...):
+ * libdbus calls back add_timeout()
+ * libdbus calls back remove_timeout()
+ * note - no callback to timeout_toggled()!
+ * (therefore there is no code yet in timeout_toggled (see above), it's not used)
+ */
+void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn,
+ const char* object_path,
+ DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data)
+) {
+//do we need this? why?
+//log("dbus_connection_set_dispatch_status_function");
+// dbus_connection_set_dispatch_status_function(conn,
+// dispatch, /* void dispatch(DBusConnection *conn, DBusDispatchStatus new_status, void* data) */
+// NULL, /* data */
+// NULL /* free_data_function */
+// )
+ VERB3 log("dbus_connection_set_watch_functions");
+ if (!dbus_connection_set_watch_functions(conn,
+ add_watch,
+ remove_watch,
+ toggled_watch,
+ NULL, /* data */
+ NULL /* free_data_function */
+ )
+ ) {
+ die_out_of_memory();
+ }
+ VERB3 log("dbus_connection_set_timeout_functions");
+ if (!dbus_connection_set_timeout_functions(conn,
+ add_timeout,
+ remove_timeout,
+ timeout_toggled,
+ NULL, /* data */
+ NULL /* free_data_function */
+ )
+ ) {
+ die_out_of_memory();
+ }
+
+ if (object_path && message_received_func)
+ {
+ /* Table */
+ const DBusObjectPathVTable vtable = {
+ /* .unregister_function = */ unregister_vtable,
+ /* .message_function = */ message_received_func,
+ };
+ VERB3 log("dbus_connection_register_object_path");
+ if (!dbus_connection_register_object_path(conn,
+ object_path,
+ &vtable,
+ NULL /* data */
+ )
+ ) {
+ die_out_of_memory();
+ }
+ }
+}
diff --git a/lib/Utils/abrt_dbus.h b/lib/Utils/abrt_dbus.h
index e2bf9fbf..731f1c10 100644
--- a/lib/Utils/abrt_dbus.h
+++ b/lib/Utils/abrt_dbus.h
@@ -6,6 +6,16 @@
extern DBusConnection* g_dbus_conn;
/*
+ * Glib integration machinery
+ */
+void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn,
+ const char* object_path_to_register = NULL, /* NULL if you are just a client */
+ /* makes sense only if you use object_path_to_register: */
+ DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data) = NULL
+);
+
+
+/*
* Helpers for building DBus messages
*/
diff --git a/lib/Utils/logging.cpp b/lib/Utils/logging.cpp
index d79ded5d..f70d23f3 100644
--- a/lib/Utils/logging.cpp
+++ b/lib/Utils/logging.cpp
@@ -8,6 +8,8 @@
int xfunc_error_retval = EXIT_FAILURE;
+int g_verbose;
+
void xfunc_die(void)
{
exit(xfunc_error_retval);