Skip to content

Commit 8aecbbf

Browse files
committed
[Bugfix] Incorrect Client connection state tracking and self delete
This adds better client state tracking so that functions like NimBLEDevice::getDisconnectedClient get a more accurate state and will not return a connecting client. This also fixes the client self delete on connection error where function call errors did not delete the client
1 parent 74443d9 commit 8aecbbf

3 files changed

Lines changed: 58 additions & 50 deletions

File tree

src/NimBLEClient.cpp

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ NimBLEClient::NimBLEClient(const NimBLEAddress& peerAddress)
6868
m_terminateFailCount{0},
6969
m_asyncSecureAttempt{0},
7070
m_config{},
71+
m_connStatus{DISCONNECTED},
7172
# if MYNEWT_VAL(BLE_EXT_ADV)
7273
m_phyMask{BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK},
7374
# endif
@@ -171,35 +172,30 @@ bool NimBLEClient::connect(bool deleteAttributes, bool asyncConnect, bool exchan
171172
*/
172173
bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes, bool asyncConnect, bool exchangeMTU) {
173174
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
175+
NimBLETaskData taskData(this);
176+
const ble_addr_t* peerAddr = address.getBase();
177+
int rc = 0;
174178

175179
if (!NimBLEDevice::m_synced) {
176-
NIMBLE_LOGE(LOG_TAG, "Host reset, wait for sync.");
177-
return false;
180+
NIMBLE_LOGE(LOG_TAG, "Host not synced with controller.");
181+
rc = BLE_HS_ENOTSYNCED;
182+
goto error;
178183
}
179184

180-
if (isConnected()) {
181-
NIMBLE_LOGE(LOG_TAG, "Client already connected");
182-
return false;
183-
}
184-
185-
const ble_addr_t* peerAddr = address.getBase();
186-
if (ble_gap_conn_find_by_addr(peerAddr, NULL) == 0) {
187-
NIMBLE_LOGE(LOG_TAG, "A connection to %s already exists", address.toString().c_str());
188-
return false;
185+
if (m_connStatus != DISCONNECTED) {
186+
NIMBLE_LOGE(LOG_TAG, "Client not disconnected, cannot connect");
187+
rc = BLE_HS_EREJECT;
188+
goto error;
189189
}
190190

191191
if (address.isNull()) {
192192
NIMBLE_LOGE(LOG_TAG, "Invalid peer address; (NULL)");
193-
return false;
194-
} else {
195-
m_peerAddress = address;
193+
rc = BLE_HS_EINVAL;
194+
goto error;
196195
}
197196

198-
if (deleteAttributes) {
199-
deleteServices();
200-
}
201-
202-
int rc = 0;
197+
m_connStatus = CONNECTING;
198+
m_peerAddress = address;
203199
m_config.asyncConnect = asyncConnect;
204200
m_config.exchangeMTU = exchangeMTU;
205201

@@ -259,22 +255,24 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
259255

260256
} while (rc == BLE_HS_EBUSY);
261257

258+
if (deleteAttributes) {
259+
deleteServices();
260+
}
261+
262262
if (rc != 0) {
263-
m_lastErr = rc;
264-
return false;
263+
goto error;
265264
}
266265

267266
if (m_config.asyncConnect) {
268267
return true;
269268
}
270269

271-
NimBLETaskData taskData(this);
272270
m_pTaskData = &taskData;
273271

274272
// Wait for the connect timeout time +1 second for the connection to complete
275273
if (!NimBLEUtils::taskWait(taskData, m_connectTimeout + 1000)) {
276274
// If a connection was made but no response from MTU exchange proceed anyway
277-
if (isConnected()) {
275+
if (m_connStatus == CONNECTED && m_config.exchangeMTU) {
278276
taskData.m_flags = 0;
279277
} else {
280278
// workaround; if the controller doesn't cancel the connection at the timeout, cancel it here.
@@ -288,17 +286,20 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
288286
rc = taskData.m_flags;
289287
if (rc != 0) {
290288
NIMBLE_LOGE(LOG_TAG, "Connection failed; status=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
291-
m_lastErr = rc;
292-
if (m_config.deleteOnConnectFail) {
293-
NimBLEDevice::deleteClient(this);
294-
}
295-
return false;
289+
goto error;
296290
}
297291

298292
m_pClientCallbacks->onConnect(this);
299293
NIMBLE_LOGD(LOG_TAG, "<< connect()");
300-
// Check if still connected before returning
301-
return isConnected();
294+
return true;
295+
296+
error:
297+
m_connStatus = DISCONNECTED;
298+
m_lastErr = rc;
299+
if (m_config.deleteOnConnectFail) {
300+
NimBLEDevice::deleteClient(this);
301+
}
302+
return false;
302303
} // connect
303304

304305
/**
@@ -358,6 +359,7 @@ bool NimBLEClient::disconnect(uint8_t reason) {
358359
return false;
359360
}
360361

362+
m_connStatus = (rc == BLE_HS_ENOTCONN) ? DISCONNECTED : DISCONNECTING;
361363
return true;
362364
} // disconnect
363365

@@ -575,8 +577,8 @@ NimBLEAddress NimBLEClient::getPeerAddress() const {
575577
* @return True if successful.
576578
*/
577579
bool NimBLEClient::setPeerAddress(const NimBLEAddress& address) {
578-
if (isConnected()) {
579-
NIMBLE_LOGE(LOG_TAG, "Cannot set peer address while connected");
580+
if (m_connStatus == CONNECTED || m_connStatus == CONNECTING) {
581+
NIMBLE_LOGE(LOG_TAG, "Cannot set peer address while connected/connecting");
580582
return false;
581583
}
582584

@@ -589,7 +591,7 @@ bool NimBLEClient::setPeerAddress(const NimBLEAddress& address) {
589591
* @return The RSSI value or 0 if there was an error.
590592
*/
591593
int NimBLEClient::getRssi() const {
592-
if (!isConnected()) {
594+
if (m_connStatus != CONNECTED) {
593595
NIMBLE_LOGE(LOG_TAG, "getRssi(): Not connected");
594596
return 0;
595597
}
@@ -732,7 +734,7 @@ bool NimBLEClient::discoverAttributes() {
732734
* @return true on success otherwise false if an error occurred
733735
*/
734736
bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) {
735-
if (!isConnected()) {
737+
if (m_connStatus != CONNECTED) {
736738
NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting");
737739
return false;
738740
}
@@ -968,6 +970,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
968970

969971
pClient->m_terminateFailCount = 0;
970972
pClient->m_asyncSecureAttempt = 0;
973+
pClient->m_connStatus = DISCONNECTED;
971974

972975
// Don't call the disconnect callback if we are waiting for a connection to complete and it fails
973976
if (rc == (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_ESTABLISHMENT) && pClient->m_config.asyncConnect) {
@@ -994,7 +997,8 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
994997

995998
case BLE_GAP_EVENT_CONNECT: {
996999
// If we aren't waiting for this connection response we should drop the connection immediately.
997-
if (pClient->isConnected() || (!pClient->m_config.asyncConnect && pClient->m_pTaskData == nullptr)) {
1000+
if (pClient->m_connStatus != CONNECTING ||
1001+
(!pClient->m_config.asyncConnect && pClient->m_pTaskData == nullptr)) {
9981002
ble_gap_terminate(event->connect.conn_handle, BLE_ERR_REM_USER_CONN_TERM);
9991003
return 0;
10001004
}
@@ -1005,6 +1009,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
10051009
}
10061010

10071011
if (rc == 0) {
1012+
pClient->m_connStatus = CONNECTED;
10081013
pClient->m_connHandle = event->connect.conn_handle;
10091014

10101015
if (pClient->m_config.asyncConnect) {
@@ -1013,13 +1018,13 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
10131018

10141019
if (pClient->m_config.exchangeMTU) {
10151020
if (!pClient->exchangeMTU()) {
1016-
rc = pClient->m_lastErr; // sets the error in the task data
1017-
break;
1021+
break; // if exchangeMTU fails we will just continue, likely will disconnect immediately after
10181022
}
10191023

10201024
return 0; // return as we may have a task waiting for the MTU before releasing it.
10211025
}
10221026
} else {
1027+
pClient->m_connStatus = DISCONNECTED;
10231028
pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE;
10241029

10251030
if (pClient->m_config.asyncConnect) {
@@ -1258,7 +1263,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
12581263
* @return True if we are connected and false if we are not connected.
12591264
*/
12601265
bool NimBLEClient::isConnected() const {
1261-
return m_connHandle != BLE_HS_CONN_HANDLE_NONE;
1266+
return m_connStatus == CONNECTED;
12621267
} // isConnected
12631268

12641269
/**

src/NimBLEClient.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ class NimBLEClient {
113113
void setConfig(Config config);
114114

115115
private:
116+
enum ConnStatus : uint8_t { CONNECTED, DISCONNECTED, CONNECTING, DISCONNECTING };
117+
116118
NimBLEClient(const NimBLEAddress& peerAddress);
117119
~NimBLEClient();
118120
NimBLEClient(const NimBLEClient&) = delete;
@@ -136,6 +138,7 @@ class NimBLEClient {
136138
uint8_t m_terminateFailCount;
137139
mutable uint8_t m_asyncSecureAttempt;
138140
Config m_config;
141+
ConnStatus m_connStatus;
139142

140143
# if MYNEWT_VAL(BLE_EXT_ADV)
141144
uint8_t m_phyMask;

src/NimBLEDevice.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -359,12 +359,12 @@ bool NimBLEDevice::deleteClient(NimBLEClient* pClient) {
359359

360360
for (auto& clt : m_pClients) {
361361
if (clt == pClient) {
362-
if (clt->isConnected()) {
362+
if (clt->m_connStatus == NimBLEClient::CONNECTED || clt->m_connStatus == NimBLEClient::DISCONNECTING) {
363363
clt->m_config.deleteOnDisconnect = true;
364364
if (!clt->disconnect()) {
365365
break;
366366
}
367-
} else if (pClient->m_pTaskData != nullptr) {
367+
} else if (pClient->m_connStatus == NimBLEClient::CONNECTING) {
368368
clt->m_config.deleteOnConnectFail = true;
369369
if (!clt->cancelConnect()) {
370370
break;
@@ -432,7 +432,7 @@ NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress& addr) {
432432
*/
433433
NimBLEClient* NimBLEDevice::getDisconnectedClient() {
434434
for (const auto clt : m_pClients) {
435-
if (clt != nullptr && !clt->isConnected()) {
435+
if (clt != nullptr && clt->m_connStatus == NimBLEClient::DISCONNECTED) {
436436
return clt;
437437
}
438438
}
@@ -682,7 +682,7 @@ bool NimBLEDevice::isBonded(const NimBLEAddress& address) {
682682
* @returns NimBLEAddress of the found bonded peer or null address if not found.
683683
*/
684684
NimBLEAddress NimBLEDevice::getBondedAddress(int index) {
685-
# if MYNEWT_VAL(BLE_STORE_MAX_BONDS)
685+
# if MYNEWT_VAL(BLE_STORE_MAX_BONDS)
686686
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
687687
int num_peers, rc;
688688
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
@@ -691,10 +691,10 @@ NimBLEAddress NimBLEDevice::getBondedAddress(int index) {
691691
}
692692

693693
return NimBLEAddress(peer_id_addrs[index]);
694-
# else
694+
# else
695695
(void)index; // unused
696696
return NimBLEAddress{};
697-
# endif
697+
# endif
698698
}
699699
# endif
700700

@@ -1275,17 +1275,17 @@ bool NimBLEDevice::startSecurity(uint16_t connHandle, int* rcPtr) {
12751275
* @return true if the passkey was injected successfully.
12761276
*/
12771277
bool NimBLEDevice::injectPassKey(const NimBLEConnInfo& peerInfo, uint32_t passkey) {
1278-
#if MYNEWT_VAL(BLE_SM_LEGACY)
1278+
# if MYNEWT_VAL(BLE_SM_LEGACY)
12791279
ble_sm_io pkey{.action = BLE_SM_IOACT_INPUT, .passkey = passkey};
12801280
int rc = ble_sm_inject_io(peerInfo.getConnHandle(), &pkey);
12811281
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_INPUT; ble_sm_inject_io result: %d", rc);
12821282
return rc == 0;
1283-
#else
1283+
# else
12841284
(void)peerInfo;
12851285
(void)passkey;
12861286
NIMBLE_LOGE(LOG_TAG, "Passkey entry not supported with current security settings");
12871287
return false;
1288-
#endif
1288+
# endif
12891289
}
12901290

12911291
/**
@@ -1294,17 +1294,17 @@ bool NimBLEDevice::injectPassKey(const NimBLEConnInfo& peerInfo, uint32_t passke
12941294
* @param [in] accept Whether the user confirmed or declined the comparison.
12951295
*/
12961296
bool NimBLEDevice::injectConfirmPasskey(const NimBLEConnInfo& peerInfo, bool accept) {
1297-
#if MYNEWT_VAL(BLE_SM_SC)
1297+
# if MYNEWT_VAL(BLE_SM_SC)
12981298
ble_sm_io pkey{.action = BLE_SM_IOACT_NUMCMP, .numcmp_accept = accept};
12991299
int rc = ble_sm_inject_io(peerInfo.getConnHandle(), &pkey);
13001300
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_NUMCMP; ble_sm_inject_io result: %d", rc);
13011301
return rc == 0;
1302-
#else
1302+
# else
13031303
(void)peerInfo;
13041304
(void)accept;
13051305
NIMBLE_LOGE(LOG_TAG, "Numeric comparison not supported with current security settings");
13061306
return false;
1307-
#endif
1307+
# endif
13081308
}
13091309
# endif // MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
13101310

0 commit comments

Comments
 (0)