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 <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2020-01-13 14:44:08 +01:00 committed by Johan Hedberg
commit 4401b6a2f3

View file

@ -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); conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, peer);
if (conn) { if (conn) {
switch (conn->state) { /* Connection object already exists.
case BT_CONN_CONNECT_SCAN: * If the connection state is "connect" or "connected" then
bt_conn_set_param_le(conn, param); * this connection object was created using this API but has not
return conn; * yet been disconnected.
case BT_CONN_CONNECT: * If the connection state is "disconnected" then the connection
case BT_CONN_CONNECTED: * still has valid references. The last reference of the stack
return conn; * is released after the disconnected callback.
case BT_CONN_DISCONNECTED: */
BT_WARN("Found valid but disconnected conn object"); BT_WARN("Found valid connection in %s state",
goto start_scan; state2str(conn->state));
default: bt_conn_unref(conn);
bt_conn_unref(conn); return NULL;
return NULL;
}
} }
if (peer->type == BT_ADDR_LE_PUBLIC_ID || 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; return NULL;
} }
start_scan:
bt_conn_set_param_le(conn, param); bt_conn_set_param_le(conn, param);
#if defined(CONFIG_BT_SMP) #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); conn = bt_conn_lookup_addr_le(param->id, peer);
if (conn) { if (conn) {
switch (conn->state) { /* Connection object already exists.
case BT_CONN_CONNECT_DIR_ADV: * If the connection state is "connect-dir-adv" or "connected"
case BT_CONN_CONNECTED: * then this connection object was created using this API but
return conn; * has not yet been disconnected.
case BT_CONN_DISCONNECTED: * If the connection state is "disconnected" then the connection
BT_WARN("Found valid but disconnected conn object"); * still has valid references. The last reference of the stack
goto start_adv; * is released after the disconnected callback.
default: */
bt_conn_unref(conn); BT_WARN("Found valid connection in %s state",
return NULL; state2str(conn->state));
} bt_conn_unref(conn);
return NULL;
} }
conn = bt_conn_add_le(param->id, peer); 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; return NULL;
} }
start_adv:
bt_conn_set_state(conn, BT_CONN_CONNECT_DIR_ADV); bt_conn_set_state(conn, BT_CONN_CONNECT_DIR_ADV);
err = bt_le_adv_start_internal(&param_int, NULL, 0, NULL, 0, peer); err = bt_le_adv_start_internal(&param_int, NULL, 0, NULL, 0, peer);