blob: 95bb7f69a1de973608bc1a75c5760adfcbee0452 [file] [log] [blame]
/*
*
* 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.
*/
/**
* @file
* Implementation of CHIP Device Controller Factory, a utility/manager class
* that vends Controller objects
*/
#include <controller/CHIPDeviceControllerFactory.h>
#include <lib/support/ErrorStr.h>
#if CONFIG_DEVICE_LAYER
#include <platform/CHIPDeviceLayer.h>
#include <platform/ConfigurationManager.h>
#endif
using namespace chip::Inet;
using namespace chip::System;
using namespace chip::Credentials;
namespace chip {
namespace Controller {
CHIP_ERROR DeviceControllerFactory::Init(FactoryInitParams params)
{
// SystemState is only set the first time init is called, after that it is managed
// internally. If SystemState is set then init has already completed.
if (mSystemState != nullptr)
{
ChipLogError(Controller, "Device Controller Factory already initialized...");
return CHIP_NO_ERROR;
}
mListenPort = params.listenPort;
mFabricStorage = params.fabricStorage;
CHIP_ERROR err = InitSystemState(params);
return err;
}
CHIP_ERROR DeviceControllerFactory::InitSystemState()
{
FactoryInitParams params;
if (mSystemState != nullptr)
{
params.systemLayer = mSystemState->SystemLayer();
params.inetLayer = mSystemState->InetLayer();
#if CONFIG_NETWORK_LAYER_BLE
params.bleLayer = mSystemState->BleLayer();
#endif
}
return InitSystemState(params);
}
CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)
{
if (mSystemState != nullptr && mSystemState->IsInitialized())
{
return CHIP_NO_ERROR;
}
if (mSystemState != nullptr)
{
mSystemState->Release();
chip::Platform::Delete(mSystemState);
mSystemState = nullptr;
}
DeviceControllerSystemStateParams stateParams;
#if CONFIG_DEVICE_LAYER
ReturnErrorOnFailure(DeviceLayer::PlatformMgr().InitChipStack());
stateParams.systemLayer = &DeviceLayer::SystemLayer();
stateParams.inetLayer = &DeviceLayer::InetLayer();
#else
stateParams.systemLayer = params.systemLayer;
stateParams.inetLayer = params.inetLayer;
ChipLogError(Controller, "Warning: Device Controller Factory should be with a CHIP Device Layer...");
#endif // CONFIG_DEVICE_LAYER
VerifyOrReturnError(stateParams.systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(stateParams.inetLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
#if CONFIG_NETWORK_LAYER_BLE
#if CONFIG_DEVICE_LAYER
stateParams.bleLayer = DeviceLayer::ConnectivityMgr().GetBleLayer();
#else
stateParams.bleLayer = params.bleLayer;
#endif // CONFIG_DEVICE_LAYER
VerifyOrReturnError(stateParams.bleLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
#endif
stateParams.transportMgr = chip::Platform::New<DeviceTransportMgr>();
ReturnErrorOnFailure(stateParams.transportMgr->Init(
Transport::UdpListenParameters(stateParams.inetLayer).SetAddressType(Inet::IPAddressType::kIPv6).SetListenPort(mListenPort)
#if INET_CONFIG_ENABLE_IPV4
,
Transport::UdpListenParameters(stateParams.inetLayer).SetAddressType(Inet::IPAddressType::kIPv4).SetListenPort(mListenPort)
#endif
#if CONFIG_NETWORK_LAYER_BLE
,
Transport::BleListenParameters(stateParams.bleLayer)
#endif
));
if (params.imDelegate == nullptr)
{
params.imDelegate = chip::Platform::New<DeviceControllerInteractionModelDelegate>();
}
stateParams.fabricTable = chip::Platform::New<FabricTable>();
stateParams.sessionMgr = chip::Platform::New<SessionManager>();
stateParams.exchangeMgr = chip::Platform::New<Messaging::ExchangeManager>();
stateParams.messageCounterManager = chip::Platform::New<secure_channel::MessageCounterManager>();
ReturnErrorOnFailure(stateParams.fabricTable->Init(mFabricStorage));
ReturnErrorOnFailure(
stateParams.sessionMgr->Init(stateParams.systemLayer, stateParams.transportMgr, stateParams.messageCounterManager));
ReturnErrorOnFailure(stateParams.exchangeMgr->Init(stateParams.sessionMgr));
ReturnErrorOnFailure(stateParams.messageCounterManager->Init(stateParams.exchangeMgr));
stateParams.imDelegate = params.imDelegate;
ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->Init(stateParams.exchangeMgr, stateParams.imDelegate));
// store the system state
mSystemState = chip::Platform::New<DeviceControllerSystemState>(stateParams);
ChipLogDetail(Controller, "System State Initialized...");
return CHIP_NO_ERROR;
}
void DeviceControllerFactory::PopulateInitParams(ControllerInitParams & controllerParams, const SetupParams & params)
{
#if CHIP_DEVICE_CONFIG_ENABLE_DNSSD
controllerParams.deviceAddressUpdateDelegate = params.deviceAddressUpdateDelegate;
#endif
controllerParams.operationalCredentialsDelegate = params.operationalCredentialsDelegate;
controllerParams.ephemeralKeypair = params.ephemeralKeypair;
controllerParams.controllerNOC = params.controllerNOC;
controllerParams.controllerICAC = params.controllerICAC;
controllerParams.controllerRCAC = params.controllerRCAC;
controllerParams.fabricIndex = params.fabricIndex;
controllerParams.fabricId = params.fabricId;
controllerParams.storageDelegate = params.storageDelegate;
controllerParams.systemState = mSystemState;
controllerParams.controllerVendorId = params.controllerVendorId;
}
CHIP_ERROR DeviceControllerFactory::SetupController(SetupParams params, DeviceController & controller)
{
VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorOnFailure(InitSystemState());
ControllerInitParams controllerParams;
PopulateInitParams(controllerParams, params);
CHIP_ERROR err = controller.Init(controllerParams);
return err;
}
CHIP_ERROR DeviceControllerFactory::SetupCommissioner(SetupParams params, DeviceCommissioner & commissioner)
{
VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorOnFailure(InitSystemState());
CommissionerInitParams commissionerParams;
PopulateInitParams(commissionerParams, params);
commissionerParams.pairingDelegate = params.pairingDelegate;
CHIP_ERROR err = commissioner.Init(commissionerParams);
return err;
}
CHIP_ERROR DeviceControllerFactory::ServiceEvents()
{
VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INCORRECT_STATE);
#if CONFIG_DEVICE_LAYER
ReturnErrorOnFailure(DeviceLayer::PlatformMgr().StartEventLoopTask());
#endif // CONFIG_DEVICE_LAYER
return CHIP_NO_ERROR;
}
DeviceControllerFactory::~DeviceControllerFactory()
{
if (mSystemState != nullptr)
{
mSystemState->Release();
chip::Platform::Delete(mSystemState);
mSystemState = nullptr;
}
mFabricStorage = nullptr;
}
CHIP_ERROR DeviceControllerSystemState::Shutdown()
{
VerifyOrReturnError(mRefCount == 1, CHIP_ERROR_INCORRECT_STATE);
ChipLogDetail(Controller, "Shutting down the System State, this will teardown the CHIP Stack");
// Shut down the interaction model
app::InteractionModelEngine::GetInstance()->Shutdown();
// Shut down the TransportMgr. This holds Inet::UDPEndPoints so it must be shut down
// before PlatformMgr().Shutdown() shuts down Inet.
if (mTransportMgr != nullptr)
{
mTransportMgr->Close();
chip::Platform::Delete(mTransportMgr);
mTransportMgr = nullptr;
}
#if CONFIG_DEVICE_LAYER
//
// We can safely call PlatformMgr().Shutdown(), which like DeviceController::Shutdown(),
// expects to be called with external thread synchronization and will not try to acquire the
// stack lock.
//
// Actually stopping the event queue is a separable call that applications will have to sequence.
// Consumers are expected to call PlaformMgr().StopEventLoopTask() before calling
// DeviceController::Shutdown() in the CONFIG_DEVICE_LAYER configuration
//
ReturnErrorOnFailure(DeviceLayer::PlatformMgr().Shutdown());
#endif
if (mExchangeMgr != nullptr)
{
mExchangeMgr->Shutdown();
}
if (mSessionMgr != nullptr)
{
mSessionMgr->Shutdown();
}
mSystemLayer = nullptr;
mInetLayer = nullptr;
if (mMessageCounterManager != nullptr)
{
chip::Platform::Delete(mMessageCounterManager);
mMessageCounterManager = nullptr;
}
if (mExchangeMgr != nullptr)
{
chip::Platform::Delete(mExchangeMgr);
mExchangeMgr = nullptr;
}
if (mSessionMgr != nullptr)
{
chip::Platform::Delete(mSessionMgr);
mSessionMgr = nullptr;
}
if (mIMDelegate != nullptr)
{
chip::Platform::Delete(mIMDelegate);
mIMDelegate = nullptr;
}
return CHIP_NO_ERROR;
}
} // namespace Controller
} // namespace chip