summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2012-12-15 03:05:04 +0100
committerMarcel Holtmann <marcel@holtmann.org>2012-12-15 03:05:04 +0100
commit4964ecdae4a106304359182f6430d521fb91ad72 (patch)
tree40a1a66214b7101d0d4a5a91d056ab88dad684bc
parentfddb94f0e89e8da2e628a2f2af18ced06197af5c (diff)
core: Add agent registration handling of agent manager
-rw-r--r--src/agent.c112
1 files changed, 111 insertions, 1 deletions
diff --git a/src/agent.c b/src/agent.c
index c0ff46ea7..c2033a6a7 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -41,7 +41,7 @@
#include <gdbus/gdbus.h>
#include "log.h"
-
+#include "error.h"
#include "dbus-common.h"
#include "adapter.h"
#include "device.h"
@@ -50,6 +50,14 @@
#define REQUEST_TIMEOUT (60 * 1000) /* 60 seconds */
#define AGENT_INTERFACE "org.bluez.Agent1"
+static GHashTable *agent_list;
+
+struct agent_data {
+ char *owner;
+ char *path;
+ guint watch;
+};
+
typedef enum {
AGENT_REQUEST_PASSKEY,
AGENT_REQUEST_CONFIRMATION,
@@ -832,15 +840,112 @@ gboolean agent_is_busy(struct agent *agent, void *user_data)
return TRUE;
}
+static struct agent_data *agent_alloc(const char *owner, const char *path)
+{
+ struct agent_data *agent;
+
+ agent = g_try_new0(struct agent_data, 1);
+ if (!agent)
+ return NULL;
+
+ agent->owner = g_strdup(owner);
+ agent->path = g_strdup(path);
+
+ return agent;
+}
+
+static void agent_destroy(gpointer data)
+{
+ struct agent_data *agent = data;
+
+ DBG("agent %s", agent->owner);
+
+ if (agent->watch > 0) {
+ DBusConnection *conn = btd_get_dbus_connection();
+ DBusMessage *msg;
+
+ g_dbus_remove_watch(conn, agent->watch);
+
+ msg = dbus_message_new_method_call(agent->owner, agent->path,
+ AGENT_INTERFACE, "Release");
+ if (msg)
+ g_dbus_send_message(conn, msg);
+ }
+
+ g_free(agent->owner);
+ g_free(agent->path);
+
+ g_free(agent);
+}
+
+static void agent_disconnect(DBusConnection *conn, void *user_data)
+{
+ struct agent_data *agent = user_data;
+
+ DBG("agent %s", agent->owner);
+
+ if (agent->watch > 0) {
+ g_dbus_remove_watch(conn, agent->watch);
+ agent->watch = 0;
+ }
+
+ g_hash_table_remove(agent_list, agent->owner);
+}
+
static DBusMessage *register_agent(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
+ struct agent_data *agent;
+ const char *sender, *path, *capability;
+
+ sender = dbus_message_get_sender(msg);
+
+ agent = g_hash_table_lookup(agent_list, sender);
+ if (agent)
+ return btd_error_already_exists(msg);
+
+ if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_STRING, &capability,
+ DBUS_TYPE_INVALID) == FALSE)
+ return btd_error_invalid_args(msg);
+
+ agent = agent_alloc(sender, path);
+ if (!agent)
+ return btd_error_invalid_args(msg);
+
+ DBG("agent %s", agent->owner);
+
+ g_hash_table_replace(agent_list, agent->owner, agent);
+
+ agent->watch = g_dbus_add_disconnect_watch(conn, agent->owner,
+ agent_disconnect, agent, NULL);
+
return dbus_message_new_method_return(msg);
}
static DBusMessage *unregister_agent(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
+ struct agent_data *agent;
+ const char *sender, *path;
+
+ sender = dbus_message_get_sender(msg);
+
+ agent = g_hash_table_lookup(agent_list, sender);
+ if (!agent)
+ return btd_error_does_not_exist(msg);
+
+ DBG("agent %s", agent->owner);
+
+ if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID) == FALSE)
+ return btd_error_invalid_args(msg);
+
+ if (g_str_equal(path, agent->path) == FALSE)
+ return btd_error_does_not_exist(msg);
+
+ agent_disconnect(conn, agent);
+
return dbus_message_new_method_return(msg);
}
@@ -855,6 +960,9 @@ static const GDBusMethodTable methods[] = {
void btd_agent_init(void)
{
+ agent_list = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, agent_destroy);
+
g_dbus_register_interface(btd_get_dbus_connection(),
"/org/bluez", "org.bluez.AgentManager1",
methods, NULL, NULL, NULL, NULL);
@@ -864,4 +972,6 @@ void btd_agent_cleanup(void)
{
g_dbus_unregister_interface(btd_get_dbus_connection(),
"/org/bluez", "org.bluez.AgentManager1");
+
+ g_hash_table_destroy(agent_list);
}