Skip to content

Commit 6737aff

Browse files
committed
Refactor NimBLEClient::connect and NimBLEClient::secureConnection.
This change ensures that only the function that sets `m_pTaskData` clears it, potentially preventing a segmentation fault. * Client will no longer disconnect if task timeout occurs when waiting for MTU exchange response.
1 parent 9a41293 commit 6737aff

File tree

2 files changed

+41
-37
lines changed

2 files changed

+41
-37
lines changed

src/NimBLEClient.cpp

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,6 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
204204
int rc = 0;
205205
m_asyncConnect = asyncConnect;
206206
m_exchangeMTU = exchangeMTU;
207-
NimBLETaskData taskData(this);
208-
if (!asyncConnect) {
209-
m_pTaskData = &taskData;
210-
}
211207

212208
// Set the connection in progress flag to prevent a scan from starting while connecting.
213209
NimBLEDevice::setConnectionInProgress(true);
@@ -263,10 +259,8 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
263259

264260
} while (rc == BLE_HS_EBUSY);
265261

266-
m_lastErr = rc;
267262
if (rc != 0) {
268-
m_lastErr = rc;
269-
m_pTaskData = nullptr;
263+
m_lastErr = rc;
270264
NimBLEDevice::setConnectionInProgress(false);
271265
return false;
272266
}
@@ -275,29 +269,31 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
275269
return true;
276270
}
277271

272+
NimBLETaskData taskData(this);
273+
m_pTaskData = &taskData;
274+
278275
// Wait for the connect timeout time +1 second for the connection to complete
279-
if (!NimBLEUtils::taskWait(*m_pTaskData, m_connectTimeout + 1000)) {
280-
m_pTaskData = nullptr;
281-
// If a connection was made but no response from MTU exchange; disconnect
276+
if (!NimBLEUtils::taskWait(taskData, m_connectTimeout + 1000)) {
277+
// If a connection was made but no response from MTU exchange proceed anyway
282278
if (isConnected()) {
283-
NIMBLE_LOGE(LOG_TAG, "Connect timeout - no response");
284-
disconnect();
279+
taskData.m_flags = 0;
285280
} else {
286-
// workaround; if the controller doesn't cancel the connection
287-
// at the timeout, cancel it here.
281+
// workaround; if the controller doesn't cancel the connection at the timeout, cancel it here.
288282
NIMBLE_LOGE(LOG_TAG, "Connect timeout - cancelling");
289283
ble_gap_conn_cancel();
284+
taskData.m_flags = BLE_HS_ETIMEOUT;
290285
}
286+
}
291287

292-
return false;
293-
294-
} else if (taskData.m_flags != 0) {
295-
m_lastErr = taskData.m_flags;
296-
NIMBLE_LOGE(LOG_TAG, "Connection failed; status=%d %s", m_lastErr, NimBLEUtils::returnCodeToString(m_lastErr));
288+
m_pTaskData = nullptr;
289+
rc = taskData.m_flags;
290+
if (rc != 0) {
291+
NIMBLE_LOGE(LOG_TAG, "Connection failed; status=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
297292
// If the failure was not a result of a disconnection, make sure we disconnect now to avoid dangling connections
298293
if (isConnected()) {
299294
disconnect();
300295
}
296+
m_lastErr = rc;
301297
return false;
302298
} else {
303299
NIMBLE_LOGI(LOG_TAG, "Connection established");
@@ -319,29 +315,27 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
319315
*/
320316
bool NimBLEClient::secureConnection() const {
321317
NIMBLE_LOGD(LOG_TAG, ">> secureConnection()");
322-
NimBLETaskData taskData(const_cast<NimBLEClient*>(this));
323-
int retryCount = 1;
324318

319+
NimBLETaskData taskData(const_cast<NimBLEClient*>(this), BLE_HS_ENOTCONN);
320+
m_pTaskData = &taskData;
321+
int retryCount = 1;
325322
do {
326-
m_pTaskData = &taskData;
327-
328-
if (!NimBLEDevice::startSecurity(m_connHandle)) {
329-
m_lastErr = BLE_HS_ENOTCONN;
330-
m_pTaskData = nullptr;
331-
return false;
323+
if (NimBLEDevice::startSecurity(m_connHandle)) {
324+
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
332325
}
333-
334-
NimBLEUtils::taskWait(*m_pTaskData, BLE_NPL_TIME_FOREVER);
335326
} while (taskData.m_flags == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--);
336327

337-
if (taskData.m_flags != 0) {
338-
m_lastErr = taskData.m_flags;
339-
NIMBLE_LOGE(LOG_TAG, "secureConnection: failed rc=%d", taskData.m_flags);
340-
return false;
328+
m_pTaskData = nullptr;
329+
330+
if (taskData.m_flags == 0) {
331+
NIMBLE_LOGD(LOG_TAG, "<< secureConnection: success");
332+
return true;
341333
}
342334

343-
NIMBLE_LOGD(LOG_TAG, "<< secureConnection: success");
344-
return true;
335+
m_lastErr = taskData.m_flags;
336+
NIMBLE_LOGE(LOG_TAG, "secureConnection: failed rc=%d", taskData.m_flags);
337+
return false;
338+
345339
} // secureConnection
346340

347341
/**
@@ -988,7 +982,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
988982
pClient->m_connEstablished = rc == 0;
989983
pClient->m_pClientCallbacks->onConnect(pClient);
990984
} else if (!pClient->m_exchangeMTU) {
991-
break; // not wating for MTU exchange so release the task now.
985+
break; // not waiting for MTU exchange so release the task now.
992986
}
993987

994988
return 0;
@@ -1177,7 +1171,6 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
11771171

11781172
if (pClient->m_pTaskData != nullptr) {
11791173
NimBLEUtils::taskRelease(*pClient->m_pTaskData, rc);
1180-
pClient->m_pTaskData = nullptr;
11811174
}
11821175

11831176
return 0;

src/nimconfig.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,13 @@
148148
*/
149149
// #define CONFIG_NIMBLE_STACK_USE_MEM_POOLS 1
150150

151+
/**
152+
* @brief Un-comment to change the bit used to block tasks during BLE operations
153+
* that call NimBLEUtils::taskWait. This should be different than any other
154+
* task notification flag used in the system.
155+
*/
156+
// #define CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT 31
157+
151158
/**********************************
152159
End Arduino user-config
153160
**********************************/
@@ -350,6 +357,10 @@
350357
#define CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED 0
351358
#endif
352359

360+
#ifndef CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT
361+
#define CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT 31
362+
#endif
363+
353364
#if CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED && !defined NDEBUG
354365
void nimble_cpp_assert(const char *file, unsigned line) __attribute((weak, noreturn));
355366
# define NIMBLE_ATT_VAL_FILE (__builtin_strrchr(__FILE__, '/') ? \

0 commit comments

Comments
 (0)