#include "systemd_dbus.h"
#include "dbus_signal_event.h"
+#include <glib.h>
+#include <gio/gio.h>
+#include <libsyscommon/dbus-system.h>
+
struct dbus_signal {
char *event_id;
char *sender;
#define to_dbus_listener(MOD) \
container_of(MOD, struct dbus_listener, module)
-static int append_param(struct epc_object *params, char type, int pos, const void *val)
+static int append_param(struct epc_object *params, enum epc_object_type type, int pos, const void *val)
{
int r;
char key[64];
if (r < 0)
return r;
- switch (type) {
- case SD_BUS_TYPE_STRING:
- r = epc_object_append_string(params, key, (char *)val);
- break;
- case SD_BUS_TYPE_BOOLEAN:
- r = epc_object_append_bool(params, key, *(bool *)val);
- break;
- case SD_BUS_TYPE_DOUBLE:
- r = epc_object_append_double(params, key, *(double *)val);
- break;
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_INT64:
- case SD_BUS_TYPE_UINT32:
- case SD_BUS_TYPE_INT32:
- r = epc_object_append_int(params, key, *(int *)val);
- break;
- default:
- r = 0;
- break;
- }
+ if (type == TYPE_STRING)
+ r = epc_object_append_string(params, key, val);
+ else
+ r = epc_object_append_new(params, key, type, val);
+
if (r < 0)
return r;
+
return 0;
}
-static int parse_message_args(sd_bus_message *m, struct epc_object *params)
+static int parse_message_args(GVariant *m, struct epc_object *params)
{
int r;
- char type;
const char *contents;
int pos = 0;
+ GVariantIter iter;
+ GVariant *child;
+ g_variant_iter_init(&iter, m);
while (1) {
- r = sd_bus_message_peek_type(m, &type, &contents);
- if (r == 0) {
+ child = g_variant_iter_next_value(&iter);
+ if (!child)
break;
- } else if (r < 0) {
- log_error("sd_bus_message_peek_type: %s\n", strerror(-r));
- return r;
- }
+
pos++;
- switch (type) {
- case SD_BUS_TYPE_STRING: {
+ if (g_variant_is_of_type(child, G_VARIANT_TYPE_STRING)){
const char *v;
- r = sd_bus_message_read_basic(m, type, &v);
- if (r < 0)
- return r;
-
- r = append_param(params, type, pos, v);
- if (r < 0)
- return r;
- break;
- }
- case SD_BUS_TYPE_BOOLEAN:
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_INT64:
- case SD_BUS_TYPE_UINT32:
- case SD_BUS_TYPE_INT32:
- case SD_BUS_TYPE_DOUBLE: {
- union {
- int b;
- uint64_t u64;
- int64_t i64;
- uint32_t u32;
- int32_t i32;
- double d;
- } v;
-
- r = sd_bus_message_read_basic(m, type, &v);
- if (r < 0)
- return r;
-
- r = append_param(params, type, pos, &v);
- if (r < 0)
- return r;
- break;
- }
- default: {
- r = sd_bus_message_read_basic(m, type, NULL);
- if (r < 0)
- return r;
- break;
- }
+ v = g_variant_get_string(child, NULL);
+ r = append_param(params, TYPE_STRING, pos, v);
+ } else if (g_variant_is_of_type(child, G_VARIANT_TYPE_BOOLEAN)) {
+ gboolean v;
+
+ v = g_variant_get_boolean(child);
+ r = append_param(params, TYPE_BOOL, pos, &v);
+ } else if (g_variant_is_of_type(child, G_VARIANT_TYPE_UINT64)) {
+ guint64 v;
+
+ v = g_variant_get_uint64(child);
+ r = append_param(params, TYPE_INT, pos, &v);
+ } else if (g_variant_is_of_type(child, G_VARIANT_TYPE_INT64)) {
+ gint64 v;
+
+ v = g_variant_get_int64(child);
+ r = append_param(params, TYPE_INT, pos, &v);
+ } else if (g_variant_is_of_type(child, G_VARIANT_TYPE_UINT32)) {
+ guint32 v;
+
+ v = g_variant_get_uint32(child);
+ r = append_param(params, TYPE_INT, pos, &v);
+ } else if (g_variant_is_of_type(child, G_VARIANT_TYPE_INT32)) {
+ gint32 v;
+
+ v = g_variant_get_int32(child);
+ r = append_param(params, TYPE_INT, pos, &v);
+ } else if (g_variant_is_of_type(child, G_VARIANT_TYPE_DOUBLE)) {
+ gdouble v;
+
+ v = g_variant_get_double(child);
+ r = append_param(params, TYPE_DOUBLE, pos, &v);
+ } else {
+ r = 0;
+ log_warning("Unsupported data type");
}
+ if (r < 0)
+ return r;
+
}
return 0;
}
-static int on_dbus_signal_match(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+static void on_dbus_signal_match(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer userdata)
+{
struct dbus_signal *s = (struct dbus_signal *)userdata;
struct dbus_signal_event_data ds_ev_data = {};
if (epc_object_new(&ds_ev_data.params) < 0)
goto finish;
- ret = parse_message_args(m, ds_ev_data.params);
+ ret = parse_message_args(parameters, ds_ev_data.params);
if (ret) {
log_error_errno(ret, "Unable to parse signal parameters: %m.");
goto finish;
}
}
-static int add_signal(struct dbus_listener *l, json_object *root, sd_bus *bus)
+static int add_signal(struct dbus_listener *l, json_object *root, dbus_handle_h bus)
{
int ret;
struct dbus_signal *s;
- char match_buf[1024];
int size;
char err[512];
(void) get_config_field(root, "destination", &s->destination, json_type_string);
- memset(match_buf, 0, sizeof match_buf);
- size = 0;
-
- ret = snprintf(match_buf+size, sizeof match_buf-size, "type='signal',");
- if (ret < 0)
- goto out;
- size += ret;
-
-#define APPEND_MATCH(x) do { \
- ret = snprintf(match_buf+size, sizeof match_buf-size, #x "='%s',", s->x); \
- if (ret < 0) \
- goto out; \
- size += ret; \
- } while (0)
-
- if (s->sender)
- APPEND_MATCH(sender);
- APPEND_MATCH(interface);
- APPEND_MATCH(member);
-
- if (s->path)
- APPEND_MATCH(path);
- else if (s->path_namespace)
- APPEND_MATCH(path_namespace);
-
- if (s->destination)
- APPEND_MATCH(destination);
-
-#undef APPEND_MATCH
-
- match_buf[size-1] = '\0';
-
- ret = sd_bus_add_match(bus, NULL, match_buf, on_dbus_signal_match, s);
+ ret = subscribe_dbus_signal(bus, s->path, s->interface, s->member, on_dbus_signal_match, s, NULL);
if (ret < 0) {
- if (strerror_r(-ret, err, sizeof err))
- log_error("Failed to add signal match: %s\n", err);
+ log_error("Failed to subscribe to dbus signals\n");
goto out;
}
struct dbus_listener *listener = to_dbus_listener(module);
int ret = 0, len, i;
json_object *arr, *obj;
- sd_bus *bus = NULL;
+ dbus_handle_h bus;
char err[512];
INIT_LIST_HEAD(&listener->signals);
if (config == NULL)
return 0;
- ret = epc_acquire_systemd_bus(&bus);
- if (ret < 0) {
+ bus = dbus_handle_get_connection(G_BUS_TYPE_SYSTEM, 0);
+ if (!bus) {
log_error_errno(ret, "Failed to acquire the default system bus connection: %m");
return -EINVAL;
}
}
}
- ret = sd_bus_attach_event(bus, loop, 0);
- if (ret < 0) {
- if (strerror_r(-ret, err, sizeof err))
- log_error("Failed to attach bus to event loop: %s\n", err);
- goto cleanup;
- }
-
return 0;
cleanup: