Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2023 Project CHIP Authors 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 <app/InteractionModelEngine.h> 19 : #include <app/SubscriptionResumptionSessionEstablisher.h> 20 : 21 : namespace chip { 22 : namespace app { 23 : 24 : class AutoDeleteEstablisher 25 : { 26 : public: 27 0 : AutoDeleteEstablisher(SubscriptionResumptionSessionEstablisher * sessionEstablisher) : mSessionEstablisher(sessionEstablisher) 28 0 : {} 29 0 : ~AutoDeleteEstablisher() { chip::Platform::Delete(mSessionEstablisher); } 30 : 31 0 : SubscriptionResumptionSessionEstablisher * operator->() const { return mSessionEstablisher; } 32 : 33 0 : SubscriptionResumptionSessionEstablisher & operator*() const { return *mSessionEstablisher; } 34 : 35 : private: 36 : SubscriptionResumptionSessionEstablisher * mSessionEstablisher; 37 : }; 38 : 39 0 : SubscriptionResumptionSessionEstablisher::SubscriptionResumptionSessionEstablisher() : 40 0 : mOnConnectedCallback(HandleDeviceConnected, this), mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this) 41 0 : {} 42 : 43 : CHIP_ERROR 44 0 : SubscriptionResumptionSessionEstablisher::ResumeSubscription( 45 : CASESessionManager & caseSessionManager, const SubscriptionResumptionStorage::SubscriptionInfo & subscriptionInfo) 46 : { 47 0 : mSubscriptionInfo.mNodeId = subscriptionInfo.mNodeId; 48 0 : mSubscriptionInfo.mFabricIndex = subscriptionInfo.mFabricIndex; 49 0 : mSubscriptionInfo.mSubscriptionId = subscriptionInfo.mSubscriptionId; 50 0 : mSubscriptionInfo.mMinInterval = subscriptionInfo.mMinInterval; 51 0 : mSubscriptionInfo.mMaxInterval = subscriptionInfo.mMaxInterval; 52 0 : mSubscriptionInfo.mFabricFiltered = subscriptionInfo.mFabricFiltered; 53 : // Copy the Attribute Paths and Event Paths 54 0 : if (subscriptionInfo.mAttributePaths.AllocatedSize() > 0) 55 : { 56 0 : mSubscriptionInfo.mAttributePaths.Alloc(subscriptionInfo.mAttributePaths.AllocatedSize()); 57 0 : if (!mSubscriptionInfo.mAttributePaths.Get()) 58 : { 59 0 : return CHIP_ERROR_NO_MEMORY; 60 : } 61 0 : for (size_t i = 0; i < mSubscriptionInfo.mAttributePaths.AllocatedSize(); ++i) 62 : { 63 0 : mSubscriptionInfo.mAttributePaths[i] = subscriptionInfo.mAttributePaths[i]; 64 : } 65 : } 66 0 : if (subscriptionInfo.mEventPaths.AllocatedSize() > 0) 67 : { 68 0 : mSubscriptionInfo.mEventPaths.Alloc(subscriptionInfo.mEventPaths.AllocatedSize()); 69 0 : if (!mSubscriptionInfo.mEventPaths.Get()) 70 : { 71 0 : return CHIP_ERROR_NO_MEMORY; 72 : } 73 0 : for (size_t i = 0; i < mSubscriptionInfo.mEventPaths.AllocatedSize(); ++i) 74 : { 75 0 : mSubscriptionInfo.mEventPaths[i] = subscriptionInfo.mEventPaths[i]; 76 : } 77 : } 78 : 79 0 : ScopedNodeId peerNode = ScopedNodeId(mSubscriptionInfo.mNodeId, mSubscriptionInfo.mFabricIndex); 80 0 : caseSessionManager.FindOrEstablishSession(peerNode, &mOnConnectedCallback, &mOnConnectionFailureCallback); 81 0 : return CHIP_NO_ERROR; 82 : } 83 : 84 0 : void SubscriptionResumptionSessionEstablisher::HandleDeviceConnected(void * context, Messaging::ExchangeManager & exchangeMgr, 85 : const SessionHandle & sessionHandle) 86 : { 87 0 : AutoDeleteEstablisher establisher(static_cast<SubscriptionResumptionSessionEstablisher *>(context)); 88 0 : SubscriptionResumptionStorage::SubscriptionInfo & subscriptionInfo = establisher->mSubscriptionInfo; 89 0 : InteractionModelEngine * imEngine = InteractionModelEngine::GetInstance(); 90 0 : if (!imEngine->EnsureResourceForSubscription(subscriptionInfo.mFabricIndex, subscriptionInfo.mAttributePaths.AllocatedSize(), 91 : subscriptionInfo.mEventPaths.AllocatedSize())) 92 : { 93 0 : ChipLogProgress(InteractionModel, "no resource for subscription resumption"); 94 0 : return; 95 : } 96 0 : ReadHandler * readHandler = imEngine->mReadHandlers.CreateObject(*imEngine, imEngine->GetReportScheduler()); 97 0 : if (readHandler == nullptr) 98 : { 99 0 : ChipLogProgress(InteractionModel, "no resource for ReadHandler creation"); 100 0 : return; 101 : } 102 0 : readHandler->OnSubscriptionResumed(sessionHandle, *establisher); 103 0 : } 104 : 105 0 : void SubscriptionResumptionSessionEstablisher::HandleDeviceConnectionFailure(void * context, const ScopedNodeId & peerId, 106 : CHIP_ERROR error) 107 : { 108 0 : AutoDeleteEstablisher establisher(static_cast<SubscriptionResumptionSessionEstablisher *>(context)); 109 0 : SubscriptionResumptionStorage::SubscriptionInfo & subscriptionInfo = establisher->mSubscriptionInfo; 110 0 : ChipLogError(DataManagement, "Failed to establish CASE for subscription-resumption with error '%" CHIP_ERROR_FORMAT "'", 111 : error.Format()); 112 : // If the device fails to establish the session, the subscriber might be offline and its subscription read client will 113 : // be deleted when the device reconnect to the subscriber. This subscription will be never used again. So clean up 114 : // the persistent subscription information storage. 115 0 : auto * subscriptionResumptionStorage = InteractionModelEngine::GetInstance()->GetSubscriptionResumptionStorage(); 116 0 : if (subscriptionResumptionStorage) 117 : { 118 0 : subscriptionResumptionStorage->Delete(subscriptionInfo.mNodeId, subscriptionInfo.mFabricIndex, 119 : subscriptionInfo.mSubscriptionId); 120 : } 121 0 : } 122 : 123 : } // namespace app 124 : } // namespace chip