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 all commits
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
91 changes: 91 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,91 @@
/*
*
* 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

// TODO Cleanup this file, as most of it is irrelevant
// Issue #30616

#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 */
35 changes: 35 additions & 0 deletions examples/lit-icd-app/linux/config/SystemProjectConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
*
* 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

// TODO Cleanup this file, as most of it is irrelevant
// Issue #30616

#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 */
37 changes: 37 additions & 0 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,43 @@ void InteractionModelEngine::ShutdownMatchingSubscriptions(const Optional<Fabric
}
#endif // CHIP_CONFIG_ENABLE_READ_CLIENT

bool InteractionModelEngine::SubjectHasActiveSubscription(const FabricIndex aFabricIndex, const NodeId & subjectID)
{
bool isActive = false;
mReadHandlers.ForEachActiveObject([aFabricIndex, subjectID, &isActive](ReadHandler * handler) {
if (!handler->IsType(ReadHandler::InteractionType::Subscribe))
{
return Loop::Continue;
}

Access::SubjectDescriptor subject = handler->GetSubjectDescriptor();
if (subject.fabricIndex != aFabricIndex)
{
return Loop::Continue;
}

if (subject.authMode == Access::AuthMode::kCase)
{
if (subject.cats.CheckSubjectAgainstCATs(subjectID) || subjectID == subject.subject)
{
isActive = handler->IsActiveSubscription();

// Exit loop only if isActive is set to true
// Otherwise keep looking for another subscription that could
// match the subject
if (isActive)
{
return Loop::Break;
}
}
}

return Loop::Continue;
});

return isActive;
}

void InteractionModelEngine::OnDone(CommandHandler & apCommandObj)
{
mCommandHandlerObjs.ReleaseObject(&apCommandObj);
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();

// Check if a given subject (CAT or NodeId) has at least 1 active subscription
bool SubjectHasActiveSubscription(const FabricIndex aFabricIndex, const NodeId & subject);

#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
//
// Get direct access to the underlying read handler pool
Expand Down
69 changes: 68 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,59 @@ 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
continue;
}

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 upon failure (should not happen).
ChipLogError(AppServer, "Failed to retrieved ICDMonitoring entry for Check-In msg, will try next entry.");
continue;
}

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

// SenderPool will be released upon transition from active to idle state
// This will happen when all ICD Check-In messages are sent on the network
ICDCheckInSender * sender = mICDSenderPool.CreateObject(mExchangeManager);
VerifyOrReturn(sender != nullptr, ChipLogError(AppServer, "Failed to allocate ICDCheckinSender"));

if (CHIP_NO_ERROR != sender->RequestResolve(entry, mFabricTable))
{
ChipLogError(AppServer, "Failed to send ICD Check-In");
}
}
}
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
}

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

// Going back to Idle, all Check-In messages are sent
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 +264,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