Skip to content

Commit

Permalink
Add EventFilter encoding (#11178)
Browse files Browse the repository at this point in the history
  • Loading branch information
yunhanw-google authored and pull[bot] committed May 9, 2023
1 parent 45ec5bf commit 6d03a87
Show file tree
Hide file tree
Showing 6 changed files with 566 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ static_library("app") {
"MessageDef/CommandPathIB.h",
"MessageDef/EventDataElement.cpp",
"MessageDef/EventDataElement.h",
"MessageDef/EventFilterIB.cpp",
"MessageDef/EventFilters.cpp",
"MessageDef/EventList.cpp",
"MessageDef/EventList.h",
"MessageDef/EventPath.cpp",
Expand Down
151 changes: 151 additions & 0 deletions src/app/MessageDef/EventFilterIB.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/**
*
* Copyright (c) 2021 Project CHIP Authors
* 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 EventFilterIB parser and builder in CHIP interaction model
*
*/

#include "EventFilterIB.h"

#include "MessageDefHelper.h"

#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>

#include <app/AppBuildConfig.h>

namespace chip {
namespace app {
CHIP_ERROR EventFilterIB::Parser::Init(const chip::TLV::TLVReader & aReader)
{
mReader.Init(aReader);
VerifyOrReturnError(chip::TLV::kTLVType_Structure == mReader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE);
ReturnErrorOnFailure(mReader.EnterContainer(mOuterContainerType));
return CHIP_NO_ERROR;
}

#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
CHIP_ERROR EventFilterIB::Parser::CheckSchemaValidity() const
{
CHIP_ERROR err = CHIP_NO_ERROR;
int TagPresenceMask = 0;
TLV::TLVReader reader;

PRETTY_PRINT("EventFilterIB =");
PRETTY_PRINT("{");

// make a copy of the reader
reader.Init(mReader);

while (CHIP_NO_ERROR == (err = reader.Next()))
{
VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG);
uint32_t tagNum = TLV::TagNumFromTag(reader.GetTag());
switch (tagNum)
{
case to_underlying(Tag::kNode):
// check if this tag has appeared before
VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kNode))), CHIP_ERROR_INVALID_TLV_TAG);
TagPresenceMask |= (1 << to_underlying(Tag::kNode));
#if CHIP_DETAIL_LOGGING
{
NodeId node;
ReturnLogErrorOnFailure(reader.Get(node));
PRETTY_PRINT("\tNode = 0x%" PRIx64 ",", node);
}
#endif // CHIP_DETAIL_LOGGING
break;
case to_underlying(Tag::kEventMin):
// check if this tag has appeared before
VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kEventMin))), CHIP_ERROR_INVALID_TLV_TAG);
TagPresenceMask |= (1 << to_underlying(Tag::kEventMin));
#if CHIP_DETAIL_LOGGING
{
uint64_t eventMin;
ReturnLogErrorOnFailure(reader.Get(eventMin));
PRETTY_PRINT("\tEventMin = 0x%" PRIx64 ",", eventMin);
}
#endif // CHIP_DETAIL_LOGGING
break;
default:
PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum);
break;
}
}

PRETTY_PRINT("},");
PRETTY_PRINT("");

if (CHIP_END_OF_TLV == err)
{
const int RequiredFields = (1 << to_underlying(Tag::kEventMin));

if ((TagPresenceMask & RequiredFields) == RequiredFields)
{
err = CHIP_NO_ERROR;
}
}

ReturnErrorOnFailure(err);
ReturnErrorOnFailure(reader.ExitContainer(mOuterContainerType));
return CHIP_NO_ERROR;
}
#endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK

CHIP_ERROR EventFilterIB::Parser::GetNode(NodeId * const apNode) const
{
return GetUnsignedInteger(to_underlying(Tag::kNode), apNode);
}

CHIP_ERROR EventFilterIB::Parser::GetEventMin(uint64_t * const apEventMin) const
{
return GetUnsignedInteger(to_underlying(Tag::kEventMin), apEventMin);
}

CHIP_ERROR EventFilterIB::Builder::Init(TLV::TLVWriter * const apWriter)
{
return InitAnonymousStructure(apWriter);
}

EventFilterIB::Builder & EventFilterIB::Builder::Node(const NodeId aNode)
{
// skip if error has already been set
if (mError == CHIP_NO_ERROR)
{
mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kNode)), aNode);
}
return *this;
}

EventFilterIB::Builder & EventFilterIB::Builder::EventMin(const uint64_t aEventMin)
{
// skip if error has already been set
if (mError == CHIP_NO_ERROR)
{
mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kEventMin)), aEventMin);
}
return *this;
}

EventFilterIB::Builder & EventFilterIB::Builder::EndOfEventFilterIB()
{
EndOfContainer();
return *this;
}
}; // namespace app
}; // namespace chip
135 changes: 135 additions & 0 deletions src/app/MessageDef/EventFilterIB.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/**
*
* Copyright (c) 2021 Project CHIP Authors
*
* 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 EventFilterIB parser and builder in CHIP interaction model
*
*/

#pragma once

#include "Builder.h"
#include "Parser.h"

#include <app/AppBuildConfig.h>
#include <app/util/basic-types.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>

namespace chip {
namespace app {
namespace EventFilterIB {
enum class Tag : uint8_t
{
kNode = 0,
kEventMin = 1,
};

class Parser : public chip::app::Parser
{
public:
/**
* @brief Initialize the parser object with TLVReader
*
* @param [in] aReader A pointer to a TLVReader, which should point to the beginning of this EventFilterIB
*
* @return #CHIP_NO_ERROR on success
*/
CHIP_ERROR Init(const chip::TLV::TLVReader & aReader);

#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
/**
* @brief Roughly verify the message is correctly formed
* 1) all mandatory tags are present
* 2) all elements have expected data type
* 3) any tag can only appear once
* 4) At the top level of the structure, unknown tags are ignored for forward compatibility
* @note The main use of this function is to print out what we're
* receiving during protocol development and debugging.
* The encoding rule has changed in IM encoding spec so this
* check is only "roughly" conformant now.
*
* @return #CHIP_NO_ERROR on success
*/
CHIP_ERROR CheckSchemaValidity() const;
#endif

/**
* @brief Get a TLVReader for the NodeId. Next() must be called before accessing them.
*
* @param [in] apNodeId A pointer to apNodeId
*
* @return #CHIP_NO_ERROR on success
* #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types
* #CHIP_END_OF_TLV if there is no such element
*/
CHIP_ERROR GetNode(NodeId * const apNodeId) const;

/**
* @brief Get a TLVReader for the ClusterId. Next() must be called before accessing them.
*
* @param [in] apEventMin A pointer to EventMin
*
* @return #CHIP_NO_ERROR on success
* #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types
* #CHIP_END_OF_TLV if there is no such element
*/
CHIP_ERROR GetEventMin(uint64_t * const apEventMin) const;
};

class Builder : public chip::app::Builder
{
public:
/**
* @brief Initialize a EventFilterIB::Builder for writing into a TLV stream
*
* @param [in] apWriter A pointer to TLVWriter
*
* @return #CHIP_NO_ERROR on success
*/
CHIP_ERROR Init(chip::TLV::TLVWriter * const apWriter);

/**
* @brief Inject Node into the TLV stream to indicate the nodeId referenced by the event filter.
*
* @param [in] aNodeId refer to the NodeId
*
* @return A reference to *this
*/
EventFilterIB::Builder & Node(const NodeId aNode);

/**
* @brief Inject EventId into the TLV stream.
*
* @param [in] aEventMin EventMin for this event filter
*
* @return A reference to *this
*/
EventFilterIB::Builder & EventMin(const uint64_t aEventMin);

/**
* @brief Mark the end of this EventFilterIB
*
* @return A reference to *this
*/
EventFilterIB::Builder & EndOfEventFilterIB();
};
}; // namespace EventFilterIB
}; // namespace app
}; // namespace chip
91 changes: 91 additions & 0 deletions src/app/MessageDef/EventFilters.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
*
* Copyright (c) 2021 Project CHIP Authors
* 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 EventFilters parser and builder in CHIP interaction model
*
*/

#include "EventFilters.h"

#include "MessageDefHelper.h"

#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>

#include <app/AppBuildConfig.h>

namespace chip {
namespace app {
#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
CHIP_ERROR EventFilters::Parser::CheckSchemaValidity() const
{
CHIP_ERROR err = CHIP_NO_ERROR;
size_t numEventFilters = 0;
TLV::TLVReader reader;

PRETTY_PRINT("EventFilters =");
PRETTY_PRINT("[");

// make a copy of the reader
reader.Init(mReader);

while (CHIP_NO_ERROR == (err = reader.Next()))
{
VerifyOrReturnError(TLV::AnonymousTag == reader.GetTag(), CHIP_ERROR_INVALID_TLV_TAG);
{
EventFilterIB::Parser eventFilter;
ReturnErrorOnFailure(eventFilter.Init(reader));
PRETTY_PRINT_INCDEPTH();
ReturnErrorOnFailure(eventFilter.CheckSchemaValidity());
PRETTY_PRINT_DECDEPTH();
}

++numEventFilters;
}

PRETTY_PRINT("],");
PRETTY_PRINT("");

// if we have exhausted this container
if (CHIP_END_OF_TLV == err)
{
// if we have at least one event filter
if (numEventFilters > 0)
{
err = CHIP_NO_ERROR;
}
}
ReturnErrorOnFailure(err);
ReturnErrorOnFailure(reader.ExitContainer(mOuterContainerType));
return CHIP_NO_ERROR;
}
#endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK

EventFilterIB::Builder & EventFilters::Builder::CreateEventFilter()
{
mError = mEventFilter.Init(mpWriter);
return mEventFilter;
}

EventFilters::Builder & EventFilters::Builder::EndOfEventFilters()
{
EndOfContainer();
return *this;
}
}; // namespace app
}; // namespace chip
Loading

0 comments on commit 6d03a87

Please sign in to comment.