summaryrefslogtreecommitdiffstats
path: root/libreport/src/include/abrt_dbus.h
diff options
context:
space:
mode:
Diffstat (limited to 'libreport/src/include/abrt_dbus.h')
-rw-r--r--libreport/src/include/abrt_dbus.h360
1 files changed, 360 insertions, 0 deletions
diff --git a/libreport/src/include/abrt_dbus.h b/libreport/src/include/abrt_dbus.h
new file mode 100644
index 00000000..efa70472
--- /dev/null
+++ b/libreport/src/include/abrt_dbus.h
@@ -0,0 +1,360 @@
+/*
+ Copyright (C) 2010 ABRT team
+ Copyright (C) 2010 RedHat Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef ABRT_DBUS_H
+#define ABRT_DBUS_H
+
+#include <dbus/dbus.h>
+#include "libreport.h"
+
+
+#define ABRTD_DBUS_NAME "com.redhat.abrt"
+#define ABRTD_DBUS_PATH "/com/redhat/abrt"
+#define ABRTD_DBUS_IFACE "com.redhat.abrt"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern DBusConnection* g_dbus_conn;
+
+/*
+ * Glib integration machinery
+ */
+
+/* Hook up to DBus and to glib main loop.
+ * Usage cases:
+ *
+ * - server:
+ * conn = dbus_bus_get(DBUS_BUS_SYSTEM/SESSION, &err);
+ * attach_dbus_conn_to_glib_main_loop(conn, "/some/path", handler_of_calls_to_some_path);
+ * rc = dbus_bus_request_name(conn, "server.name", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
+ *
+ * - client which does not receive signals (only makes calls and emits signals):
+ * conn = dbus_bus_get(DBUS_BUS_SYSTEM/SESSION, &err);
+ * // needed only if you need to use async dbus calls (not shown below):
+ * attach_dbus_conn_to_glib_main_loop(conn, NULL, NULL);
+ * // synchronous method call:
+ * msg = dbus_message_new_method_call("some.serv", "/path/on/serv", "optional.iface.on.serv", "method_name");
+ * reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout, &err);
+ * // emitting signal:
+ * msg = dbus_message_new_signal("/path/sig/emitted/from", "iface.sig.emitted.from", "sig_name");
+ * // (note: "iface.sig.emitted.from" is not optional for signals!)
+ * dbus_message_set_destination(msg, "peer"); // optional
+ * dbus_connection_send(conn, msg, &serial); // &serial can be NULL
+ * dbus_connection_unref(conn); // if you don't want to *stay* connected
+ *
+ * - client which receives and processes signals:
+ * conn = dbus_bus_get(DBUS_BUS_SYSTEM/SESSION, &err);
+ * attach_dbus_conn_to_glib_main_loop(conn, NULL, NULL);
+ * dbus_connection_add_filter(conn, handle_message, NULL, NULL)
+ * dbus_bus_add_match(system_conn, "type='signal',...", &err);
+ * // signal is a dbus message which looks like this:
+ * // sender=XXX dest=YYY(or null) path=/path/sig/emitted/from interface=iface.sig.emitted.from member=sig_name
+ * // and handler_for_signals(conn,msg,opaque) will be called by glib
+ * // main loop to process received signals (and other messages
+ * // if you ask for them in dbus_bus_add_match[es], but this
+ * // would turn you into a server if you handle them too) ;]
+ */
+void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn,
+ /* NULL if you are just a client */
+ const char* object_path_to_register,
+ /* makes sense only if you use object_path_to_register: */
+ DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data)
+);
+
+/* Log dbus error if err has it set. Then log msg if it's !NULL.
+ * In both cases return 1. Otherwise return 0.
+ */
+int log_dbus_error(const char *msg, DBusError *err);
+
+/* Perform "DeleteDebugDump" call over g_dbus_conn */
+int32_t call_DeleteDebugDump(const char *dump_dir_name);
+
+/* Connect to system bus, find abrtd, perform "DeleteDebugDump" call, close g_dbus_conn */
+/* now static: int connect_to_abrtd_and_call_DeleteDebugDump(const char *dump_dir_name); */
+int delete_dump_dir_possibly_using_abrtd(const char *dump_dir_name);
+
+
+/*
+ * Helpers for building DBus messages
+ */
+//void store_bool(DBusMessageIter* iter, bool val);
+void store_int32(DBusMessageIter* iter, int32_t val);
+void store_uint32(DBusMessageIter* iter, uint32_t val);
+void store_int64(DBusMessageIter* iter, int64_t val);
+void store_uint64(DBusMessageIter* iter, uint64_t val);
+void store_string(DBusMessageIter* iter, const char* val);
+
+/*
+ * Helpers for parsing DBus messages
+ */
+enum {
+ ABRT_DBUS_ERROR = -1,
+ ABRT_DBUS_LAST_FIELD = 0,
+ ABRT_DBUS_MORE_FIELDS = 1,
+ /* note that dbus_message_iter_next() returns FALSE on last field
+ * and TRUE if there are more fields.
+ * It maps exactly on the above constants. */
+};
+/* Checks type, loads data, advances to the next arg.
+ * Returns TRUE if next arg exists.
+ */
+//int load_bool(DBusMessageIter* iter, bool& val);
+int load_int32(DBusMessageIter* iter, int32_t *val);
+int load_uint32(DBusMessageIter* iter, uint32_t *val);
+int load_int64(DBusMessageIter* iter, int64_t *val);
+int load_uint64(DBusMessageIter* iter, uint64_t *val);
+int load_charp(DBusMessageIter* iter, const char **val);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*
+ * C++ style stuff
+ */
+
+#ifdef __cplusplus
+
+#include <map>
+#include <vector>
+
+/*
+ * Helpers for building DBus messages
+ */
+
+static inline std::string ssprintf(const char *format, ...)
+{
+ va_list p;
+ char *string_ptr;
+
+ va_start(p, format);
+ string_ptr = xvasprintf(format, p);
+ va_end(p);
+
+ std::string res = string_ptr;
+ free(string_ptr);
+ return res;
+}
+
+//static inline void store_val(DBusMessageIter* iter, bool val) { store_bool(iter, val); }
+static inline void store_val(DBusMessageIter* iter, int32_t val) { store_int32(iter, val); }
+static inline void store_val(DBusMessageIter* iter, uint32_t val) { store_uint32(iter, val); }
+static inline void store_val(DBusMessageIter* iter, int64_t val) { store_int64(iter, val); }
+static inline void store_val(DBusMessageIter* iter, uint64_t val) { store_uint64(iter, val); }
+static inline void store_val(DBusMessageIter* iter, const char* val) { store_string(iter, val); }
+static inline void store_val(DBusMessageIter* iter, const std::string& val) { store_string(iter, val.c_str()); }
+
+/* Templates for vector and map */
+template <typename T> struct abrt_dbus_type {};
+//template <> struct abrt_dbus_type<bool> { static const char* csig() { return "b"; } };
+template <> struct abrt_dbus_type<int32_t> { static const char* csig() { return "i"; } static std::string sig(); };
+template <> struct abrt_dbus_type<uint32_t> { static const char* csig() { return "u"; } static std::string sig(); };
+template <> struct abrt_dbus_type<int64_t> { static const char* csig() { return "x"; } static std::string sig(); };
+template <> struct abrt_dbus_type<uint64_t> { static const char* csig() { return "t"; } static std::string sig(); };
+template <> struct abrt_dbus_type<std::string> { static const char* csig() { return "s"; } static std::string sig(); };
+#define ABRT_DBUS_SIG(T) (abrt_dbus_type<T>::csig() ? abrt_dbus_type<T>::csig() : abrt_dbus_type<T>::sig().c_str())
+template <typename E>
+struct abrt_dbus_type< std::vector<E> > {
+ static const char* csig() { return NULL; }
+ static std::string sig() { return ssprintf("a%s", ABRT_DBUS_SIG(E)); }
+};
+template <typename K, typename V>
+struct abrt_dbus_type< std::map<K,V> > {
+ static const char* csig() { return NULL; }
+ static std::string sig() { return ssprintf("a{%s%s}", ABRT_DBUS_SIG(K), ABRT_DBUS_SIG(V)); }
+};
+
+template <typename E>
+static void store_vector(DBusMessageIter* iter, const std::vector<E>& val)
+{
+ DBusMessageIter sub_iter;
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, ABRT_DBUS_SIG(E), &sub_iter))
+ die_out_of_memory();
+
+ typename std::vector<E>::const_iterator vit = val.begin();
+ for (; vit != val.end(); ++vit)
+ {
+ store_val(&sub_iter, *vit);
+ }
+
+ if (!dbus_message_iter_close_container(iter, &sub_iter))
+ die_out_of_memory();
+}
+/*
+template<>
+static void store_vector(DBus::MessageIter &iter, const std::vector<uint8_t>& val)
+{
+ if we use such vector, MUST add specialized code here (see in dbus-c++ source)
+}
+*/
+template <typename K, typename V>
+static void store_map(DBusMessageIter* iter, const std::map<K,V>& val)
+{
+ DBusMessageIter sub_iter;
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ ssprintf("{%s%s}", ABRT_DBUS_SIG(K), ABRT_DBUS_SIG(V)).c_str(),
+ &sub_iter))
+ die_out_of_memory();
+
+ typename std::map<K,V>::const_iterator mit = val.begin();
+ for (; mit != val.end(); ++mit)
+ {
+ DBusMessageIter sub_sub_iter;
+ if (!dbus_message_iter_open_container(&sub_iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub_sub_iter))
+ die_out_of_memory();
+ store_val(&sub_sub_iter, mit->first);
+ store_val(&sub_sub_iter, mit->second);
+ if (!dbus_message_iter_close_container(&sub_iter, &sub_sub_iter))
+ die_out_of_memory();
+ }
+
+ if (!dbus_message_iter_close_container(iter, &sub_iter))
+ die_out_of_memory();
+}
+
+template <typename E>
+static inline void store_val(DBusMessageIter* iter, const std::vector<E>& val) { store_vector(iter, val); }
+template <typename K, typename V>
+static inline void store_val(DBusMessageIter* iter, const std::map<K,V>& val) { store_map(iter, val); }
+
+
+/*
+ * Helpers for parsing DBus messages
+ */
+
+//static inline int load_val(DBusMessageIter* iter, bool &val) { return load_bool(iter, &val); }
+static inline int load_val(DBusMessageIter* iter, int32_t &val) { return load_int32(iter, &val); }
+static inline int load_val(DBusMessageIter* iter, uint32_t &val) { return load_uint32(iter, &val); }
+static inline int load_val(DBusMessageIter* iter, int64_t &val) { return load_int64(iter, &val); }
+static inline int load_val(DBusMessageIter* iter, uint64_t &val) { return load_uint64(iter, &val); }
+static inline int load_val(DBusMessageIter* iter, const char*& val) { return load_charp(iter, &val); }
+static inline int load_val(DBusMessageIter* iter, std::string& val)
+{
+ const char* str;
+ int r = load_charp(iter, &str);
+ val = str;
+ return r;
+}
+
+/* Templates for vector and map */
+template <typename E>
+static int load_vector(DBusMessageIter* iter, std::vector<E>& val)
+{
+ int type = dbus_message_iter_get_arg_type(iter);
+ if (type != DBUS_TYPE_ARRAY)
+ {
+ error_msg("array expected in dbus message, but not found ('%c')", type);
+ return -1;
+ }
+
+ DBusMessageIter sub_iter;
+ dbus_message_iter_recurse(iter, &sub_iter);
+
+ int r;
+//int cnt = 0;
+ /* When the vector has 0 elements, we see DBUS_TYPE_INVALID here */
+ type = dbus_message_iter_get_arg_type(&sub_iter);
+ if (type != DBUS_TYPE_INVALID)
+ {
+ do {
+ E elem;
+//cnt++;
+ r = load_val(&sub_iter, elem);
+ if (r < 0)
+ return r;
+ val.push_back(elem);
+ } while (r == ABRT_DBUS_MORE_FIELDS);
+ }
+//log("%s: %d elems", __func__, cnt);
+
+ return dbus_message_iter_next(iter);
+}
+/*
+template<>
+static int load_vector(DBusMessageIter* iter, std::vector<uint8_t>& val)
+{
+ if we use such vector, MUST add specialized code here (see in dbus-c++ source)
+}
+*/
+template <typename K, typename V>
+static int load_map(DBusMessageIter* iter, std::map<K,V>& val)
+{
+ int type = dbus_message_iter_get_arg_type(iter);
+ if (type != DBUS_TYPE_ARRAY)
+ {
+ error_msg("array expected in dbus message, but not found ('%c')", type);
+ return -1;
+ }
+
+ DBusMessageIter sub_iter;
+ dbus_message_iter_recurse(iter, &sub_iter);
+
+ bool next_exists;
+ int r;
+//int cnt = 0;
+ do {
+ type = dbus_message_iter_get_arg_type(&sub_iter);
+ if (type != DBUS_TYPE_DICT_ENTRY)
+ {
+ /* When the map has 0 elements, we see DBUS_TYPE_INVALID (on the first iteration) */
+ if (type == DBUS_TYPE_INVALID)
+ break;
+ error_msg("sub_iter type is not DBUS_TYPE_DICT_ENTRY (%c)!", type);
+ return -1;
+ }
+
+ DBusMessageIter sub_sub_iter;
+ dbus_message_iter_recurse(&sub_iter, &sub_sub_iter);
+
+ K key;
+ r = load_val(&sub_sub_iter, key);
+ if (r != ABRT_DBUS_MORE_FIELDS)
+ {
+ if (r == ABRT_DBUS_LAST_FIELD)
+ error_msg("malformed map element in dbus message");
+ return -1;
+ }
+ V value;
+ r = load_val(&sub_sub_iter, value);
+ if (r != ABRT_DBUS_LAST_FIELD)
+ {
+ if (r == ABRT_DBUS_MORE_FIELDS)
+ error_msg("malformed map element in dbus message");
+ return -1;
+ }
+ val[key] = value;
+//cnt++;
+ next_exists = dbus_message_iter_next(&sub_iter);
+ } while (next_exists);
+//log("%s: %d elems", __func__, cnt);
+
+ return dbus_message_iter_next(iter);
+}
+
+template <typename E>
+static inline int load_val(DBusMessageIter* iter, std::vector<E>& val) { return load_vector(iter, val); }
+template <typename K, typename V>
+static inline int load_val(DBusMessageIter* iter, std::map<K,V>& val) { return load_map(iter, val); }
+
+#endif /* __cplusplus */
+
+#endif