Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ICD] Send Check-In messages #30526

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/lit-icd-app/linux/args.gni
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ chip_system_project_config_include = "<SystemProjectConfig.h>"

chip_project_config_include_dirs =
[ "${chip_root}/examples/lit-icd-app/linux/include" ]
chip_project_config_include_dirs += [ "${chip_root}/config/standalone" ]
chip_project_config_include_dirs +=
[ "${chip_root}/examples/lit-icd-app/linux/config/" ]
matter_enable_tracing_support = true

# ICD configurations
Expand Down
88 changes: 88 additions & 0 deletions examples/lit-icd-app/linux/config/CHIPProjectConfig.h
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2016-2017 Nest Labs, Inc.
*
* 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
* CHIP project configuration for standalone builds on Linux and OS X.
*
*/
#ifndef CHIPPROJECTCONFIG_H
#define CHIPPROJECTCONFIG_H

#define CHIP_CONFIG_EVENT_LOGGING_NUM_EXTERNAL_CALLBACKS 2

// Uncomment this for a large Tunnel MTU.
// #define CHIP_CONFIG_TUNNEL_INTERFACE_MTU (9000)

// Enable support functions for parsing command-line arguments
#define CHIP_CONFIG_ENABLE_ARG_PARSER 1

// Enable use of test setup parameters for testing purposes only.
//
// WARNING: This option makes it possible to circumvent basic chip security functionality.
// Because of this it SHOULD NEVER BE ENABLED IN PRODUCTION BUILDS.
//
#ifndef CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS
#define CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS 1
#endif

// Enable reading DRBG seed data from /dev/(u)random.
// This is needed for test applications and the CHIP device manager to function
// properly when CHIP_CONFIG_RNG_IMPLEMENTATION_CHIPDRBG is enabled.
#define CHIP_CONFIG_DEV_RANDOM_DRBG_SEED 1

// For convenience, Chip Security Test Mode can be enabled and the
// requirement for authentication in various protocols can be disabled.
//
// WARNING: These options make it possible to circumvent basic Chip security functionality,
// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
//
// To build with this flag, pass 'treat_warnings_as_errors=false' to gn/ninja.
//
#define CHIP_CONFIG_SECURITY_TEST_MODE 0

#define CHIP_CONFIG_ENABLE_UPDATE 1

#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 0

#define CHIP_CONFIG_DATA_MANAGEMENT_CLIENT_EXPERIMENTAL 1

#ifndef CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT
#define CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT 4
#endif

#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 1
#endif

#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "1.0"
#endif

//
// Default of 8 ECs is not sufficient for some of the unit tests
// that try to validate multiple simultaneous interactions.
// In tests like TestReadHandler_MultipleSubscriptions, we are trying to issue as many read / subscription requests as possible in
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
// parallel. Since the default config says we support 16 fabrics, and we will have 4 read handlers for each fabric (3 subscriptions
// + 1 reserved for read) that is read transactions in parallel. Since the report handlers are allocated on the heap, we will issue
// 65 requests (the TestReadHandler_MultipleSubscriptions will issue CHIP_IM_MAX_NUM_READ_HANDLER + 1 subscriptions to verify heap
// allocation logic) in total and that is 130 ECs. Round this up to 150 ECs
//
#define CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS 150

#endif /* CHIPPROJECTCONFIG_H */
32 changes: 32 additions & 0 deletions examples/lit-icd-app/linux/config/SystemProjectConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2018 Nest Labs, Inc.
*
* 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
* chip::System project configuration for standalone builds on Linux and OS X.
*
*/
#ifndef SYSTEMPROJECTCONFIG_H
#define SYSTEMPROJECTCONFIG_H

#if CHIP_SYSTEM_CONFIG_USE_SOCKETS
// Uncomment this for larger buffers (e.g. to support a bigger CHIP_CONFIG_TUNNEL_INTERFACE_MTU).
// #define CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX 9050
#endif

#endif /* SYSTEMPROJECTCONFIG_H */
31 changes: 31 additions & 0 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,37 @@ CHIP_ERROR InteractionModelEngine::ShutdownSubscription(const ScopedNodeId & aPe
return CHIP_ERROR_KEY_NOT_FOUND;
}

bool InteractionModelEngine::IsMatchingSubscriptionActive(const FabricIndex & aFabricIndex, const NodeId & subjectID)
{
for (uint16_t index = 0; index < GetNumActiveReadHandlers(); index++)
{
ReadHandler * readHandler = ActiveHandlerAt(index);
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
if (readHandler == nullptr)
{
// Should not happen
continue;
}

if (readHandler->IsType(ReadHandler::InteractionType::Subscribe))
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
{
Access::SubjectDescriptor subject = readHandler->GetSubjectDescriptor();
if (subject.fabricIndex != aFabricIndex)
{
continue;
}

if (subject.authMode == Access::AuthMode::kCase)
{
if (subject.cats.CheckSubjectAgainstCATs(subjectID) || subjectID == subject.subject)
{
return readHandler->IsActiveSubscription();
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
return false;
}

void InteractionModelEngine::ShutdownSubscriptions(FabricIndex aFabricIndex, NodeId aPeerNodeId)
{
assertChipStackLockedByCurrentThread();
Expand Down
3 changes: 3 additions & 0 deletions src/app/InteractionModelEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,9 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,

CHIP_ERROR ResumeSubscriptions();

// Return the state of a subscription matching a CAT Tag or a NodeId
bool IsMatchingSubscriptionActive(const FabricIndex & aFabricIndex, const NodeId & nodeIdOrCAT);
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved

#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
//
// Get direct access to the underlying read handler pool
Expand Down
70 changes: 69 additions & 1 deletion src/app/icd/ICDManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <platform/internal/CHIPDeviceLayerInternal.h>
#include <stdlib.h>

#include <app/InteractionModelEngine.h>

#ifndef ICD_ENFORCE_SIT_SLOW_POLL_LIMIT
// Set to 1 to enforce SIT Slow Polling Max value to 15seconds (spec 9.16.1.5)
#define ICD_ENFORCE_SIT_SLOW_POLL_LIMIT 0
Expand All @@ -43,11 +45,13 @@ using namespace chip::app::Clusters::IcdManagement;
static_assert(UINT8_MAX >= CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS,
"ICDManager::mOpenExchangeContextCount cannot hold count for the max exchange count");

void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeystore)
void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeystore,
Messaging::ExchangeManager * exchangeManager)
{
VerifyOrDie(storage != nullptr);
VerifyOrDie(fabricTable != nullptr);
VerifyOrDie(symmetricKeystore != nullptr);
VerifyOrDie(exchangeManager != nullptr);

bool supportLIT = SupportsFeature(Feature::kLongIdleTimeSupport);
VerifyOrDieWithMsg((supportLIT == false) || SupportsFeature(Feature::kCheckInProtocolSupport), AppServer,
Expand All @@ -63,6 +67,7 @@ void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricT
mFabricTable = fabricTable;
VerifyOrDie(ICDNotifier::GetInstance().Subscribe(this) == CHIP_NO_ERROR);
mSymmetricKeystore = symmetricKeystore;
mExchangeManager = exchangeManager;

ICDManagementServer::GetInstance().SetSymmetricKeystore(mSymmetricKeystore);

Expand All @@ -87,6 +92,7 @@ void ICDManager::Shutdown()
mStorage = nullptr;
mFabricTable = nullptr;
mStateObserverPool.ReleaseAll();
mICDSenderPool.ReleaseAll();
}

bool ICDManager::SupportsFeature(Feature feature)
Expand All @@ -101,6 +107,60 @@ bool ICDManager::SupportsFeature(Feature feature)
#endif // !CONFIG_BUILD_FOR_HOST_UNIT_TEST
}

void ICDManager::SendCheckInMsgs()
{
#if !CONFIG_BUILD_FOR_HOST_UNIT_TEST
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
VerifyOrDie(mStorage != nullptr);
VerifyOrDie(mFabricTable != nullptr);
for (const auto & fabricInfo : *mFabricTable)
{
uint16_t supported_clients = ICDManagementServer::GetInstance().GetClientsSupportedPerFabric();

ICDMonitoringTable table(*mStorage, fabricInfo.GetFabricIndex(), supported_clients /*Table entry limit*/,
mSymmetricKeystore);
if (!table.IsEmpty())
{
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
for (uint16_t i = 0; i < table.Limit(); i++)
{
ICDMonitoringEntry entry(mSymmetricKeystore);
CHIP_ERROR err = table.Get(i, entry);
if (err == CHIP_ERROR_NOT_FOUND)
{
break;
}

if (err != CHIP_NO_ERROR)
{
// Try to fetch the next entry.
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
continue;
}

bool active =
InteractionModelEngine::GetInstance()->IsMatchingSubscriptionActive(entry.fabricIndex, entry.monitoredSubject);
if (active)
{
continue;
}

// SenderPool will be release upon transition from active to idle state
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
// This will happen when all ICD Check-In messages are sent on the network
ICDCheckInSender * sender = mICDSenderPool.CreateObject(mExchangeManager);
if (sender == nullptr)
{
ChipLogError(AppServer, "Failed to allocate ICDCheckinSender");
return;
}
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved

if (CHIP_NO_ERROR != sender->RequestResolve(entry, mFabricTable))
{
ChipLogError(AppServer, "Failed to send ICD Check-In");
bzbarsky-apple marked this conversation as resolved.
Show resolved Hide resolved
}
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
}

void ICDManager::UpdateICDMode()
{
assertChipStackLockedByCurrentThread();
Expand Down Expand Up @@ -166,6 +226,9 @@ void ICDManager::UpdateOperationState(OperationalState state)
}
#endif

// Going back to Idle, all check-in messages are sent
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
mICDSenderPool.ReleaseAll();
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved

CHIP_ERROR err = DeviceLayer::ConnectivityMgr().SetPollingInterval(slowPollInterval);
if (err != CHIP_NO_ERROR)
{
Expand Down Expand Up @@ -202,6 +265,11 @@ void ICDManager::UpdateOperationState(OperationalState state)
ChipLogError(AppServer, "Failed to set Fast Polling Interval: err %" CHIP_ERROR_FORMAT, err.Format());
}

if (SupportsFeature(Feature::kCheckInProtocolSupport))
{
SendCheckInMsgs();
}

postObserverEvent(ObserverEventType::EnterActiveMode);
}
else
Expand Down
7 changes: 6 additions & 1 deletion src/app/icd/ICDManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#pragma once

#include <app-common/zap-generated/cluster-enums.h>
#include <app/icd/ICDCheckInSender.h>
#include <app/icd/ICDMonitoringTable.h>
#include <app/icd/ICDNotifier.h>
#include <app/icd/ICDStateObserver.h>
Expand Down Expand Up @@ -69,7 +70,8 @@ class ICDManager : public ICDListener
};

ICDManager() {}
void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeyStore);
void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeyStore,
Messaging::ExchangeManager * exchangeManager);
void Shutdown();
void UpdateICDMode();
void UpdateOperationState(OperationalState state);
Expand Down Expand Up @@ -97,6 +99,7 @@ class ICDManager : public ICDListener
void postObserverEvent(ObserverEventType event);
ICDMode GetICDMode() { return mICDMode; }
OperationalState GetOperationalState() { return mOperationalState; }
void SendCheckInMsgs();

static System::Clock::Milliseconds32 GetSITPollingThreshold() { return kSITPollingThreshold; }
static System::Clock::Milliseconds32 GetFastPollingInterval() { return kFastPollingInterval; }
Expand Down Expand Up @@ -148,9 +151,11 @@ class ICDManager : public ICDListener
ICDMode mICDMode = ICDMode::SIT;
PersistentStorageDelegate * mStorage = nullptr;
FabricTable * mFabricTable = nullptr;
Messaging::ExchangeManager * mExchangeManager = nullptr;
bool mTransitionToIdleCalled = false;
Crypto::SymmetricKeystore * mSymmetricKeystore = nullptr;
ObjectPool<ObserverPointer, CHIP_CONFIG_ICD_OBSERVERS_POOL_SIZE> mStateObserverPool;
ObjectPool<ICDCheckInSender, (CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC * CHIP_CONFIG_MAX_FABRICS)> mICDSenderPool;

#ifdef CONFIG_BUILD_FOR_HOST_UNIT_TEST
// feature map that can be changed at runtime for testing purposes
Expand Down
18 changes: 9 additions & 9 deletions src/app/server/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,15 +255,6 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams)
// This initializes clusters, so should come after lower level initialization.
InitDataModelHandler();

// ICD Init needs to be after data model init
#if CHIP_CONFIG_ENABLE_ICD_SERVER
mICDManager.Init(mDeviceStorage, &GetFabricTable(), mSessionKeystore);
// Register the ICDStateObservers. All observers are released at mICDManager.Shutdown()
// They can be released individually with ReleaseObserver
mICDManager.RegisterObserver(mReportScheduler);
mICDManager.RegisterObserver(&app::DnssdServer::Instance());
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER

#if defined(CHIP_APP_USE_ECHO)
err = InitEchoHandler(&mExchangeMgr);
SuccessOrExit(err);
Expand Down Expand Up @@ -328,6 +319,15 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams)
&mCASESessionManager, mSubscriptionResumptionStorage);
SuccessOrExit(err);

// ICD Init needs to be after data model init and InteractionModel Init
#if CHIP_CONFIG_ENABLE_ICD_SERVER
mICDManager.Init(mDeviceStorage, &GetFabricTable(), mSessionKeystore, &mExchangeMgr);
// Register the ICDStateObservers. All observers are released at mICDManager.Shutdown()
// They can be released individually with ReleaseObserver
mICDManager.RegisterObserver(mReportScheduler);
mICDManager.RegisterObserver(&app::DnssdServer::Instance());
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER

// This code is necessary to restart listening to existing groups after a reboot
// Each manufacturer needs to validate that they can rejoin groups by placing this code at the appropriate location for them
//
Expand Down
2 changes: 1 addition & 1 deletion src/app/tests/TestICDManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class TestContext : public Test::AppContext
{
return FAILURE;
}
ctx->mICDManager.Init(&ctx->testStorage, &ctx->GetFabricTable(), &(ctx->mKeystore));
ctx->mICDManager.Init(&ctx->testStorage, &ctx->GetFabricTable(), &(ctx->mKeystore), &ctx.GetExchangeManager());
ctx->mICDManager.RegisterObserver(&mICDStateObserver);
return SUCCESS;
}
Expand Down
Loading