-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Enable CASE session establishment #7666
Enable CASE session establishment #7666
Conversation
- Match the generated cert against CSR and operational keypairconnectedhomeip/src/controller/CHIPDeviceController.cpp Lines 307 to 317 in 3b7cd86
This comment was generated by todo based on a
|
- Update SessionID allocator to use freed session IDsconnectedhomeip/src/protocols/secure_channel/SessionIDAllocator.cpp Lines 29 to 39 in 3b7cd86
This comment was generated by todo based on a
|
/rebase |
3521803
to
7a459ab
Compare
7a459ab
to
dca2797
Compare
|
||
for (uint32_t i = 0; i < kIterationCount && device->IsSessionSetupInProgress(); i++) | ||
{ | ||
nanosleep(&sleep_time, nullptr); |
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.
could we instead have some sort of notification from the device of 'session done'?
May not care much for test tools, however I imagine most other commisioners want to avoid sleeps.
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.
Added a TODO for this. This is big enough change to handle in a separate PR.
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.
There is missing synchronization here. We can show this with the following argument:
- Calling IsSessionSetupInProgress loads shared controller & protocol state
- The loop performs no stores that could change the state
- The loop synchronizes with no other thread that could change the state
Assuming those propositions, one of the following is true:
- Every iteration loads the same state (i.e., IsSessionSetupInProgress remains true)
- This code relies on a data race
And since data races are specified as undefined behavior in C++, all bets are off as to whether the resulting program does anything useful.
One correct implementation of waiting on a 2nd thread to do something is to synchronize access to the state with a mutex and use a condition variable for the "wait". Not to sleep; sleeping is not a useful primitive for waiting on a 2nd thread because it does not avoid the race that arises.
Fixing errors like this is not something that should be left as a TODO.
- Implement notification from device object when the secure session is available.connectedhomeip/examples/chip-tool/commands/clusters/ModelCommand.cpp Lines 76 to 85 in 95aba4d
This comment was generated by todo based on a
|
- Check if ID is already allocated in SessionIDAllocator::Reserve()connectedhomeip/src/protocols/secure_channel/SessionIDAllocator.cpp Lines 52 to 62 in 95aba4d
This comment was generated by todo based on a
|
/rebase |
95aba4d
to
74b9891
Compare
74b9891
to
9c5c6f3
Compare
91a81b7
to
5373ba5
Compare
Size increase report for "gn_qpg6100-example-build" from 59e4a16
Full report output
|
Size increase report for "esp32-example-build" from 59e4a16
Full report output
|
Size increase report for "nrfconnect-example-build" from 59e4a16
Full report output
|
@mspang do you have any further comments? |
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.
@mspang do you have any further comments?
I do but nothing major, they could be fixed in a followup.
{ | ||
ModelCommand * command = reinterpret_cast<ModelCommand *>(context); | ||
VerifyOrReturn(command != nullptr, | ||
ChipLogError(chipTool, "Device connected, but cannot send the command, as the context is null")); |
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.
Can this happen (how)?
If not suggest VerifyOrDie(command != nullptr)
or just leave it off since it's obvious anyway due to the call below.
|
||
CHIP_ERROR Device::EstablishConnectivity(Callback::Callback<OnDeviceConnected> * onConnection, | ||
Callback::Callback<OnDeviceConnectionFailure> * onFailure) | ||
{ |
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.
Can we:
VerifyOrDie(!onConnection->IsRegistered());
VerifyOrDie(!onFailure->IsRegistered());
and document that the callback must not be registered?
(taking it as a Cancelable accomplishes similar but currently trades away the type safety which doesn't seem like a good tradeoff)
{ | ||
ModelCommand * command = reinterpret_cast<ModelCommand *>(context); | ||
ChipLogError(chipTool, "Failed in connecting to the device %" PRIu64 ". Error %d", deviceId, error); | ||
VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "ModelCommand context is null")); |
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.
VerifyOrDie(command != nullptr) here too.
@@ -475,35 +492,118 @@ bool Device::GetAddress(Inet::IPAddress & addr, uint16_t & port) const | |||
return true; | |||
} | |||
|
|||
CHIP_ERROR Device::EstablishCASESession() | |||
void Device::OperationalCertProvisioned() |
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.
nit: Suggest OnOperationalCertProvisioned
as I think this reads a bit easier and we use that convention elsewhere.
* The function updates the state of device proxy object such that all subsequent messages | ||
* will use secure session established via CASE handshake. | ||
*/ | ||
CHIP_ERROR OperationalDiscoveryComplete(NodeId remoteDeviceId); |
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.
nit: Suggest OnOperationalDiscoveryComplete
void DeviceCommissioner::OnDeviceConnectedFn(void * context, Device * device) | ||
{ | ||
DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context); | ||
VerifyOrReturn(commissioner != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); |
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.
How can this happen? If it can't please use VerifyOrDie.
{ | ||
DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context); | ||
ChipLogProgress(Controller, "Device connection failed. Error %s", ErrorStr(error)); | ||
VerifyOrReturn(commissioner != nullptr, |
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.
How can this happen? If it can't please use VerifyOrDie.
/** | ||
* This function finds the device corresponding to deviceId, and establishes a secure connection with it. | ||
* Once the connection is successfully establishes (or if it's already connected), it calls `onConnectedDevice` | ||
* callback. If it fails to establish the connection, it calls `onError` callback. |
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.
.. These callbacks must not be already registered with a source (i.e., if they were used previously, they must be canceled).
Callback::Callback<OnDeviceConnectionFailure> * onFailure) | ||
{ | ||
CHIP_ERROR err = CHIP_NO_ERROR; | ||
Device * device = nullptr; |
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.
VerifyOrDie(!onConnection->IsRegistered());
VerifyOrDie(!onFailure->IsRegistered());
namespace chip { | ||
|
||
class SessionIDAllocator | ||
{ |
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.
Please document.
* Enable CASE session establishment * persist counter if device is connected * enable CASE sessions for chip-tool * address review comments * add tests for SessionIDAllocator * address review comments * address review comments * add ReserveUpTo * release resouces on cleanup, and reduce message timeout * release resources on cleanup and init. * Remove sleep from ModelCommand * some cleanup
Problem
We are currently using secure sessions established via PASE for non commissioning cluster messages. This needs to be changed to CASE sessions.
Change overview
Testing
Tested flow using Python controller, chip-tool, and iOS CHIP Tool applications.