Skip to content

Commit

Permalink
Icd handler (#30731)
Browse files Browse the repository at this point in the history
* ICDHandler initialization

* ICDHandler initialization

* Restyled by gn

* Update src/app/icd/ICDHandler.cpp

Co-authored-by: Jean-Francois Penven <[email protected]>

* ICDHandler initialization

* ICDHandler initialization

* ICDHandler initialization

* Restyled by gn

* ICDHandler initialization

* ICDHandler initialization

* Restyled by gn

* ICDHandler initialization

* Restyled by gn

* ICDHandler initialization

* ICDHandler initialization

* ICDHandler initialization

* ICDHandler initialization

* ICDHandler initialization

* Moved counter validation to DefaultICDClientStorage.

* Renamed ICDHandler to CheckInHandler

* Included CheckInDelegate in BUILD.gn

* Restyled by gn

* Added DefaultCheckInDelegate

* Restyled by whitespace

* Restyled by gn

* Modified error codes

* Updated variables

* Added condition for VerifyOrReturnError

* Resolve conflicts with master branch

* Added CheckInHandler init in chiptool

* Restyled by clang-format

* Restyled by gn

* Added include file

* Modified the access operator

* Added ICD client deps for tv-casting-app

* Restyled by gn

* Added unit test case for ProcessCheckInPayload

* Updated doxygen comments

* Addressed review comments

* Addressed review comments

* Addressed review comments.

* Moved checkin counter validation to CheckInHandler.

* Removed TestDefaultICDClientStorage from iotsdk.

* Restyled by gn

* add CheckInExchangeDispatch to accept unsecure check-in message

* Restyled by clang-format

* Removed DefaultICDClientInfoPersistentStorage.cpp.

* Addressed a few review comments.

* Modified a macro to make sure it is taken as a 64-bit interger.

* Restyled by clang-format

* Removed redundant error code CHIP_ERROR_DUPLICATE_MESSAGE

* Restyled by clang-format

* Modified the datatype for checkInCounter to CounterType from auto.

* Added code to refresh key.

* ICDHandler initialization

* ICDHandler initialization

* Resolve conflicts with master branch

* Added CheckInHandler init in chiptool

* Moved checkin counter validation to CheckInHandler.

* [icd] integrate ICD management command into CHIP tool (#30863)

* [icd] integrate ICD management command into CHIP tool

* Delete entry on failure

* Fix build

* ICDHandler initialization

* Added CheckInHandler init in chiptool

* Fixing merge conflicts

* Added OnRefreshKey callback

* Restyled by gn

* Modified APPDATA_LENGTh macro to inline consexpr variable.

* Modified CheckInDelegate and CheckInHandler to static members in chiptool.

* Return CHIP_NO_ERROR for failures in processing checkin message.

* Addressed review comments

* Fixed a spelling error

* Moved variable definition

* Reenable TestDefaultClientStorage for open iot.

* Restyled by gn

* Modified code to use updated API

* Removed obsolete comments

* Added comments

* Addressed review comments

* Improve ICDClientStorage (#30931)

* Added const qualifier to payload

* Return CHIP_NO_ERROR for duplicate check in message and log error.

* Return CHIP_NO_ERROR on duplicate checkin messages

* Added OnRefreshKeyRetrieve and addressed review comments

* Update src/lib/core/CHIPError.h

Co-authored-by: mkardous-silabs <[email protected]>

* Restyled by whitespace

* Restyled by clang-format

* Restyled by gn

* Added a temporary suppression of error for including <unordered_map>

* Added a comment to suppress Lint error

* Addressed review comments

* Addressed review comments

* Addressed review comments.

* Removed code pertaining to key refresh. Will be a separate PR.

* Added a link to an issue

---------

Co-authored-by: Restyled.io <[email protected]>
Co-authored-by: Jean-Francois Penven <[email protected]>
Co-authored-by: yunhanw <[email protected]>
Co-authored-by: Song GUO <[email protected]>
Co-authored-by: mkardous-silabs <[email protected]>
  • Loading branch information
6 people authored and pull[bot] committed May 30, 2024
1 parent 5e5b341 commit 92808b2
Show file tree
Hide file tree
Showing 18 changed files with 479 additions and 13 deletions.
1 change: 1 addition & 0 deletions examples/chip-tool/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static_library("chip-tool-utils") {

public_deps = [
"${chip_root}/examples/common/tracing:commandline",
"${chip_root}/src/app/icd/client:handler",
"${chip_root}/src/app/icd/client:manager",
"${chip_root}/src/app/server",
"${chip_root}/src/app/tests/suites/commands/interaction_model",
Expand Down
6 changes: 6 additions & 0 deletions examples/chip-tool/commands/common/CHIPCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ chip::Credentials::GroupDataProviderImpl CHIPCommand::sGroupDataProvider{ kMaxGr
// All fabrics share the same ICD client storage.
chip::app::DefaultICDClientStorage CHIPCommand::sICDClientStorage;
chip::Crypto::RawKeySessionKeystore CHIPCommand::sSessionKeystore;
chip::app::DefaultCheckInDelegate CHIPCommand::sCheckInDelegate;
chip::app::CheckInHandler CHIPCommand::sCheckInHandler;

namespace {

Expand Down Expand Up @@ -139,6 +141,10 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack()

ReturnErrorOnFailure(GetAttestationTrustStore(mPaaTrustStorePath.ValueOr(nullptr), &sTrustStore));

ReturnLogErrorOnFailure(sCheckInDelegate.Init(&sICDClientStorage));
ReturnLogErrorOnFailure(sCheckInHandler.Init(DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(),
&sICDClientStorage, &sCheckInDelegate));

CommissionerIdentity nullIdentity{ kIdentityNull, chip::kUndefinedNodeId };
ReturnLogErrorOnFailure(InitializeCommissioner(nullIdentity, kIdentityNullFabricId));

Expand Down
4 changes: 4 additions & 0 deletions examples/chip-tool/commands/common/CHIPCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "Command.h"

#include <TracingCommandLineArgument.h>
#include <app/icd/client/CheckInHandler.h>
#include <app/icd/client/DefaultCheckInDelegate.h>
#include <app/icd/client/DefaultICDClientStorage.h>
#include <commands/common/CredentialIssuerCommands.h>
#include <commands/example/ExampleCredentialIssuerCommands.h>
Expand Down Expand Up @@ -160,6 +162,8 @@ class CHIPCommand : public Command

static chip::Credentials::GroupDataProviderImpl sGroupDataProvider;
static chip::app::DefaultICDClientStorage sICDClientStorage;
static chip::app::DefaultCheckInDelegate sCheckInDelegate;
static chip::app::CheckInHandler sCheckInHandler;
CredentialIssuerCommands * mCredIssuerCmds;

std::string GetIdentity();
Expand Down
1 change: 1 addition & 0 deletions examples/tv-casting-app/tv-casting-common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ chip_data_model("tv-casting-common") {

deps = [
"${chip_root}/examples/common/tracing:commandline",
"${chip_root}/src/app/icd/client:handler",
"${chip_root}/src/app/icd/client:manager",
"${chip_root}/src/app/tests/suites/commands/interaction_model",
"${chip_root}/src/lib/support/jsontlv",
Expand Down
20 changes: 20 additions & 0 deletions src/app/icd/client/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,25 @@ source_set("manager") {
"${chip_root}/src/app:app_config",
"${chip_root}/src/crypto",
"${chip_root}/src/lib/support",
"${chip_root}/src/protocols",
]
}

# ICD Handler source-set is broken out of the main source-set to enable unit tests
# All sources and configurations used by the CheckInHandler need to go in this source-set
source_set("handler") {
sources = [
"CheckInDelegate.h",
"CheckInHandler.cpp",
"CheckInHandler.h",
"DefaultCheckInDelegate.cpp",
"DefaultCheckInDelegate.h",
]
public_deps = [
":manager",
"${chip_root}/src/app",
"${chip_root}/src/lib/core",
"${chip_root}/src/messaging",
"${chip_root}/src/protocols",
]
}
45 changes: 45 additions & 0 deletions src/app/icd/client/CheckInDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
*
* Copyright (c) 2023 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.
*/

#pragma once

#include <app/icd/client/ICDClientInfo.h>

namespace chip {
namespace app {

/// Callbacks for check in protocol
/**
* @brief The application implementing an ICD client should inherit the CheckInDelegate and implement the listed callbacks
*/
class DLL_EXPORT CheckInDelegate
{
public:
virtual ~CheckInDelegate() {}

/**
* @brief Callback used to let the application know that a check-in message was received and validated.
*
* @param[in] clientInfo - ICDClientInfo object representing the state associated with the
node that sent the check-in message.
*/
virtual void OnCheckInComplete(const ICDClientInfo & clientInfo) = 0;
};

} // namespace app
} // namespace chip
126 changes: 126 additions & 0 deletions src/app/icd/client/CheckInHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
*
* Copyright (c) 2023 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
* This file defines objects for a CHIP ICD handler which handles unsolicited check-in messages.
*
*/

#include <app/InteractionModelTimeout.h>
#include <app/icd/client/CheckInDelegate.h>
#include <app/icd/client/CheckInHandler.h>

#include <cinttypes>

#include <lib/core/Global.h>
#include <lib/support/CodeUtils.h>
#include <messaging/Flags.h>
#include <protocols/Protocols.h>

#include <protocols/secure_channel/Constants.h>

namespace chip {
namespace app {

inline constexpr uint64_t kCheckInCounterMax = (1ULL << 32);
inline constexpr uint32_t kKeyRefreshLimit = (1U << 31);

CheckInHandler::CheckInHandler() {}

CHIP_ERROR CheckInHandler::Init(Messaging::ExchangeManager * exchangeManager, ICDClientStorage * clientStorage,
CheckInDelegate * delegate)
{
VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(clientStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(mpExchangeManager == nullptr, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mpICDClientStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);

mpExchangeManager = exchangeManager;
mpICDClientStorage = clientStorage;
mpCheckInDelegate = delegate;

return mpExchangeManager->RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::ICD_CheckIn, this);
}

void CheckInHandler::Shutdown()
{
mpICDClientStorage = nullptr;
mpCheckInDelegate = nullptr;
if (mpExchangeManager)
{
mpExchangeManager->UnregisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::ICD_CheckIn);
mpExchangeManager = nullptr;
}
}

CHIP_ERROR CheckInHandler::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate)
{
// Return error for wrong message type
VerifyOrReturnError(payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::ICD_CheckIn),
CHIP_ERROR_INVALID_MESSAGE_TYPE);

newDelegate = this;
return CHIP_NO_ERROR;
}

CHIP_ERROR CheckInHandler::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
System::PacketBufferHandle && payload)
{
// If the message type is not ICD_CheckIn, return CHIP_NO_ERROR and exit
VerifyOrReturnError(payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::ICD_CheckIn), CHIP_NO_ERROR);

ByteSpan payloadByteSpan{ payload->Start(), payload->DataLength() };
ICDClientInfo clientInfo;
CounterType counter = 0;
// If the check-in message processing fails, return CHIP_NO_ERROR and exit.
CHIP_ERROR err = mpICDClientStorage->ProcessCheckInPayload(payloadByteSpan, clientInfo, counter);
if (CHIP_NO_ERROR != err)
{
ChipLogError(ICD, "ProcessCheckInPayload failed: %" CHIP_ERROR_FORMAT, err.Format());
return CHIP_NO_ERROR;
}
CounterType receivedCheckInCounterOffset = (counter - clientInfo.start_icd_counter) % kCheckInCounterMax;

// Detect duplicate check-in messages and return CHIP_NO_ERROR on receiving a duplicate message
if (receivedCheckInCounterOffset <= clientInfo.offset)
{
ChipLogError(ICD, "A duplicate check-in message was received and discarded");
return CHIP_NO_ERROR;
}

clientInfo.offset = receivedCheckInCounterOffset;
bool refreshKey = (receivedCheckInCounterOffset > kKeyRefreshLimit);

if (refreshKey)
{
// TODO: A new CASE session should be established to re-register the client using a new key. The registration will happen in
// CASE session callback
}
else
{
mpCheckInDelegate->OnCheckInComplete(clientInfo);
}

return CHIP_NO_ERROR;
}

void CheckInHandler::OnResponseTimeout(Messaging::ExchangeContext * ec) {}

} // namespace app
} // namespace chip
93 changes: 93 additions & 0 deletions src/app/icd/client/CheckInHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
*
* Copyright (c) 2023 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
* This file defines objects for a CHIP check-in message unsolicited
* handler
*
*/

#pragma once

#include <app-common/zap-generated/cluster-objects.h>
#include <app/CommandSender.h>
#include <app/OperationalSessionSetup.h>
#include <app/icd/client/CheckInDelegate.h>
#include <app/icd/client/DefaultICDClientStorage.h>
#include <lib/support/logging/CHIPLogging.h>
#include <messaging/ExchangeContext.h>
#include <messaging/ExchangeMgr.h>

namespace chip {
namespace app {

class CheckInHandler : public Messaging::ExchangeDelegate, public Messaging::UnsolicitedMessageHandler
{

public:
CHIP_ERROR Init(Messaging::ExchangeManager * exchangeManager, ICDClientStorage * clientStorage, CheckInDelegate * delegate);
void Shutdown();

CheckInHandler();

virtual ~CheckInHandler() = default;

protected:
// ExchangeDelegate
CHIP_ERROR
OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
System::PacketBufferHandle && payload) override;

// UnsolicitedMessageHandler
CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate) override;

// TODO : Follow up to check if this really needs to be a pure virtual function in Exchange delegate
// https://github.com/project-chip/connectedhomeip/issues/31322
void OnResponseTimeout(Messaging::ExchangeContext * ec) override;

Messaging::ExchangeMessageDispatch & GetMessageDispatch() override { return CheckInExchangeDispatch::Instance(); }

private:
class CheckInExchangeDispatch : public Messaging::ExchangeMessageDispatch
{
public:
static ExchangeMessageDispatch & Instance()
{
static CheckInExchangeDispatch instance;
return instance;
}

CheckInExchangeDispatch() {}
~CheckInExchangeDispatch() override {}

protected:
bool MessagePermitted(Protocols::Id, uint8_t type) override
{
return type == to_underlying(Protocols::SecureChannel::MsgType::ICD_CheckIn);
}
bool IsEncryptionRequired() const override { return false; }
};

Messaging::ExchangeManager * mpExchangeManager = nullptr;
CheckInDelegate * mpCheckInDelegate = nullptr;
ICDClientStorage * mpICDClientStorage = nullptr;
};

} // namespace app
} // namespace chip
44 changes: 44 additions & 0 deletions src/app/icd/client/DefaultCheckInDelegate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2023 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 "CheckInHandler.h"
#include <app/icd/client/DefaultCheckInDelegate.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <memory>

namespace chip {
namespace app {

CHIP_ERROR DefaultCheckInDelegate::Init(ICDClientStorage * storage)
{
VerifyOrReturnError(storage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(mpStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
mpStorage = storage;
return CHIP_NO_ERROR;
}

void DefaultCheckInDelegate::OnCheckInComplete(const ICDClientInfo & clientInfo)
{
ChipLogProgress(
ICD, "Check In Message processing complete: start_counter=%" PRIu32 " offset=%" PRIu32 " nodeid=" ChipLogFormatScopedNodeId,
clientInfo.start_icd_counter, clientInfo.offset, ChipLogValueScopedNodeId(clientInfo.peer_node));
}

} // namespace app
} // namespace chip
Loading

0 comments on commit 92808b2

Please sign in to comment.