Skip to content

Commit 622ca76

Browse files
Get the commissioner reusable more quickly after StopPairing() (project-chip#32473)
* Get the commissioner reusable more quickly after StopPairing() Don't need to keep state and the CommissioneeDeviceProxy around; instead hold on to just the Session and evict it when the disarm request succeeds or fails. * Tweaks from review
1 parent 5aa5555 commit 622ca76

4 files changed

+77
-26
lines changed

src/controller/CHIPDeviceController.cpp

+61-24
Original file line numberDiff line numberDiff line change
@@ -1658,13 +1658,30 @@ void DeviceCommissioner::OnBasicFailure(void * context, CHIP_ERROR error)
16581658
commissioner->CommissioningStageComplete(error);
16591659
}
16601660

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+
16611677
void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId, const CompletionStatus & completionStatus)
16621678
{
1679+
// At this point, proxy == mDeviceBeingCommissioned, nodeId == mDeviceBeingCommissioned->GetDeviceId()
1680+
16631681
mCommissioningCompletionStatus = completionStatus;
16641682

16651683
if (completionStatus.err == CHIP_NO_ERROR)
16661684
{
1667-
16681685
CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice(nodeId);
16691686
if (commissionee != nullptr)
16701687
{
@@ -1674,13 +1691,40 @@ void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId
16741691
CommissioningStageComplete(CHIP_NO_ERROR);
16751692
SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus);
16761693
}
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)
16791724
{
16801725
// If we were already doing network setup, we need to retain the pase session and start again from network setup stage.
16811726
// 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).
16841728
CommissioningStageComplete(CHIP_NO_ERROR);
16851729
SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus);
16861730
}
@@ -1689,21 +1733,14 @@ void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId
16891733
// If we've failed somewhere in the early stages (or we don't have a failedStage specified), we need to start from the
16901734
// beginning. However, because some of the commands can only be sent once per arm-failsafe, we also need to force a reset on
16911735
// 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);
17001739
if (err != CHIP_NO_ERROR)
17011740
{
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.
17041742
ChipLogError(Controller, "Failed to send command to disarm fail-safe: %" CHIP_ERROR_FORMAT, err.Format());
1705-
DisarmDone();
1706-
return;
1743+
CleanupDoneAfterError();
17071744
}
17081745
}
17091746
}
@@ -1713,17 +1750,17 @@ void DeviceCommissioner::OnDisarmFailsafe(void * context,
17131750
{
17141751
ChipLogProgress(Controller, "Failsafe disarmed");
17151752
DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1716-
commissioner->DisarmDone();
1753+
commissioner->CleanupDoneAfterError();
17171754
}
17181755

17191756
void DeviceCommissioner::OnDisarmFailsafeFailure(void * context, CHIP_ERROR error)
17201757
{
17211758
ChipLogProgress(Controller, "Ignoring failure to disarm failsafe: %" CHIP_ERROR_FORMAT, error.Format());
17221759
DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1723-
commissioner->DisarmDone();
1760+
commissioner->CleanupDoneAfterError();
17241761
}
17251762

1726-
void DeviceCommissioner::DisarmDone()
1763+
void DeviceCommissioner::CleanupDoneAfterError()
17271764
{
17281765
// If someone nulled out our mDeviceBeingCommissioned, there's nothing else
17291766
// to do here.
@@ -1735,13 +1772,15 @@ void DeviceCommissioner::DisarmDone()
17351772

17361773
// Signal completion - this will reset mDeviceBeingCommissioned.
17371774
CommissioningStageComplete(CHIP_NO_ERROR);
1738-
SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus);
17391775

17401776
// If we've disarmed the failsafe, it's because we're starting again, so kill the pase connection.
17411777
if (commissionee != nullptr)
17421778
{
17431779
ReleaseCommissioneeDevice(commissionee);
17441780
}
1781+
1782+
// Invoke callbacks last, after we have cleared up all state.
1783+
SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus);
17451784
}
17461785

17471786
void DeviceCommissioner::SendCommissioningCompleteCallbacks(NodeId nodeId, const CompletionStatus & completionStatus)
@@ -2572,13 +2611,11 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio
25722611
params.GetCompletionStatus().err.AsString());
25732612
}
25742613

2575-
// For now, we ignore errors coming in from the device since not all commissioning clusters are implemented on the device
2576-
// side.
25772614
mCommissioningStage = step;
25782615
mCommissioningDelegate = delegate;
25792616
mDeviceBeingCommissioned = proxy;
2580-
// TODO: Extend timeouts to the DAC and Opcert requests.
25812617

2618+
// TODO: Extend timeouts to the DAC and Opcert requests.
25822619
// TODO(cecille): We probably want something better than this for breadcrumbs.
25832620
uint64_t breadcrumb = static_cast<uint64_t>(step);
25842621

src/controller/CHIPDeviceController.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController,
908908
static void OnDisarmFailsafe(void * context,
909909
const app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data);
910910
static void OnDisarmFailsafeFailure(void * context, CHIP_ERROR error);
911-
void DisarmDone();
911+
void CleanupDoneAfterError();
912912
static void OnArmFailSafeExtendedForDeviceAttestation(
913913
void * context, const chip::app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data);
914914
static void OnFailedToExtendedArmFailSafeDeviceAttestation(void * context, CHIP_ERROR error);
@@ -961,7 +961,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController,
961961
CHIP_ERROR SendCommissioningCommand(DeviceProxy * device, const RequestObjectT & request,
962962
CommandResponseSuccessCallback<typename RequestObjectT::ResponseType> successCb,
963963
CommandResponseFailureCallback failureCb, EndpointId endpoint,
964-
Optional<System::Clock::Timeout> timeout);
964+
Optional<System::Clock::Timeout> timeout = NullOptional);
965965
void SendCommissioningReadRequest(DeviceProxy * proxy, Optional<System::Clock::Timeout> timeout,
966966
app::AttributePathParams * readPaths, size_t readPathsSize);
967967
void CancelCommissioningInteractions();

src/controller/CommissioneeDeviceProxy.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ void CommissioneeDeviceProxy::CloseSession()
6666
mPairing.Clear();
6767
}
6868

69+
chip::Optional<SessionHandle> CommissioneeDeviceProxy::DetachSecureSession()
70+
{
71+
auto session = mSecureSession.Get();
72+
mSecureSession.Release();
73+
mState = ConnectionState::NotConnected;
74+
mPairing.Clear();
75+
return session;
76+
}
77+
6978
CHIP_ERROR CommissioneeDeviceProxy::UpdateDeviceData(const Transport::PeerAddress & addr,
7079
const ReliableMessageProtocolConfig & config)
7180
{

src/controller/CommissioneeDeviceProxy.h

+5
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ class CommissioneeDeviceProxy : public DeviceProxy, public SessionDelegate
105105
*/
106106
void CloseSession();
107107

108+
/**
109+
* Detaches the underlying session (if any) from this proxy and returns it.
110+
*/
111+
chip::Optional<SessionHandle> DetachSecureSession();
112+
108113
void Disconnect() override { CloseSession(); }
109114

110115
/**

0 commit comments

Comments
 (0)