@@ -953,6 +953,20 @@ void DeviceCommissioner::CancelCommissioningInteractions()
953
953
mInvokeCancelFn ();
954
954
mInvokeCancelFn = nullptr ;
955
955
}
956
+ if (mOnDeviceConnectedCallback .IsRegistered ())
957
+ {
958
+ ChipLogDetail (Controller, " Cancelling CASE setup for step '%s'" , StageToString (mCommissioningStage ));
959
+ CancelCASECallbacks ();
960
+ }
961
+ }
962
+
963
+ void DeviceCommissioner::CancelCASECallbacks ()
964
+ {
965
+ mOnDeviceConnectedCallback .Cancel ();
966
+ mOnDeviceConnectionFailureCallback .Cancel ();
967
+ #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
968
+ mOnDeviceConnectionRetryCallback .Cancel ();
969
+ #endif
956
970
}
957
971
958
972
CHIP_ERROR DeviceCommissioner::UnpairDevice (NodeId remoteDeviceId)
@@ -1216,9 +1230,10 @@ void DeviceCommissioner::OnICDManagementRegisterClientResponse(
1216
1230
commissioner->CommissioningStageComplete (CHIP_NO_ERROR, report);
1217
1231
}
1218
1232
1219
- bool DeviceCommissioner::ExtendArmFailSafe (DeviceProxy * proxy, CommissioningStage step, uint16_t armFailSafeTimeout,
1220
- Optional<System::Clock::Timeout> commandTimeout, OnExtendFailsafeSuccess onSuccess,
1221
- OnExtendFailsafeFailure onFailure)
1233
+ bool DeviceCommissioner::ExtendArmFailSafeInternal (DeviceProxy * proxy, CommissioningStage step, uint16_t armFailSafeTimeout,
1234
+ Optional<System::Clock::Timeout> commandTimeout,
1235
+ OnExtendFailsafeSuccess onSuccess, OnExtendFailsafeFailure onFailure,
1236
+ bool fireAndForget)
1222
1237
{
1223
1238
using namespace System ;
1224
1239
using namespace System ::Clock;
@@ -1237,17 +1252,15 @@ bool DeviceCommissioner::ExtendArmFailSafe(DeviceProxy * proxy, CommissioningSta
1237
1252
request.expiryLengthSeconds = armFailSafeTimeout;
1238
1253
request.breadcrumb = breadcrumb;
1239
1254
ChipLogProgress (Controller, " Arming failsafe (%u seconds)" , request.expiryLengthSeconds );
1240
- CHIP_ERROR err = SendCommissioningCommand (proxy, request, onSuccess, onFailure, kRootEndpointId , commandTimeout);
1255
+ CHIP_ERROR err = SendCommissioningCommand (proxy, request, onSuccess, onFailure, kRootEndpointId , commandTimeout, fireAndForget );
1241
1256
if (err != CHIP_NO_ERROR)
1242
1257
{
1243
- onFailure (this , err);
1244
- }
1245
- else
1246
- {
1247
- // TODO: Handle the situation when our command ends up erroring out
1248
- // asynchronously?
1249
- proxy->SetFailSafeExpirationTimestamp (newFailSafeTimeout);
1258
+ onFailure ((!fireAndForget) ? this : nullptr , err);
1259
+ return true ; // we have called onFailure already
1250
1260
}
1261
+
1262
+ // Note: The stored timestamp may become invalid if we fail asynchronously
1263
+ proxy->SetFailSafeExpirationTimestamp (newFailSafeTimeout);
1251
1264
return true ;
1252
1265
}
1253
1266
@@ -1269,9 +1282,9 @@ void DeviceCommissioner::ExtendArmFailSafeForDeviceAttestation(const Credentials
1269
1282
// Per spec, anything we do with the fail-safe armed must not time out
1270
1283
// in less than kMinimumCommissioningStepTimeout.
1271
1284
waitForFailsafeExtension =
1272
- ExtendArmFailSafe (mDeviceBeingCommissioned , mCommissioningStage , expiryLengthSeconds.Value (),
1273
- MakeOptional (kMinimumCommissioningStepTimeout ), OnArmFailSafeExtendedForDeviceAttestation,
1274
- OnFailedToExtendedArmFailSafeDeviceAttestation);
1285
+ ExtendArmFailSafeInternal (mDeviceBeingCommissioned , mCommissioningStage , expiryLengthSeconds.Value (),
1286
+ MakeOptional (kMinimumCommissioningStepTimeout ), OnArmFailSafeExtendedForDeviceAttestation,
1287
+ OnFailedToExtendedArmFailSafeDeviceAttestation, /* fireAndForget = */ false );
1275
1288
}
1276
1289
else
1277
1290
{
@@ -1848,58 +1861,34 @@ void DeviceCommissioner::OnDeviceConnectedFn(void * context, Messaging::Exchange
1848
1861
{
1849
1862
// CASE session established.
1850
1863
DeviceCommissioner * commissioner = static_cast <DeviceCommissioner *>(context);
1851
- VerifyOrReturn (commissioner != nullptr , ChipLogProgress (Controller, " Device connected callback with null context. Ignoring" ));
1864
+ VerifyOrDie (commissioner->mCommissioningStage == CommissioningStage::kFindOperational );
1865
+ VerifyOrDie (commissioner->mDeviceBeingCommissioned ->GetDeviceId () == sessionHandle->GetPeer ().GetNodeId ());
1866
+ commissioner->CancelCASECallbacks (); // ensure all CASE callbacks are unregistered
1852
1867
1853
- if (commissioner->mCommissioningStage != CommissioningStage::kFindOperational )
1854
- {
1855
- // This call is definitely not us finding our commissionee device.
1856
- // This is presumably us trying to re-establish CASE on MRP failure.
1857
- return ;
1858
- }
1859
-
1860
- if (commissioner->mDeviceBeingCommissioned == nullptr ||
1861
- commissioner->mDeviceBeingCommissioned ->GetDeviceId () != sessionHandle->GetPeer ().GetNodeId ())
1862
- {
1863
- // Not the device we are trying to commission.
1864
- return ;
1865
- }
1866
-
1867
- if (commissioner->mCommissioningDelegate != nullptr )
1868
- {
1869
- CommissioningDelegate::CommissioningReport report;
1870
- report.Set <OperationalNodeFoundData>(OperationalNodeFoundData (OperationalDeviceProxy (&exchangeMgr, sessionHandle)));
1871
- commissioner->CommissioningStageComplete (CHIP_NO_ERROR, report);
1872
- }
1868
+ CommissioningDelegate::CommissioningReport report;
1869
+ report.Set <OperationalNodeFoundData>(OperationalNodeFoundData (OperationalDeviceProxy (&exchangeMgr, sessionHandle)));
1870
+ commissioner->CommissioningStageComplete (CHIP_NO_ERROR, report);
1873
1871
}
1874
1872
1875
1873
void DeviceCommissioner::OnDeviceConnectionFailureFn (void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
1876
1874
{
1877
1875
// CASE session establishment failed.
1878
1876
DeviceCommissioner * commissioner = static_cast <DeviceCommissioner *>(context);
1877
+ VerifyOrDie (commissioner->mCommissioningStage == CommissioningStage::kFindOperational );
1878
+ VerifyOrDie (commissioner->mDeviceBeingCommissioned ->GetDeviceId () == peerId.GetNodeId ());
1879
+ commissioner->CancelCASECallbacks (); // ensure all CASE callbacks are unregistered
1879
1880
1880
- ChipLogProgress (Controller, " Device connection failed. Error %s" , ErrorStr (error));
1881
- VerifyOrReturn (commissioner != nullptr ,
1882
- ChipLogProgress (Controller, " Device connection failure callback with null context. Ignoring" ));
1883
-
1884
- // Ensure that commissioning stage advancement is done based on seeing an error.
1885
- if (error == CHIP_NO_ERROR)
1881
+ if (error != CHIP_NO_ERROR)
1886
1882
{
1887
- ChipLogError (Controller, " Device connection failed without a valid error code. Making one up." );
1888
- error = CHIP_ERROR_INTERNAL;
1883
+ ChipLogProgress (Controller, " Device connection failed. Error %" CHIP_ERROR_FORMAT, error.Format ());
1889
1884
}
1890
-
1891
- if (commissioner->mDeviceBeingCommissioned == nullptr ||
1892
- commissioner->mDeviceBeingCommissioned ->GetDeviceId () != peerId.GetNodeId ())
1893
- {
1894
- // Not the device we are trying to commission.
1895
- return ;
1896
- }
1897
-
1898
- if (commissioner->mCommissioningStage == CommissioningStage::kFindOperational &&
1899
- commissioner->mCommissioningDelegate != nullptr )
1885
+ else
1900
1886
{
1901
- commissioner->CommissioningStageComplete (error);
1887
+ // Ensure that commissioning stage advancement is done based on seeing an error.
1888
+ ChipLogError (Controller, " Device connection failed without a valid error code." );
1889
+ error = CHIP_ERROR_INTERNAL;
1902
1890
}
1891
+ commissioner->CommissioningStageComplete (error);
1903
1892
}
1904
1893
1905
1894
#if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
@@ -1926,6 +1915,8 @@ void DeviceCommissioner::OnDeviceConnectionRetryFn(void * context, const ScopedN
1926
1915
ChipLogValueScopedNodeId (peerId), error.Format (), retryTimeout.count ());
1927
1916
1928
1917
auto self = static_cast <DeviceCommissioner *>(context);
1918
+ VerifyOrDie (self->mCommissioningStage == CommissioningStage::kFindOperational );
1919
+ VerifyOrDie (self->mDeviceBeingCommissioned ->GetDeviceId () == peerId.GetNodeId ());
1929
1920
1930
1921
// We need to do the fail-safe arming over the PASE session.
1931
1922
auto * commissioneeDevice = self->FindCommissioneeDevice (peerId.GetNodeId ());
@@ -1950,11 +1941,11 @@ void DeviceCommissioner::OnDeviceConnectionRetryFn(void * context, const ScopedN
1950
1941
{
1951
1942
failsafeTimeout = static_cast <uint16_t >(retryTimeout.count () + kDefaultFailsafeTimeout );
1952
1943
}
1953
- // A false return from ExtendArmFailSafe is fine; we don't want to make the
1954
- // fail-safe shorter here.
1955
- self->ExtendArmFailSafe (commissioneeDevice, CommissioningStage::kFindOperational , failsafeTimeout,
1956
- MakeOptional (kMinimumCommissioningStepTimeout ), OnExtendFailsafeForCASERetrySuccess,
1957
- OnExtendFailsafeForCASERetryFailure);
1944
+
1945
+ // A false return is fine; we don't want to make the fail-safe shorter here.
1946
+ self->ExtendArmFailSafeInternal (commissioneeDevice, CommissioningStage::kFindOperational , failsafeTimeout,
1947
+ MakeOptional (kMinimumCommissioningStepTimeout ), OnExtendFailsafeForCASERetrySuccess,
1948
+ OnExtendFailsafeForCASERetryFailure, /* fireAndForget = */ true );
1958
1949
}
1959
1950
#endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
1960
1951
@@ -2552,19 +2543,22 @@ CHIP_ERROR
2552
2543
DeviceCommissioner::SendCommissioningCommand (DeviceProxy * device, const RequestObjectT & request,
2553
2544
CommandResponseSuccessCallback<typename RequestObjectT::ResponseType> successCb,
2554
2545
CommandResponseFailureCallback failureCb, EndpointId endpoint,
2555
- Optional<System::Clock::Timeout> timeout)
2546
+ Optional<System::Clock::Timeout> timeout, bool fireAndForget )
2556
2547
2557
2548
{
2558
- VerifyOrDie (!mInvokeCancelFn ); // we don't make parallel calls
2549
+ // Default behavior is to make sequential, cancellable calls tracked via mInvokeCancelFn.
2550
+ // Fire-and-forget calls are not cancellable and don't receive `this` as context in callbacks.
2551
+ VerifyOrDie (fireAndForget || !mInvokeCancelFn ); // we don't make parallel (cancellable) calls
2559
2552
2560
- auto onSuccessCb = [context = this , successCb](const app::ConcreteCommandPath & aPath, const app::StatusIB & aStatus,
2561
- const typename RequestObjectT::ResponseType & responseData) {
2553
+ void * context = (!fireAndForget) ? this : nullptr ;
2554
+ auto onSuccessCb = [context, successCb](const app::ConcreteCommandPath & aPath, const app::StatusIB & aStatus,
2555
+ const typename RequestObjectT::ResponseType & responseData) {
2562
2556
successCb (context, responseData);
2563
2557
};
2564
- auto onFailureCb = [context = this , failureCb](CHIP_ERROR aError) { failureCb (context, aError); };
2558
+ auto onFailureCb = [context, failureCb](CHIP_ERROR aError) { failureCb (context, aError); };
2565
2559
2566
2560
return InvokeCommandRequest (device->GetExchangeManager (), device->GetSecureSession ().Value (), endpoint, request, onSuccessCb,
2567
- onFailureCb, NullOptional, timeout, &mInvokeCancelFn );
2561
+ onFailureCb, NullOptional, timeout, (!fireAndForget) ? &mInvokeCancelFn : nullptr );
2568
2562
}
2569
2563
2570
2564
void DeviceCommissioner::SendCommissioningReadRequest (DeviceProxy * proxy, Optional<System::Clock::Timeout> timeout,
@@ -2626,8 +2620,8 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio
2626
2620
// Make sure the fail-safe value we set here actually ends up being used
2627
2621
// no matter what.
2628
2622
proxy->SetFailSafeExpirationTimestamp (System::Clock::kZero );
2629
- VerifyOrDie (ExtendArmFailSafe (proxy, step, params.GetFailsafeTimerSeconds ().ValueOr (kDefaultFailsafeTimeout ), timeout ,
2630
- OnArmFailSafe, OnBasicFailure));
2623
+ VerifyOrDie (ExtendArmFailSafeInternal (proxy, step, params.GetFailsafeTimerSeconds ().ValueOr (kDefaultFailsafeTimeout ),
2624
+ timeout, OnArmFailSafe, OnBasicFailure, /* fireAndForget = */ false ));
2631
2625
}
2632
2626
break ;
2633
2627
case CommissioningStage::kReadCommissioningInfo : {
@@ -3270,12 +3264,10 @@ void DeviceCommissioner::ExtendFailsafeBeforeNetworkEnable(DeviceProxy * device,
3270
3264
failSafeTimeoutSecs = static_cast <uint16_t >(failSafeTimeoutSecs + sigma1TimeoutSecs);
3271
3265
}
3272
3266
3273
- // A false return from ExtendArmFailSafe is fine; we don't want to make the
3274
- // fail-safe shorter here.
3275
- if (!ExtendArmFailSafe (commissioneeDevice, step, failSafeTimeoutSecs, MakeOptional (kMinimumCommissioningStepTimeout ),
3276
- OnArmFailSafe, OnBasicFailure))
3267
+ if (!ExtendArmFailSafeInternal (commissioneeDevice, step, failSafeTimeoutSecs, MakeOptional (kMinimumCommissioningStepTimeout ),
3268
+ OnArmFailSafe, OnBasicFailure, /* fireAndForget = */ false ))
3277
3269
{
3278
- // Just move on to the next step .
3270
+ // A false return is fine; we don't want to make the fail-safe shorter here .
3279
3271
CommissioningStageComplete (CHIP_NO_ERROR, CommissioningDelegate::CommissioningReport ());
3280
3272
}
3281
3273
}
0 commit comments