@@ -1658,13 +1658,30 @@ void DeviceCommissioner::OnBasicFailure(void * context, CHIP_ERROR error)
1658
1658
commissioner->CommissioningStageComplete (error);
1659
1659
}
1660
1660
1661
+ static GeneralCommissioning::Commands::ArmFailSafe::Type DisarmFailsafeRequest ()
1662
+ {
1663
+ GeneralCommissioning::Commands::ArmFailSafe::Type request;
1664
+ request.expiryLengthSeconds = 0 ; // Expire immediately.
1665
+ request.breadcrumb = 0 ;
1666
+ return request;
1667
+ }
1668
+
1669
+ static void MarkForEviction (const Optional<SessionHandle> & session)
1670
+ {
1671
+ if (session.HasValue ())
1672
+ {
1673
+ session.Value ()->AsSecureSession ()->MarkForEviction ();
1674
+ }
1675
+ }
1676
+
1661
1677
void DeviceCommissioner::CleanupCommissioning (DeviceProxy * proxy, NodeId nodeId, const CompletionStatus & completionStatus)
1662
1678
{
1679
+ // At this point, proxy == mDeviceBeingCommissioned, nodeId == mDeviceBeingCommissioned->GetDeviceId()
1680
+
1663
1681
mCommissioningCompletionStatus = completionStatus;
1664
1682
1665
1683
if (completionStatus.err == CHIP_NO_ERROR)
1666
1684
{
1667
-
1668
1685
CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice (nodeId);
1669
1686
if (commissionee != nullptr )
1670
1687
{
@@ -1674,13 +1691,40 @@ void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId
1674
1691
CommissioningStageComplete (CHIP_NO_ERROR);
1675
1692
SendCommissioningCompleteCallbacks (nodeId, mCommissioningCompletionStatus );
1676
1693
}
1677
- else if (completionStatus.failedStage .HasValue () && completionStatus.failedStage .Value () >= kWiFiNetworkSetup &&
1678
- completionStatus.err != CHIP_ERROR_CANCELLED)
1694
+ else if (completionStatus.err == CHIP_ERROR_CANCELLED)
1695
+ {
1696
+ // If we're cleaning up because cancellation has been requested via StopPairing(), expire the failsafe
1697
+ // in the background and reset our state synchronously, so a new commissioning attempt can be started.
1698
+ CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice (nodeId);
1699
+ SessionHolder session ((commissionee == proxy) ? commissionee->DetachSecureSession ().Value ()
1700
+ : proxy->GetSecureSession ().Value ());
1701
+
1702
+ auto request = DisarmFailsafeRequest ();
1703
+ auto onSuccessCb = [session](const app::ConcreteCommandPath & aPath, const app::StatusIB & aStatus,
1704
+ const decltype (request)::ResponseType & responseData) {
1705
+ ChipLogProgress (Controller, " Failsafe disarmed" );
1706
+ MarkForEviction (session.Get ());
1707
+ };
1708
+ auto onFailureCb = [session](CHIP_ERROR aError) {
1709
+ ChipLogProgress (Controller, " Ignoring failure to disarm failsafe: %" CHIP_ERROR_FORMAT, aError.Format ());
1710
+ MarkForEviction (session.Get ());
1711
+ };
1712
+
1713
+ ChipLogProgress (Controller, " Disarming failsafe on device %p in background" , proxy);
1714
+ CHIP_ERROR err = InvokeCommandRequest (proxy->GetExchangeManager (), session.Get ().Value (), kRootEndpointId , request,
1715
+ onSuccessCb, onFailureCb);
1716
+ if (err != CHIP_NO_ERROR)
1717
+ {
1718
+ ChipLogError (Controller, " Failed to send command to disarm fail-safe: %" CHIP_ERROR_FORMAT, err.Format ());
1719
+ }
1720
+
1721
+ CleanupDoneAfterError ();
1722
+ }
1723
+ else if (completionStatus.failedStage .HasValue () && completionStatus.failedStage .Value () >= kWiFiNetworkSetup )
1679
1724
{
1680
1725
// If we were already doing network setup, we need to retain the pase session and start again from network setup stage.
1681
1726
// We do not need to reset the failsafe here because we want to keep everything on the device up to this point, so just
1682
- // send the completion callbacks (see "Commissioning Flows Error Handling" in the spec). This does not apply if
1683
- // we're cleaning up because cancellation has been requested via StopPairing().
1727
+ // send the completion callbacks (see "Commissioning Flows Error Handling" in the spec).
1684
1728
CommissioningStageComplete (CHIP_NO_ERROR);
1685
1729
SendCommissioningCompleteCallbacks (nodeId, mCommissioningCompletionStatus );
1686
1730
}
@@ -1689,21 +1733,14 @@ void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId
1689
1733
// If we've failed somewhere in the early stages (or we don't have a failedStage specified), we need to start from the
1690
1734
// beginning. However, because some of the commands can only be sent once per arm-failsafe, we also need to force a reset on
1691
1735
// the failsafe so we can start fresh on the next attempt.
1692
- GeneralCommissioning::Commands::ArmFailSafe::Type request;
1693
- request.expiryLengthSeconds = 0 ; // Expire immediately.
1694
- request.breadcrumb = 0 ;
1695
- ChipLogProgress (Controller, " Expiring failsafe on proxy %p" , proxy);
1696
- mDeviceBeingCommissioned = proxy;
1697
- // We actually want to do the same thing on success or failure because we're already in a failure state
1698
- CHIP_ERROR err = SendCommissioningCommand (proxy, request, OnDisarmFailsafe, OnDisarmFailsafeFailure, kRootEndpointId ,
1699
- /* timeout = */ NullOptional);
1736
+ ChipLogProgress (Controller, " Disarming failsafe on device %p" , proxy);
1737
+ auto request = DisarmFailsafeRequest ();
1738
+ CHIP_ERROR err = SendCommissioningCommand (proxy, request, OnDisarmFailsafe, OnDisarmFailsafeFailure, kRootEndpointId );
1700
1739
if (err != CHIP_NO_ERROR)
1701
1740
{
1702
- // We won't get any async callbacks here, so just pretend like the
1703
- // command errored out async.
1741
+ // We won't get any async callbacks here, so just pretend like the command errored out async.
1704
1742
ChipLogError (Controller, " Failed to send command to disarm fail-safe: %" CHIP_ERROR_FORMAT, err.Format ());
1705
- DisarmDone ();
1706
- return ;
1743
+ CleanupDoneAfterError ();
1707
1744
}
1708
1745
}
1709
1746
}
@@ -1713,17 +1750,17 @@ void DeviceCommissioner::OnDisarmFailsafe(void * context,
1713
1750
{
1714
1751
ChipLogProgress (Controller, " Failsafe disarmed" );
1715
1752
DeviceCommissioner * commissioner = static_cast <DeviceCommissioner *>(context);
1716
- commissioner->DisarmDone ();
1753
+ commissioner->CleanupDoneAfterError ();
1717
1754
}
1718
1755
1719
1756
void DeviceCommissioner::OnDisarmFailsafeFailure (void * context, CHIP_ERROR error)
1720
1757
{
1721
1758
ChipLogProgress (Controller, " Ignoring failure to disarm failsafe: %" CHIP_ERROR_FORMAT, error.Format ());
1722
1759
DeviceCommissioner * commissioner = static_cast <DeviceCommissioner *>(context);
1723
- commissioner->DisarmDone ();
1760
+ commissioner->CleanupDoneAfterError ();
1724
1761
}
1725
1762
1726
- void DeviceCommissioner::DisarmDone ()
1763
+ void DeviceCommissioner::CleanupDoneAfterError ()
1727
1764
{
1728
1765
// If someone nulled out our mDeviceBeingCommissioned, there's nothing else
1729
1766
// to do here.
@@ -1735,13 +1772,15 @@ void DeviceCommissioner::DisarmDone()
1735
1772
1736
1773
// Signal completion - this will reset mDeviceBeingCommissioned.
1737
1774
CommissioningStageComplete (CHIP_NO_ERROR);
1738
- SendCommissioningCompleteCallbacks (nodeId, mCommissioningCompletionStatus );
1739
1775
1740
1776
// If we've disarmed the failsafe, it's because we're starting again, so kill the pase connection.
1741
1777
if (commissionee != nullptr )
1742
1778
{
1743
1779
ReleaseCommissioneeDevice (commissionee);
1744
1780
}
1781
+
1782
+ // Invoke callbacks last, after we have cleared up all state.
1783
+ SendCommissioningCompleteCallbacks (nodeId, mCommissioningCompletionStatus );
1745
1784
}
1746
1785
1747
1786
void DeviceCommissioner::SendCommissioningCompleteCallbacks (NodeId nodeId, const CompletionStatus & completionStatus)
@@ -2572,13 +2611,11 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio
2572
2611
params.GetCompletionStatus ().err .AsString ());
2573
2612
}
2574
2613
2575
- // For now, we ignore errors coming in from the device since not all commissioning clusters are implemented on the device
2576
- // side.
2577
2614
mCommissioningStage = step;
2578
2615
mCommissioningDelegate = delegate;
2579
2616
mDeviceBeingCommissioned = proxy;
2580
- // TODO: Extend timeouts to the DAC and Opcert requests.
2581
2617
2618
+ // TODO: Extend timeouts to the DAC and Opcert requests.
2582
2619
// TODO(cecille): We probably want something better than this for breadcrumbs.
2583
2620
uint64_t breadcrumb = static_cast <uint64_t >(step);
2584
2621
0 commit comments