From 4401b6a2f38c06ca445bf13eda783c212a609767 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Mon, 13 Jan 2020 14:44:08 +0100 Subject: [PATCH] Bluetooth: host: Stop using existing conn object when creating new conn Remove re-using connection objects in disconnected state when creating directed advertiser or establishing a connection as a central using direct connection procedure. This makes the API mores consistent it terms of which connection roles can be started from the disconnected callback. This also avoids a central connection object being re-used for a connection as a peripheral instead and vice versa. When attempting to create a new connection the API would returning a valid connection object if there is already an existing connection object. This existing connection object could be either in the process of establishing the connection or already connected. Returning the connection object in this would give the false impression that the stack has initiated connection procedure, when in fact it just returned an existing connection object. The application has the ability to check for existing connection objects using the bt_conn_lookup_addr_le API. Add warning plus comment possible scenarios why the a valid connection object might exists. Most important is to explain why a valid connection object exists during the disconnected callback. Signed-off-by: Joakim Andersson --- subsys/bluetooth/host/conn.c | 51 +++++++++++++++++------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index c6793f93a2e..c77b3f667cf 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -2220,20 +2220,18 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, peer); if (conn) { - switch (conn->state) { - case BT_CONN_CONNECT_SCAN: - bt_conn_set_param_le(conn, param); - return conn; - case BT_CONN_CONNECT: - case BT_CONN_CONNECTED: - return conn; - case BT_CONN_DISCONNECTED: - BT_WARN("Found valid but disconnected conn object"); - goto start_scan; - default: - bt_conn_unref(conn); - return NULL; - } + /* Connection object already exists. + * If the connection state is "connect" or "connected" then + * this connection object was created using this API but has not + * yet been disconnected. + * If the connection state is "disconnected" then the connection + * still has valid references. The last reference of the stack + * is released after the disconnected callback. + */ + BT_WARN("Found valid connection in %s state", + state2str(conn->state)); + bt_conn_unref(conn); + return NULL; } if (peer->type == BT_ADDR_LE_PUBLIC_ID || @@ -2250,7 +2248,6 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, return NULL; } -start_scan: bt_conn_set_param_le(conn, param); #if defined(CONFIG_BT_SMP) @@ -2344,17 +2341,18 @@ struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer, conn = bt_conn_lookup_addr_le(param->id, peer); if (conn) { - switch (conn->state) { - case BT_CONN_CONNECT_DIR_ADV: - case BT_CONN_CONNECTED: - return conn; - case BT_CONN_DISCONNECTED: - BT_WARN("Found valid but disconnected conn object"); - goto start_adv; - default: - bt_conn_unref(conn); - return NULL; - } + /* Connection object already exists. + * If the connection state is "connect-dir-adv" or "connected" + * then this connection object was created using this API but + * has not yet been disconnected. + * If the connection state is "disconnected" then the connection + * still has valid references. The last reference of the stack + * is released after the disconnected callback. + */ + BT_WARN("Found valid connection in %s state", + state2str(conn->state)); + bt_conn_unref(conn); + return NULL; } conn = bt_conn_add_le(param->id, peer); @@ -2362,7 +2360,6 @@ struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer, return NULL; } -start_adv: bt_conn_set_state(conn, BT_CONN_CONNECT_DIR_ADV); err = bt_le_adv_start_internal(¶m_int, NULL, 0, NULL, 0, peer);