struct operation_queue {
enum block_dev_operation op;
- dbus_method_reply_handle_h reply_handle;
+ GDBusMethodInvocation *invocation;
void *data;
bool done;
};
static int add_operation(struct block_device *bdev,
enum block_dev_operation operation,
- dbus_method_reply_handle_h reply_handle, void *data);
+ GDBusMethodInvocation *invocation, void *data);
static void remove_operation(struct block_device *bdev);
static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
static int change_mount_point(struct block_device *bdev, const char *mount_point);
+#define nullstr(x) (x ? x : "")
+static GVariant *block_data_to_gvariant(struct block_data *data, int flags);
+static GVariant *block_data_to_gvariant2(struct block_data *data, int flags);
+
+#define block_send_dbus_reply(invocation, result) if (invocation) {g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", result)); }
+
static void uevent_block_handler(struct udev_device *dev);
static struct uevent_handler uh = {
.subsystem = BLOCK_SUBSYSTEM,
static void signal_device_blocked(struct block_device *bdev)
{
struct block_data *data;
- char *arr[13];
- char str_block_type[32];
- char str_readonly[32];
- char str_state[32];
- char str_primary[32];
- char str_flags[32];
- char str_id[32];
- char *str_null = "";
- int flags;
if (!bdev || !bdev->data)
return;
data = bdev->data;
- flags = 0;
- /* Broadcast outside with BlockManager iface */
- snprintf(str_block_type, sizeof(str_block_type),
- "%d", data->block_type);
- arr[0] = str_block_type;
- arr[1] = (data->devnode ? data->devnode : str_null);
- arr[2] = (data->syspath ? data->syspath : str_null);
- arr[3] = (data->fs_usage ? data->fs_usage : str_null);
- arr[4] = (data->fs_type ? data->fs_type : str_null);
- arr[5] = (data->fs_version ? data->fs_version : str_null);
- arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
- snprintf(str_readonly, sizeof(str_readonly),
- "%d", data->readonly);
- arr[7] = str_readonly;
- arr[8] = (data->mount_point ? data->mount_point : str_null);
- snprintf(str_state, sizeof(str_state),
- "%d", data->state);
- arr[9] = str_state;
- snprintf(str_primary, sizeof(str_primary),
- "%d", data->primary);
- arr[10] = str_primary;
- snprintf(str_flags, sizeof(str_flags), "%d", flags);
- arr[11] = str_flags;
- snprintf(str_id, sizeof(str_id), "%d", data->id);
- arr[12] = str_id;
-
- broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
+ dbus_handle_broadcast_dbus_signal_var(STORAGED_PATH_BLOCK_MANAGER,
STORAGED_INTERFACE_BLOCK_MANAGER,
BLOCK_DEVICE_BLOCKED,
- "issssssisibii", arr);
+ block_data_to_gvariant(data, 0));
}
static void signal_device_changed(struct block_device *bdev,
enum block_dev_operation op)
{
struct block_data *data;
- char *arr[13];
- char str_block_type[32];
- char str_readonly[32];
- char str_state[32];
- char str_primary[32];
- char str_flags[32];
- char str_id[32];
- char *str_null = "";
+ GVariant *var = NULL;
int flags;
if (!bdev || !bdev->data)
}
/* Broadcast outside with BlockManager iface */
- snprintf(str_block_type, sizeof(str_block_type),
- "%d", data->block_type);
- arr[0] = str_block_type;
- arr[1] = (data->devnode ? data->devnode : str_null);
- arr[2] = (data->syspath ? data->syspath : str_null);
- arr[3] = (data->fs_usage ? data->fs_usage : str_null);
- arr[4] = (data->fs_type ? data->fs_type : str_null);
- arr[5] = (data->fs_version ? data->fs_version : str_null);
- arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
- snprintf(str_readonly, sizeof(str_readonly),
- "%d", data->readonly);
- arr[7] = str_readonly;
- arr[8] = (data->mount_point ? data->mount_point : str_null);
- snprintf(str_state, sizeof(str_state),
- "%d", data->state);
- arr[9] = str_state;
- snprintf(str_primary, sizeof(str_primary),
- "%d", data->primary);
- arr[10] = str_primary;
- snprintf(str_flags, sizeof(str_flags), "%d", flags);
- arr[11] = str_flags;
- snprintf(str_id, sizeof(str_id), "%d", data->id);
- arr[12] = str_id;
+ var = block_data_to_gvariant(data, flags);
if (op == BLOCK_DEV_INSERT)
- broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
+ dbus_handle_broadcast_dbus_signal_var(STORAGED_PATH_BLOCK_MANAGER,
STORAGED_INTERFACE_BLOCK_MANAGER,
BLOCK_DEVICE_ADDED,
- "issssssisibii", arr);
+ var);
else if (op == BLOCK_DEV_REMOVE)
- broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
+ dbus_handle_broadcast_dbus_signal_var(STORAGED_PATH_BLOCK_MANAGER,
STORAGED_INTERFACE_BLOCK_MANAGER,
BLOCK_DEVICE_REMOVED,
- "issssssisibii", arr);
+ var);
else {
- broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
+ dbus_handle_broadcast_dbus_signal_var(STORAGED_PATH_BLOCK_MANAGER,
STORAGED_INTERFACE_BLOCK_MANAGER,
BLOCK_DEVICE_CHANGED,
- "issssssisibii", arr);
- broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
+ var);
+ dbus_handle_broadcast_dbus_signal_var(STORAGED_PATH_BLOCK_MANAGER,
STORAGED_INTERFACE_BLOCK_MANAGER,
BLOCK_DEVICE_CHANGED_2,
- "issssssisibi", arr);
+ block_data_to_gvariant2(data, flags));
}
}
{
int ret;
- ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
- PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
- NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
+ ret = dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
+ PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs", NULL, NULL);
if (ret)
_E("Fail to create external directory");
}
}
}
-static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
-{
- DBusMessage *rep;
-
- if (!reply_handle)
- return;
-
- rep = make_dbus_reply_message_simple(reply_handle, result);
- reply_dbus_method_result(reply_handle, rep);
-}
-
// Called by BlockThread
static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
{
}
temp->done = true;
th_manager[thread_id].op_len--;
- block_send_dbus_reply((*op)->reply_handle, 0);
+ block_send_dbus_reply((*op)->invocation, 0);
}
remove_operation(bdev);
}
temp->done = true;
th_manager[thread_id].op_len--;
- block_send_dbus_reply((*op)->reply_handle, 0);
+ block_send_dbus_reply((*op)->invocation, 0);
}
remove_operation(bdev);
op->done = true;
th_manager[thread_id].op_len--;
- block_send_dbus_reply(op->reply_handle, ret);
+ block_send_dbus_reply(op->invocation, ret);
queue = bdev->op_queue;
if (queue != NULL) {
// Called by MainThread
static int add_operation(struct block_device *bdev,
enum block_dev_operation operation,
- dbus_method_reply_handle_h reply_handle, void *data)
+ GDBusMethodInvocation *invocation, void *data)
{
struct operation_queue *op;
int ret;
op->op = operation;
op->data = data;
- op->reply_handle = reply_handle;
+ op->invocation = invocation;
/* LOCK
* during adding queue and checking the queue length */
}
}
-static void booting_done(const char *sender_name,
- const char *object_path, const char *interface_name,
- const char *signal_name, DBusMessage *msg,
- void *data)
+static void booting_done(GDBusConnection *conn,
+ const gchar *sender,
+ const gchar *path,
+ const gchar *iface,
+ const gchar *name,
+ GVariant *param,
+ gpointer data)
{
static int done = 0;
int ret;
block_boot = true;
}
-static void block_poweroff(const char *sender_name,
- const char *object_path, const char *interface_name,
- const char *signal_name, DBusMessage *msg,
- void *data)
+static void block_poweroff(GDBusConnection *conn,
+ const gchar *sender,
+ const gchar *path,
+ const gchar *iface,
+ const gchar *name,
+ GVariant *param,
+ gpointer data)
{
static int status = 0;
if (status > 0)
}
}
-static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg, bool onprivate)
+static GVariant *request_mount_block(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data, bool onprivate)
{
struct block_device *bdev;
- char *mount_point;
+ char *mount_point = NULL;
int id;
int ret = -EBADMSG;
goto out;
}
- if (!reply_handle || !msg)
- goto out;
-
- ret = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &id,
- DBUS_TYPE_STRING, &mount_point,
- DBUS_TYPE_INVALID);
- if (!ret)
- goto out;
+ g_variant_get(param, "(is)", &id, &mount_point);
bdev = find_block_device_by_id(id);
if (!bdev) {
if (onprivate) {
bdev->on_private_op = REQ_PRIVATE;
- bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
+ bdev->private_pid = dbus_handle_get_sender_pid(NULL, sender);
_D("Private operation state: %d", bdev->on_private_op);
} else {
if (bdev->on_private_op != REQ_NORMAL) {
create_file(bdev->data->id, bdev->data->mount_point, false);
}
- ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
+ ret = add_operation(bdev, BLOCK_DEV_MOUNT, invocation, NULL);
if (ret < 0) {
_E("Failed to add operation (mount %s)", bdev->data->devnode);
goto out;
}
+ g_free(mount_point);
return NULL;
out:
- return make_dbus_reply_message_simple(reply_handle, ret);
+ g_free(mount_point);
+ return g_variant_new("(i)", ret);
}
-static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_public_mount_block(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
- return request_mount_block(reply_handle, msg, false);
+ return request_mount_block(conn, sender, path, iface, name, param, invocation, user_data, false);
}
-static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_private_mount_block(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
- return request_mount_block(reply_handle, msg, true);
+ return request_mount_block(conn, sender, path, iface, name, param, invocation, user_data, true);
}
-static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg, bool onprivate)
+static GVariant *request_unmount_block(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data, bool onprivate)
{
struct block_device *bdev;
pid_t pid;
goto out;
}
- if (!reply_handle || !msg)
- goto out;
-
- ret = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &id,
- DBUS_TYPE_INT32, &option,
- DBUS_TYPE_INVALID);
- if (!ret)
- goto out;
+ g_variant_get(param, "(ii)", &id, &option);
bdev = find_block_device_by_id(id);
if (!bdev) {
}
if (onprivate) {
- pid = get_dbus_method_sender_pid(reply_handle);
+ pid = dbus_handle_get_sender_pid(NULL, sender);
if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
_E("Failed to process private unmount operation");
ret = -EPERM;
}
}
- ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
+ ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, invocation, (void *)option);
if (ret < 0) {
_E("Failed to add operation (unmount %s)", bdev->data->devnode);
goto out;
return NULL;
out:
- return make_dbus_reply_message_simple(reply_handle, ret);
+ return g_variant_new("(i)", ret);
}
-static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_public_unmount_block(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
- return request_unmount_block(reply_handle, msg, false);
+ return request_unmount_block(conn, sender, path, iface, name, param, invocation, user_data, false);
}
-static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_private_unmount_block(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
- return request_unmount_block(reply_handle, msg, true);
+ return request_unmount_block(conn, sender, path, iface, name, param, invocation, user_data, true);
}
-static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_format_block(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
struct block_device *bdev;
struct format_data *fdata;
goto out;
}
- if (!reply_handle || !msg)
- goto out;
-
- ret = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &id,
- DBUS_TYPE_INT32, &option,
- DBUS_TYPE_INVALID);
- if (!ret)
- goto out;
+ g_variant_get(param, "(ii)", &id, &option);
bdev = find_block_device_by_id(id);
if (!bdev) {
goto out;
}
- pid = get_dbus_method_sender_pid(reply_handle);
+ pid = dbus_handle_get_sender_pid(NULL, sender);
if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
_E("Failed to format on private state");
ret = -EPERM;
}
}
- ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
+ ret = add_operation(bdev, BLOCK_DEV_FORMAT, invocation, (void *)fdata);
if (ret < 0) {
_E("Failed to add operation (format %s)", bdev->data->devnode);
release_format_data(fdata);
return NULL;
out:
- return make_dbus_reply_message_simple(reply_handle, ret);
+ return g_variant_new("(i)", ret);
}
-static DBusMessage *request_format_block_type(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_format_block_type(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
struct block_device *bdev;
struct format_data *fdata;
- char *type;
+ char *type = NULL;
pid_t pid;
int id;
int option;
goto out;
}
- if (!reply_handle || !msg)
- goto out;
-
- ret = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &id,
- DBUS_TYPE_INT32, &option,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_INVALID);
- if (!ret)
- goto out;
+ g_variant_get(param, "(iis)", &id, &option, &type);
bdev = find_block_device_by_id(id);
if (!bdev) {
goto out;
}
- pid = get_dbus_method_sender_pid(reply_handle);
+ pid = dbus_handle_get_sender_pid(NULL, sender);
if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
_E("Failed to format on private state");
ret = -EPERM;
}
}
- ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
+ ret = add_operation(bdev, BLOCK_DEV_FORMAT, invocation, (void *)fdata);
if (ret < 0) {
_E("Failed to add operation (format %s)", bdev->data->devnode);
release_format_data(fdata);
}
}
+ g_free(type);
return NULL;
out:
- return make_dbus_reply_message_simple(reply_handle, ret);
-}
-
-static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
-{
- char *str_null = "";
-
- if (!data || !piter)
- return -EINVAL;
-
- dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
- &(data->block_type));
- dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
- data->devnode ? &(data->devnode) : &str_null);
- dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
- data->syspath ? &(data->syspath) : &str_null);
- dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
- data->fs_usage ? &(data->fs_usage) : &str_null);
- dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
- data->fs_type ? &(data->fs_type) : &str_null);
- dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
- data->fs_version ? &(data->fs_version) : &str_null);
- dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
- data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
- dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
- &(data->readonly));
- dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
- data->mount_point ? &(data->mount_point) : &str_null);
- dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
- &(data->state));
- dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
- &(data->primary));
- dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
- &(data->flags));
- dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
- &(data->id));
-
- return 0;
-}
-
-
-static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
-{
- DBusMessageIter piter;
-
- if (!data || !iter)
- return -EINVAL;
-
- dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
- add_device_to_iter(data, &piter);
- dbus_message_iter_close_container(iter, &piter);
-
- return 0;
+ g_free(type);
+ return g_variant_new("(i)", ret);
}
-static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
+static GVariant *block_data_to_gvariant(struct block_data *data, int flags)
{
- DBusMessageIter piter;
- char *str_null = "";
-
- if (!data || !iter)
- return -EINVAL;
-
- dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
- &(data->block_type));
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
- data->devnode ? &(data->devnode) : &str_null);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
- data->syspath ? &(data->syspath) : &str_null);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
- data->fs_usage ? &(data->fs_usage) : &str_null);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
- data->fs_type ? &(data->fs_type) : &str_null);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
- data->fs_version ? &(data->fs_version) : &str_null);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
- data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
- &(data->readonly));
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
- data->mount_point ? &(data->mount_point) : &str_null);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
- &(data->state));
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
- &(data->primary));
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
- &(data->flags));
- dbus_message_iter_close_container(iter, &piter);
-
- return 0;
-}
-
-static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+ if (!data)
+ return dbus_handle_new_g_variant_tuple();
+
+ return g_variant_new("(issssssisibii)",
+ data->block_type,
+ nullstr(data->devnode),
+ nullstr(data->syspath),
+ nullstr(data->fs_usage),
+ nullstr(data->fs_type),
+ nullstr(data->fs_version),
+ nullstr(data->fs_uuid_enc),
+ data->readonly,
+ nullstr(data->mount_point),
+ data->state,
+ data->primary,
+ flags >= 0 ? flags : data->flags,
+ data->id);
+}
+
+static GVariant *block_data_to_gvariant2(struct block_data *data, int flags)
{
- DBusMessageIter iter;
- DBusMessage *reply;
- struct block_device *bdev;
- struct block_data *data;
- int ret, id;
-
- if (!reply_handle || !msg)
- return NULL;
-
- reply = make_dbus_reply_message(reply_handle);
- if (!reply)
- goto out;
+ if (!data)
+ return dbus_handle_new_g_variant_tuple();
+
+ return g_variant_new("(issssssisibi)",
+ data->block_type,
+ nullstr(data->devnode),
+ nullstr(data->syspath),
+ nullstr(data->fs_usage),
+ nullstr(data->fs_type),
+ nullstr(data->fs_version),
+ nullstr(data->fs_uuid_enc),
+ data->readonly,
+ nullstr(data->mount_point),
+ data->state,
+ data->primary,
+ flags >= 0 ? flags : data->flags);
+}
+
+
+//static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
+//{
+// //DBusMessageIter piter;
+//
+// //if (!data || !iter)
+// // return -EINVAL;
+//
+// //dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
+// //add_device_to_iter(data, &piter);
+// //dbus_message_iter_close_container(iter, &piter);
+//
+// return 0;
+//}
+
+//static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
+//{
+// DBusMessageIter piter;
+// char *str_null = "";
+//
+// if (!data || !iter)
+// return -EINVAL;
+//
+// //dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
+// // &(data->block_type));
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
+// // data->devnode ? &(data->devnode) : &str_null);
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
+// // data->syspath ? &(data->syspath) : &str_null);
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
+// // data->fs_usage ? &(data->fs_usage) : &str_null);
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
+// // data->fs_type ? &(data->fs_type) : &str_null);
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
+// // data->fs_version ? &(data->fs_version) : &str_null);
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
+// // data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
+// // &(data->readonly));
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
+// // data->mount_point ? &(data->mount_point) : &str_null);
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
+// // &(data->state));
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
+// // &(data->primary));
+// //dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
+// // &(data->flags));
+// //dbus_message_iter_close_container(iter, &piter);
+//
+// return 0;
+//}
+
+static GVariant *request_get_device_info(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ struct block_device *bdev = NULL;
+ struct block_data *data = NULL;
+ int id;
- ret = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &id,
- DBUS_TYPE_INVALID);
- if (!ret)
- goto out;
+ g_variant_get(param, "(i)", &id);
bdev = find_block_device_by_id(id);
if (!bdev)
if (!data)
goto out;
- dbus_message_iter_init_append(reply, &iter);
- add_device_to_iter(data, &iter);
-
out:
- return reply;
+ return block_data_to_gvariant(data, -1);
}
-static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_show_device_list(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
show_block_device_list();
- return make_dbus_reply_message(reply_handle);
+ return dbus_handle_new_g_variant_tuple();
}
-
// Called by MainThread
-static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_get_device_list(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
- DBusMessageIter iter;
- DBusMessageIter aiter;
- DBusMessage *reply;
+ GVariant *reply = NULL;
struct block_device *bdev;
struct block_data *data;
dd_list *elem;
char *type = NULL;
- int ret = -EBADMSG;
int block_type;
int i;
+ GVariantBuilder *builder = NULL;
- reply = make_dbus_reply_message(reply_handle);
-
- ret = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_INVALID);
- if (!ret) {
- _E("Failed to get args");
- goto out;
- }
+ g_variant_get(param, "(s)", &type);
if (!type) {
_E("Delivered type is NULL");
goto out;
}
- dbus_message_iter_init_append(reply, &iter);
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a(issssssisibii)"));
for (i = 0; i < THREAD_MAX; i++) {
pthread_mutex_lock(&(th_manager[i].mutex));
default:
break;
}
- add_device_to_struct_iter(data, &aiter);
+
+ g_variant_builder_add(builder, "(issssssisibii)",
+ data->block_type,
+ nullstr(data->devnode),
+ nullstr(data->syspath),
+ nullstr(data->fs_usage),
+ nullstr(data->fs_type),
+ nullstr(data->fs_version),
+ nullstr(data->fs_uuid_enc),
+ data->readonly,
+ nullstr(data->mount_point),
+ data->state,
+ data->primary,
+ data->flags,
+ data->id);
}
pthread_mutex_unlock(&(th_manager[i].mutex));
}
- dbus_message_iter_close_container(&iter, &aiter);
+ reply = g_variant_new("(a(issssssisibii))", builder);
+ g_variant_builder_unref(builder);
out:
+ g_free(type);
+ if (!reply)
+ reply = dbus_handle_new_g_variant_tuple();
return reply;
}
// Called by MainThread
-static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_get_device_list_2(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
- DBusMessageIter iter;
- DBusMessageIter aiter;
- DBusMessage *reply;
+ GVariant *reply = NULL;
struct block_device *bdev;
struct block_data *data;
dd_list *elem;
char *type = NULL;
- int ret = -EBADMSG;
int block_type;
int i;
+ GVariantBuilder *builder = NULL;
- reply = make_dbus_reply_message(reply_handle);
-
- ret = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_INVALID);
- if (!ret) {
- _E("Failed to get args");
- goto out;
- }
+ g_variant_get(param, "(s)", &type);
if (!type) {
_E("Delivered type is NULL");
goto out;
}
- dbus_message_iter_init_append(reply, &iter);
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a(issssssisibi)"));
for (i = 0; i < THREAD_MAX; i++) {
pthread_mutex_lock(&(th_manager[i].mutex));
break;
}
- add_device_to_iter_2(data, &aiter);
+ g_variant_builder_add(builder, "(issssssisibi)",
+ data->block_type,
+ nullstr(data->devnode),
+ nullstr(data->syspath),
+ nullstr(data->fs_usage),
+ nullstr(data->fs_type),
+ nullstr(data->fs_version),
+ nullstr(data->fs_uuid_enc),
+ data->readonly,
+ nullstr(data->mount_point),
+ data->state,
+ data->primary,
+ data->flags);
}
pthread_mutex_unlock(&(th_manager[i].mutex));
}
- dbus_message_iter_close_container(&iter, &aiter);
+ reply = g_variant_new("(a(issssssisibi))", builder);
+ g_variant_builder_unref(builder);
out:
+ g_free(type);
return reply;
}
-static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_get_mmc_primary(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
- DBusMessageIter iter;
- DBusMessage *reply;
struct block_device *bdev;
struct block_data *data, nodata = {0,};
dd_list *elem;
- bool found;
+ bool found = false;
int i;
- if (!reply_handle || !msg)
- return NULL;
-
- reply = make_dbus_reply_message(reply_handle);
- if (!reply)
- goto out;
-
- found = false;
for (i = 0; i < THREAD_MAX; i++) {
pthread_mutex_lock(&(th_manager[i].mutex));
DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
break;
}
- dbus_message_iter_init_append(reply, &iter);
- if (found)
- add_device_to_iter(data, &iter);
- else {
+ if (!found) {
nodata.id = -ENODEV;
- add_device_to_iter(&nodata, &iter);
+ data = &nodata;
}
-out:
- return reply;
+ return block_data_to_gvariant(data, -1);
}
-static DBusMessage *request_check_speed(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_check_speed(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
struct timespec start_time, end_time;
- DBusMessageIter iter;
- DBusMessage *reply;
struct block_device *bdev;
struct block_data *data;
char *buf;
int fd;
int time_diff;
- if (!reply_handle || !msg)
- return NULL;
-
- ret = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &id,
- DBUS_TYPE_INVALID);
- if (!ret) {
- result = -1;
- goto out;
- }
+ g_variant_get(param, "(i)", &id);
bdev = find_block_device_by_id(id);
if (!bdev) {
close(fd);
out:
- reply = dbus_message_new_method_return(msg);
- dbus_message_iter_init_append(reply, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &result);
- return reply;
+ return g_variant_new("(i)", result);
}
-static DBusMessage *request_control_block(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_control_block(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
- int ret;
int enable;
int result;
- DBusMessage *reply;
- DBusMessageIter iter;
- ret = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &enable,
- DBUS_TYPE_INVALID);
- if (!ret) {
- result = -1;
- goto out;
- }
+ g_variant_get(param, "(i)", &enable);
switch (enable) {
case 0:
break;
}
-out:
- reply = dbus_message_new_method_return(msg);
- dbus_message_iter_init_append(reply, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &result);
-
- return reply;
+ return g_variant_new("(i)", result);
}
-static DBusMessage *request_getcontrol_block(dbus_method_reply_handle_h reply_handle,
- DBusMessage *msg)
+static GVariant *request_getcontrol_block(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
{
int result;
- DBusMessage *reply;
- DBusMessageIter iter;
_I("getcontrol block");
result = block_control;
- reply = dbus_message_new_method_return(msg);
- dbus_message_iter_init_append(reply, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &result);
-
- return reply;
+ return g_variant_new("(i)", result);
}
/*
*/
static const dbus_method_s manager_methods[] = {
- { "ShowDeviceList", NULL, request_show_device_list },
- { "GetDeviceList" , "s", request_get_device_list },
- { "GetDeviceList2", "s", request_get_device_list_2 },
- { "Mount", "is", request_public_mount_block },
- { "Unmount", "ii", request_public_unmount_block },
- { "Format", "ii", request_format_block },
- { "FormatwithType", "iis", request_format_block_type },
- { "GetDeviceInfo", "i", request_get_device_info },
- { "GetMmcPrimary" , NULL, request_get_mmc_primary },
- { "PrivateMount", "is", request_private_mount_block },
- { "PrivateUnmount", "ii", request_private_unmount_block },
- { "CheckSpeed", "i", request_check_speed },
- { "Control", "i", request_control_block },
- { "GetControl", "i", request_getcontrol_block },
+ { "ShowDeviceList", NULL, NULL, request_show_device_list },
+ { "GetDeviceList" , "s", "a(issssssisibii)", request_get_device_list },
+ { "GetDeviceList2", "s", "a(issssssisibi)", request_get_device_list_2 },
+ { "Mount", "is", "i", request_public_mount_block },
+ { "Unmount", "ii", "i", request_public_unmount_block },
+ { "Format", "ii", "i", request_format_block },
+ { "FormatwithType", "iis", "i", request_format_block_type },
+ { "GetDeviceInfo", "i", "issssssisibii", request_get_device_info },
+ { "GetMmcPrimary", NULL, "issssssisibii", request_get_mmc_primary },
+ { "PrivateMount", "is", "i", request_private_mount_block },
+ { "PrivateUnmount", "ii", "i", request_private_unmount_block },
+ { "CheckSpeed", "i", "i", request_check_speed },
+ { "Control", "i", "i", request_control_block },
+ { "GetControl", "i", "i", request_getcontrol_block },
};
-static dbus_interface_s block_interface = {
+static const dbus_interface_u block_interface = {
.name = STORAGED_INTERFACE_BLOCK_MANAGER,
.methods = manager_methods,
.nr_methods = ARRAY_SIZE(manager_methods),
#define mount_root_path_tmpfs() 0
#endif
+static guint id_booting_done;
+static guint id_block_poweroff;
+
static void block_init(void *data)
{
struct stat buf;
int ret;
int i;
- dbus_handle_h handle;
udev_init(NULL);
if (ret < 0)
_E("Failed to mount tmpfs to root mount path (%d)", ret);
- ret = dbus_get_connection(&handle);
- if (ret < 0)
- _E("Failed to get dbus connection(%d)", ret);
-
/* register block manager object and interface */
- ret = register_dbus_methods(handle,
- STORAGED_PATH_BLOCK_MANAGER, &block_interface,
- NULL, NULL);
+ ret = dbus_handle_register_dbus_object(NULL, STORAGED_PATH_BLOCK_MANAGER, &block_interface);
if (ret < 0)
_E("Failed to register block interface and methods (%d)", ret);
_E("fail to init pipe");
/* System Session is loaded completely */
- register_dbus_signal(SYSTEMD_DBUS_PATH,
+ id_booting_done = subscribe_dbus_signal(NULL, SYSTEMD_DBUS_PATH,
SYSTEMD_DBUS_IFACE_MANAGER,
SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
booting_done, NULL, NULL);
- register_dbus_signal(DEVICED_PATH_POWEROFF,
+ id_block_poweroff = subscribe_dbus_signal(NULL, DEVICED_PATH_POWEROFF,
DEVICED_INTERFACE_POWEROFF,
SIGNAL_POWEROFF_STATE,
block_poweroff, NULL, NULL);
udev_exit(NULL);
/* unregister notifier for below each event */
- unregister_dbus_signal(SYSTEMD_DBUS_PATH,
- SYSTEMD_DBUS_IFACE_MANAGER,
- SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
- booting_done);
-
- unregister_dbus_signal(DEVICED_PATH_POWEROFF,
- DEVICED_INTERFACE_POWEROFF,
- SIGNAL_POWEROFF_STATE, block_poweroff);
+ unsubscribe_dbus_signal(NULL, id_booting_done);
+ unsubscribe_dbus_signal(NULL, id_block_poweroff);
/* unregister mmc uevent control routine */
ret = unregister_udev_uevent_control(&uh);
* limitations under the License.
*/
+
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
-#include <dbus/dbus.h>
#include <stdbool.h>
-#include <limits.h>
-#include "fd_handler.h"
-#include "dbus.h"
+#include <stdint.h>
+#include <errno.h>
+
+#include "common.h"
#include "log.h"
+#include "dbus.h"
-/* -1 is a default timeout value, it's converted to 25*1000 internally. */
-#define DBUS_REPLY_TIMEOUT (-1)
+/* 10 seconds */
+#define DBUS_REPLY_TIMEOUT (10000)
-struct dbus_handle_s {
- DBusConnection *conn;
- char *name;
- GList *method_handle_list;
-};
+int check_systemd_active(void)
+{
+ int ret = FALSE;
+ GVariant *msg = NULL;
+ GVariant *var = NULL;
+ char *state;
+
+ _I("%s %s", "org.freedesktop.systemd1.Unit", "ActiveState");
+
+ msg = dbus_method_sync_with_reply_var("org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1/unit/default_2etarget",
+ "org.freedesktop.DBus.Properties",
+ "Get", g_variant_new("(ss)", "org.freedesktop.systemd1.Unit", "ActiveState"));
+ if (!msg)
+ return -EBADMSG;
-struct dbus_method_reply_handle_s {
- struct dbus_handle_s *handle;
- DBusMessage *msg;
-};
+ if (!dh_get_param_from_var(msg, "(v)", &var)) {
+ _E("reply is not variant type");
+ ret = -EBADMSG;
+ goto out;
+ }
+ if (!dh_get_param_from_var(var, "(s)", &state)) {
+ _E("variant doesn't have string (%s)", g_variant_get_type_string(var));
+ ret = -EBADMSG;
+ goto out;
+ }
-struct dbus_method_handle_s {
- struct dbus_handle_s *handle;
- const char *path;
- const dbus_interface_s *iface;
- void (*method_handle_received)(void *method_handle, void *data);
- void *data;
-};
+ if (strncmp(state, "active", 6) == 0)
+ ret = TRUE;
-struct signal_info {
- const char *path;
- const char *iface;
- const char *name;
- dbus_signal_received cb;
- destroy_notified free_func;
- void *data;
- guint handler;
-};
+ g_free(state);
+out:
+ if (var)
+ g_variant_unref(var);
+ if (msg)
+ g_variant_unref(msg);
-struct pending_call_data {
- dbus_pending_cb func;
- void *data;
-};
+ return ret;
+}
-static GList *connection_handle_list;
-static GList *signal_handler_list;
+static GBusType g_default_bus_type = G_BUS_TYPE_SYSTEM;
+pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
-static DBusConnection *get_dbus_connection(void)
+void dbus_handle_set_default_bus_type(GBusType bus_type)
{
- static DBusConnection *conn;
- DBusError err;
+ if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION)
+ return ;
- if (conn)
- return conn;
+ pthread_mutex_lock(&g_mutex);
+ g_default_bus_type = bus_type;
+ pthread_mutex_unlock(&g_mutex);
+}
- dbus_error_init(&err);
+GBusType dbus_handle_get_default_bus_type(void)
+{
+ GBusType type;
- conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
- if (!conn) {
- if (dbus_error_is_set(&err)) {
- _E("dbus_bus_get error(%s, %s)", err.name, err.message);
- dbus_error_free(&err);
- } else
- _E("dbus_bus_get error");
- }
+ pthread_mutex_lock(&g_mutex);
+ type = g_default_bus_type;
+ pthread_mutex_unlock(&g_mutex);
- return conn;
+ return type;
}
-int dbus_get_connection(dbus_handle_h *handle)
-{
- static DBusConnection *conn;
- struct dbus_handle_s *h;
- int ret;
+typedef struct {
+ const char *bus_name;
+ guint id;
+} dbus_name;
+
+/* basic information */
+typedef struct {
+ GDBusConnection *conn;
+ GBusType bus_type;
+ gboolean priv;
+ GList *list_names; // dbus_name
+ GList *list_object; /* dbus_object_handle_s */
+ pthread_mutex_t mutex;// = PTHREAD_MUTEX_INITIALIZER;
+} dbus_handle_s;
+
+/* path + interfaces */
+typedef struct {
+ dbus_handle_s *dh; /* dbus handle */
+ const char *path;
+ GList *list_ifaces; /* dbus_interface_s */
+} dbus_object_handle_s;
+
+typedef struct {
+ dbus_object_handle_s *oh;
+ const char *name;
+ GList *list_methods; // const dbus_method_s;
+ guint reg_id;
+ int modified;
+} dbus_interface_s;
+
+#define get_dh_from_oh(oh) ((dbus_object_handle_s*)oh)->dh
- if (!handle)
- return -EINVAL;
+static dbus_handle_s g_dh[2];
+
+static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type);
+
+dbus_handle_s * _dbus_handle_get_default_connection(void)
+{
+ return _dbus_handle_get_connection(dbus_handle_get_default_bus_type());
+}
- h = calloc(1, sizeof(struct dbus_handle_s));
- if (!h) {
- _E("calloc() failed");
- return -ENOMEM;
+#define dbus_handle_lock(handle) do {\
+ assert(handle);\
+ pthread_mutex_lock(&((handle)->mutex));\
+} while (0);
+
+#define dbus_handle_unlock(handle) do {\
+ assert(handle);\
+ pthread_mutex_unlock(&(handle)->mutex);\
+} while (0);
+
+#define dcl_dbus_handle() dbus_handle_s *dh = (dbus_handle_s *)handle;
+#define dcl_dbus_handle_null_check() dbus_handle_s *dh = (dbus_handle_s *)handle;\
+ if (!dh) {\
+ _E("dbus handle is null\n");\
+ return 0;\
}
- conn = get_dbus_connection();
- if (!conn) {
- _E("Failed to get dbus connection");
- ret = -ECOMM;
- goto out;
+dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path);
+dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name);
+dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name);
+static GVariant* _append_variant(const char *signature, const char *param[]);
+
+dbus_interface_s *_iface_u_to_s(const dbus_interface_u *iface_u)
+{
+ dbus_interface_s *iface = NULL;
+
+ if (!iface_u || !iface_u->methods) {
+ _E("param is null");
+ return NULL;
}
- h->conn = conn;
- *handle = h;
+ iface = (dbus_interface_s *)calloc(1, sizeof(dbus_interface_s));
+ if (!iface) {
+ _E("failed to calloc");
+ return NULL;
+ }
- connection_handle_list = g_list_append(connection_handle_list, h);
+ iface->name = iface_u->name;
+ iface->modified = TRUE;
- return 0;
+ for (int i = 0 ; i < iface_u->nr_methods; ++i) {
+ //_D("attached %s:%p", iface_u->methods[i].member, iface_u->methods[i].func);
+ iface->list_methods = g_list_prepend(iface->list_methods, (void*)(iface_u->methods + i));
+ }
-out:
- free(h);
- return ret;
+ return iface;
}
-int get_dbus_method_sender_name(dbus_method_reply_handle_h reply_handle,
- char *name, size_t len)
+static GDBusConnection * _get_bus(GBusType bus_type)
{
- struct dbus_method_reply_handle_s *reply = reply_handle;
- const char *sender;
+ GDBusConnection *conn = NULL;
+ GError *err = NULL;
- if (!reply || !reply->msg || !name)
- return -EINVAL;
+ if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
+ _E("Wrong bus_type %d", bus_type);
+ return NULL;
+ }
- sender = dbus_message_get_sender(reply->msg);
- snprintf(name, len, "%s", sender);
+ conn = g_bus_get_sync(bus_type, NULL, &err);
+ if (!conn || err) {
+ _E("failed to get bus:type:%d, %s\n", bus_type, err->message);
+ g_error_free(err);
+ return NULL;
+ }
- return 0;
+ return conn;
}
-int get_dbus_method_sender_pid(dbus_method_reply_handle_h reply_handle)
+static GDBusConnection * _get_bus_private(GBusType bus_type)
{
- char *param[1];
- pid_t pid;
- char name[NAME_MAX];
- DBusMessage *msg;
- DBusError err;
- int ret;
+ GError *err = NULL;
+ GDBusConnection *conn = NULL;
+ const char * address;
- ret = get_dbus_method_sender_name(reply_handle, name, sizeof(name));
- if (ret < 0)
- return ret;
-
- param[0] = name;
- ret = call_dbus_method_sync(DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "GetConnectionUnixProcessID",
- "s", param, DBUS_REPLY_TIMEOUT,
- &msg);
- if (ret < 0) {
- _E("Faild to get pid of sender(%s)", name);
- return ret;
+ if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
+ _E("Wrong bus_type %d", bus_type);
+ return NULL;
}
- dbus_error_init(&err);
-
- ret = dbus_message_get_args(msg, &err, DBUS_TYPE_UINT32, &pid, DBUS_TYPE_INVALID);
- dbus_message_unref(msg);
- if (dbus_error_is_set(&err)) {
- _E("no message : [%s:%s]", err.name, err.message);
- dbus_error_free(&err);
- return -ENOMSG;
+ address = g_dbus_address_get_for_bus_sync(bus_type, NULL, &err);
+ if (!address || err) {
+ _E("failed to get bus address\n");
+ g_error_free(err);
+ return NULL;
}
- if (!ret) {
- _E("no message");
- return -ENOMSG;
+
+ conn = g_dbus_connection_new_for_address_sync(address,
+ (GDBusConnectionFlags) (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+ G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
+ NULL, /* GDBusAuthObserver */
+ NULL,
+ &err);
+ if (!conn || err) {
+ _E("failed to get private bus\n");
+ g_error_free(err);
+ return NULL;
}
- return pid;
+ return conn;
}
-DBusMessage *make_dbus_reply_message(dbus_method_reply_handle_h reply_handle)
+/* ref cout is 1 */
+static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type)
{
- struct dbus_method_reply_handle_s *reply = reply_handle;
+ int ibus = bus_type - 1;
+ dbus_handle_s *dh = NULL;
- if (!reply || !(reply->msg)) {
- _E("Invalid parameter");
+ if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
+ _E("Unknown bus type %d", bus_type);
return NULL;
}
+ dh = &g_dh[ibus];
- return dbus_message_new_method_return(reply->msg);
-}
-
-DBusMessage *make_dbus_reply_message_simple(dbus_method_reply_handle_h reply_handle, int result)
-{
- DBusMessage *rep;
- DBusMessageIter iter;
- rep = make_dbus_reply_message(reply_handle);
- dbus_message_iter_init_append(rep, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &result);
- return rep;
-}
+ dbus_handle_lock(dh);
-void reply_dbus_method_result(dbus_method_reply_handle_h reply_handle, DBusMessage *reply_msg)
-{
- struct dbus_method_reply_handle_s *reply = reply_handle;
+ if (!dh->conn) {
+ dh->conn = _get_bus(bus_type);
+ dh->priv = FALSE;
+ dh->bus_type = bus_type;
+ if (!dh->conn)
+ dh = NULL;
+ }
- if (!reply || !reply_msg)
- return;
+ dbus_handle_unlock(dh);
- dbus_connection_send(reply->handle->conn, reply_msg, NULL);
- if (reply->msg)
- dbus_message_unref(reply->msg);
- dbus_message_unref(reply_msg);
- if (reply)
- free(reply);
+ return dh;
}
-static DBusHandlerResult method_call_handler(DBusConnection *connection,
- DBusMessage *msg, void *user_data)
+/* ref cout is 1 */
+static dbus_handle_s *_dbus_handle_get_connection_private(GBusType bus_type)
{
- int i;
- struct dbus_method_handle_s *mh = user_data;
- struct dbus_method_reply_handle_s *reply;
- const dbus_interface_s *iface;
- const dbus_method_s *methods;
- DBusMessage *result = NULL;
- bool method_is_implemented = false;
+ dbus_handle_s * dh;
- _D("Method call handler");
-
- if (!msg || !mh)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; // No message to handle
-
- iface = mh->iface;
- methods = iface->methods;
+ if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
+ _E("Unknown bus type %d", bus_type);
+ return NULL;
+ }
- for (i = 0 ; i < iface->nr_methods ; i++) {
- if (dbus_message_is_method_call(msg, iface->name, methods[i].member) != TRUE)
- continue;
+ dh = (dbus_handle_s *)calloc(1, sizeof(dbus_handle_s));
+ if (!dh) {
+ _E("failed to allocate memory for dbus handle");
+ return NULL;
+ }
- method_is_implemented = true;
- reply = calloc(1, sizeof(struct dbus_method_reply_handle_s));
- if (!reply) {
- _E("calloc() failed");
- return DBUS_HANDLER_RESULT_NEED_MEMORY; // Failed to create reply, try again later
- }
+ dbus_handle_lock(dh);
- reply->handle = mh->handle;
- reply->msg = dbus_message_ref(msg);
- result = methods[i].func(reply, msg);
- if (!result)
- _E("result == NULL");
- break;
+ if (!dh->conn) {
+ dh->conn = _get_bus_private(bus_type);
+ dh->bus_type = bus_type;
+ if (!dh->conn)
+ goto err;
}
- if (!method_is_implemented)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; // Missing method, no reply
- /* If result is null, reply will be sent by worker thread */
- if (result)
- reply_dbus_method_result(reply, result); // Method handled, reply sent
+ dbus_handle_unlock(dh);
- return DBUS_HANDLER_RESULT_HANDLED;
+ return dh;
+err:
+ if (dh) {
+ dbus_handle_unlock(dh);
+ free(dh);
+ }
+ return NULL;
}
-static const DBusObjectPathVTable path_vtable = {
- NULL,
- method_call_handler,
- NULL, NULL, NULL, NULL,
-};
-
-static gboolean register_methods(gpointer data)
+dbus_handle_h dbus_handle_get_connection(GBusType bus_type, gboolean priv)
{
- dbus_bool_t ret;
- struct dbus_method_handle_s *mh = data;
-
- if (!mh)
- return FALSE;
+ dbus_handle_s *dh = NULL;
- ret = dbus_connection_register_object_path(mh->handle->conn,
- mh->path, &path_vtable, mh);
- if (ret == FALSE) {
- _E("Failed to register methods (%s)", mh->path);
- return FALSE;
+ if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
+ _E("Wrong bus_type %d\n", bus_type);
+ return dh;
}
- if (mh->method_handle_received)
- mh->method_handle_received(mh, mh->data);
+ /* private */
+ if (priv)
+ dh = _dbus_handle_get_connection_private(bus_type);
+ /* shared */
+ else
+ dh = _dbus_handle_get_connection(bus_type);
- _I("object path(%s)", mh->path);
-
- return FALSE;
+ return dh;
}
-struct watch_info {
- DBusWatch *watch;
- void *data;
-};
+static void _dbus_handle_add_bus_name(dbus_handle_s *handle, const char *name, guint id)
+{
+ dbus_name *dn = NULL;
+ int locked = 0;
-static fd_handler_h watch_handler;
+ if (!handle || !name || !id)
+ return ;
-static bool watch_changed_cb(int fd, void *data)
-{
- struct watch_info *winfo = data;
+ dn = (dbus_name*)calloc(1, sizeof(dbus_name));
+ if (!dn) {
+ _E("failed to calloc");
+ assert(0);
+ }
+ dn->bus_name = name;
+ dn->id = id;
+
+ // todo : delete lock ?
+ locked = pthread_mutex_trylock(&handle->mutex);
+ if (locked != 0 && locked != EBUSY) {
+ _E("failed to lock %d\n", locked);
+ assert(0);
+ }
- dbus_watch_handle(winfo->watch, DBUS_WATCH_READABLE | DBUS_WATCH_ERROR);
+ handle->list_names = g_list_prepend(handle->list_names, dn);
- return true;
+ // todo : delete lock ?
+ if (locked != EBUSY)
+ dbus_handle_unlock(handle);
}
-static void free_watch_info(void *data)
+static gint _compare_dbus_name(gconstpointer a, gconstpointer b)
{
- if (data)
- free(data);
+ const char *bus_name = ((dbus_name *)a)->bus_name;
+ if (!bus_name || !b)
+ return -1;
+ return strcmp(bus_name, (const char *)b);
}
-static dbus_bool_t add_watch_cb(DBusWatch *watch, void *data)
+dbus_name * _dbus_handle_lookup_dbus_name(GList *list_name, const char *bus_name)
{
- int fd;
- int ret;
- struct watch_info *winfo;
- dbus_bool_t enabled;
-
- _I("add_watch_cb %s", (dbus_watch_get_enabled(watch) == 0 ? "disabled" : "enabled"));
+ if (!list_name || !bus_name)
+ return NULL;
- enabled = dbus_watch_get_enabled(watch);
+ GList *item = g_list_find_custom(list_name, bus_name, _compare_dbus_name);
+ if (!item)
+ return NULL;
- if (watch_handler || !enabled)
- return TRUE;
+ return (dbus_name *)item->data;
+}
- winfo = calloc(1, sizeof(struct watch_info));
- if (!winfo) {
- _E("calloc() failed");
- return TRUE;
- }
+#define dh_to_ds(x) ((dbus_handle_s*)x)
- winfo->watch = watch;
- winfo->data = NULL;
+/* remove dbus_name from dbus handle */
+static void _dbus_handle_remove_bus_name(dbus_handle_s *handle, const char *bus_name)
+{
+ dcl_dbus_handle();
+ dbus_name *dn = NULL;
- fd = dbus_watch_get_unix_fd(watch);
- ret = add_fd_read_handler(fd, watch_changed_cb, winfo, free_watch_info, &watch_handler);
- if (ret < 0)
- _E("Failed to add fd handler (%d)", ret);
+ if (!bus_name) {
+ _E("wrong bus_name %s", bus_name);
+ return ;
+ }
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return ;
+ }
+ }
- return TRUE;
+ dbus_handle_lock(dh);
+ dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name);
+ if (!dn) {
+ _E("failed to find dbus name %s", bus_name);
+ goto out;
+ }
+ dh->list_names = g_list_remove(dh->list_names, dn);
+ free(dn);
+out:
+ dbus_handle_unlock(dh);
}
-static void remove_watch_cb(DBusWatch *watch, void *data)
+static void _name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
{
- int ret;
+ dbus_handle_s *dh = (dbus_handle_s *)user_data;
- if (!watch_handler)
- return;
+ _D("name %s", name);
- ret = remove_fd_read_handler(&watch_handler);
- if (ret < 0)
- _E("Failed to remove fd handler (%d)", ret);
- watch_handler = NULL;
+ if (!dh) {
+ _E("%s:%d:dbus handle is null\n", __func__, __LINE__);
+ return ;
+ }
+ // todo: add bus name?
+ //dh->bus_name = name;
}
-static void toggle_watch_cb(DBusWatch *watch, void *data)
+static void _name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
{
- return;
+ _E("%s:%d:%s\n", __func__, __LINE__, name);
+ dbus_handle_s *dh = (dbus_handle_s *)user_data;
+ if (!dh) {
+ _E("%s:%d:dbus handle is null\n", __func__, __LINE__);
+ return ;
+ }
+ _dbus_handle_remove_bus_name(dh, name);
}
-static dbus_bool_t add_timeout_cb(DBusTimeout *timeout, void *data)
+int dbus_handle_request_bus_name(dbus_handle_h handle, const char *bus_name)
{
- return TRUE;
-}
+ dcl_dbus_handle();
+ int id = -1;
+ GList *item = NULL;
-static void remove_timeout_cb(DBusTimeout *timeout, void *data)
-{
- return;
-}
+ if (!bus_name) {
+ _E("bus_name is NULL");
+ return -1;
+ }
-static void toggle_timeout_cb(DBusTimeout *timeout, void *data)
-{
- return;
+ /* get shared connection */
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
+
+ dbus_handle_lock(dh);
+ if (!dh->conn) {
+ _E("failed to register name: connection is null\n");
+ goto out;
+ }
+
+ /* todo : search name on connection */
+ item = g_list_find_custom(dh->list_names, bus_name, _compare_dbus_name);
+ if (item) {
+ id = ((dbus_name*)(item->data))->id;
+ _E("name already exist:%u", id);
+ goto out;
+ }
+
+ id = g_bus_own_name_on_connection(dh->conn, bus_name, G_BUS_NAME_OWNER_FLAGS_NONE, _name_acquired, _name_lost, dh, NULL);
+ if (!id) {
+ _E("failed to own name:%s\n", bus_name);
+ goto out;
+ }
+
+ _dbus_handle_add_bus_name(dh, bus_name, id);
+
+out:
+ dbus_handle_unlock(dh);
+ return id;
}
-static gboolean dispatch_idler_cb(gpointer data)
+int dbus_handle_release_bus_name(dbus_handle_h handle, const char *bus_name)
{
- DBusConnection *conn = data;
+ dcl_dbus_handle();
+ dbus_name *dn = NULL;
- if (!conn) {
- _E("conn == NULL");
- return FALSE;
+ if (!bus_name) {
+ _E("Wrong bus name");
+ return -1;
}
- dbus_connection_ref(conn);
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
- while (dbus_connection_get_dispatch_status(conn) == DBUS_DISPATCH_DATA_REMAINS)
- dbus_connection_dispatch(conn);
+ dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name);
+ if (!dn) {
+ _E("failed to find bus_name %s on dbus handle", bus_name);
+ return -1;
+ }
- dbus_connection_unref(conn);
+ _E("unown name %d", dn->id);
+ /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */
+ g_bus_unown_name(dn->id);
- return FALSE;
-}
+ dbus_handle_lock(dh);
+ dh->list_names = g_list_remove(dh->list_names, dn);
+ free(dn);
+ dbus_handle_unlock(dh);
-static void dispatch_status_cb(DBusConnection *conn, DBusDispatchStatus new_status, void *data)
-{
- if (new_status == DBUS_DISPATCH_DATA_REMAINS)
- g_idle_add(dispatch_idler_cb, conn);
+ return 0;
}
-int register_dbus_methods(dbus_handle_h handle,
- const char *object_path, const dbus_interface_s *interface,
- void (*method_handle_received)(dbus_method_handle_h method_handle, void *data),
- void *data)
+int dbus_handle_free_connection(dbus_handle_h handle)
{
- struct dbus_method_handle_s *mh;
- struct dbus_handle_s *h = handle;
- static bool set_dispatch = false;
-
- if (!h || !(h->conn) || !object_path || !interface)
- return -EINVAL;
+ dcl_dbus_handle();
+ dbus_handle_s *pdh = NULL;
+ GError *err = NULL;
+ GList *item = NULL;
+
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
- mh = calloc(1, sizeof(struct dbus_method_handle_s));
- if (!mh) {
- _E("calloc() failed");
- return -ENOMEM;
+ if (!dh->conn) {
+ _E("connection is NULL");
+ return 0;
}
- mh->handle = h;
- mh->path = object_path;
- mh->iface = interface;
- mh->method_handle_received = method_handle_received;
- mh->data = data;
+ pdh = dh;
- h->method_handle_list = g_list_append(h->method_handle_list, mh);
+ /* disable dbus handler */
+ dbus_handle_lock(dh);
+ if (!pdh->conn) {
+ _E("conn is null");
+ free(pdh);
+ return 0;
+ }
- if (!set_dispatch) {
- set_dispatch = true;
+ /* flush everything */
+ if (!g_dbus_connection_flush_sync(pdh->conn, NULL, &err)) {
+ _E("failed to flush %s\n", err->message);
+ g_error_free(err);
+ err = NULL;
+ }
- dbus_connection_set_watch_functions(h->conn,
- add_watch_cb, remove_watch_cb, toggle_watch_cb,
- NULL, NULL);
+ _D("list_names %u", g_list_length(pdh->list_names));
- dbus_connection_set_timeout_functions(h->conn,
- add_timeout_cb, remove_timeout_cb, toggle_timeout_cb,
- NULL, NULL);
+ /* unown every well-knwon name */
+ if (pdh->list_names) {
+ dbus_name *dn = NULL;
+ for (item = g_list_first(pdh->list_names); item != NULL; item = g_list_next(item)) {
+ dn = (dbus_name *)item->data;
+ if (!dn)
+ continue;
- dbus_connection_set_dispatch_status_function(h->conn,
- dispatch_status_cb, NULL, NULL);
+ /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */
+ _D("unown name id : %u", dn->id);
+ g_bus_unown_name(dn->id);
+ free(dn);
+ }
+ g_list_free(pdh->list_names);
+ pdh->list_names = NULL;
}
- dispatch_status_cb(h->conn, dbus_connection_get_dispatch_status(h->conn), NULL);
+ _D("list_object %u", g_list_length(pdh->list_object));
- register_methods(mh);
+ /* unregister every object */
+ if (pdh->list_object) {
+ dbus_object_handle_s * oh = NULL;
+ //g_list_foreach(pdh->list_object, [] (gpointer data, gpointer user_data) {}, NULL);
+ for (item = g_list_first(pdh->list_object); item != NULL; item = g_list_next(item)) {
+ oh = (dbus_object_handle_s *)item->data;
+ if (!oh || !oh->list_ifaces)
+ continue;
- return 0;
-}
+ _D("delete object path %s", oh->path);
-void unregister_dbus_methods(dbus_handle_h handle, dbus_method_handle_h method_handle)
-{
- GList *l;
- struct dbus_method_handle_s *item;
- struct dbus_handle_s *h = handle;
- struct dbus_method_handle_s *mh = method_handle;
- bool found = false;
+ /* unregister every interface, method handles */
+ for (GList *iface = g_list_first(oh->list_ifaces); iface != NULL; iface = g_list_next(iface)) {
+ dbus_interface_s *ih = (dbus_interface_s *)iface->data;
+ if (!ih)
+ continue;
- if (!h || !h->conn)
- return;
- if (!mh)
- return;
+ _D("delete object iface %s", ih->name);
- for (l = h->method_handle_list ; l && (item = l->data) ;
- l = g_list_next(l), item = NULL) {
- if (item == mh) {
- h->method_handle_list = g_list_remove(h->method_handle_list, item);
- found = true;
- break;
+ if (ih->reg_id)
+ g_dbus_connection_unregister_object(pdh->conn, ih->reg_id);
+ }
}
}
- if (!found)
- return;
+ /* close connection */
+ if (pdh->priv) {
+ _E("close private connection\n");
+
+ if (!g_dbus_connection_close_sync(pdh->conn, NULL, &err)) {
+ _E("Error closing connection %s\n", err->message);
+ g_error_free(err);
+ err = NULL;
+ }
+ }
+
+ /* _free_func_object callback free the data */
+ //assert(g_list_length(pdh->list_names) == 0);
+ //assert(g_list_length(pdh->list_object) == 0);
+
+ g_object_unref(pdh->conn);
+
+ dbus_handle_unlock(dh);
+
+ if (dh->priv)
+ free(dh);
- dbus_connection_unregister_object_path(h->conn, item->path);
- free(item);
+ return 0;
+
+ // todo: signal ?
}
-static int append_variant(DBusMessageIter *iter, const char *sig, char *param[])
+#define buf_cal_free_space(size, nwrite) ((size - nwrite - 1) > 0 ? (size - nwrite - 1) : 0)
+#define buf_block_size 8192
+
+#define buf_check_space_realloc(buf, nwrite, buf_len) do {\
+ if ((nwrite >= buf_len - 1024)) {\
+ if (buf_len >= buf_block_size * 10) {\
+ _E("buf is too big to allocate. %d", buf_len);\
+ } else {\
+ _E("buf_check_space_realloc");\
+ char *tmp = NULL;\
+ buf_len += buf_block_size;\
+ tmp = (char *)realloc(buf, buf_len);\
+ if (!tmp) {\
+ _E("failed to realloc");\
+ } else\
+ buf = tmp;\
+ } \
+ } \
+} while (0);
+
+static int _check_brace(const char * expr)
{
- char *ch;
- int i;
- int int_type;
- dbus_bool_t bool_type;
- unsigned long long int64_type;
- DBusMessageIter arr;
- struct dbus_byte *byte;
+ int len = 0;
+ char qu[128];
+ int qucnt = 0;
- if (!sig || !param)
- return 0;
+ if (!expr)
+ return -1;
- for (ch = (char *)sig, i = 0; *ch != '\0'; ++i, ++ch) {
- switch (*ch) {
- case 'b':
- bool_type = (atoi(param[i]) == 0 ? FALSE : TRUE);
- dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &bool_type);
- break;
- case 'i':
- int_type = atoi(param[i]);
- dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &int_type);
- break;
- case 'u':
- int_type = strtoul(param[i], NULL, 10);
- dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &int_type);
- break;
- case 't':
- int64_type = atoll(param[i]);
- dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &int64_type);
- break;
- case 's':
- dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, ¶m[i]);
- break;
- case 'a':
- ++ch;
- switch (*ch) {
- case 'y':
- ++i;
- dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &arr);
- byte = (struct dbus_byte *)param[i];
- dbus_message_iter_append_fixed_array(&arr, DBUS_TYPE_BYTE, &(byte->data), byte->size);
- dbus_message_iter_close_container(iter, &arr);
- break;
- default:
- break;
+ len = strlen(expr);
+
+ if (expr[0] != '(' && expr[0] != '{')
+ return -1;
+
+ for (int i = 0 ; i < len; ++i) {
+
+ if (expr[i] == '(' || expr[i] == '{') {
+ qu[qucnt++] = expr[i];
+ if (qucnt >= sizeof(qu)) {
+ _E("queue is too large. %s", expr);
+ return -1;
+ }
+ continue;
+ }
+
+ if (expr[i] == ')' || expr[i] == '}') {
+ char ch;
+
+ if (qucnt > 0)
+ ch = qu[qucnt-1];
+ else
+ return -1;
+
+ if (expr[i] == ')') {
+ if (ch == '(') {
+ --qucnt;
+ } else
+ return -1;
+ } else if (expr[i] == '}') {
+ if (ch == '{') {
+ --qucnt;
+ } else
+ return -1;
+ } else
+ return -1;
+
+ if (qucnt == 0) {
+ return i + 1;
}
- break;
- default:
- return -EINVAL;
}
}
- return 0;
+ return -1;
}
-int broadcast_dbus_signal(const char *path, const char *iface,
- const char *name, const char *sig, char *param[])
+static int _get_xml_from_interfaces(char **xml, const dbus_interface_s *interfaces)
{
- DBusConnection *conn;
- DBusMessage *msg;
- DBusMessageIter iter;
- int ret;
-
- conn = get_dbus_connection();
- if (!conn) {
- _E("Failed to get dbus connection");
- return -ECOMM;
+ int nwrite = 0;
+ int len_args;
+ char *buf = NULL;
+ const dbus_method_s *pmethod;
+ int buf_len = buf_block_size;
+
+ if (!interfaces) {
+ _E("interfaces is null");
+ return -1;
}
- msg = dbus_message_new_signal(path, iface, name);
- if (!msg) {
- _E("fail to allocate new %s.%s signal", iface, name);
- return -EPERM;
+ // todo : check dbus naming rule for interface name. ?
+ if (!interfaces->name) {
+ _E("wrong interface name");
+ return -1;
+ }
+ if (!interfaces->list_methods) {
+ _E("no methods");
+ return -1;
}
- dbus_message_iter_init_append(msg, &iter);
- ret = append_variant(&iter, sig, param);
- if (ret < 0) {
- _E("append_variant error(%d)", ret);
- return -EPERM;
+ buf = (char *)malloc(buf_len);
+ if (!buf) {
+ _E("buf is null. not enough memory\n");
+ return -1;
}
- ret = dbus_connection_send(conn, msg, NULL);
- dbus_message_unref(msg);
- if (ret != TRUE) {
- _E("dbus_connection_send error(%s:%s-%s)", path, iface, name);
- return -ECOMM;
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "<node>""\n""\t""<interface name='%s'>""\n", interfaces->name);
+
+ /* members */
+ for (GList *item = g_list_first(interfaces->list_methods); item != NULL; item = g_list_next(item)) {
+ pmethod = (const dbus_method_s *)item->data;
+ if (!pmethod)
+ continue;
+
+ /* check free space of buf */
+ buf_check_space_realloc(buf, nwrite, buf_len);
+
+ if (pmethod->signature_in == NULL && pmethod->signature_out == NULL) {
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""<method name='%s'/>""\n", pmethod->member);
+ continue;
+ }
+
+ /* <method name='###'> */
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""<method name='%s'>""\n", pmethod->member);
+
+ /* in args */
+ len_args = pmethod->signature_in ? strlen(pmethod->signature_in) : 0;
+ for (int m = 0; m < len_args; ++m) {
+ // todo
+ // array a(), as, ay ?
+ if (pmethod->signature_in[m] == 'a') {
+ int ei; //end index
+ ei = _check_brace(pmethod->signature_in + m + 1);
+ if (ei > 0) {
+ char tmp[128] = {0,};
+ strncpy(tmp, pmethod->signature_in + m, ei + 1);
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%s' name='arg%d' direction='in'/>""\n", tmp, m);
+ m += ei;
+ continue;
+ } else {
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='in'/>""\n", pmethod->signature_in[m], pmethod->signature_in[m+1], m);
+ m += 1;
+ continue;
+ }
+ }
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c' name='arg%d' direction='in'/>""\n", pmethod->signature_in[m], m);
+ }
+
+ /* out args */
+ len_args = pmethod->signature_out ? strlen(pmethod->signature_out) : 0;
+ for (int m = 0; m < len_args; ++m) {
+ // array
+ // todo: container type
+ if (pmethod->signature_out[m] == 'a') {
+ int ei; //end index
+ ei = _check_brace(pmethod->signature_out + m + 1);
+ if (ei > 0) {
+ char tmp[128] = {0,};
+ strncpy(tmp, pmethod->signature_out + m, ei + 1);
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%s' name='arg%d' direction='out'/>""\n", tmp, m);
+ m += ei;
+ continue;
+ } else {
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='out'/>""\n", pmethod->signature_out[m], pmethod->signature_out[m+1], m);
+ m += 1;
+ continue;
+ }
+ }
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c' name='arg%d' direction='out'/>""\n", pmethod->signature_out[m], m);
+ }
+
+ /* </method> */
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""</method>""\n");
}
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t""</interface>""\n""</node>""");
+
+ *xml = buf;
+
+ /* todo: delete log */
+#if 0
+ if (nwrite <= 512)
+ _E("%s", buf);
+ else
+ _E("%s", buf + nwrite - 512);
+#endif
return 0;
}
-static void release_signal_info(struct signal_info *info)
+static gint _compare_dbus_object(gconstpointer a, gconstpointer b)
{
- if (info) {
- if (info->free_func)
- info->free_func(info->data);
- free(info);
- }
+ dbus_object_handle_s * pa = (dbus_object_handle_s *)a;
+ if (!pa->path || !((const char*)b))
+ return -1;
+ return strcmp(pa->path, (const char*)b);
}
-static struct signal_info *find_signal_info(const char *path,
- const char *iface, const char *name, dbus_signal_received cb)
+static gint _compare_dbus_interface(gconstpointer a, gconstpointer b)
{
- GList *l;
- size_t path_len, iface_len, name_len;
- struct signal_info *info;
-
- path_len = strlen(path) + 1;
- iface_len = strlen(iface) + 1;
- name_len = strlen(name) + 1;
+ dbus_interface_s * pa = (dbus_interface_s *)a;
+ if (!pa->name || !((const char*)b))
+ return -1;
+ return strcmp(pa->name, (const char*)b);
+}
- for (l = signal_handler_list ; l && (info = l->data) ; l = g_list_next(l), info = NULL) {
- if (strncmp(info->path, path, path_len))
- continue;
- if (strncmp(info->iface, iface, iface_len))
- continue;
- if (strncmp(info->name, name, name_len))
- continue;
- if (cb && info->cb != cb)
- continue;
- return info;
- }
+static gint _compare_dbus_interface_by_id(gconstpointer a, gconstpointer b)
+{
+ dbus_interface_s * pa = (dbus_interface_s *)a;
+ if (!pa->reg_id || !((guint*)b))
+ return -1;
+ return !(pa->reg_id == *((guint*)b));
+}
- return NULL;
+static gint _compare_dbus_method(gconstpointer a, gconstpointer b)
+{
+ dbus_method_s *pa = (dbus_method_s*)a;
+ if (!pa->member || !((const char*)b))
+ return -1;
+ return strcmp(pa->member, (const char*)b);
}
-static void call_signal_callbacks(const char *path,
- const char *iface, const char *name, DBusMessage *msg)
+dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path)
{
- GList *l;
- size_t path_len, iface_len, name_len;
- struct signal_info *info;
+ if (!list_obj || !obj_path)
+ return NULL;
- path_len = strlen(path) + 1;
- iface_len = strlen(iface) + 1;
- name_len = strlen(name) + 1;
+ GList *item = g_list_find_custom(list_obj, obj_path, _compare_dbus_object);
+ if (!item)
+ return NULL;
- for (l = signal_handler_list ; l && (info = l->data) ; l = g_list_next(l), info = NULL) {
- _I("path(%s), info(%s), name(%s)", info->path, info->iface, info->name);
- if (strncmp(info->path, path, path_len))
- continue;
- if (strncmp(info->iface, iface, iface_len))
- continue;
- if (strncmp(info->name, name, name_len))
- continue;
- if (info->cb)
- info->cb(NULL, path, iface, name, msg, info->data);
- }
+ return (dbus_object_handle_s *)item->data;
}
-static int make_match(const char *path, const char *iface,
- const char *name, char *buf, size_t len)
+dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name)
{
- if (!path || !iface || ! name || !buf)
- return -EINVAL;
+ if (!list_iface || !iface_name)
+ return NULL;
- snprintf(buf, len,
- "type='signal',path=%s,interface=%s,member=%s",
- path, iface, name);
+ GList *item = g_list_find_custom(list_iface, iface_name, _compare_dbus_interface);
+ if (!item)
+ return NULL;
- return 0;
+ return (dbus_interface_s *)item->data;
}
-void unregister_dbus_signal_all(void)
+dbus_interface_s * _dbus_handle_lookup_interface_by_id(GList *list_iface, guint id)
{
- GList *l, *l_next;
- struct signal_info *info;
- char match[256];
- int ret;
- DBusConnection *conn;
-
- for (l = signal_handler_list, l_next = g_list_next(l) ;
- l && (info = l->data) ;
- l = l_next, l_next = g_list_next(l), info = NULL) {
- signal_handler_list = g_list_remove(signal_handler_list, info);
+ if (!list_iface || !id)
+ return NULL;
- ret = make_match(info->path, info->iface, info->name,
- match, sizeof(match));
- if (ret == 0) {
- conn = get_dbus_connection();
- if (conn)
- dbus_bus_remove_match(conn, match, NULL);
- }
+ GList *item = g_list_find_custom(list_iface, &id, _compare_dbus_interface_by_id);
+ if (!item)
+ return NULL;
- release_signal_info(info);
- }
+ return (dbus_interface_s *)item->data;
}
-static DBusHandlerResult signal_filter(DBusConnection *conn, DBusMessage *msg, void *data)
+dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name)
{
- const char *path, *iface, *name;
-
- if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- path = dbus_message_get_path(msg);
- iface = dbus_message_get_interface(msg);
- name = dbus_message_get_member(msg);
+ if (!list_methods || !method_name)
+ return NULL;
- call_signal_callbacks(path, iface, name, msg);
+ GList *item = g_list_find_custom(list_methods, method_name, _compare_dbus_method);
+ if (!item)
+ return NULL;
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ return (dbus_method_s *)item->data;
}
-int register_dbus_signal(const char *path,
- const char *interface, const char *name,
- dbus_signal_received cb, void *data,
- destroy_notified free_func)
+static void _free_func_object(gpointer data)
{
- struct signal_info *info;
- DBusConnection *conn;
- static int add_filter = 0;
- char match[256];
- int ret;
+ dbus_interface_s *ih = (dbus_interface_s *)data;
+ dbus_object_handle_s *oh = NULL;
- conn = get_dbus_connection();
- if (!conn) {
- _E("Failed to get dbus connection");
- return -ECOMM;
+ if (!ih) {
+ _E("interface handle is null");
+ assert(0); // something wrong
+ return ;
}
- info = find_signal_info(path, interface, name, cb);
- if (info)
- return -EEXIST;
+ _E("unregister interface %s", ih->name);
+
+ /* just free list, not data(static dbus_method_s) */
+ g_list_free(ih->list_methods);
- info = calloc(1, sizeof(struct signal_info));
- if (!info) {
- _E("calloc failed");
- return -ENOMEM;
+ oh = ih->oh;
+ if (!oh) {
+ _E("object handle is null");
+ assert(0); // something wrong
+ return ;
}
- info->path = path;
- info->iface = interface;
- info->name = name;
- info->cb = cb;
- info->free_func = free_func;
- info->data = data;
+ /* remove ih from list_ifaces */
+ oh->list_ifaces = g_list_remove(oh->list_ifaces, ih);
- if (add_filter == 0) {
- add_filter = 1;
- dbus_connection_add_filter(conn, signal_filter, NULL, NULL);
- }
+ /* interface_s is copy of interface_u */
+ free(ih);
- ret = make_match(path, interface, name, match, sizeof(match));
- if (ret < 0) {
- _E("Failed to make match (%d)", ret);
- free(info);
- return ret;
+ /* remove oh from list_object */
+ if (!oh->list_ifaces) {
+ oh->dh->list_object = g_list_remove(oh->dh->list_object, oh);
+ free(oh);
}
- dbus_bus_add_match(conn, match, NULL);
+}
- signal_handler_list = g_list_append(signal_handler_list, info);
+static int _dbus_handle_attach_object(dbus_handle_s *dh, const char *obj_path, dbus_interface_s *iface)
+{
+ dbus_object_handle_s *oh = NULL;
+ if (!dh || !obj_path || !iface) {
+ _E("failed to attache object. wrong parameter");
+ return -1;
+ }
+
+ /* find object handle */
+ if (dh->list_object)
+ oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
+
+ if (!oh) {
+ oh = (dbus_object_handle_s*)calloc(1, sizeof(dbus_object_handle_s));
+ if (!oh) {
+ _E("failed to calloc");
+ return -1;
+ }
+ oh->dh = dh;
+ oh->path = obj_path;
+
+ /* attach object */
+ dh->list_object = g_list_prepend(dh->list_object, oh);
+ }
+
+ iface->oh = oh;
+ /* attach interface */
+ oh->list_ifaces = g_list_prepend(oh->list_ifaces, iface);
+
+ return 0;
+}
+
+/* libgio verify path and interface */
+static void _method_call_handler(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ dbus_interface_s *iface_s = (dbus_interface_s *)user_data;
+ const dbus_method_s *methods;
+ GVariant *result = NULL;
+
+ /* todo: ghash ? */
+ methods = _dbus_handle_lookup_method(iface_s->list_methods, name);
+ if (methods) {
+ result = methods->func(conn, sender, path, iface, name, param, invocation, get_dh_from_oh(iface_s->oh));
+
+ /* async, maybe they will reply...maybe.. */
+ if (!result) {
+ _E("finish method handle : NULL");
+ return ;
+ }
+ } else {
+ _E("no methods");
+ }
+
+ g_dbus_method_invocation_return_value(invocation, result);
+ //if (g_variant_is_of_type(result, G_VARIANT_TYPE_TUPLE)) {
+ // //_E("TUPLE %s", g_variant_get_type_string(result));
+ // g_dbus_method_invocation_return_value(invocation, result);
+ //}
+ //else if (g_variant_is_container(result)) {
+ // /* todo: we don't have any plan to using variant type for reply */
+ // _E("CONTAINER %s", g_variant_get_type_string(result));
+ // g_dbus_method_invocation_return_value(invocation, result);
+ // //g_dbus_method_invocation_return_value(invocation, g_variant_new("(v)", result));
+ //} else {
+ // _E("Type is not Container : %s", g_variant_get_type_string(result));
+ //}
+}
+
+static GDBusInterfaceVTable path_vtable = {_method_call_handler};
+
+
+/*
+before register object, attach object into dbus handle
+_dbus_handle_attach_object()
+*/
+static int _dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, dbus_interface_s *iface)
+{
+ dcl_dbus_handle();
+ int ret = 0;
+ char *buf = NULL;
+ GError *err = NULL;
+ GDBusNodeInfo * nodeinfo = NULL;
+ GDBusInterfaceInfo *ifaceinfo = NULL;
+
+ if (!obj_path || !iface) {
+ _E("wrong parameter\n");
+ return -1;
+ }
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
+ if (!dh->conn) {
+ _E("connection is null\n");
+ return -1;
+ }
+
+ ret = _get_xml_from_interfaces(&buf, iface);
+ if (ret < 0) {
+ _E("failed to make xml format");
+ goto err;
+ }
+
+ /* todo: delete this */
+#if 0
+ if (strlen(buf) <= 512) {
+ _E("%s", buf);
+ } else {
+ _E("%s", buf + strlen(buf) - 512);
+ }
+#endif
+
+ nodeinfo = g_dbus_node_info_new_for_xml(buf, &err);
+ if (!nodeinfo || err) {
+ _E("failed to make introspection data:err:%s:xml:%s\n", err->message, buf);
+ ret = -1;
+ goto err;
+ }
+
+ ifaceinfo = g_dbus_node_info_lookup_interface(nodeinfo, iface->name);
+ if (!ifaceinfo) {
+ _E("failed to g_dbus_node_info_lookup_interface");
+ ret = -1;
+ goto err;
+ }
+
+ /*
+ path own single interface
+ if interface is already registered, then failed.
+ g_dbus_connection_register_object ref(ifaceinfo) now, unref if object is unregistered
+ */
+ ret = g_dbus_connection_register_object(dh->conn, obj_path, ifaceinfo/*ref 2*/, &path_vtable, (void*)iface,
+ _free_func_object,
+ &err);
+ if (err) {
+ _E("failed to register object:err:%s:\n", err->message);
+ ret = -1;
+ goto err;
+ }
+
+ iface->reg_id = ret;
+ iface->modified = FALSE;
+
+err:
+ /* todo: detach object */
+ //_dbus_handle_detach_object(dh, obj_path, iface);
+ /* attach interface before register object */
+ /*ret = _dbus_handle_detach_object(dh, obj_path, iface);
+ if (ret < 0) {
+ _E("failed to attach object");
+ goto err;
+ }*/
+
+ if (nodeinfo)
+ g_dbus_node_info_unref(nodeinfo);
+ if (buf)
+ free(buf);
+ if (err)
+ g_error_free(err);
+
+ return ret;
+}
+
+/*
+register same interface at once
+
+if interface is constructed by multiple methods,
+also it is not possible to make methods struct at once,
+
+use dbus_handle_add_dbus_object(), dbus_handle_register_dbus_object_all().
+
+return reg_id
+*/
+int dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u)
+{
+ dcl_dbus_handle();
+ int ret = 0;
+ dbus_interface_s *iface = NULL;
+
+ if (!obj_path || !iface_u) {
+ _E("wrong parameter\n");
+ return -1;
+ }
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
+ if (!dh->conn) {
+ _E("connection is null\n");
+ return -1;
+ }
+
+ /* check registered interface */
+ if (dh->list_object) {
+ dbus_object_handle_s *oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
+ if (oh) {
+ dbus_interface_s *ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name);
+ if (ih) {
+ _E("path %s, interface %s already registered", obj_path, iface_u->name);
+ return -1;
+ }
+ }
+ }
+
+ iface = _iface_u_to_s(iface_u);
+ if (!iface) {
+ _E("failed to _iface_u_to_s");
+ return -1;
+ }
+
+ /* attach interface before register object */
+ ret = _dbus_handle_attach_object(dh, obj_path, iface);
+ if (ret < 0) {
+ _E("failed to attach object");
+ goto err;
+ }
+
+ ret = _dbus_handle_register_dbus_object(dh, obj_path, iface);
+ if (ret <= 0) {
+ _E("failed to register dbus object%d", ret);
+ goto err;
+ }
+err:
+ return ret;
+}
+
+int dbus_handle_unregister_dbus_object(dbus_handle_h handle, const char *obj_path)
+{
+ dcl_dbus_handle();
+ dbus_object_handle_s *oh = NULL;
+ int ret = 0;
+
+ if (!obj_path) {
+ return -1;
+ }
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
+ if (!dh->list_object) {
+ _E("list_object is empty");
+ return 0;
+ }
+
+ oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
+ if (!oh) {
+ _E("no object with name %s", obj_path);
+ return -1;
+ }
+
+ /* unregister every interface of object*/
+ for (GList *item = g_list_first(oh->list_ifaces); item != NULL; item = g_list_next(item)) {
+ dbus_interface_s *ih = item->data;
+ if (!ih) {
+ _E("this is error");
+ assert(0);
+ }
+
+ /* remove ih from list_ifaces */
+ if (!ih->reg_id) {
+ item = g_list_previous(item);
+
+ /* remove and free link */
+ oh->list_ifaces = g_list_remove(oh->list_ifaces, ih);
+
+ /* free list_methods */
+ g_list_free(ih->list_methods);
+
+ /* free data */
+ free(ih);
+ continue;
+ }
+
+ /* unregister object by id */
+ ret = g_dbus_connection_unregister_object(dh->conn, ih->reg_id);
+ if (!ret)
+ _E("failed to unregister object %s, interface %s, regid %d", oh->path, ih->name, ih->reg_id);
+ }
+
+ return 0;
+}
+
+/*
+add object temporarily.
+dbus_handle_register_dbus_object_all will register every objects on connection.
+
+return registered method count
+*/
+int dbus_handle_add_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u)
+{
+ dcl_dbus_handle();
+ dbus_object_handle_s *oh = NULL;
+ dbus_interface_s *ih = NULL;
+ int cnt;
+
+ if (!obj_path || !iface_u) {
+ _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u);
+ return -1;
+ }
+ if (iface_u && (!iface_u->name || !iface_u->methods)) {
+ _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u);
+ return -1;
+ }
+
+ cnt = iface_u->nr_methods;
+
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
+
+ if (!dh->conn) {
+ _E("failed to register method. connection is null\n");
+ return -1;
+ }
+
+ /* if there are no object list, just add */
+ if (!dh->list_object) {
+ if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
+ _E("failed to attach object");
+ return -1;
+ }
+ goto out;
+ }
+
+ oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
+ /* if there are no matched object, just add */
+ if (!oh) {
+ if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
+ _E("failed to attach object");
+ return -1;
+ }
+ goto out;
+ }
+
+ /* this is an error, interface must have one or more item ? */
+ if (!oh->list_ifaces) {
+ _E("error. list_ifaces is null\n");
+ assert(0);
+ goto out;
+ }
+
+ ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name);
+ /* if there are no matched interface, just add */
+ if (!ih) {
+ if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
+ _E("failed to attach object");
+ return -1;
+ }
+ goto out;
+ }
+
+ /* todo:
+ 1. unregister interface
+ 2. update interface and methods
+ 3. register interface
+ */
+ if (ih->reg_id) {
+ _E("interface already registered, ignore new interface");
+ return -1;
+ }
+
+ /* attach new methods */
+ cnt = 0;
+ for (int i = 0; i < iface_u->nr_methods; ++i) {
+ GList *item = g_list_find_custom(g_list_first(ih->list_methods), iface_u->methods[i].member, _compare_dbus_method);
+ if (!item) {
+ //_D("attached %s", iface_u->methods[i].member);
+ ih->list_methods = g_list_prepend(ih->list_methods, (void*)(iface_u->methods + i));
+ ++cnt;
+ }
+ }
+
+ if (cnt)
+ ih->modified = TRUE;
+
+out:
+ /*todo: delete debugging log */
+ //if (dh && dh->list_object)
+ // _D("obj list len %d", g_list_length(dh->list_object));
+ //if (oh && oh->list_ifaces)
+ // _D("iface list len %d", g_list_length(oh->list_ifaces));
+ //if (ih && ih->list_methods)
+ // _D("method list len %d", g_list_length(ih->list_methods));
+
+ return cnt;
+}
+
+int dbus_handle_register_dbus_object_all(dbus_handle_h handle)
+{
+ dcl_dbus_handle();
+ dbus_object_handle_s *oh = NULL;
+ dbus_interface_s *ih = NULL;
+ int ret = 0;
+
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
+ if (!dh->conn) {
+ _E("connection is null\n");
+ return -1;
+ }
+
+ if (!dh->list_object) {
+ _E("obj list is empty");
+ return -1;
+ }
+
+ /*if (dh && dh->list_object)
+ _D("obj list len %d", g_list_length(dh->list_object));*/
+
+ for (GList *item = g_list_first(dh->list_object); item != NULL; item = g_list_next(item)) {
+ oh = (dbus_object_handle_s *)item->data;
+
+ if (!oh) {
+ _E("something wrong");
+ assert(0);
+ }
+ if (!oh->list_ifaces) {
+ _E("path %s: list_ifaces are null", oh->path);
+ goto err;
+ }
+
+ //_D("iface list len %d", g_list_length(oh->list_ifaces));
+
+ for (GList *li = g_list_first(oh->list_ifaces); li != NULL; li = g_list_next(li)) {
+ ih = (dbus_interface_s *)li->data;
+
+ /* if there are no modification, goto next */
+ if (!ih->modified)
+ continue;
+
+ /* todo: if already registered interface, unregister first */
+
+ /*_E("interface %s:", ih->name);
+ if (ih && ih->list_methods)
+ _D("method list len %d", g_list_length(ih->list_methods));*/
+
+ ret = _dbus_handle_register_dbus_object(dh, oh->path, ih);
+ if (ret <= 0)
+ _E("failed to register dbus object%d", ret);
+
+ }
+ }
return 0;
+err:
+
+ // todo: delete all updates
+
+ return -1;
+}
+
+static void _free_func_signal(gpointer data)
+{
+ //_D("free signal subscribe");
+}
+
+guint subscribe_dbus_signal(dbus_handle_h handle, const char *path,
+ const char *iface, const char *name,
+ GDBusSignalCallback cb, void *data,
+ destroy_notified free_func)
+{
+ dcl_dbus_handle();
+
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return 0;
+ }
+ }
+
+ if (!dh->conn) {
+ _E("connection is null. check bus status");
+ return 0;
+ }
+ return g_dbus_connection_signal_subscribe(dh->conn, NULL, iface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, cb, data, _free_func_signal);
+}
+
+void unsubscribe_dbus_signal(dbus_handle_h handle, guint id)
+{
+ dcl_dbus_handle();
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return ;
+ }
+ }
+
+ if (!dh->conn) {
+ _E("connection is null. check bus status");
+ return ;
+ }
+
+ g_dbus_connection_signal_unsubscribe(dh->conn, id);
+}
+
+int _check_type_string_is_container(const char *signature)
+{
+ if (!signature)
+ return FALSE;
+
+ switch (signature[0]) {
+ case 'a':
+ case 'm':
+ case 'r':
+ case '(':
+ case '{':
+ case 'v':
+ return TRUE;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+GVariant *dbus_handle_make_simple_array(const char *sig, int *param)
+{
+ GVariantBuilder *builder = NULL;
+ GVariant *var = NULL;
+ char format[256];
+ int i = 0;
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE(sig));
+ if (!builder) {
+ _E("failed to g_variant_builder_new");
+ return NULL;
+ }
+
+ while (param[i])
+ g_variant_builder_add(builder, "i", param[i++]);
+
+ snprintf(format, sizeof(format) - 1, "(%s)", sig);
+ var = g_variant_new(format, builder);
+ g_variant_builder_unref(builder);
+ return var;
+}
+
+/* todo: looks like garbage... */
+static GVariant* _append_variant(const char *signature, const char *param[])
+{
+ char *ch;
+ int i;
+ int pi;
+ int int_type;
+ gboolean bool_type;
+ unsigned long long int64_type;
+ GVariant *ret;
+ int len;
+ char container[255];// The maximum length of a signature is 255.
+ const char *sig = signature;
+ GVariantBuilder *builder = NULL;
+
+ if (!signature || !param)
+ return 0;
+
+ /* workaround for user fault "(i) != i" but we treat this as same signature */
+ /* G_VARIANT_TYPE("si") return NULL */
+ /* todo: actually user have to use correct signature */
+ if (!_check_type_string_is_container(signature)) {
+ snprintf(container, sizeof(container) - 1, "(%s)", signature);
+ sig = container;
+ }
+ if (!g_variant_type_is_container(G_VARIANT_TYPE(sig))) {
+ _E("signature (%s) is not container type", signature);
+ }
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE(sig));
+ len = strlen(sig);
+ pi = 0;
+ for (ch = (char *)sig, i = 0; i < len; ++i, ++ch) {
+ switch (*ch) {
+ case '(':
+ case ')':
+ continue;
+ case 'b':
+ bool_type = (atoi(param[pi++]) == 0 ? FALSE : TRUE);
+ g_variant_builder_add(builder, "b", bool_type);
+ break;
+ case 'i':
+ int_type = atoi(param[pi++]);
+ g_variant_builder_add(builder, "i", int_type);
+ break;
+ case 'u':
+ int_type = strtoul(param[pi++], NULL, 10);
+ g_variant_builder_add(builder, "u", int_type);
+ break;
+ case 't':
+ int64_type = atoll(param[pi++]);
+ g_variant_builder_add(builder, "t", int64_type);
+ break;
+ case 's':
+ g_variant_builder_add(builder, "s", param[pi++]);
+ break;
+ case 'a':
+ ++ch;
+ switch (*ch) {
+ case 'y':
+ g_variant_builder_add(builder, "^ay", param[pi++]);
+ ++i;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ ret = g_variant_builder_end(builder);
+ g_variant_builder_clear(builder);
+ g_variant_builder_unref(builder);
+
+ return ret;
+}
+
+int dbus_handle_broadcast_dbus_signal(const char *path,
+ const char *iface, const char *name,
+ const char *signature, const char *param[])
+{
+ dbus_handle_s *dh = NULL;
+ GError *err = NULL;
+ gboolean ret = 0;
+ GVariant *var = NULL;
+
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+
+ if (signature && param)
+ var = _append_variant(signature, param);
+ ret = g_dbus_connection_emit_signal(dh->conn, NULL, path, iface, name, var, &err);
+ if (err) {
+ _E("%d %s\n", ret, err ? err->message : NULL);
+ g_error_free(err);
+ }
+
+ return ret;
+}
+
+int dbus_handle_broadcast_dbus_signal_var(const char *path,
+ const char *iface, const char *name,
+ GVariant *param)
+{
+ dbus_handle_s *dh = NULL;
+ GError *err = NULL;
+ gboolean ret = 0;
+
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+
+ ret = g_dbus_connection_emit_signal(dh->conn, NULL, path, iface, name, param, &err);
+ if (err) {
+ _E("%d %s\n", ret, err ? err->message : NULL);
+ g_error_free(err);
+ }
+
+ return ret;
+}
+
+GVariant *dbus_method_sync_with_reply(const char *dest, const char *path,
+ const char *iface, const char *method,
+ const char *signature, const char *param[])
+{
+ GError *err = NULL;
+ GVariant * var = NULL;
+ GVariant * ret = NULL;
+ dbus_handle_s *dh = NULL;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return NULL;
+ }
+
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return NULL;
+ }
+
+ if (signature && param)
+ var = _append_variant(signature, param);
+
+ ret = g_dbus_connection_call_sync(dh->conn,
+ dest, path, iface, method,
+ var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err);
+ if (!ret || err) {
+ if (err) {
+ _E("failed to g_dbus_connection_call_sync:%s", err->message);
+ g_error_free(err);
+ } else {
+ _E("failed to g_dbus_connection_call_sync");
+ g_variant_unref(var);
+ }
+ return NULL;
+ }
+
+ return ret;
+}
+
+GVariant *dbus_method_sync_with_reply_var(const char *dest, const char *path,
+ const char *iface, const char *method, GVariant *var)
+{
+ GError *err = NULL;
+ GVariant * ret = NULL;
+ dbus_handle_s *dh = NULL;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ if (var)
+ g_variant_unref(var);
+ return NULL;
+ }
+
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ if (var)
+ g_variant_unref(var);
+ return NULL;
+ }
+
+ ret = g_dbus_connection_call_sync(dh->conn,
+ dest, path, iface, method,
+ var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err);
+ if (!ret || err) {
+ if (err) {
+ _E("failed to g_dbus_connection_call_sync:%s", err->message);
+ g_error_free(err);
+ } else {
+ _E("failed to g_dbus_connection_call_sync");
+ }
+ return NULL;
+ }
+
+ return ret;
}
-int unregister_dbus_signal(const char *path,
- const char *interface, const char *name,
- dbus_signal_received cb)
+gint* dbus_handle_get_unix_fd_list(GDBusMethodInvocation *invocation, int *size)
{
- struct signal_info *info;
- DBusConnection *conn;
- char match[256];
- int ret;
+ GUnixFDList *fd_list = NULL;
+ int length = 0;
- conn = get_dbus_connection();
- if (!conn) {
- _E("Failed to get dbus connection");
- return -ECOMM;
+ fd_list = g_dbus_message_get_unix_fd_list(g_dbus_method_invocation_get_message(invocation));
+
+ if (!fd_list) {
+ _E("failed to g_unix_fd_list_get_length: fd_list is null");
+ return NULL;
}
- info = find_signal_info(path, interface, name, cb);
- if (!info)
- return -ENOENT;
+ length = g_unix_fd_list_get_length(fd_list);
+ if (length == 0) {
+ _E("failed to g_unix_fd_list_get_length: list size is 0");
+ return NULL;
+ }
+ if (size)
+ *size = length;
- signal_handler_list = g_list_remove(signal_handler_list, info);
- release_signal_info(info);
+ return g_unix_fd_list_steal_fds(fd_list, NULL);
+}
- ret = make_match(path, interface, name, match, sizeof(match));
- if (ret < 0) {
- _E("Failed to make match (%d)", ret);
- return ret;
+GVariant *dbus_method_with_unix_fd_list_sync_with_reply(const char *dest, const char *path,
+ const char *iface, const char *method,
+ const char *signature, const char *param[],
+ int *in_fdlist, int in_size,
+ int **out_fdlist, int *out_size)
+{
+ GError *err = NULL;
+ GVariant * var = NULL;
+ GVariant * ret = NULL;
+ dbus_handle_s *dh = NULL;
+ GDBusProxy *proxy = NULL;
+ GUnixFDList *g_infdlist = NULL;
+ GUnixFDList *g_outfdlist = NULL;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return NULL;
+ }
+ if (in_fdlist && in_size == 0) {
+ _E("wrong in_fdlist is not null but in_size is 0");
+ return NULL;
+ }
+
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return NULL;
}
- dbus_bus_remove_match(conn, match, NULL);
+ if (signature && param)
+ var = _append_variant(signature, param);
+
+ proxy = g_dbus_proxy_new_sync(dh->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, dest, path, iface, NULL, &err);
+ if (!proxy) {
+ if (err) {
+ _E("failed to proxy_new_sync(%s)\n", err->message);
+ g_error_free(err);
+ } else {
+ _E("failed to proxy_new_sync\n");
+ if (var)
+ g_variant_unref(var);
+ }
+ }
- return 0;
+ /* append fd */
+ if (in_fdlist) {
+ g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size);
+ if (!g_infdlist) {
+ _E("failed to g_unix_fd_list_new_from_array\n");
+ goto out;
+ }
+ //g_infdlist = g_unix_fd_list_new();
+ //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) {
+ }
+
+ ret = g_dbus_proxy_call_with_unix_fd_list_sync(proxy, method, var, G_DBUS_CALL_FLAGS_NONE, -1,
+ g_infdlist, &g_outfdlist, NULL, &err);
+ if (!ret || err) {
+ if (err) {
+ _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:%s", err->message);
+ g_error_free(err);
+ } else {
+ _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:");
+ if (var)
+ g_variant_unref(var);
+ if (g_infdlist)
+ g_object_unref(g_infdlist);
+ }
+ goto out;
+ }
+
+ /* fds to out array */
+ if (g_outfdlist) {
+ *out_size = g_unix_fd_list_get_length(g_outfdlist);
+ if (*out_size == 0)
+ goto out;
+
+ *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL);
+ }
+
+out:
+ if (g_outfdlist)
+ g_object_unref(g_outfdlist);
+ if (proxy)
+ g_object_unref(proxy);
+
+ return ret;
}
-int call_dbus_method_sync(const char *dest, const char *path,
- const char *interface, const char *method,
- const char *sig, char *param[], int timeout,
- DBusMessage **reply)
+GVariant *dbus_method_with_unix_fd_list_sync_with_reply_var(const char *dest, const char *path,
+ const char *iface, const char *method,
+ GVariant *param,
+ int *in_fdlist, int in_size,
+ int **out_fdlist, int *out_size)
{
- DBusConnection *conn;
- DBusMessage *msg;
- DBusMessageIter iter;
- DBusMessage *rep;
- DBusError err;
- int r;
+ GError *err = NULL;
+ GVariant * ret = NULL;
+ dbus_handle_s *dh = NULL;
+ GDBusProxy *proxy = NULL;
+ GUnixFDList *g_infdlist = NULL;
+ GUnixFDList *g_outfdlist = NULL;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return NULL;
+ }
+ if (in_fdlist && in_size == 0) {
+ _E("wrong in_fdlist is not null but in_size is 0");
+ return NULL;
+ }
- if (!dest || !path || !interface || !method || !reply)
- return -EINVAL;
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return NULL;
+ }
- conn = get_dbus_connection();
- if (!conn) {
- _E("Failed to get dbus connection");
- return -ECOMM;
+ proxy = g_dbus_proxy_new_sync(dh->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, dest, path, iface, NULL, &err);
+ if (!proxy) {
+ if (err) {
+ _E("failed to proxy_new_sync(%s)\n", err->message);
+ g_error_free(err);
+ } else {
+ _E("failed to proxy_new_sync\n");
+ if (param)
+ g_variant_unref(param);
+ }
+ goto out;
}
- msg = dbus_message_new_method_call(dest, path, interface, method);
- if (!msg) {
- _E("dbus_message_new_method_call(%s:%s-%s)",
- path, interface, method);
- return -EPERM;
+ /* append fd */
+ if (in_fdlist) {
+ g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size);
+ if (!g_infdlist) {
+ _E("failed to g_unix_fd_list_new_from_array\n");
+ goto out;
+ }
+ //g_infdlist = g_unix_fd_list_new();
+ //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) {
}
- dbus_message_iter_init_append(msg, &iter);
- r = append_variant(&iter, sig, param);
- if (r < 0) {
- _E("append_variant error(%d) %s %s:%s-%s",
- r, dest, path, interface, method);
- dbus_message_unref(msg);
- return r;
+ /* send message */
+ ret = g_dbus_proxy_call_with_unix_fd_list_sync(proxy, method, param, G_DBUS_CALL_FLAGS_NONE, -1,
+ g_infdlist, &g_outfdlist, NULL, &err);
+ if (!ret || err) {
+ if (err) {
+ _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:%s", err->message);
+ g_error_free(err);
+ } else {
+ _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:");
+ if (param)
+ g_variant_unref(param);
+ if (g_infdlist)
+ g_object_unref(g_infdlist);
+ }
+ goto out;
}
- dbus_error_init(&err);
+ /* copy fds to out array */
+ if (g_outfdlist) {
+ *out_size = g_unix_fd_list_get_length(g_outfdlist);
+ if (*out_size == 0)
+ goto out;
+ *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL);
+ }
+out:
+ if (g_outfdlist)
+ g_object_unref(g_outfdlist);
+ if (proxy)
+ g_object_unref(proxy);
+ return ret;
+}
- rep = dbus_connection_send_with_reply_and_block(conn, msg, timeout, &err);
- dbus_message_unref(msg);
- if (dbus_error_is_set(&err)) {
- _E("dbus_connection_send error(%s:%s) %s %s:%s-%s",
- err.name, err.message, dest, path, interface, method);
- dbus_error_free(&err);
- return -EPERM;
+int dbus_method_sync(const char *dest, const char *path,
+ const char *iface, const char *method,
+ const char *signature, const char *param[])
+{
+ int result;
+ gboolean result_bool;
+ GVariant *reply = NULL;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return -1;
}
- if (!rep) {
- _E("dbus_connection_send error(No reply) %s %s:%s-%s",
- dest, path, interface, method);
- return -EPERM;
+
+ reply = dbus_method_sync_with_reply(dest, path, iface, method, signature, param);
+ if (!reply)
+ return -ECOMM;
+
+ if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) {
+ g_variant_get(reply, "(i)", &result);
+ } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) {
+ g_variant_get(reply, "(b)", &result_bool);
+ result = (int)result_bool;
+ } else {
+ result = -ENOMSG;
}
- *reply = rep;
+ g_variant_unref(reply);
- return 0;
+ return result;
}
-int call_dbus_method_sync_pairs(const char *dest,
- const char *path, const char *interface, const char *method,
- int num, va_list args)
+int dbus_method_sync_var(const char *dest, const char *path,
+ const char *iface, const char *method, GVariant *param)
{
- DBusConnection *conn;
- DBusMessage *msg;
- DBusMessageIter iter;
- DBusMessageIter aiter, piter;
- DBusMessage *reply;
- DBusError err;
- char *key, *value;
- int ret, result;
- int i;
+ int result;
+ gboolean result_bool;
+ GVariant *reply = NULL;
- if (!dest || !path || !interface || !method)
- return -EINVAL;
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return -1;
+ }
- conn = get_dbus_connection();
- if (!conn) {
- _E("Failed to get dbus connection");
+ reply = dbus_method_sync_with_reply_var(dest, path, iface, method, param);
+ if (!reply)
return -ECOMM;
+
+ if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) {
+ g_variant_get(reply, "(i)", &result);
+ } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) {
+ g_variant_get(reply, "(b)", &result_bool);
+ result = (int)result_bool;
+ } else {
+ result = -ENOMSG;
+ }
+
+ g_variant_unref(reply);
+
+ return result;
+}
+
+int dbus_method_sync_timeout(const char *dest, const char *path,
+ const char *iface, const char *method,
+ const char *signature, const char *param[], int timeout)
+{
+ dbus_handle_s *dh = NULL;
+ GError *err = NULL;
+ GVariant * var = NULL;
+ GVariant * reply = NULL;
+ int result = 0;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return -1;
}
- msg = dbus_message_new_method_call(dest, path, interface, method);
- if (!msg) {
- _E("dbus_message_new_method_call(%s:%s-%s)",
- path, interface, method);
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
return -EPERM;
}
- dbus_message_iter_init_append(msg, &iter);
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{ss}", &aiter);
+ if (signature && param)
+ var = _append_variant(signature, param);
- for (i = 0 ; i < num ; i = i + 2) {
- key = va_arg(args, char *);
- value = va_arg(args, char *);
- _I("key(%s), value(%s)", key, value);
- dbus_message_iter_open_container(&aiter, DBUS_TYPE_DICT_ENTRY, NULL, &piter);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING, &key);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING, &value);
- dbus_message_iter_close_container(&aiter, &piter);
+ reply = g_dbus_connection_call_sync(dh->conn,
+ dest, path, iface, method,
+ var, NULL, G_DBUS_CALL_FLAGS_NONE, timeout, NULL, &err);
+ if (!reply || err) {
+ _E("failed to g_dbus_connection_call_sync:%s", err->message);
+ g_error_free(err);
+ return -1;
}
- dbus_message_iter_close_container(&iter, &aiter);
+ if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0)
+ g_variant_get(reply, "(i)", &result);
+ else
+ result = -ENOMSG;
+
+ g_variant_unref(reply);
- dbus_error_init(&err);
+ return result;
+}
- reply = dbus_connection_send_with_reply_and_block(conn, msg, DBUS_REPLY_TIMEOUT, &err);
- if (!reply) {
- _E("dbus_connection_send error(No reply) %s %s:%s-%s",
- dest, path, interface, method);
+int dbus_method_sync_pairs(const char *dest, const char *path,
+ const char *iface, const char *method,
+ int num, va_list args)
+{
+ GError *err = NULL;
+ GVariant * reply = NULL;
+ char *key, *value;
+ int ret = 0;
+ GVariant *var;
+ GVariantBuilder *builder;
+ dbus_handle_s *dh = NULL;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return -1;
}
- if (dbus_error_is_set(&err)) {
- _E("dbus_connection_send error(%s:%s) %s %s:%s-%s",
- err.name, err.message, dest, path, interface, method);
- dbus_error_free(&err);
- reply = NULL;
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
}
- dbus_message_unref(msg);
- if (!reply)
- return -EPERM;
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}"));
- ret = dbus_message_get_args(reply, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
- dbus_message_unref(reply);
- if (!ret) {
- _E("no message : [%s:%s] %s %s:%s-%s",
- err.name, err.message, dest, path, interface, method);
- dbus_error_free(&err);
- return -ENOMSG;
+ for (int i = 0 ; i < num ; i = i + 2) {
+ key = va_arg(args, char *);
+ value = va_arg(args, char *);
+ _I("key(%s), value(%s)", key, value);
+ g_variant_builder_add(builder, "{ss}", key, value);
}
- return result;
+ var = g_variant_new("(a{ss})", builder);
+ g_variant_builder_unref(builder);
+
+ reply = g_dbus_connection_call_sync(dh->conn,
+ dest, path, iface, method,
+ var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err);
+ if (!reply || err) {
+ _E("failed to g_dbus_connection_call_sync");
+ return -1;
+ }
+
+ if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0)
+ g_variant_get(reply, "(i)", &ret);
+ else
+ ret = -ENOMSG;
+
+ g_variant_unref(reply);
+
+ return ret;
}
-int call_dbus_method_async_pairs(const char *dest,
- const char *path, const char *interface, const char *method,
- int num, va_list args)
+int dbus_method_async_pairs(const char *dest, const char *path,
+ const char *iface, const char *method,
+ int num, va_list args)
{
- DBusConnection *conn;
- DBusMessage *msg;
- DBusMessageIter iter;
- DBusMessageIter aiter, piter;
char *key, *value;
- int ret, i;
+ GVariant *var;
+ GVariantBuilder *builder;
+ dbus_handle_s *dh = NULL;
- if (!dest || !path || !interface || !method)
- return -EINVAL;
-
- conn = get_dbus_connection();
- if (!conn) {
- _E("Failed to get dbus connection");
- return -ECOMM;
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return -1;
}
- msg = dbus_message_new_method_call(dest, path, interface, method);
- if (!msg) {
- _E("dbus_message_new_method_call(%s:%s-%s)",
- path, interface, method);
- return -EPERM;
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
}
- dbus_message_iter_init_append(msg, &iter);
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{ss}", &aiter);
+ // dict
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}"));
- for (i = 0 ; i < num ; i = i + 2) {
+ for (int i = 0 ; i < num ; i = i + 2) {
key = va_arg(args, char *);
value = va_arg(args, char *);
_I("key(%s), value(%s)", key, value);
- dbus_message_iter_open_container(&aiter, DBUS_TYPE_DICT_ENTRY, NULL, &piter);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING, &key);
- dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING, &value);
- dbus_message_iter_close_container(&aiter, &piter);
+ g_variant_builder_add(builder, "{ss}", key, value);
}
- dbus_message_iter_close_container(&iter, &aiter);
+ var = g_variant_new("(a{ss})", builder);
+ g_variant_builder_unref(builder);
- ret = dbus_connection_send(conn, msg, NULL);
- dbus_message_unref(msg);
- if (ret != TRUE) {
- _E("dbus_connection_send error(%s %s:%s-%s)",
- dest, path, interface, method);
- return -ECOMM;
+ g_dbus_connection_call(dh->conn, dest, path, iface, method,
+ var, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ NULL,
+ NULL);
+
+ return 0;
+}
+
+int dbus_method_async(const char *dest, const char *path,
+ const char *iface, const char *method,
+ const char *signature, const char *param[])
+{
+ GVariant * var = NULL;
+ dbus_handle_s *dh = NULL;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return -1;
+ }
+
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
}
+ if (signature && param)
+ var = _append_variant(signature, param);
+
+ g_dbus_connection_call(dh->conn, dest, path, iface, method,
+ var, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ NULL,
+ NULL);
+
return 0;
}
-static void cb_pending(DBusPendingCall *pending, void *user_data)
+int dbus_method_async_var(const char *dest, const char *path,
+ const char *iface, const char *method, GVariant *param)
{
- DBusMessage *msg;
- struct pending_call_data *data = user_data;
- int ret;
+ dbus_handle_s *dh = NULL;
- ret = dbus_pending_call_get_completed(pending);
- if (!ret) {
- _I("dbus_pending_call_get_completed() fail");
- dbus_pending_call_unref(pending);
- return;
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return -1;
}
- msg = dbus_pending_call_steal_reply(pending);
- if (!msg) {
- _E("message is NULL");
- if (data->func)
- data->func(data->data, NULL, -ECOMM);
- return;
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
}
- if (data->func)
- data->func(data->data, msg, 0);
+ g_dbus_connection_call(dh->conn, dest, path, iface, method,
+ param, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ NULL,
+ NULL);
- dbus_message_unref(msg);
- dbus_pending_call_unref(pending);
+ return 0;
}
-int call_dbus_method_async(const char *dest, const char *path,
- const char *interface, const char *method,
- const char *sig, char *param[],
- dbus_pending_cb cb, int timeout, void *data)
+/* callback should free gvariant */
+static void _cb_pending(GDBusConnection *conn,
+ GAsyncResult *res,
+ gpointer user_data)
{
- DBusConnection *conn;
- DBusMessage *msg;
- DBusMessageIter iter;
- DBusPendingCall *pending = NULL;
- struct pending_call_data *pdata;
- int ret;
+ GVariant *reply = NULL;
+ GError *err = NULL;
+ pending_call_data *data = (pending_call_data *)user_data;
+
+ reply = g_dbus_connection_call_finish(conn, res, &err);
+ if (!reply || err) {
+ if (err) {
+ _E("no message : [%s]", err->message);
+ g_error_free(err);
+ } else {
+ _E("no message");
+ }
- conn = get_dbus_connection();
- if (!conn) {
- _E("Failed to get dbus connection");
- return -ECOMM;
+ if (data && data->func)
+ data->func(NULL, data->data, err);
+ goto out;
}
- msg = dbus_message_new_method_call(dest, path, interface, method);
- if (!msg) {
- _E("dbus_message_new_method_call(%s:%s-%s)",
- path, interface, method);
- return -EBADMSG;
+ if (data && data->func)
+ data->func(reply, data->data, err);
+out:
+ if (data)
+ free(data);
+}
+
+int dbus_method_async_with_reply(const char *dest,
+ const char *path,
+ const char *iface,
+ const char *method,
+ const char *signature,
+ const char *param[],
+ dbus_pending_cb cb,
+ int timeout_msec,
+ void *data)
+{
+ dbus_handle_s *dh = NULL;
+ pending_call_data *pdata = NULL;
+ GVariant * var = NULL;
+ int ret = 0;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return -1;
}
- dbus_message_iter_init_append(msg, &iter);
- ret = append_variant(&iter, sig, param);
- if (ret < 0) {
- _E("append_variant error(%d)%s %s:%s-%s",
- ret, dest, path, interface, method);
- dbus_message_unref(msg);
- return ret;
+ if (timeout_msec < -1) {
+ _E("wrong timeout %d", timeout_msec);
+ return -1;
}
- ret = dbus_connection_send_with_reply(conn, msg, &pending, timeout);
- if (!ret) {
- dbus_message_unref(msg);
- _E("dbus_connection_send error(%s %s:%s-%s)",
- dest, path, interface, method);
- return -ECOMM;
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -EPERM;
+ }
+
+ if (signature && param)
+ var = _append_variant(signature, param);
+
+ if (cb) {
+ pdata = (pending_call_data*)malloc(sizeof(pending_call_data));
+ if (!pdata) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ pdata->func = cb;
+ pdata->data = data;
+ }
+ g_dbus_connection_call(dh->conn, dest, path, iface, method,
+ var, NULL, G_DBUS_CALL_FLAGS_NONE, timeout_msec, NULL,
+ (GAsyncReadyCallback)_cb_pending,
+ pdata);
+
+ return ret;
+err:
+ if (var)
+ g_variant_unref(var);
+ return ret;
+}
+
+int dbus_method_async_with_reply_var(const char *dest,
+ const char *path,
+ const char *iface,
+ const char *method,
+ GVariant *param,
+ dbus_pending_cb cb,
+ int timeout_msec,
+ void *data)
+{
+ dbus_handle_s *dh = NULL;
+ pending_call_data *pdata = NULL;
+ int ret = 0;
+
+ if (!dest || !path || !iface || !method) {
+ _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
+ return -1;
+ }
+
+ if (timeout_msec < -1) {
+ _E("wrong timeout %d", timeout_msec);
+ return -1;
}
- dbus_message_unref(msg);
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -EPERM;
+ }
- if (cb && pending) {
- pdata = calloc(1, sizeof(struct pending_call_data));
+ if (cb) {
+ pdata = (pending_call_data*)malloc(sizeof(pending_call_data));
if (!pdata) {
- _E("malloc error : %s-%s", interface, method);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err;
}
pdata->func = cb;
pdata->data = data;
+ }
+ g_dbus_connection_call(dh->conn, dest, path, iface, method,
+ param, NULL, G_DBUS_CALL_FLAGS_NONE, timeout_msec, NULL,
+ (GAsyncReadyCallback)_cb_pending,
+ pdata);
+
+ return ret;
+err:
+ if (param)
+ g_variant_unref(param);
+ return ret;
+}
+
+int dbus_connection_get_sender_pid(GDBusConnection *conn, const char * sender)
+{
+ GError *err = NULL;
+ GVariant *vret = NULL;
+ pid_t pid = 0;
+
+ if (!conn) {
+ _E("connection is null");
+ return -1;
+ }
+ if (!sender) {
+ _E("sender is null");
+ return -1;
+ }
+
+ vret = g_dbus_connection_call_sync(conn,
+ "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetConnectionUnixProcessID",
+ g_variant_new("(s)", sender),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_REPLY_TIMEOUT,
+ NULL,
+ &err);
+ if (!vret || err) {
+ _E("failed to g_dbus_connection_call_sync:%s", err->message);
+ g_error_free(err);
+ return -1;
+ }
+
+ g_variant_get(vret, "(u)", &pid);
+ g_variant_unref(vret);
+
+ return pid;
+}
+
+int dbus_handle_get_sender_pid(dbus_handle_h handle, const char * sender)
+{
+ dcl_dbus_handle();
+
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
+ if (!dh->conn) {
+ _E("wrong dbus handle. connection is null");
+ assert(0);
+ return -1;
+ }
+
+ return dbus_connection_get_sender_pid(dh->conn, sender);
+}
+
+int dbus_handle_get_sender_credentials(dbus_handle_h handle, const char *name, GDBusCredentials *creds)
+{
+ dcl_dbus_handle();
+ GVariant *vret = NULL;
+ GError *err = NULL;
+ GVariantIter *iter = NULL;
+ char * item;
+ GVariant *sub;
+
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return -1;
+ }
+ }
+ vret = g_dbus_connection_call_sync(dh->conn, DBUS_BUS_NAME, DBUS_OBJECT_PATH, DBUS_INTERFACE_NAME,
+ "GetConnectionCredentials", g_variant_new("(s)", name), NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err);
+ if (!vret || err) {
+ _E("failed to g_dbus_connection_call_sync:%s", err->message);
+ return -1;
+ }
- ret = dbus_pending_call_set_notify(pending, cb_pending, pdata, free);
- if (!ret) {
- free(pdata);
- dbus_pending_call_cancel(pending);
- return -ECOMM;
+ g_variant_get(vret, "(a{sv})", &iter);
+
+ while (g_variant_iter_loop(iter, "{sv}", &item, &sub)) {
+ if (!g_strcmp0(item, "UnixUserID")) {
+ g_variant_get(sub, "u", &creds->uid);
+ _D("UnixUserID %u", creds->uid);
+ } else if (!g_strcmp0(item, "ProcessID")) {
+ g_variant_get(sub, "u", &creds->pid);
+ _D("ProcessID %u", creds->pid);
+ } else if (!g_strcmp0(item, "LinuxSecurityLabel")) {
+ g_variant_get(sub, "^ay", &creds->sec_label);
+ _D("%s", creds->sec_label);
}
}
+ if (iter)
+ g_variant_iter_free(iter);
+ if (vret)
+ g_variant_unref(vret);
+
+ return 0;
+}
+
+void _destroy_notify_watch_name(gpointer data)
+{
+ if (data)
+ free(data);
+}
+
+int dbus_handle_watch_name(const char *name,
+ GBusNameAppearedCallback name_appeared_handler,
+ GBusNameVanishedCallback name_vanished_handler,
+ void *user_data)
+{
+ guint id = 0;
+
+ if (!name) {
+ _E("wrong name name %s", name);
+ return -1;
+ }
+ if (!name_appeared_handler && !name_vanished_handler) {
+ _E("both function pointers are null");
+ return -1;
+ }
+
+ id = g_bus_watch_name(dbus_handle_get_default_bus_type(), name, G_BUS_NAME_WATCHER_FLAGS_NONE, name_appeared_handler, name_vanished_handler, user_data, _destroy_notify_watch_name);
+ if (!id) {
+ _E("failed to g_bus_watch_name");
+ return -1;
+ }
+
+ return id;
+}
+
+void dbus_handle_unwatch_name(guint id)
+{
+ if (id == 0) {
+ _E("wrong id %d", id);
+ return;
+ }
+ g_bus_unwatch_name(id);
+}
+
+int _get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size)
+{
+ int fd, ret;
+ char buf[PATH_MAX + 1];
+ char *filename;
+
+ snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
+ fd = open(buf, O_RDONLY);
+ if (fd < 0) {
+ errno = ESRCH;
+ return -1;
+ }
+
+ ret = read(fd, buf, PATH_MAX);
+ close(fd);
+ if (ret < 0)
+ return -1;
+
+ buf[PATH_MAX] = '\0';
+
+ filename = strrchr(buf, '/');
+ if (filename == NULL)
+ filename = buf;
+ else
+ filename = filename + 1;
+
+ if (cmdline_size < strlen(filename) + 1) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+ strncpy(cmdline, filename, cmdline_size - 1);
+ cmdline[cmdline_size - 1] = '\0';
return 0;
}
+
+// g_strfreev(strv)
+char **dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name)
+{
+ dcl_dbus_handle();
+ GError *err = NULL;
+ GVariant *vret = NULL;
+ GVariantIter *iter = NULL;
+ gchar **strv = NULL;
+ gchar *str = NULL;
+ int i = 0;
+
+ if (!bus_name) {
+ _E("wrong parameter bus_name(%s)", bus_name);
+ return NULL;
+ }
+
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return NULL;
+ }
+ }
+
+ vret = g_dbus_connection_call_sync(dh->conn,
+ "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListQueuedOwners",
+ g_variant_new("(s)", bus_name),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_REPLY_TIMEOUT,
+ NULL,
+ &err);
+ if (!vret || err) {
+ _E("failed to g_dbus_connection_call_sync:%s", err->message);
+ g_error_free(err);
+ return NULL;
+ }
+
+ g_variant_get(vret, "(as)", &iter);
+ strv = g_new(gchar *, g_variant_iter_n_children(iter) + 1);
+
+ i = 0;
+ while (g_variant_iter_loop(iter, "s", &str))
+ strv[i++] = g_strdup(str);
+ strv[i] = NULL;
+
+ g_variant_iter_free(iter);
+ g_variant_unref(vret);
+
+ return strv;
+}
+
+void dbush_handle_check_owner_name(dbus_handle_h handle, const char *owner_name)
+{
+ dcl_dbus_handle();
+ char exe_name[PATH_MAX];
+ int pid;
+ char **strv = NULL;
+ int i;
+
+ if (!dh) {
+ dh = _dbus_handle_get_default_connection();
+ if (!dh) {
+ _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
+ return ;
+ }
+ }
+
+ strv = dbus_handle_get_owner_list(dh, owner_name);
+ if (!strv) {
+ _E("failed to get owner list of %s", owner_name);
+ return ;
+ }
+
+ for (i = 0; strv[i] != NULL; ++i) {
+ pid = dbus_handle_get_sender_pid(dh, strv[i]);
+ if (_get_cmdline_name(pid, exe_name, PATH_MAX) != 0)
+ break;
+ _I("%s(%d)", exe_name, pid);
+ }
+
+ g_strfreev(strv);
+}
+
+dbus_handle_h dbus_handle_init(GBusType type, const char* bus_name)
+{
+ dbus_handle_h handle = NULL;
+ int i, ret = 0;
+
+ if (!bus_name) {
+ _E("Wrong bus name, %s", bus_name);
+ return NULL;
+ }
+
+ // todo: do we need retry ? - booting time
+ for (i = 0 ; i < 3; ++i) {
+ handle = dbus_handle_get_connection(type, FALSE);
+ if (handle)
+ break;
+ usleep(5000);
+ }
+ ret = dbus_handle_request_bus_name(handle, bus_name);
+ if (ret <= 0)
+ goto out;
+
+ dbush_handle_check_owner_name(NULL, bus_name);
+
+ return handle;
+
+out:
+ return NULL;
+}
+