diff options
Diffstat (limited to 'hcid')
-rw-r--r-- | hcid/dbus-rfcomm.c | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/hcid/dbus-rfcomm.c b/hcid/dbus-rfcomm.c index e85fefb4..c9f862e0 100644 --- a/hcid/dbus-rfcomm.c +++ b/hcid/dbus-rfcomm.c @@ -58,6 +58,7 @@ struct rfcomm_node { /* The following members are only valid for connected nodes */ GIOChannel *io; /* IO Channel for the connection */ + guint io_id; /* ID for IO channel */ char *owner; /* D-Bus name that created the node */ }; @@ -81,6 +82,17 @@ static char *rfcomm_node_name_from_id(int16_t id, char *dev, size_t len) return dev; } +static void rfcomm_node_free(struct rfcomm_node *node) +{ + if (node->io) { + g_io_channel_close(node->io); + g_io_remove_watch(node->io_id); + } + if (node->owner) + free(node->owner); + free(node); +} + static struct rfcomm_node *find_node_by_name(struct slist *nodes, const char *name) { struct slist *l; @@ -160,6 +172,7 @@ static int rfcomm_release(struct rfcomm_node *node, int *err) if (node->io) { g_io_channel_close(node->io); + g_io_remove_watch(node->io_id); node->io = NULL; } @@ -174,16 +187,18 @@ static int rfcomm_release(struct rfcomm_node *node, int *err) return -1; } - bound_nodes = slist_remove(bound_nodes, node); - - if (node->owner) - free(node->owner); - - free(node); - return 0; } +static gboolean rfcomm_disconnect_cb(GIOChannel *io, GIOCondition cond, + struct rfcomm_node *node) +{ + debug("RFCOMM node %s was disconnected", node->name); + connected_nodes = slist_remove(connected_nodes, node); + rfcomm_node_free(node); + return FALSE; +} + static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, struct pending_connect *c) { @@ -264,9 +279,9 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, err = errno; error("Could not open %s: %s (%d)", node->name, strerror(err), err); - /* This will also try to remove the node from bound_nodes, but - * that's ok since the slist_remove just silently fails */ rfcomm_release(node, NULL); + rfcomm_node_free(node); + error_connection_attempt_failed(c->conn, c->msg, err); goto failed; } @@ -291,9 +306,11 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, goto failed; } - send_reply_and_unref(c->conn, reply); - node->io = g_io_channel_unix_new(fd); + node->io_id = g_io_add_watch(node->io, G_IO_ERR | G_IO_HUP, + (GIOFunc)rfcomm_disconnect_cb, node); + + send_reply_and_unref(c->conn, reply); connected_nodes = slist_append(connected_nodes, node); @@ -302,8 +319,10 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, failed: if (fd >= 0) close(fd); - if (node) + if (node) { rfcomm_release(node, NULL); + rfcomm_node_free(node); + } if (reply) dbus_message_unref(reply); done: @@ -423,7 +442,7 @@ static struct rfcomm_node *rfcomm_bind(bdaddr_t *src, const char *bda, uint8_t c if (err) *err = errno; error("RFCOMMCREATEDEV failed: %s (%d)", strerror(errno), errno); - free(node); + rfcomm_node_free(node); return NULL; } @@ -526,6 +545,9 @@ static DBusHandlerResult rfcomm_disconnect_req(DBusConnection *conn, return error_failed(conn, msg, err); } + connected_nodes = slist_remove(connected_nodes, node); + rfcomm_node_free(node); + return send_reply_and_unref(conn, reply); } @@ -574,8 +596,11 @@ static DBusHandlerResult rfcomm_bind_by_ch_req(DBusConnection *conn, need_memory: if (reply) dbus_message_unref(reply); - if (node) + if (node) { + bound_nodes = slist_remove(bound_nodes, node); rfcomm_release(node, NULL); + rfcomm_node_free(node); + } return DBUS_HANDLER_RESULT_NEED_MEMORY; } @@ -605,6 +630,9 @@ static DBusHandlerResult rfcomm_release_req(DBusConnection *conn, return error_failed(conn, msg, err); } + bound_nodes = slist_remove(bound_nodes, node); + rfcomm_node_free(node); + return send_reply_and_unref(conn, reply); } |