Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions src/NimBLEClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ NimBLEClient::NimBLEClient(const NimBLEAddress& peerAddress)
m_pClientCallbacks{&defaultCallbacks},
m_connHandle{BLE_HS_CONN_HANDLE_NONE},
m_terminateFailCount{0},
m_asyncSecureAttempt{0},
m_config{},
# if CONFIG_BT_NIMBLE_EXT_ADV
m_phyMask{BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK},
Expand Down Expand Up @@ -293,12 +294,26 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
/**
* @brief Initiate a secure connection (pair/bond) with the server.\n
* Called automatically when a characteristic or descriptor requires encryption or authentication to access it.
* @param [in] async If true, the connection will be secured asynchronously and this function will return immediately.\n
* If false, this function will block until the connection is secured or the client disconnects.
* @return True on success.
* @details This is a blocking function and should not be used in a callback.
* @details If async=false, this function will block and should not be used in a callback.
*/
bool NimBLEClient::secureConnection() const {
bool NimBLEClient::secureConnection(bool async) const {
NIMBLE_LOGD(LOG_TAG, ">> secureConnection()");

int rc = 0;
if (async && !NimBLEDevice::startSecurity(m_connHandle, &rc)) {
m_lastErr = rc;
m_asyncSecureAttempt = 0;
return false;
}

if (async) {
m_asyncSecureAttempt++;
return true;
}

NimBLETaskData taskData(const_cast<NimBLEClient*>(this), BLE_HS_ENOTCONN);
m_pTaskData = &taskData;
int retryCount = 1;
Expand Down Expand Up @@ -988,6 +1003,8 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
NIMBLE_LOGD(LOG_TAG, "disconnect; reason=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));

pClient->m_terminateFailCount = 0;
pClient->m_asyncSecureAttempt = 0;

// Don't call the disconnect callback if we are waiting for a connection to complete and it fails
if (rc != (BLE_HS_ERR_HCI_BASE + BLE_ERR_CONN_ESTABLISHMENT) || pClient->m_config.asyncConnect) {
pClient->m_pClientCallbacks->onDisconnect(pClient, rc);
Expand Down Expand Up @@ -1150,7 +1167,12 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
if (event->enc_change.status == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING)) {
// Key is missing, try deleting.
ble_store_util_delete_peer(&peerInfo.m_desc.peer_id_addr);
// Attempt a retry if async secure failed.
if (pClient->m_asyncSecureAttempt == 1) {
pClient->secureConnection(true);
}
} else {
pClient->m_asyncSecureAttempt = 0;
pClient->m_pClientCallbacks->onAuthenticationComplete(peerInfo);
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/NimBLEClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class NimBLEClient {
bool setConnection(uint16_t connHandle);
uint16_t getMTU() const;
bool exchangeMTU();
bool secureConnection() const;
bool secureConnection(bool async = false) const;
void setConnectTimeout(uint32_t timeout);
bool setDataLen(uint16_t txOctets);
bool discoverAttributes();
Expand Down Expand Up @@ -131,6 +131,7 @@ class NimBLEClient {
NimBLEClientCallbacks* m_pClientCallbacks;
uint16_t m_connHandle;
uint8_t m_terminateFailCount;
mutable uint8_t m_asyncSecureAttempt;
Config m_config;

# if CONFIG_BT_NIMBLE_EXT_ADV
Expand Down
9 changes: 6 additions & 3 deletions src/NimBLEDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1136,14 +1136,17 @@ uint32_t NimBLEDevice::getSecurityPasskey() {
/**
* @brief Start the connection securing and authorization for this connection.
* @param connHandle The connection handle of the peer device.
* @returns NimBLE stack return code, 0 = success.
* @param rcPtr Optional pointer to pass the return code to the caller.
* @returns True if successfully started, success = 0 or BLE_HS_EALREADY.
*/
bool NimBLEDevice::startSecurity(uint16_t connHandle) {
bool NimBLEDevice::startSecurity(uint16_t connHandle, int* rcPtr) {
int rc = ble_gap_security_initiate(connHandle);
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gap_security_initiate: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
}

if (rcPtr) {
*rcPtr = rc;
}
return rc == 0 || rc == BLE_HS_EALREADY;
} // startSecurity

Expand Down
2 changes: 1 addition & 1 deletion src/NimBLEDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class NimBLEDevice {
static void setSecurityRespKey(uint8_t respKey);
static void setSecurityPasskey(uint32_t passKey);
static uint32_t getSecurityPasskey();
static bool startSecurity(uint16_t connHandle);
static bool startSecurity(uint16_t connHandle, int* rcPtr = nullptr);
static bool setMTU(uint16_t mtu);
static uint16_t getMTU();
static void onReset(int reason);
Expand Down
Loading