-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve API to facilitate full shutdown procedure #141
Conversation
The BLE API exposes a shutdown() function in BLE.h. This function is meant to be overwridden by platform-specific sub-classes to clear all GAP and GATT state. However, from the platform-specific implementation it is dificult to achieve this because the Gap, GattClient, GattServer and SecurityManager components of the API do not expose any functionality to shutdown. This commit introduces the following changes: * Add a static member pointer to Gap, GattClient, GattServer and SecurityManager that is used to keep track of the initialized objects. * Add a function member cleanup() to Gap, GattClient, GattServer and SecurityManager to allow easy reset of the instance's state. This function is meant to be overriden and called from the derived classes to fully clear the state of the BLE API and the platform-specific implementation. * Add a static member function shutdown() to Gap, GattClient, GattServer and SecurityManager. This function shall be called from the shutdown() overriding BLE::shutdown() for Gap, GattClient, GattServer and SecurityManager that will in-turn clear the state of each of the components. **NOTE:** Platform-specific implementations of this API must be modified to this changes into account.
Please note that there is a pending pull request for ble-nrf51822 module. |
The idea is simple, functions exposed are public and non virtual. Functions to overload are private (or protected and virtual). In our case, it will be something like this: public:
ble_error_t cleanup(void) {
ble_error_t err = doCleanup();
if (err) {
return err;
}
/* Clear Gap state */
state.advertising = 0;
state.connected = 0;
/* Clear scanning state */
scanningActive = false;
/* Clear advertising and scanning data */
_advPayload.clear();
_scanResponse.clear();
return BLE_ERROR_NONE;
}
private:
virtual ble_error_t doCleanup() = 0; You can read more about this pattern here: http://www.gotw.ca/publications/mill18.htm
ble_error_t BLE::shutdown(void)
{
if (!transport) {
error("bad handle to underlying transport");
}
ble_error_t err = gap().shutdown();
if (err) { return err; }
err = gattClient().shutdown();
if (err) { return err; }
// OTHER SHUTDOWN PROCEDURE
return transport->shutdown();
}
|
/* Clear advertising and scanning data */ | ||
_advPayload.clear(); | ||
_scanResponse.clear(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should the callback states also be reset? similar to what you've done for GattClient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I missed this ones. They should also be cleared.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe it would be interesting to call clearAdvertisingPayload
and clearScanResponse
, it seems that these functions does more things.
is this still needed: https://github.com/ARMmbed/ble/blob/master/source/BLE.cpp#L134? |
Now that I look at the pull request as a whole, I realize that I may have partly misguided Andres. Gap should not have private:
static Gap *gapInstance; The same for GattServer, GattClient, etc. A Gap object should be able to offer an API for The class
Within Does this make sense? I'm suggesting that we rename Please comment. |
@rgrover: https://github.com/ARMmbed/ble/blob/master/source/BLE.cpp#L134 is required depending on the actual implementation. For instance in the nRF51 I have the impression that is required because it clears the advertising data in the SoftDevice. |
it just call the function void clearAdvertisingPayload(void) {
gap().clearAdvertisingPayload();
} I think it belongs to Gap cleanup |
@andresag01 yes, I believe https://github.com/ARMmbed/ble/blob/master/source/BLE.cpp#L134 should be transferred to |
Modify the shutdown API to remove the static shutdown function in Gap, SecurityManager, GattClient and GattServer. Futhermore, remove the static references to Gap, SecurityManager, GattClient and GattServer objects inside their own classes. The cleanup method is renamed to `reset()` and made public. Finally, additional functionality is added to the reset implementation in Gap.
@rgrover @pan- : The clearAdvertisingPayload() call https://github.com/ARMmbed/ble/blob/master/source/BLE.cpp#L134 has been completely removed. The reason for this is that in the ble-nrf51822 port it results in a call to the softdevice. This is problematic because we would have already disabled the softdevice by then. The same effect can be achieved by the code I have placed Gap. For more information have a look here and here. |
Like we discuss yesterday, a big question remain: How to notify user code that a shutdown has been made ? This is really important to cleanup pending operations like read or write. For instance, I have added a function in Internally, a new callback object is dynamically allocated, registered into If there are no means to know when a shutdown occur, objects like this will never been released and memory will leak. |
@pan- can we create a generic abstraction to capture such temporary state? Can you register such temporary objects with GattClient such that GattClient::shutdown() [or nRFGattClient::shutdown()] will clean them up? In general, it will be the user's code which calls shutdown(); and so the application should be aware of when shutdown is triggered. shutdown is a multi-stage process. It won't be actualized until we call softdevice_shutdown(); but once we call softdevice_shutdown() then all system state is reset and we won't get any callbacks from the softdevice to indicate state teardown. Any state that needs to be torn down alongside shutdown should be handled in Gap::shutdown() etc. |
@andresag01 +1 for this PR. We'll wait on @pan- to approve. |
I'm happy for this to go ahead as it stands now. And then we can add |
Andres, please wait for @pan- to approve. |
Improve API to facilitate full shutdown procedure
published "ble-2.1.16". I had to do this because I had merged in the corresponding change to ble-nrf51822 without realizing that it needed this PR to build. |
The BLE API exposes a shutdown() function in BLE.h. This function is meant to
be overwridden by platform-specific sub-classes to clear all GAP and GATT
state. However, from the platform-specific implementation it is dificult to
achieve this because the Gap, GattClient, GattServer and SecurityManager
components of the API do not expose any functionality to shutdown.
This commit introduces the following changes:
SecurityManager that is used to keep track of the initialized objects.
SecurityManager to allow easy reset of the instance's state. This function
is meant to be overriden and called from the derived classes to fully clear the
state of the BLE API and the platform-specific implementation.
SecurityManager. This function shall be called from the shutdown()
overriding BLE::shutdown() for Gap, GattClient, GattServer and SecurityManager
that will in-turn clear the state of each of the components.
NOTE: Platform-specific implementations of this API must be modified to
this changes into account.
@rgrover @LiyouZhou @pan-