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 0 : CHIP_ERROR RefreshKeySender::RegisterClientWithNewKey(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle)
40 : {
41 0 : auto onSuccess = [&](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
42 0 : ChipLogProgress(ICD, "RegisterClient command succeeded");
43 : CHIP_ERROR error;
44 :
45 : // Update the ICDClientInfo with new key and start counter and store it to persistence
46 0 : mICDClientInfo.start_icd_counter = dataResponse.ICDCounter;
47 0 : mICDClientInfo.offset = 0;
48 0 : mpICDClientStorage->RemoveKey(mICDClientInfo);
49 0 : error = mpICDClientStorage->SetKey(mICDClientInfo, mNewKey.Span());
50 0 : if (error != CHIP_NO_ERROR)
51 : {
52 0 : ChipLogError(ICD, "Failed to set the new key after re-registration: %" CHIP_ERROR_FORMAT, error.Format());
53 0 : mpCheckInDelegate->OnKeyRefreshDone(this, error);
54 0 : return;
55 : }
56 :
57 0 : error = mpICDClientStorage->StoreEntry(mICDClientInfo);
58 0 : if (error != CHIP_NO_ERROR)
59 : {
60 0 : ChipLogError(ICD, "Failed to store the new key after re-registration: %" CHIP_ERROR_FORMAT, error.Format());
61 0 : mpCheckInDelegate->OnKeyRefreshDone(this, error);
62 0 : return;
63 : }
64 :
65 0 : mpCheckInDelegate->OnCheckInComplete(mICDClientInfo);
66 : #if CHIP_CONFIG_ENABLE_READ_CLIENT
67 0 : mpImEngine->OnActiveModeNotification(mICDClientInfo.peer_node);
68 : #endif // CHIP_CONFIG_ENABLE_READ_CLIENT
69 0 : mpCheckInDelegate->OnKeyRefreshDone(this, CHIP_NO_ERROR);
70 0 : };
71 :
72 0 : auto onFailure = [&](CHIP_ERROR error) {
73 0 : ChipLogError(ICD, "RegisterClient command failed: %" CHIP_ERROR_FORMAT, error.Format());
74 0 : mpCheckInDelegate->OnKeyRefreshDone(this, error);
75 0 : };
76 :
77 0 : EndpointId endpointId = 0;
78 :
79 0 : Clusters::IcdManagement::Commands::RegisterClient::Type registerClientCommand;
80 0 : registerClientCommand.checkInNodeID = mICDClientInfo.check_in_node.GetNodeId();
81 0 : registerClientCommand.monitoredSubject = mICDClientInfo.monitored_subject;
82 0 : registerClientCommand.key = mNewKey.Span();
83 0 : registerClientCommand.clientType = mICDClientInfo.client_type;
84 0 : return Controller::InvokeCommandRequest(&exchangeMgr, sessionHandle, endpointId, registerClientCommand, onSuccess, onFailure);
85 0 : }
86 :
87 1 : CHIP_ERROR RefreshKeySender::EstablishSessionToPeer()
88 : {
89 1 : ChipLogProgress(ICD, "Trying to establish a CASE session for re-registering an ICD client");
90 1 : auto * caseSessionManager = mpImEngine->GetCASESessionManager();
91 1 : VerifyOrReturnError(caseSessionManager != nullptr, CHIP_ERROR_INVALID_CASE_PARAMETER);
92 0 : caseSessionManager->FindOrEstablishSession(mICDClientInfo.peer_node, &mOnConnectedCallback, &mOnConnectionFailureCallback);
93 0 : return CHIP_NO_ERROR;
94 : }
95 :
96 0 : void RefreshKeySender::HandleDeviceConnected(void * context, Messaging::ExchangeManager & exchangeMgr,
97 : const SessionHandle & sessionHandle)
98 : {
99 0 : RefreshKeySender * const _this = static_cast<RefreshKeySender *>(context);
100 0 : VerifyOrDie(_this != nullptr);
101 :
102 0 : CHIP_ERROR err = _this->RegisterClientWithNewKey(exchangeMgr, sessionHandle);
103 0 : if (CHIP_NO_ERROR != err)
104 : {
105 0 : ChipLogError(ICD, "Failed to send register client command");
106 0 : _this->mpCheckInDelegate->OnKeyRefreshDone(_this, err);
107 : }
108 0 : }
109 :
110 0 : void RefreshKeySender::HandleDeviceConnectionFailure(void * context, const ScopedNodeId & peerId, CHIP_ERROR err)
111 : {
112 0 : RefreshKeySender * const _this = static_cast<RefreshKeySender *>(context);
113 0 : VerifyOrDie(_this != nullptr);
114 :
115 0 : ChipLogError(ICD, "Failed to establish CASE for re-registration with error '%" CHIP_ERROR_FORMAT "'", err.Format());
116 0 : _this->mpCheckInDelegate->OnKeyRefreshDone(_this, err);
117 0 : }
118 : } // namespace app
119 : } // namespace chip
|