summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpr.jung <pr.jung@samsung.com>2016-10-24 19:57:23 +0900
committerpr.jung <pr.jung@samsung.com>2016-10-27 15:34:47 +0900
commitbf2f7c30c56ead7b4ea3f7312b8c53e53aabc934 (patch)
tree2989ec31c3231aac89ff0451b662e98e63121918
parentf46e61fe14215f1ceecee79725fd8ce5d113a73f (diff)
downloadlibsvi-bf2f7c30c56ead7b4ea3f7312b8c53e53aabc934.tar.gz
libsvi-bf2f7c30c56ead7b4ea3f7312b8c53e53aabc934.tar.bz2
libsvi-bf2f7c30c56ead7b4ea3f7312b8c53e53aabc934.zip
Change libdbus to gdbus and add proxy pool
- Instead use async call for VibrateEffect, libsvi use sync call and deviced-vibrator return after parameter check(and security check). deviced-vibrator add idler callback for further operation for VibrateEffect(For async operation) Change-Id: I374ced886bc827bb9caa953874ccccb6a618a41a Signed-off-by: pr.jung <pr.jung@samsung.com>
-rw-r--r--src/dbus.c278
-rw-r--r--src/dbus.h8
2 files changed, 221 insertions, 65 deletions
diff --git a/src/dbus.c b/src/dbus.c
index 53db49b..0a8c18c 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <stdbool.h>
#include <errno.h>
#include "common.h"
@@ -29,111 +30,260 @@
/* -1 is a default timeout value, it's converted to 25*1000 internally. */
#define DBUS_REPLY_TIMEOUT (-1)
-static int append_variant(DBusMessageIter *iter, const char *sig, char *param[])
+/** extract from dbus/dbus-protocol.h
+ * (GDbus use the same maximum value.)
+ * Max length in bytes of a bus name, interface, or member (not object
+ * path, paths are unlimited). This is limited because lots of stuff
+ * is O(n) in this number, plus it would be obnoxious to type in a
+ * paragraph-long method name so most likely something like that would
+ * be an exploit.
+ */
+#define DBUS_MAXIMUM_NAME_LENGTH 255
+
+struct proxy_node {
+ GDBusProxy *proxy;
+ char *dest;
+ char *path;
+ char *interface;
+};
+
+static GList *proxy_pool;
+static pthread_mutex_t dmutex = PTHREAD_MUTEX_INITIALIZER;
+static int bus_init;
+
+static int g_dbus_error_to_errno(int code)
{
+ /**
+ * if device is not supported,
+ * deviced does not register the method call of the device.
+ * in this case, dbus will return UNKNOWN_METHOD error.
+ */
+ /* refer to gio/gioenums.h */
+ if (code == G_DBUS_ERROR_ACCESS_DENIED)
+ return -EACCES;
+ else if (code == G_DBUS_ERROR_UNKNOWN_METHOD)
+ return -ENOTSUP;
+ return -ECOMM;
+}
+
+static GVariant *append_g_variant(const char *sig, char *param[])
+{
+ GVariantBuilder builder;
char *ch;
int i;
- int int_type;
- uint64_t int64_type;
- DBusMessageIter arr;
- struct dbus_byte *byte;
+ struct dbus_byte *bytes;
if (!sig || !param)
- return 0;
+ return NULL;
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
- for (ch = (char*)sig, i = 0; *ch != '\0'; ++i, ++ch) {
+ for (ch = (char *)sig, i = 0; *ch != '\0'; ++i, ++ch) {
switch (*ch) {
case 'i':
- int_type = atoi(param[i]);
- dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &int_type);
+ g_variant_builder_add(&builder, "i", atoi(param[i]));
break;
case 'u':
- int_type = strtoul(param[i], NULL, 10);
- dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &int_type);
+ g_variant_builder_add(&builder, "u", strtoul(param[i], NULL, 10));
break;
case 't':
- int64_type = atoll(param[i]);
- dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &int64_type);
+ g_variant_builder_add(&builder, "t", atoll(param[i]));
break;
case 's':
- dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &param[i]);
+ g_variant_builder_add(&builder, "s", param[i]);
break;
case 'a':
++i, ++ch;
switch (*ch) {
case 'y':
- 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);
+ bytes = (struct dbus_byte *)param[i];
+ g_variant_builder_add(&builder, "@ay",
+ g_variant_new_from_data(G_VARIANT_TYPE("ay"),
+ bytes->data, bytes->size, TRUE, NULL, NULL));
break;
default:
break;
}
break;
default:
- return -EINVAL;
+ return NULL;
}
}
- return 0;
+ return g_variant_builder_end(&builder);
}
-int dbus_method_sync(const char *dest, const char *path,
- const char *interface, const char *method,
- const char *sig, char *param[])
+static struct proxy_node *find_matched_proxy_node(const char *dest,
+ const char *path,
+ const char *interface)
{
- DBusConnection *conn;
- DBusMessage *msg;
- DBusMessageIter iter;
- DBusMessage *reply;
- DBusError err;
- int ret, result;
-
- conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
- if (!conn) {
- _E("dbus_bus_get error"); //LCOV_EXCL_LINE
- return -EPERM;
+ GList *elem;
+ struct proxy_node *node;
+ int plen;
+
+ if (!dest || !path || !interface)
+ return NULL;
+
+ plen = strlen(path) + 1;
+
+ /* find matched proxy object */
+ for (elem = proxy_pool; elem; elem = elem->next) {
+ node = elem->data;
+ if (!node)
+ continue;
+ if (!strncmp(node->dest, dest, DBUS_MAXIMUM_NAME_LENGTH) &&
+ !strncmp(node->path, path, plen) &&
+ !strncmp(node->interface, interface,
+ DBUS_MAXIMUM_NAME_LENGTH))
+ return node;
}
- msg = dbus_message_new_method_call(dest, path, interface, method);
- if (!msg) {
- _E("dbus_message_new_method_call(%s:%s-%s)", //LCOV_EXCL_LINE
- path, interface, method);
- return -EBADMSG;
+ return NULL;
+}
+
+static void on_name_vanished(GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GList *elem;
+ GList *next;
+ struct proxy_node *node;
+
+ pthread_mutex_lock(&dmutex);
+ for (elem = proxy_pool, next = g_list_next(elem); elem;
+ elem = next, next = g_list_next(elem)) {
+ node = elem->data;
+ if (!node)
+ continue;
+ proxy_pool = g_list_delete_link(proxy_pool, elem);
+ g_object_unref(node->proxy);
+ free(node->dest);
+ free(node->path);
+ free(node->interface);
+ free(node);
}
+ pthread_mutex_unlock(&dmutex);
+}
+
+static GDBusProxy *get_proxy_from_proxy_pool(const char *dest,
+ const char *path,
+ const char *interface,
+ GError **err)
+{
+ GDBusConnection *conn;
+ GDBusProxy *proxy;
+ struct proxy_node *node;
- 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", //LCOV_EXCL_LINE
- ret, dest, path, interface, method);
- dbus_message_unref(msg);
- return ret;
+ if (!dest || !path || !interface) {
+ if (err)
+ g_set_error(err, G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ "Cannot determine destination address");
+ return NULL;
}
- dbus_error_init(&err);
+ /* find matched proxy node in proxy pool */
+ node = find_matched_proxy_node(dest, path, interface);
+ if (node)
+ return node->proxy;
- reply = dbus_connection_send_with_reply_and_block(conn, msg, DBUS_REPLY_TIMEOUT, &err);
- dbus_message_unref(msg);
- if (!reply) {
- _E("dbus_connection_send error(%s:%s) %s %s:%s-%s", //LCOV_EXCL_LINE
- err.name, err.message, dest, path, interface, method);
- dbus_error_free(&err); //LCOV_EXCL_LINE System Error
- return -ECOMM;
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, err);
+ if (!conn)
+ return NULL;
+
+ if (!bus_init) {
+ bus_init++;
+ g_bus_watch_name_on_connection(conn,
+ DEVICED_BUS_NAME,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ NULL,
+ on_name_vanished,
+ NULL,
+ NULL);
+ }
+
+ proxy = g_dbus_proxy_new_sync(conn,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL, /* GDBusinterfaceinfo */
+ dest, /* bus name */
+ path, /* object path */
+ interface, /* interface name */
+ NULL, /* GCancellable */
+ err);
+ if (!proxy)
+ return NULL;
+
+ node = malloc(sizeof(struct proxy_node));
+ if (!node) {
+ g_object_unref(proxy);
+ if (err)
+ g_set_error(err, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Cannot allocate proxy_node memory");
+ return NULL;
+ }
+
+ node->proxy = proxy;
+ node->dest = strdup(dest);
+ node->path = strdup(path);
+ node->interface = strdup(interface);
+
+ proxy_pool = g_list_append(proxy_pool, node);
+
+ return proxy;
+}
+
+int dbus_method_sync(const char *dest, const char *path,
+ const char *interface, const char *method,
+ const char *sig, char *param[])
+{
+ GDBusProxy *proxy;
+ GError *err = NULL;
+ GVariant *output;
+ int result;
+
+#if !GLIB_CHECK_VERSION(2,35,0)
+ g_type_init();
+#endif
+
+ pthread_mutex_lock(&dmutex);
+ proxy = get_proxy_from_proxy_pool(dest, path, interface, &err);
+ if (!proxy) {
+ pthread_mutex_unlock(&dmutex);
+ _E("fail to get proxy from proxy pool : %s-%s (%d-%s)",
+ interface, method, err->code, err->message);
+ result = g_dbus_error_to_errno(err->code);
+ g_clear_error(&err);
+ return result;
}
- ret = dbus_message_get_args(reply, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
- dbus_message_unref(reply);
- if (!ret) {
- if (dbus_error_is_set(&err)) {
- _E("error : [%s:%s] %s %s:%s-%s", //LCOV_EXCL_LINE
- err.name, err.message, dest, path, interface, method);
- dbus_error_free(&err); //LCOV_EXCL_LINE System Error
- } else
- _E("no message"); //LCOV_EXCL_LINE
- return -ENOMSG;
+ output = g_dbus_proxy_call_sync(proxy,
+ method, /* method name */
+ append_g_variant(sig, param), /* parameters */
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_REPLY_TIMEOUT, /* timeout */
+ NULL, /* GCancellable */
+ &err);
+ pthread_mutex_unlock(&dmutex);
+
+ if (!output) {
+ if (err) {
+ _E("g_dbus_proxy_call_sync error : %s-%s (%d-%s)",
+ interface, method, err->code, err->message);
+ result = g_dbus_error_to_errno(err->code);
+ g_clear_error(&err);
+ } else {
+ _E("g_dbus_proxy_call_sync error : %s-%s",
+ interface, method);
+ result = -ECOMM;
+ }
+ return result;
}
+ /* get output value */
+ g_variant_get(output, "(i)", &result);
+
+ g_variant_unref(output);
+
return result;
}
diff --git a/src/dbus.h b/src/dbus.h
index 8c66655..65bf222 100644
--- a/src/dbus.h
+++ b/src/dbus.h
@@ -20,7 +20,7 @@
#ifndef __DBUS_H__
#define __DBUS_H__
-#include <dbus/dbus.h>
+#include <gio/gio.h>
/*
* Device daemon
@@ -46,4 +46,10 @@ struct dbus_byte {
int dbus_method_sync(const char *dest, const char *path,
const char *interface, const char *method,
const char *sig, char *param[]);
+
+/**
+ * If result is NULL, err is set.
+ * Do not invoke g_variant_unref() with result.
+ */
+typedef void (*dbus_pending_cb)(void *data, GVariant *result, GError *err);
#endif