/* * * Copyright (c) 2021 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include using namespace chip::app::Clusters; namespace chip { namespace Controller { CHIP_ERROR CurrentFabricRemover::RemoveCurrentFabric(NodeId remoteNodeId, Callback::Callback * callback) { mRemoteNodeId = remoteNodeId; mCurrentFabricRemoveCallback = callback; mNextStep = Step::kReadCurrentFabricIndex; return mController->GetConnectedDevice(remoteNodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); } CHIP_ERROR CurrentFabricRemover::ReadCurrentFabricIndex(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) { using TypeInfo = OperationalCredentials::Attributes::CurrentFabricIndex::TypeInfo; ClusterBase cluster(exchangeMgr, sessionHandle, kRootEndpointId); return cluster.ReadAttribute(this, OnSuccessReadCurrentFabricIndex, OnReadAttributeFailure); } CHIP_ERROR CurrentFabricRemover::SendRemoveFabricIndex(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) { if (mFabricIndex == kUndefinedFabricIndex) { return CHIP_ERROR_INVALID_FABRIC_INDEX; } OperationalCredentials::Commands::RemoveFabric::Type request; request.fabricIndex = mFabricIndex; ClusterBase cluster(exchangeMgr, sessionHandle, 0); return cluster.InvokeCommand(request, this, OnSuccessRemoveFabric, OnCommandFailure); } void CurrentFabricRemover::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) { CHIP_ERROR err = CHIP_NO_ERROR; auto * self = static_cast(context); VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); switch (self->mNextStep) { case Step::kReadCurrentFabricIndex: { err = self->ReadCurrentFabricIndex(exchangeMgr, sessionHandle); break; } case Step::kSendRemoveFabric: { err = self->SendRemoveFabricIndex(exchangeMgr, sessionHandle); break; } default: err = CHIP_ERROR_INCORRECT_STATE; break; } if (err != CHIP_NO_ERROR) { ChipLogError(Controller, "Current Fabric Remover failure : %" CHIP_ERROR_FORMAT, err.Format()); FinishRemoveCurrentFabric(context, err); } } void CurrentFabricRemover::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR err) { ChipLogProgress(Controller, "OnDeviceConnectionFailureFn: %" CHIP_ERROR_FORMAT, err.Format()); auto * self = static_cast(context); VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected failure callback with null context. Ignoring")); FinishRemoveCurrentFabric(context, err); } void CurrentFabricRemover::OnSuccessReadCurrentFabricIndex(void * context, FabricIndex fabricIndex) { auto * self = static_cast(context); VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Success Read Current Fabric index callback with null context. Ignoring")); self->mFabricIndex = fabricIndex; self->mNextStep = Step::kSendRemoveFabric; CHIP_ERROR err = self->mController->GetConnectedDevice(self->mRemoteNodeId, &self->mOnDeviceConnectedCallback, &self->mOnDeviceConnectionFailureCallback); if (err != CHIP_NO_ERROR) { FinishRemoveCurrentFabric(context, err); } } void CurrentFabricRemover::OnReadAttributeFailure(void * context, CHIP_ERROR err) { ChipLogProgress(Controller, "OnReadAttributeFailure %" CHIP_ERROR_FORMAT, err.Format()); auto * self = static_cast(context); VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Read Attribute failure callback with null context. Ignoring")); FinishRemoveCurrentFabric(context, err); } void CurrentFabricRemover::OnSuccessRemoveFabric(void * context, const OperationalCredentials::Commands::NOCResponse::DecodableType & data) { auto * self = static_cast(context); VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Success Remove Fabric command callback with null context. Ignoring")); FinishRemoveCurrentFabric(context, CHIP_NO_ERROR); } void CurrentFabricRemover::OnCommandFailure(void * context, CHIP_ERROR err) { ChipLogProgress(Controller, "OnCommandFailure %" CHIP_ERROR_FORMAT, err.Format()); auto * self = static_cast(context); VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Send command failure callback with null context. Ignoring")); FinishRemoveCurrentFabric(context, err); } void CurrentFabricRemover::FinishRemoveCurrentFabric(void * context, CHIP_ERROR err) { if (err == CHIP_NO_ERROR) { ChipLogProgress(Controller, "Remove Current Fabric succeeded."); } else { ChipLogError(Controller, "Remove Current Fabric Failed : %" CHIP_ERROR_FORMAT, err.Format()); } auto * self = static_cast(context); self->mNextStep = Step::kAcceptRemoveFabricStart; if (self->mCurrentFabricRemoveCallback != nullptr) { self->mCurrentFabricRemoveCallback->mCall(self->mCurrentFabricRemoveCallback->mContext, self->mRemoteNodeId, err); } } AutoCurrentFabricRemover::AutoCurrentFabricRemover(DeviceController * controller) : CurrentFabricRemover(controller), mOnRemoveCurrentFabricCallback(OnRemoveCurrentFabric, this) {} CHIP_ERROR AutoCurrentFabricRemover::RemoveCurrentFabric(DeviceController * controller, NodeId remoteNodeId) { // Not using Platform::New because we want to keep our constructor private. auto * remover = new (std::nothrow) AutoCurrentFabricRemover(controller); if (remover == nullptr) { return CHIP_ERROR_NO_MEMORY; } CHIP_ERROR err = remover->CurrentFabricRemover::RemoveCurrentFabric(remoteNodeId, &remover->mOnRemoveCurrentFabricCallback); if (err != CHIP_NO_ERROR) { delete remover; } // Else will clean up when the callback is called. return err; } void AutoCurrentFabricRemover::OnRemoveCurrentFabric(void * context, NodeId remoteNodeId, CHIP_ERROR status) { auto * self = static_cast(context); delete self; } } // namespace Controller } // namespace chip