Skip to content

Commit b8fd564

Browse files
authored
[Bugfix] NimBLEDevice::createServer can crash if stack not initialized.
* [Bugfix] NimBLEDevice::createServer can crash if stack not initialized. This removes the gatts/gap reset calls from NimBLEDevice::createServer so that it can be safely used before initializing the stack. This also deprecates NimBLEService::start the the services will now be added/created only when the server is started.
1 parent 66522ce commit b8fd564

13 files changed

Lines changed: 48 additions & 58 deletions

File tree

examples/Bluetooth_5/NimBLE_extended_server/NimBLE_extended_server.ino

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,6 @@ void setup() {
9898

9999
pCharacteristic->setValue("Hello World");
100100

101-
/** Start the service */
102-
pService->start();
103-
104101
/**
105102
* Create an extended advertisement with the instance ID 0 and set the PHY's.
106103
* Multiple instances can be added as long as the instance ID is incremented.

examples/Bluetooth_5/NimBLE_multi_advertiser/NimBLE_multi_advertiser.ino

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,6 @@ void setup() {
116116

117117
pCharacteristic->setValue("Hello World");
118118

119-
/** Start the service */
120-
pService->start();
121-
122119
/** Create our multi advertising instances */
123120

124121
/** extended scannable instance advertising on coded and 1m PHY's. */

examples/L2CAP/L2CAP_Server/L2CAP_Server.ino

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ void setup() {
7070
auto service = server->createService(SERVICE_UUID);
7171
auto characteristic = service->createCharacteristic(CHARACTERISTIC_UUID, NIMBLE_PROPERTY::READ);
7272
characteristic->setValue(L2CAP_CHANNEL);
73-
service->start();
7473

7574
auto advertising = BLEDevice::getAdvertising();
7675
advertising->addServiceUUID(SERVICE_UUID);

examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ void setup() {
2929
pService->createCharacteristic("1235",
3030
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN);
3131

32-
pService->start();
3332
pNonSecureCharacteristic->setValue("Hello Non Secure BLE");
3433
pSecureCharacteristic->setValue("Hello Secure BLE");
3534

examples/NimBLE_Server/NimBLE_Server.ino

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,6 @@ void setup(void) {
186186
pC01Ddsc->setValue("Send it back!");
187187
pC01Ddsc->setCallbacks(&dscCallbacks);
188188

189-
/** Start the services when finished creating all Characteristics and Descriptors */
190-
pDeadService->start();
191-
pBaadService->start();
192-
193189
/** Create an advertising instance and add the services to the advertised data */
194190
NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
195191
pAdvertising->setName("NimBLE-Server");

examples/NimBLE_Server_Whitelist/NimBLE_Server_Whitelist.ino

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ void setup() {
5555
pCharacteristic =
5656
pService->createCharacteristic(CHARACTERISTIC_UUID,
5757
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY);
58-
pService->start();
5958

6059
NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
6160
pAdvertising->addServiceUUID(SERVICE_UUID);

src/NimBLEAdvertising.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,9 @@ bool NimBLEAdvertising::start(uint32_t duration, const NimBLEAddress* dirAddr) {
197197

198198
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
199199
NimBLEServer* pServer = NimBLEDevice::getServer();
200-
if (pServer != nullptr) {
201-
pServer->start(); // make sure the GATT server is ready before advertising
200+
if (pServer != nullptr && !pServer->start()) { // make sure the GATT server is ready before advertising
201+
NIMBLE_LOGE(LOG_TAG, "Failed to start GATT server");
202+
return false;
202203
}
203204
# endif
204205

src/NimBLEDevice.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,6 @@ extern "C" int ble_vhci_disc_duplicate_mode_enable(int mode);
125125
NimBLEServer* NimBLEDevice::createServer() {
126126
if (NimBLEDevice::m_pServer == nullptr) {
127127
NimBLEDevice::m_pServer = new NimBLEServer();
128-
ble_gatts_reset();
129-
ble_svc_gap_init();
130-
ble_svc_gatt_init();
131128
}
132129

133130
return m_pServer;

src/NimBLEServer.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,18 @@ void NimBLEServer::gattRegisterCallback(ble_gatt_register_ctxt* ctxt, void* arg)
269269
* @details Required to be called after setup of all services and characteristics / descriptors
270270
* for the NimBLE host to register them.
271271
*/
272-
void NimBLEServer::start() {
272+
bool NimBLEServer::start() {
273273
if (m_svcChanged && !getConnectedCount()) {
274274
NIMBLE_LOGD(LOG_TAG, "Services have changed since last start, resetting GATT server");
275-
resetGATT();
275+
m_gattsStarted = false;
276276
}
277277

278278
if (m_gattsStarted) {
279-
return; // already started
279+
return true; // already started
280+
}
281+
282+
if (!resetGATT()) {
283+
return false;
280284
}
281285

282286
ble_hs_cfg.gatts_register_cb = NimBLEServer::gattRegisterCallback;
@@ -286,7 +290,7 @@ void NimBLEServer::start() {
286290
int rc = ble_gatts_start();
287291
if (rc != 0) {
288292
NIMBLE_LOGE(LOG_TAG, "ble_gatts_start; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
289-
return;
293+
return false;
290294
}
291295

292296
# if MYNEWT_VAL(NIMBLE_CPP_LOG_LEVEL) >= 4
@@ -313,6 +317,7 @@ void NimBLEServer::start() {
313317
}
314318

315319
m_gattsStarted = true;
320+
return true;
316321
} // start
317322

318323
/**
@@ -335,7 +340,7 @@ bool NimBLEServer::disconnect(uint16_t connHandle, uint8_t reason) const {
335340
* @brief Disconnect the specified client with optional reason.
336341
* @param [in] connInfo Connection of the client to disconnect.
337342
* @param [in] reason code for disconnecting.
338-
* @return NimBLE host return code.
343+
* @return True if successful.
339344
*/
340345
bool NimBLEServer::disconnect(const NimBLEConnInfo& connInfo, uint8_t reason) const {
341346
return disconnect(connInfo.getConnHandle(), reason);
@@ -505,7 +510,7 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
505510

506511
peerInfo.m_desc = event->disconnect.conn;
507512
pServer->m_pServerCallbacks->onDisconnect(pServer, peerInfo, event->disconnect.reason);
508-
# if !MYNEWT_VAL(BLE_EXT_ADV)
513+
# if !MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
509514
if (pServer->m_advertiseOnDisconnect) {
510515
pServer->startAdvertising();
511516
}
@@ -863,8 +868,13 @@ void NimBLEServer::addService(NimBLEService* service) {
863868

864869
/**
865870
* @brief Resets the GATT server, used when services are added/removed after initialization.
871+
* @return True if successful.
872+
* @details This will reset the GATT server and re-register all services, characteristics, and
873+
* descriptors that have not been removed. Services, characteristics, and descriptors that have been
874+
* removed but not deleted will be skipped and have their handles cleared, and those that have been
875+
* deleted will be removed from the server's service vector.
866876
*/
867-
void NimBLEServer::resetGATT() {
877+
bool NimBLEServer::resetGATT() {
868878
# if MYNEWT_VAL(BLE_ROLE_BROADCASTER)
869879
NimBLEDevice::stopAdvertising();
870880
# endif
@@ -873,8 +883,6 @@ void NimBLEServer::resetGATT() {
873883
ble_svc_gap_init();
874884
ble_svc_gatt_init();
875885

876-
m_gattsStarted = false;
877-
878886
for (auto svcIt = m_svcVec.begin(); svcIt != m_svcVec.end();) {
879887
auto* pSvc = *svcIt;
880888
if (pSvc->getRemoved() == NIMBLE_ATT_REMOVE_DELETE) {
@@ -908,12 +916,17 @@ void NimBLEServer::resetGATT() {
908916
}
909917

910918
if (pSvc->getRemoved() == 0) {
911-
pSvc->start();
919+
if (!pSvc->start_internal()) {
920+
NIMBLE_LOGE(LOG_TAG, "Failed to start service: %s", pSvc->getUUID().toString().c_str());
921+
return false;
922+
}
912923
}
913924

914925
pSvc->m_handle = 0;
915926
++svcIt;
916927
}
928+
929+
return true;
917930
} // resetGATT
918931

919932
/**

src/NimBLEServer.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class NimBLEClient;
6161
*/
6262
class NimBLEServer {
6363
public:
64-
void start();
64+
bool start();
6565
uint8_t getConnectedCount() const;
6666
bool disconnect(uint16_t connHandle, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM) const;
6767
bool disconnect(const NimBLEConnInfo& connInfo, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM) const;
@@ -123,12 +123,12 @@ class NimBLEServer {
123123
static int handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_gatt_access_ctxt* ctxt, void* arg);
124124
static void gattRegisterCallback(struct ble_gatt_register_ctxt* ctxt, void* arg);
125125
void serviceChanged();
126-
void resetGATT();
126+
bool resetGATT();
127127

128128
bool m_gattsStarted : 1;
129129
bool m_svcChanged : 1;
130130
bool m_deleteCallbacks : 1;
131-
# if !MYNEWT_VAL(BLE_EXT_ADV)
131+
# if !MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_BROADCASTER)
132132
bool m_advertiseOnDisconnect : 1;
133133
# endif
134134
NimBLEServerCallbacks* m_pServerCallbacks;

0 commit comments

Comments
 (0)