Line data Source code
1 : /*
2 : * Copyright (c) 2024 Project CHIP Authors
3 : * All rights reserved.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #include "RefreshKeySender.h"
19 : #include "CheckInDelegate.h"
20 : #include "controller/InvokeInteraction.h"
21 : #include <app-common/zap-generated/cluster-objects.h>
22 : #include <app/AppConfig.h>
23 : #include <app/CommandPathParams.h>
24 : #include <app/InteractionModelEngine.h>
25 : #include <app/OperationalSessionSetup.h>
26 : #include <memory>
27 :
28 : namespace chip {
29 : namespace app {
30 :
31 1 : RefreshKeySender::RefreshKeySender(CheckInDelegate * checkInDelegate, const ICDClientInfo & icdClientInfo,
32 : ICDClientStorage * icdClientStorage, InteractionModelEngine * engine,
33 1 : const RefreshKeyBuffer & refreshKeyBuffer) :
34 1 : mpCheckInDelegate(checkInDelegate),
35 1 : mICDClientInfo(icdClientInfo), mpICDClientStorage(icdClientStorage), mpImEngine(engine), mNewKey(refreshKeyBuffer),
36 1 : mOnConnectedCallback(HandleDeviceConnected, this), mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this)
37 1 : {}
38 :
39 1 : const ICDClientInfo & RefreshKeySender::GetICDClientInfo()
40 : {
41 1 : return mICDClientInfo;
42 : }
43 :
44 0 : CHIP_ERROR RefreshKeySender::RegisterClientWithNewKey(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle)
45 : {
46 0 : auto onSuccess = [&](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
47 0 : ChipLogProgress(ICD, "RegisterClient command succeeded");
48 : CHIP_ERROR error;
49 :
50 : // Update the ICDClientInfo with new key and start counter and store it to persistence
51 0 : mICDClientInfo.start_icd_counter = dataResponse.ICDCounter;
52 0 : mICDClientInfo.offset = 0;
53 0 : mpICDClientStorage->RemoveKey(mICDClientInfo);
54 0 : error = mpICDClientStorage->SetKey(mICDClientInfo, mNewKey.Span());
55 0 : if (error != CHIP_NO_ERROR)
56 : {
57 0 : ChipLogError(ICD, "Failed to set the new key after re-registration: %" CHIP_ERROR_FORMAT, error.Format());
58 0 : mpCheckInDelegate->OnKeyRefreshDone(this, error);
59 0 : return;
60 : }
61 :
62 0 : error = mpICDClientStorage->StoreEntry(mICDClientInfo);
63 0 : if (error != CHIP_NO_ERROR)
64 : {
65 0 : ChipLogError(ICD, "Failed to store the new key after re-registration: %" CHIP_ERROR_FORMAT, error.Format());
66 0 : mpCheckInDelegate->OnKeyRefreshDone(this, error);
67 0 : return;
68 : }
69 :
70 0 : mpCheckInDelegate->OnCheckInComplete(mICDClientInfo);
71 : #if CHIP_CONFIG_ENABLE_READ_CLIENT
72 0 : mpImEngine->OnActiveModeNotification(mICDClientInfo.peer_node);
73 : #endif // CHIP_CONFIG_ENABLE_READ_CLIENT
74 0 : mpCheckInDelegate->OnKeyRefreshDone(this, CHIP_NO_ERROR);
75 0 : };
76 :
77 0 : auto onFailure = [&](CHIP_ERROR error) {
78 0 : ChipLogError(ICD, "RegisterClient command failed: %" CHIP_ERROR_FORMAT, error.Format());
79 0 : mpCheckInDelegate->OnKeyRefreshDone(this, error);
80 0 : };
81 :
82 0 : EndpointId endpointId = 0;
83 :
84 0 : Clusters::IcdManagement::Commands::RegisterClient::Type registerClientCommand;
85 0 : registerClientCommand.checkInNodeID = mICDClientInfo.check_in_node.GetNodeId();
86 0 : registerClientCommand.monitoredSubject = mICDClientInfo.monitored_subject;
87 0 : registerClientCommand.key = mNewKey.Span();
88 0 : registerClientCommand.clientType = mICDClientInfo.client_type;
89 0 : return Controller::InvokeCommandRequest(&exchangeMgr, sessionHandle, endpointId, registerClientCommand, onSuccess, onFailure);
90 : }
91 :
92 1 : CHIP_ERROR RefreshKeySender::EstablishSessionToPeer()
93 : {
94 1 : ChipLogProgress(ICD, "Trying to establish a CASE session for re-registering an ICD client");
95 1 : auto * caseSessionManager = mpImEngine->GetCASESessionManager();
96 1 : VerifyOrReturnError(caseSessionManager != nullptr, CHIP_ERROR_INVALID_CASE_PARAMETER);
97 0 : caseSessionManager->FindOrEstablishSession(mICDClientInfo.peer_node, &mOnConnectedCallback, &mOnConnectionFailureCallback);
98 0 : return CHIP_NO_ERROR;
99 : }
100 :
101 0 : void RefreshKeySender::HandleDeviceConnected(void * context, Messaging::ExchangeManager & exchangeMgr,
102 : const SessionHandle & sessionHandle)
103 : {
104 0 : RefreshKeySender * const _this = static_cast<RefreshKeySender *>(context);
105 0 : VerifyOrDie(_this != nullptr);
106 :
107 0 : CHIP_ERROR err = _this->RegisterClientWithNewKey(exchangeMgr, sessionHandle);
108 0 : if (CHIP_NO_ERROR != err)
109 : {
110 0 : ChipLogError(ICD, "Failed to send register client command");
111 0 : _this->mpCheckInDelegate->OnKeyRefreshDone(_this, err);
112 : }
113 0 : }
114 :
115 0 : void RefreshKeySender::HandleDeviceConnectionFailure(void * context, const ScopedNodeId & peerId, CHIP_ERROR err)
116 : {
117 0 : RefreshKeySender * const _this = static_cast<RefreshKeySender *>(context);
118 0 : VerifyOrDie(_this != nullptr);
119 :
120 0 : ChipLogError(ICD, "Failed to establish CASE for re-registration with error '%" CHIP_ERROR_FORMAT "'", err.Format());
121 0 : _this->mpCheckInDelegate->OnKeyRefreshDone(_this, err);
122 0 : }
123 : } // namespace app
124 : } // namespace chip
|