From ec3ac41ca8876f36cc8869ab1c384980f793c40f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 20 Aug 2006 21:41:59 +0000 Subject: Preliminary support for passkey agent timeouts --- common/glib-ectomy.c | 41 ++++++++++++++--------------- hcid/dbus-security.c | 73 +++++++++++++++++++++++++++++++++++----------------- hcid/dbus.c | 33 ++++++++++++------------ hcid/dbus.h | 1 + 4 files changed, 87 insertions(+), 61 deletions(-) diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 214ee571..f90973ba 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -225,16 +225,7 @@ static void timeout_handlers_prepare(GMainContext *context) static int timeout_cmp(const void *t1, const void *t2) { - const struct timeout *tout1 = t1; - const struct timeout *tout2 = t2; - - if (!tout2) - return -1; - - if (tout1 != tout2) - return -1; - - return tout1->id - tout2->id; + return t1 - t2; } static void timeout_handlers_check(GMainContext *context) @@ -246,24 +237,30 @@ static void timeout_handlers_check(GMainContext *context) gettimeofday(&tv, NULL); while (l) { + struct slist *match; + gboolean ret; + t = l->data; l = l->next; if (timercmp(&tv, &t->expiration, <)) continue; - if (t->function(t->data)) { - struct slist *match; - /* if false/expired: remove it from the list - * Before remove check again in order to cover the situation - * when the handler is removed/freed by the callback function - */ - match = slist_find(context->ltimeout, t, timeout_cmp); - if (match) { - t = match->data; - context->ltimeout = slist_remove(context->ltimeout, t); - free(t); - } + ret = t->function(t->data); + + /* Check if the handler was removed/freed by the callback + * function */ + match = slist_find(context->ltimeout, t, timeout_cmp); + + if (!match) + continue; + + /* Update next pointer if callback changed the list */ + l = match->next; + + if (ret == FALSE) { + context->ltimeout = slist_remove(context->ltimeout, t); + free(t); } else { glong secs, msecs; /* update the next expiration time */ diff --git a/hcid/dbus-security.c b/hcid/dbus-security.c index 91a03e5d..c9c6763f 100644 --- a/hcid/dbus-security.c +++ b/hcid/dbus-security.c @@ -39,7 +39,8 @@ #include "dbus.h" #include "hcid.h" -#define TIMEOUT (30 * 1000) /* 30 seconds */ +#define REQUEST_TIMEOUT (30 * 1000) /* 30 seconds */ +#define AGENT_TIMEOUT (1 * 10 * 1000) /* 3 minutes */ static struct passkey_agent *default_agent = NULL; @@ -64,6 +65,9 @@ static void passkey_agent_free(struct passkey_agent *agent) free(req); } + if (agent->timeout) + g_timeout_remove(agent->timeout); + if (!agent->exited) release_agent(agent); @@ -81,6 +85,45 @@ static void passkey_agent_free(struct passkey_agent *agent) free(agent); } +static void agent_exited(const char *name, struct hci_dbus_data *adapter) +{ + struct slist *cur, *next; + + debug("Passkey agent %s exited without calling Unregister", name); + + for (cur = adapter->passkey_agents; cur != NULL; cur = next) { + struct passkey_agent *agent = cur->data; + + next = cur->next; + + if (strcmp(agent->name, name)) + continue; + + agent->exited = 1; + + adapter->passkey_agents = slist_remove(adapter->passkey_agents, agent); + passkey_agent_free(agent); + } +} + +static gboolean agent_timeout(struct passkey_agent *agent) +{ + struct hci_dbus_data *pdata = agent->pdata; + + debug("Passkey Agent at %s, %s timed out", agent->name, agent->path); + + if (pdata) + pdata->passkey_agents = slist_remove(pdata->passkey_agents, agent); + + name_listener_remove(agent->conn, agent->name, (name_cb_t)agent_exited, pdata); + + agent->timeout = 0; + + passkey_agent_free(agent); + + return FALSE; +} + static void default_agent_exited(const char *name, void *data) { debug("%s exited without unregistering the default passkey agent", name); @@ -167,27 +210,6 @@ static int agent_cmp(const struct passkey_agent *a, const struct passkey_agent * return 0; } -static void agent_exited(const char *name, struct hci_dbus_data *adapter) -{ - struct slist *cur, *next; - - debug("Passkey agent %s exited without calling Unregister", name); - - for (cur = adapter->passkey_agents; cur != NULL; cur = next) { - struct passkey_agent *agent = cur->data; - - next = cur->next; - - if (strcmp(agent->name, name)) - continue; - - agent->exited = 1; - - adapter->passkey_agents = slist_remove(adapter->passkey_agents, agent); - passkey_agent_free(agent); - } -} - static DBusHandlerResult register_agent(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -233,6 +255,11 @@ static DBusHandlerResult register_agent(DBusConnection *conn, if (!slist_find(adapter->passkey_agents, &ref, (cmp_func_t)agent_cmp)) name_listener_add(conn, ref.name, (name_cb_t)agent_exited, adapter); + /* Because of bugs in glib-ectonomy.c this doesn't work yet */ +#if 0 + agent->timeout = g_timeout_add(AGENT_TIMEOUT, (GSourceFunc)agent_timeout, agent); +#endif + adapter->passkey_agents = slist_append(adapter->passkey_agents, agent); return send_reply_and_unref(conn, reply); @@ -486,7 +513,7 @@ static int call_passkey_agent(DBusConnection *conn, DBUS_TYPE_INVALID); if (dbus_connection_send_with_reply(conn, message, - &req->call, TIMEOUT) == FALSE) { + &req->call, REQUEST_TIMEOUT) == FALSE) { error("D-Bus send failed"); goto failed; } diff --git a/hcid/dbus.c b/hcid/dbus.c index 269d255d..2bb9bf85 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -1440,16 +1440,16 @@ failed: * Section reserved to D-Bus watch functions * *****************************************************************/ -static int message_dispatch_cb(void *data) +static gboolean message_dispatch_cb(void *data) { dbus_connection_ref(connection); /* Dispatch messages */ - while(dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS); + while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS); dbus_connection_unref(connection); - return -1; + return FALSE; } static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data) @@ -1520,17 +1520,17 @@ static void watch_toggled(DBusWatch *watch, void *data) remove_watch(watch, data); } -static int timeout_handler_dispatch(gpointer data) +static gboolean timeout_handler_dispatch(gpointer data) { timeout_handler_t *handler = data; /* if not enabled should not be polled by the main loop */ if (dbus_timeout_get_enabled(handler->timeout) != TRUE) - return -1; + return FALSE; dbus_timeout_handle(handler->timeout); - return -1; + return FALSE; } static void timeout_handler_free(void *data) @@ -1672,21 +1672,21 @@ done: * *****************************************************************/ -int discoverable_timeout_handler(void *data) +gboolean discoverable_timeout_handler(void *data) { struct hci_dbus_data *dbus_data = data; struct hci_request rq; int dd = -1; uint8_t hci_mode = dbus_data->mode; uint8_t status = 0; - int8_t retval = 0; + gboolean retval = TRUE; hci_mode &= ~SCAN_INQUIRY; dd = hci_open_dev(dbus_data->dev_id); if (dd < 0) { error("HCI device open failed: hci%d", dbus_data->dev_id); - return 0; + return TRUE; } memset(&rq, 0, sizeof(rq)); @@ -1708,7 +1708,7 @@ int discoverable_timeout_handler(void *data) } dbus_data->timeout_id = 0; - retval = -1; + retval = FALSE; failed: if (dd >= 0) @@ -1717,24 +1717,25 @@ failed: return retval; } -static int system_bus_reconnect(void *data) +static gboolean system_bus_reconnect(void *data) { struct hci_dev_list_req *dl = NULL; struct hci_dev_req *dr; - int sk, i, ret_val = 0; + int sk, i; + gboolean ret_val = TRUE; if (dbus_connection_get_is_connected(connection)) - return -1; + return FALSE; if (hcid_dbus_init() == FALSE) - return 0; + return TRUE; /* Create and bind HCI socket */ sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (sk < 0) { error("Can't open HCI socket: %s (%d)", strerror(errno), errno); - return 0; + return TRUE; } dl = malloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl)); @@ -1758,7 +1759,7 @@ static int system_bus_reconnect(void *data) for (i = 0; i < dl->dev_num; i++, dr++) hcid_dbus_register_device(dr->dev_id); - ret_val = -1; + ret_val = FALSE; failed: if (sk >= 0) diff --git a/hcid/dbus.h b/hcid/dbus.h index 4aae9164..36c369bc 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -120,6 +120,7 @@ struct passkey_agent { char *path; struct slist *pending_requests; int exited; + guint timeout; }; struct pending_agent_request { -- cgit