diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 8e109c2cea4eb8..56a9d0af129fd1 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -57,6 +57,7 @@ static_library("app") { "EventManagement.cpp", "EventPathParams.h", "InteractionModelEngine.cpp", + "InteractionModelRevision.h", "MessageDef/ArrayBuilder.cpp", "MessageDef/ArrayParser.cpp", "MessageDef/AttributeDataIB.cpp", @@ -107,8 +108,12 @@ static_library("app") { "MessageDef/InvokeResponseMessage.cpp", "MessageDef/ListBuilder.cpp", "MessageDef/ListParser.cpp", + "MessageDef/MessageBuilder.cpp", + "MessageDef/MessageBuilder.h", "MessageDef/MessageDefHelper.cpp", "MessageDef/MessageDefHelper.h", + "MessageDef/MessageParser.cpp", + "MessageDef/MessageParser.h", "MessageDef/Parser.cpp", "MessageDef/Parser.h", "MessageDef/ReadRequestMessage.cpp", diff --git a/src/app/InteractionModelRevision.h b/src/app/InteractionModelRevision.h new file mode 100644 index 00000000000000..9ad606493dbc92 --- /dev/null +++ b/src/app/InteractionModelRevision.h @@ -0,0 +1,29 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#pragma once + +/** + * CHIP_DEVICE_CONFIG_INTERACTION_MODEL_REVISION + * + * A monothonic number identifying the interaction model revision. + */ +#ifndef CHIP_DEVICE_CONFIG_INTERACTION_MODEL_REVISION +#define CHIP_DEVICE_CONFIG_INTERACTION_MODEL_REVISION 1 +#endif + +constexpr uint8_t kInteractionModelRevisionTag = 0xFF; diff --git a/src/app/MessageDef/InvokeRequestMessage.cpp b/src/app/MessageDef/InvokeRequestMessage.cpp index 7393849cac7491..54bd6670a4cbd2 100644 --- a/src/app/MessageDef/InvokeRequestMessage.cpp +++ b/src/app/MessageDef/InvokeRequestMessage.cpp @@ -29,7 +29,7 @@ namespace app { CHIP_ERROR InvokeRequestMessage::Parser::CheckSchemaValidity() const { CHIP_ERROR err = CHIP_NO_ERROR; - int TagPresenceMask = 0; + int tagPresenceMask = 0; TLV::TLVReader reader; PRETTY_PRINT("InvokeRequestMessage ="); @@ -46,8 +46,8 @@ CHIP_ERROR InvokeRequestMessage::Parser::CheckSchemaValidity() const { case to_underlying(Tag::kSuppressResponse): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kSuppressResponse))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kSuppressResponse)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kSuppressResponse))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kSuppressResponse)); #if CHIP_DETAIL_LOGGING { bool suppressResponse; @@ -59,8 +59,8 @@ CHIP_ERROR InvokeRequestMessage::Parser::CheckSchemaValidity() const case to_underlying(Tag::kTimedRequest): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kTimedRequest))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kTimedRequest)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kTimedRequest))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kTimedRequest)); #if CHIP_DETAIL_LOGGING { bool timedRequest; @@ -71,8 +71,8 @@ CHIP_ERROR InvokeRequestMessage::Parser::CheckSchemaValidity() const break; case to_underlying(Tag::kInvokeRequests): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kInvokeRequests))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kInvokeRequests)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kInvokeRequests))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kInvokeRequests)); { InvokeRequests::Parser invokeRequests; ReturnErrorOnFailure(invokeRequests.Init(reader)); @@ -82,6 +82,9 @@ CHIP_ERROR InvokeRequestMessage::Parser::CheckSchemaValidity() const PRETTY_PRINT_DECDEPTH(); } break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); break; @@ -96,7 +99,7 @@ CHIP_ERROR InvokeRequestMessage::Parser::CheckSchemaValidity() const const int RequiredFields = (1 << to_underlying(Tag::kSuppressResponse)) | (1 << to_underlying(Tag::kTimedRequest)) | (1 << to_underlying(Tag::kInvokeRequests)); - if ((TagPresenceMask & RequiredFields) == RequiredFields) + if ((tagPresenceMask & RequiredFields) == RequiredFields) { err = CHIP_NO_ERROR; } @@ -159,7 +162,14 @@ InvokeRequests::Builder & InvokeRequestMessage::Builder::CreateInvokeRequests() InvokeRequestMessage::Builder & InvokeRequestMessage::Builder::EndOfInvokeRequestMessage() { - EndOfContainer(); + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); + } return *this; } }; // namespace app diff --git a/src/app/MessageDef/InvokeRequestMessage.h b/src/app/MessageDef/InvokeRequestMessage.h index dcf3bdf4c0353c..9cfd13ac89c86b 100644 --- a/src/app/MessageDef/InvokeRequestMessage.h +++ b/src/app/MessageDef/InvokeRequestMessage.h @@ -25,8 +25,8 @@ #include #include "InvokeRequests.h" -#include "StructBuilder.h" -#include "StructParser.h" +#include "MessageBuilder.h" +#include "MessageParser.h" namespace chip { namespace app { @@ -38,7 +38,7 @@ enum class Tag : uint8_t kInvokeRequests = 2, }; -class Parser : public StructParser +class Parser : public MessageParser { public: #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK @@ -85,7 +85,7 @@ class Parser : public StructParser CHIP_ERROR GetInvokeRequests(InvokeRequests::Parser * const apInvokeRequests) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: /** @@ -122,6 +122,6 @@ class Builder : public StructBuilder private: InvokeRequests::Builder mInvokeRequests; }; -}; // namespace InvokeRequestMessage -}; // namespace app -}; // namespace chip +} // namespace InvokeRequestMessage +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/InvokeResponseMessage.cpp b/src/app/MessageDef/InvokeResponseMessage.cpp index c7643f7964eb3c..c36e76abfdefc3 100644 --- a/src/app/MessageDef/InvokeResponseMessage.cpp +++ b/src/app/MessageDef/InvokeResponseMessage.cpp @@ -29,7 +29,7 @@ namespace app { CHIP_ERROR InvokeResponseMessage::Parser::CheckSchemaValidity() const { CHIP_ERROR err = CHIP_NO_ERROR; - int TagPresenceMask = 0; + int tagPresenceMask = 0; TLV::TLVReader reader; PRETTY_PRINT("InvokeResponseMessage ="); @@ -46,8 +46,8 @@ CHIP_ERROR InvokeResponseMessage::Parser::CheckSchemaValidity() const { case to_underlying(Tag::kSuppressResponse): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kSuppressResponse))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kSuppressResponse)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kSuppressResponse))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kSuppressResponse)); #if CHIP_DETAIL_LOGGING { bool suppressResponse; @@ -58,8 +58,8 @@ CHIP_ERROR InvokeResponseMessage::Parser::CheckSchemaValidity() const break; case to_underlying(Tag::kInvokeResponses): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kInvokeResponses))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kInvokeResponses)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kInvokeResponses))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kInvokeResponses)); { InvokeResponseIBs::Parser invokeResponses; ReturnErrorOnFailure(invokeResponses.Init(reader)); @@ -69,6 +69,9 @@ CHIP_ERROR InvokeResponseMessage::Parser::CheckSchemaValidity() const PRETTY_PRINT_DECDEPTH(); } break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); break; @@ -82,7 +85,7 @@ CHIP_ERROR InvokeResponseMessage::Parser::CheckSchemaValidity() const { const int RequiredFields = (1 << to_underlying(Tag::kSuppressResponse)) | (1 << to_underlying(Tag::kInvokeResponses)); - if ((TagPresenceMask & RequiredFields) == RequiredFields) + if ((tagPresenceMask & RequiredFields) == RequiredFields) { err = CHIP_NO_ERROR; } @@ -131,7 +134,14 @@ InvokeResponseIBs::Builder & InvokeResponseMessage::Builder::CreateInvokeRespons InvokeResponseMessage::Builder & InvokeResponseMessage::Builder::EndOfInvokeResponseMessage() { - EndOfContainer(); + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); + } return *this; } } // namespace app diff --git a/src/app/MessageDef/InvokeResponseMessage.h b/src/app/MessageDef/InvokeResponseMessage.h index 7f7f87d6635c11..2d317a252a7858 100644 --- a/src/app/MessageDef/InvokeResponseMessage.h +++ b/src/app/MessageDef/InvokeResponseMessage.h @@ -25,8 +25,8 @@ #include #include "InvokeResponseIBs.h" -#include "StructBuilder.h" -#include "StructParser.h" +#include "MessageBuilder.h" +#include "MessageParser.h" namespace chip { namespace app { @@ -37,7 +37,7 @@ enum class Tag : uint8_t kInvokeResponses = 1, }; -class Parser : public StructParser +class Parser : public MessageParser { public: #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK @@ -76,7 +76,7 @@ class Parser : public StructParser CHIP_ERROR GetInvokeResponses(InvokeResponseIBs::Parser * const apInvokeResponses) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: /** diff --git a/src/app/MessageDef/MessageBuilder.cpp b/src/app/MessageDef/MessageBuilder.cpp new file mode 100644 index 00000000000000..129b5c1531b3b9 --- /dev/null +++ b/src/app/MessageDef/MessageBuilder.cpp @@ -0,0 +1,32 @@ +/** + * + * 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. + */ + +#include "MessageBuilder.h" + +#include +#include +#include + +namespace chip { +namespace app { +CHIP_ERROR MessageBuilder::EncodeInteractionModelRevision() +{ + ReturnErrorOnFailure(mpWriter->Put(TLV::ContextTag(kInteractionModelRevisionTag), + static_cast(CHIP_DEVICE_CONFIG_INTERACTION_MODEL_REVISION))); + return CHIP_NO_ERROR; +} +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/MessageBuilder.h b/src/app/MessageDef/MessageBuilder.h new file mode 100644 index 00000000000000..03210b3011cf21 --- /dev/null +++ b/src/app/MessageDef/MessageBuilder.h @@ -0,0 +1,32 @@ +/** + * + * 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. + */ + +#pragma once + +#include "StructBuilder.h" +#include +#include + +namespace chip { +namespace app { +class MessageBuilder : public StructBuilder +{ +public: + CHIP_ERROR EncodeInteractionModelRevision(); +}; +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/MessageDefHelper.cpp b/src/app/MessageDef/MessageDefHelper.cpp index f57feed0c35356..6bb137c2401e0d 100644 --- a/src/app/MessageDef/MessageDefHelper.cpp +++ b/src/app/MessageDef/MessageDefHelper.cpp @@ -23,16 +23,16 @@ #include "MessageDefHelper.h" #include +#include +#include +#include #include +#include #include #include -#include -#include - namespace chip { namespace app { - #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK && CHIP_DETAIL_LOGGING // this is used to run in signle thread for IM message debug purpose namespace { @@ -94,5 +94,6 @@ void DecreaseDepth() gPrettyPrintingDepthLevel--; } #endif + }; // namespace app }; // namespace chip diff --git a/src/app/MessageDef/MessageParser.cpp b/src/app/MessageDef/MessageParser.cpp new file mode 100644 index 00000000000000..9cbe8c087876c4 --- /dev/null +++ b/src/app/MessageDef/MessageParser.cpp @@ -0,0 +1,43 @@ +/** + * + * 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. + */ + +#include "MessageParser.h" +#include "MessageDefHelper.h" +#include + +namespace chip { +namespace app { +#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK +CHIP_ERROR MessageParser::CheckInteractionModelRevision(TLV::TLVReader & aReader) const +{ +#if CHIP_DETAIL_LOGGING + { + uint8_t interactionModelRevision = 0; + ReturnErrorOnFailure(aReader.Get(interactionModelRevision)); + PRETTY_PRINT("\tInteractionModelRevision = %u", interactionModelRevision); + } +#endif // CHIP_DETAIL_LOGGING + return CHIP_NO_ERROR; +} +#endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK + +CHIP_ERROR MessageParser::GetInteractionModelRevision(InteractionModelRevision * const apInteractionModelRevision) const +{ + return GetUnsignedInteger(kInteractionModelRevisionTag, apInteractionModelRevision); +} + +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/MessageParser.h b/src/app/MessageDef/MessageParser.h new file mode 100644 index 00000000000000..daee6e23693c88 --- /dev/null +++ b/src/app/MessageDef/MessageParser.h @@ -0,0 +1,38 @@ +/** + * + * Copyright (c) 2020 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. + */ + +#pragma once + +#include "StructParser.h" +#include +#include +#include + +namespace chip { +namespace app { +class MessageParser : public StructParser +{ +public: +#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK + CHIP_ERROR CheckInteractionModelRevision(TLV::TLVReader & aReader) const; +#endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK + + CHIP_ERROR GetInteractionModelRevision(InteractionModelRevision * const apInteractionModelRevision) const; +}; +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/ReadRequestMessage.cpp b/src/app/MessageDef/ReadRequestMessage.cpp index 0c80dcb3572a4c..97478821551ebc 100644 --- a/src/app/MessageDef/ReadRequestMessage.cpp +++ b/src/app/MessageDef/ReadRequestMessage.cpp @@ -29,7 +29,7 @@ namespace app { CHIP_ERROR ReadRequestMessage::Parser::CheckSchemaValidity() const { CHIP_ERROR err = CHIP_NO_ERROR; - int TagPresenceMask = 0; + int tagPresenceMask = 0; TLV::TLVReader reader; PRETTY_PRINT("ReadRequestMessage ="); @@ -46,8 +46,8 @@ CHIP_ERROR ReadRequestMessage::Parser::CheckSchemaValidity() const { case to_underlying(Tag::kAttributeRequests): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kAttributeRequests))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kAttributeRequests)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kAttributeRequests))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kAttributeRequests)); { AttributePathIBs::Parser attributeRequests; ReturnErrorOnFailure(attributeRequests.Init(reader)); @@ -59,8 +59,8 @@ CHIP_ERROR ReadRequestMessage::Parser::CheckSchemaValidity() const break; case to_underlying(Tag::kDataVersionFilters): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kEventFilters))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kDataVersionFilters)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kEventFilters))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kDataVersionFilters)); { DataVersionFilterIBs::Parser dataVersionFilters; ReturnErrorOnFailure(dataVersionFilters.Init(reader)); @@ -72,8 +72,8 @@ CHIP_ERROR ReadRequestMessage::Parser::CheckSchemaValidity() const break; case to_underlying(Tag::kEventRequests): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kEventRequests))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kEventRequests)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kEventRequests))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kEventRequests)); { EventPathIBs::Parser eventRequests; ReturnErrorOnFailure(eventRequests.Init(reader)); @@ -85,8 +85,8 @@ CHIP_ERROR ReadRequestMessage::Parser::CheckSchemaValidity() const break; case to_underlying(Tag::kEventFilters): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kEventFilters))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kEventFilters)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kEventFilters))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kEventFilters)); { EventFilterIBs::Parser eventFilters; ReturnErrorOnFailure(eventFilters.Init(reader)); @@ -98,8 +98,8 @@ CHIP_ERROR ReadRequestMessage::Parser::CheckSchemaValidity() const break; case to_underlying(Tag::kIsFabricFiltered): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kIsFabricFiltered))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kIsFabricFiltered)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kIsFabricFiltered))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kIsFabricFiltered)); #if CHIP_DETAIL_LOGGING { bool isFabricFiltered; @@ -108,6 +108,9 @@ CHIP_ERROR ReadRequestMessage::Parser::CheckSchemaValidity() const } #endif // CHIP_DETAIL_LOGGING break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); break; @@ -121,7 +124,7 @@ CHIP_ERROR ReadRequestMessage::Parser::CheckSchemaValidity() const { const int RequiredFields = (1 << to_underlying(Tag::kIsFabricFiltered)); - if ((TagPresenceMask & RequiredFields) == RequiredFields) + if ((tagPresenceMask & RequiredFields) == RequiredFields) { err = CHIP_NO_ERROR; } @@ -221,7 +224,14 @@ ReadRequestMessage::Builder & ReadRequestMessage::Builder::IsFabricFiltered(cons ReadRequestMessage::Builder & ReadRequestMessage::Builder::EndOfReadRequestMessage() { - EndOfContainer(); + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); + } return *this; } } // namespace app diff --git a/src/app/MessageDef/ReadRequestMessage.h b/src/app/MessageDef/ReadRequestMessage.h index 1db10868db8d67..9b67b945cef3b0 100644 --- a/src/app/MessageDef/ReadRequestMessage.h +++ b/src/app/MessageDef/ReadRequestMessage.h @@ -21,7 +21,8 @@ #include "DataVersionFilterIBs.h" #include "EventFilterIBs.h" #include "EventPathIBs.h" - +#include "MessageBuilder.h" +#include "MessageParser.h" #include #include #include @@ -41,7 +42,7 @@ enum class Tag : uint8_t kIsFabricFiltered = 4, }; -class Parser : public StructParser +class Parser : public MessageParser { public: #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK @@ -60,7 +61,6 @@ class Parser : public StructParser */ CHIP_ERROR CheckSchemaValidity() const; #endif - /** * @brief Get a TLVReader for the AttributePathIBs. Next() must be called before accessing them. * @@ -108,7 +108,7 @@ class Parser : public StructParser CHIP_ERROR GetIsFabricFiltered(bool * const apIsFabricFiltered) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: /** diff --git a/src/app/MessageDef/ReportDataMessage.cpp b/src/app/MessageDef/ReportDataMessage.cpp index 7beb73b9704e2a..51d6b678a3fe00 100644 --- a/src/app/MessageDef/ReportDataMessage.cpp +++ b/src/app/MessageDef/ReportDataMessage.cpp @@ -32,16 +32,15 @@ #include using namespace chip; -using namespace chip::TLV; namespace chip { namespace app { #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK CHIP_ERROR ReportDataMessage::Parser::CheckSchemaValidity() const { - CHIP_ERROR err = CHIP_NO_ERROR; - uint16_t tagPresenceMask = 0; - chip::TLV::TLVReader reader; + CHIP_ERROR err = CHIP_NO_ERROR; + int tagPresenceMask = 0; + TLV::TLVReader reader; AttributeReportIBs::Parser attributeReportIBs; EventReportIBs::Parser eventReportIBs; @@ -53,83 +52,82 @@ CHIP_ERROR ReportDataMessage::Parser::CheckSchemaValidity() const while (CHIP_NO_ERROR == (err = reader.Next())) { - VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG); - - switch (chip::TLV::TagNumFromTag(reader.GetTag())) + VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG); + uint32_t tagNum = TLV::TagNumFromTag(reader.GetTag()); + switch (tagNum) { - case kCsTag_SuppressResponse: - VerifyOrExit(!(tagPresenceMask & (1 << kCsTag_SuppressResponse)), err = CHIP_ERROR_INVALID_TLV_TAG); - tagPresenceMask |= (1 << kCsTag_SuppressResponse); - VerifyOrExit(chip::TLV::kTLVType_Boolean == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + case to_underlying(Tag::kSuppressResponse): + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kSuppressResponse))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kSuppressResponse)); + VerifyOrReturnError(TLV::kTLVType_Boolean == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { bool SuppressResponse; - err = reader.Get(SuppressResponse); - SuccessOrExit(err); + ReturnErrorOnFailure(reader.Get(SuppressResponse)); PRETTY_PRINT("\tSuppressResponse = %s, ", SuppressResponse ? "true" : "false"); } #endif // CHIP_DETAIL_LOGGING break; - case kCsTag_SubscriptionId: - VerifyOrExit(!(tagPresenceMask & (1 << kCsTag_SubscriptionId)), err = CHIP_ERROR_INVALID_TLV_TAG); - tagPresenceMask |= (1 << kCsTag_SubscriptionId); - VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + case to_underlying(Tag::kSubscriptionId): + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kSubscriptionId))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kSubscriptionId)); + VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { uint64_t subscriptionId; - err = reader.Get(subscriptionId); - SuccessOrExit(err); + ReturnErrorOnFailure(reader.Get(subscriptionId)); PRETTY_PRINT("\tSubscriptionId = 0x%" PRIx64 ",", subscriptionId); } #endif // CHIP_DETAIL_LOGGING break; - case kCsTag_AttributeReportIBs: + case to_underlying(Tag::kAttributeReportIBs): // check if this tag has appeared before - VerifyOrExit(!(tagPresenceMask & (1 << kCsTag_AttributeReportIBs)), err = CHIP_ERROR_INVALID_TLV_TAG); - tagPresenceMask |= (1 << kCsTag_AttributeReportIBs); - VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kAttributeReportIBs))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kAttributeReportIBs)); + VerifyOrReturnError(TLV::kTLVType_Array == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { attributeReportIBs.Init(reader); PRETTY_PRINT_INCDEPTH(); - err = attributeReportIBs.CheckSchemaValidity(); - SuccessOrExit(err); + ReturnErrorOnFailure(attributeReportIBs.CheckSchemaValidity()); PRETTY_PRINT_DECDEPTH(); } #endif // CHIP_DETAIL_LOGGING break; - case kCsTag_EventReports: + case to_underlying(Tag::kEventReports): // check if this tag has appeared before - VerifyOrExit(!(tagPresenceMask & (1 << kCsTag_EventReports)), err = CHIP_ERROR_INVALID_TLV_TAG); - tagPresenceMask |= (1 << kCsTag_EventReports); - VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kEventReports))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kEventReports)); + VerifyOrReturnError(TLV::kTLVType_Array == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { eventReportIBs.Init(reader); PRETTY_PRINT_INCDEPTH(); - err = eventReportIBs.CheckSchemaValidity(); - SuccessOrExit(err); + ReturnErrorOnFailure(eventReportIBs.CheckSchemaValidity()); PRETTY_PRINT_DECDEPTH(); } #endif // CHIP_DETAIL_LOGGING break; - case kCsTag_MoreChunkedMessages: - VerifyOrExit(!(tagPresenceMask & (1 << kCsTag_MoreChunkedMessages)), err = CHIP_ERROR_INVALID_TLV_TAG); - tagPresenceMask |= (1 << kCsTag_MoreChunkedMessages); - VerifyOrExit(chip::TLV::kTLVType_Boolean == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + case to_underlying(Tag::kMoreChunkedMessages): + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kMoreChunkedMessages))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kMoreChunkedMessages)); + VerifyOrReturnError(TLV::kTLVType_Boolean == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { bool moreChunkedMessages; - err = reader.Get(moreChunkedMessages); - SuccessOrExit(err); + ReturnErrorOnFailure(reader.Get(moreChunkedMessages)); PRETTY_PRINT("\tMoreChunkedMessages = %s, ", moreChunkedMessages ? "true" : "false"); } #endif // CHIP_DETAIL_LOGGING break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: - ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG); + PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); + break; } } @@ -140,75 +138,47 @@ CHIP_ERROR ReportDataMessage::Parser::CheckSchemaValidity() const { err = CHIP_NO_ERROR; } - SuccessOrExit(err); - err = reader.ExitContainer(mOuterContainerType); - -exit: - - return err; + ReturnErrorOnFailure(err); + return reader.ExitContainer(mOuterContainerType); } #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK CHIP_ERROR ReportDataMessage::Parser::GetSuppressResponse(bool * const apSuppressResponse) const { - return GetSimpleValue(kCsTag_SuppressResponse, chip::TLV::kTLVType_Boolean, apSuppressResponse); + return GetSimpleValue(to_underlying(Tag::kSuppressResponse), TLV::kTLVType_Boolean, apSuppressResponse); } CHIP_ERROR ReportDataMessage::Parser::GetSubscriptionId(uint64_t * const apSubscriptionId) const { - return GetUnsignedInteger(kCsTag_SubscriptionId, apSubscriptionId); + return GetUnsignedInteger(to_underlying(Tag::kSubscriptionId), apSubscriptionId); } CHIP_ERROR ReportDataMessage::Parser::GetAttributeReportIBs(AttributeReportIBs::Parser * const apAttributeReportIBs) const { - CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVReader reader; - - err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_AttributeReportIBs), reader); - SuccessOrExit(err); - - VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); - - err = apAttributeReportIBs->Init(reader); - SuccessOrExit(err); - -exit: - ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err)); - - return err; + TLV::TLVReader reader; + ReturnErrorOnFailure(mReader.FindElementWithTag(TLV::ContextTag(to_underlying(Tag::kAttributeReportIBs)), reader)); + return apAttributeReportIBs->Init(reader); } CHIP_ERROR ReportDataMessage::Parser::GetEventReports(EventReportIBs::Parser * const apEventReports) const { - CHIP_ERROR err = CHIP_NO_ERROR; - chip::TLV::TLVReader reader; - - err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_EventReports), reader); - SuccessOrExit(err); - - VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); - - err = apEventReports->Init(reader); - SuccessOrExit(err); - -exit: - ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err)); - - return err; + TLV::TLVReader reader; + ReturnErrorOnFailure(mReader.FindElementWithTag(TLV::ContextTag(to_underlying(Tag::kEventReports)), reader)); + return apEventReports->Init(reader); } CHIP_ERROR ReportDataMessage::Parser::GetMoreChunkedMessages(bool * const apMoreChunkedMessages) const { - return GetSimpleValue(kCsTag_MoreChunkedMessages, chip::TLV::kTLVType_Boolean, apMoreChunkedMessages); + return GetSimpleValue(to_underlying(Tag::kMoreChunkedMessages), TLV::kTLVType_Boolean, apMoreChunkedMessages); } ReportDataMessage::Builder & ReportDataMessage::Builder::SuppressResponse(const bool aSuppressResponse) { // skip if error has already been set - SuccessOrExit(mError); - mError = mpWriter->PutBoolean(chip::TLV::ContextTag(kCsTag_SuppressResponse), aSuppressResponse); - -exit: + if (mError == CHIP_NO_ERROR) + { + mError = mpWriter->PutBoolean(TLV::ContextTag(to_underlying(Tag::kSuppressResponse)), aSuppressResponse); + } return *this; } @@ -217,7 +187,7 @@ ReportDataMessage::Builder & ReportDataMessage::Builder::SubscriptionId(const ui // skip if error has already been set if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_SubscriptionId), aSubscriptionId); + mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kSubscriptionId)), aSubscriptionId); } return *this; } @@ -227,11 +197,7 @@ AttributeReportIBs::Builder & ReportDataMessage::Builder::CreateAttributeReportI // skip if error has already been set if (mError == CHIP_NO_ERROR) { - mError = mAttributeReportIBsBuilder.Init(mpWriter, kCsTag_AttributeReportIBs); - } - else - { - mAttributeReportIBsBuilder.ResetError(mError); + mError = mAttributeReportIBsBuilder.Init(mpWriter, to_underlying(Tag::kAttributeReportIBs)); } return mAttributeReportIBsBuilder; } @@ -241,11 +207,7 @@ EventReportIBs::Builder & ReportDataMessage::Builder::CreateEventReports() // skip if error has already been set if (mError == CHIP_NO_ERROR) { - mError = mEventReportsBuilder.Init(mpWriter, kCsTag_EventReports); - } - else - { - mAttributeReportIBsBuilder.ResetError(mError); + mError = mEventReportsBuilder.Init(mpWriter, to_underlying(Tag::kEventReports)); } return mEventReportsBuilder; } @@ -255,15 +217,22 @@ ReportDataMessage::Builder & ReportDataMessage::Builder::MoreChunkedMessages(con // skip if error has already been set if (mError == CHIP_NO_ERROR) { - mError = mpWriter->PutBoolean(chip::TLV::ContextTag(kCsTag_MoreChunkedMessages), aMoreChunkedMessages); + mError = mpWriter->PutBoolean(TLV::ContextTag(to_underlying(Tag::kMoreChunkedMessages)), aMoreChunkedMessages); } return *this; } ReportDataMessage::Builder & ReportDataMessage::Builder::EndOfReportDataMessage() { - EndOfContainer(); + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); + } return *this; } -}; // namespace app -}; // namespace chip +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/ReportDataMessage.h b/src/app/MessageDef/ReportDataMessage.h index fa4aeb2977b019..1e539a9068d138 100644 --- a/src/app/MessageDef/ReportDataMessage.h +++ b/src/app/MessageDef/ReportDataMessage.h @@ -32,22 +32,22 @@ #include "AttributeReportIBs.h" #include "EventReportIBs.h" -#include "StructBuilder.h" -#include "StructParser.h" +#include "MessageBuilder.h" +#include "MessageParser.h" namespace chip { namespace app { namespace ReportDataMessage { -enum +enum class Tag : uint8_t { - kCsTag_SubscriptionId = 0, - kCsTag_AttributeReportIBs = 1, - kCsTag_EventReports = 2, - kCsTag_MoreChunkedMessages = 3, - kCsTag_SuppressResponse = 4, + kSubscriptionId = 0, + kAttributeReportIBs = 1, + kEventReports = 2, + kMoreChunkedMessages = 3, + kSuppressResponse = 4, }; -class Parser : public StructParser +class Parser : public MessageParser { public: #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK @@ -121,7 +121,7 @@ class Parser : public StructParser CHIP_ERROR GetMoreChunkedMessages(bool * const apMoreChunkedMessages) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: /** @@ -179,7 +179,6 @@ class Builder : public StructBuilder AttributeReportIBs::Builder mAttributeReportIBsBuilder; EventReportIBs::Builder mEventReportsBuilder; }; -}; // namespace ReportDataMessage - -}; // namespace app -}; // namespace chip +} // namespace ReportDataMessage +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/StatusResponseMessage.cpp b/src/app/MessageDef/StatusResponseMessage.cpp index 6eb0422c8980d0..c306aba2618a9a 100644 --- a/src/app/MessageDef/StatusResponseMessage.cpp +++ b/src/app/MessageDef/StatusResponseMessage.cpp @@ -22,8 +22,8 @@ namespace app { #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK CHIP_ERROR StatusResponseMessage::Parser::CheckSchemaValidity() const { - CHIP_ERROR err = CHIP_NO_ERROR; - bool statusTagPresence = false; + CHIP_ERROR err = CHIP_NO_ERROR; + int tagPresenceMask = 0; TLV::TLVReader reader; PRETTY_PRINT("StatusResponseMessage ="); PRETTY_PRINT("{"); @@ -36,9 +36,9 @@ CHIP_ERROR StatusResponseMessage::Parser::CheckSchemaValidity() const VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG); switch (TLV::TagNumFromTag(reader.GetTag())) { - case kCsTag_Status: - VerifyOrReturnError(!statusTagPresence, CHIP_ERROR_INVALID_TLV_TAG); - statusTagPresence = true; + case to_underlying(Tag::kStatus): + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kStatus))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kStatus)); VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { @@ -48,6 +48,9 @@ CHIP_ERROR StatusResponseMessage::Parser::CheckSchemaValidity() const } #endif // CHIP_DETAIL_LOGGING break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: ReturnErrorOnFailure(CHIP_ERROR_INVALID_TLV_TAG); } @@ -55,9 +58,18 @@ CHIP_ERROR StatusResponseMessage::Parser::CheckSchemaValidity() const PRETTY_PRINT("}"); PRETTY_PRINT(""); - if (CHIP_END_OF_TLV == err && statusTagPresence) + if (CHIP_END_OF_TLV == err) { - err = CHIP_NO_ERROR; + const int requiredFields = (1 << to_underlying(Tag::kStatus)); + + if ((tagPresenceMask & requiredFields) == requiredFields) + { + err = CHIP_NO_ERROR; + } + else + { + err = CHIP_ERROR_IM_MALFORMED_STATUS_RESPONSE_MESSAGE; + } } ReturnErrorOnFailure(err); return reader.ExitContainer(mOuterContainerType); @@ -67,7 +79,7 @@ CHIP_ERROR StatusResponseMessage::Parser::CheckSchemaValidity() const CHIP_ERROR StatusResponseMessage::Parser::GetStatus(Protocols::InteractionModel::Status & aStatus) const { uint16_t status = 0; - CHIP_ERROR err = GetUnsignedInteger(kCsTag_Status, &status); + CHIP_ERROR err = GetUnsignedInteger(to_underlying(Tag::kStatus), &status); aStatus = static_cast(status); return err; } @@ -77,9 +89,16 @@ StatusResponseMessage::Builder & StatusResponseMessage::Builder::Status(const Pr // skip if error has already been set if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(TLV::ContextTag(kCsTag_Status), aStatus); + mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kStatus)), aStatus); + } + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); } - EndOfContainer(); return *this; } diff --git a/src/app/MessageDef/StatusResponseMessage.h b/src/app/MessageDef/StatusResponseMessage.h index ecec0dd5479a21..124091215ec820 100644 --- a/src/app/MessageDef/StatusResponseMessage.h +++ b/src/app/MessageDef/StatusResponseMessage.h @@ -16,8 +16,8 @@ */ #pragma once -#include "StructBuilder.h" -#include "StructParser.h" +#include "MessageBuilder.h" +#include "MessageParser.h" #include #include #include @@ -29,12 +29,13 @@ namespace chip { namespace app { namespace StatusResponseMessage { -enum + +enum class Tag : uint8_t { - kCsTag_Status = 0, + kStatus = 0, }; -class Parser : public StructParser +class Parser : public MessageParser { public: #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK @@ -63,7 +64,7 @@ class Parser : public StructParser CHIP_ERROR GetStatus(Protocols::InteractionModel::Status & aStatus) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: StatusResponseMessage::Builder & Status(const Protocols::InteractionModel::Status aStatus); diff --git a/src/app/MessageDef/SubscribeRequestMessage.cpp b/src/app/MessageDef/SubscribeRequestMessage.cpp index 4b73a34bae571c..38f5acbd0b47cc 100644 --- a/src/app/MessageDef/SubscribeRequestMessage.cpp +++ b/src/app/MessageDef/SubscribeRequestMessage.cpp @@ -152,6 +152,9 @@ CHIP_ERROR SubscribeRequestMessage::Parser::CheckSchemaValidity() const } #endif // CHIP_DETAIL_LOGGING break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); break; @@ -321,7 +324,14 @@ SubscribeRequestMessage::Builder & SubscribeRequestMessage::Builder::IsFabricFil SubscribeRequestMessage::Builder & SubscribeRequestMessage::Builder::EndOfSubscribeRequestMessage() { - EndOfContainer(); + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); + } return *this; } } // namespace app diff --git a/src/app/MessageDef/SubscribeRequestMessage.h b/src/app/MessageDef/SubscribeRequestMessage.h index acb8a4187fcd8a..f874b6b927c032 100644 --- a/src/app/MessageDef/SubscribeRequestMessage.h +++ b/src/app/MessageDef/SubscribeRequestMessage.h @@ -21,8 +21,8 @@ #include "DataVersionFilterIBs.h" #include "EventFilterIBs.h" #include "EventPathIBs.h" -#include "StructBuilder.h" -#include "StructParser.h" +#include "MessageBuilder.h" +#include "MessageParser.h" #include #include #include @@ -46,7 +46,7 @@ enum class Tag : uint8_t kIsFabricFiltered = 8, }; -class Parser : public StructParser +class Parser : public MessageParser { public: #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK @@ -136,7 +136,7 @@ class Parser : public StructParser CHIP_ERROR GetIsFabricFiltered(bool * const apIsFabricFiltered) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: /** diff --git a/src/app/MessageDef/SubscribeResponseMessage.cpp b/src/app/MessageDef/SubscribeResponseMessage.cpp index 6236e870388a97..553b026186d5dd 100644 --- a/src/app/MessageDef/SubscribeResponseMessage.cpp +++ b/src/app/MessageDef/SubscribeResponseMessage.cpp @@ -22,9 +22,9 @@ namespace app { #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK CHIP_ERROR SubscribeResponseMessage::Parser::CheckSchemaValidity() const { - CHIP_ERROR err = CHIP_NO_ERROR; - uint16_t TagPresenceMask = 0; - chip::TLV::TLVReader reader; + CHIP_ERROR err = CHIP_NO_ERROR; + int tagPresenceMask = 0; + TLV::TLVReader reader; PRETTY_PRINT("SubscribeResponseMessage ="); PRETTY_PRINT("{"); @@ -33,12 +33,13 @@ CHIP_ERROR SubscribeResponseMessage::Parser::CheckSchemaValidity() const while (CHIP_NO_ERROR == (err = reader.Next())) { - VerifyOrReturnError(chip::TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG); - switch (chip::TLV::TagNumFromTag(reader.GetTag())) + VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG); + uint32_t tagNum = TLV::TagNumFromTag(reader.GetTag()); + switch (tagNum) { - case kCsTag_SubscriptionId: - VerifyOrReturnError(!(TagPresenceMask & (1 << kCsTag_SubscriptionId)), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << kCsTag_SubscriptionId); + case to_underlying(Tag::kSubscriptionId): + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kSubscriptionId))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kSubscriptionId)); VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { @@ -48,10 +49,11 @@ CHIP_ERROR SubscribeResponseMessage::Parser::CheckSchemaValidity() const } #endif // CHIP_DETAIL_LOGGING break; - case kCsTag_MinIntervalFloorSeconds: - VerifyOrReturnError(!(TagPresenceMask & (1 << kCsTag_MinIntervalFloorSeconds)), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << kCsTag_MinIntervalFloorSeconds); - VerifyOrReturnError(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); + case to_underlying(Tag::kMinIntervalFloorSeconds): + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kMinIntervalFloorSeconds))), + CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kMinIntervalFloorSeconds)); + VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { uint16_t minIntervalFloorSeconds; @@ -60,10 +62,11 @@ CHIP_ERROR SubscribeResponseMessage::Parser::CheckSchemaValidity() const } #endif // CHIP_DETAIL_LOGGING break; - case kCsTag_MaxIntervalCeilingSeconds: - VerifyOrReturnError(!(TagPresenceMask & (1 << kCsTag_MaxIntervalCeilingSeconds)), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << kCsTag_MaxIntervalCeilingSeconds); - VerifyOrReturnError(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); + case to_underlying(Tag::kMaxIntervalCeilingSeconds): + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kMaxIntervalCeilingSeconds))), + CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kMaxIntervalCeilingSeconds)); + VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { uint16_t maxIntervalCeilingSeconds; @@ -72,8 +75,12 @@ CHIP_ERROR SubscribeResponseMessage::Parser::CheckSchemaValidity() const } #endif // CHIP_DETAIL_LOGGING break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: - ReturnErrorOnFailure(CHIP_ERROR_INVALID_TLV_TAG); + PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); + break; } } PRETTY_PRINT("}"); @@ -81,10 +88,10 @@ CHIP_ERROR SubscribeResponseMessage::Parser::CheckSchemaValidity() const if (CHIP_END_OF_TLV == err) { - const uint16_t RequiredFields = - (1 << kCsTag_SubscriptionId) | (1 << kCsTag_MinIntervalFloorSeconds) | (1 << kCsTag_MaxIntervalCeilingSeconds); + const uint16_t RequiredFields = (1 << to_underlying(Tag::kSubscriptionId)) | + (1 << to_underlying(Tag::kMinIntervalFloorSeconds)) | (1 << to_underlying(Tag::kMaxIntervalCeilingSeconds)); - if ((TagPresenceMask & RequiredFields) == RequiredFields) + if ((tagPresenceMask & RequiredFields) == RequiredFields) { err = CHIP_NO_ERROR; } @@ -100,24 +107,24 @@ CHIP_ERROR SubscribeResponseMessage::Parser::CheckSchemaValidity() const CHIP_ERROR SubscribeResponseMessage::Parser::GetSubscriptionId(uint64_t * const apSubscribeId) const { - return GetUnsignedInteger(kCsTag_SubscriptionId, apSubscribeId); + return GetUnsignedInteger(to_underlying(Tag::kSubscriptionId), apSubscribeId); } CHIP_ERROR SubscribeResponseMessage::Parser::GetMinIntervalFloorSeconds(uint16_t * const apMinIntervalFloorSeconds) const { - return GetUnsignedInteger(kCsTag_MinIntervalFloorSeconds, apMinIntervalFloorSeconds); + return GetUnsignedInteger(to_underlying(Tag::kMinIntervalFloorSeconds), apMinIntervalFloorSeconds); } CHIP_ERROR SubscribeResponseMessage::Parser::GetMaxIntervalCeilingSeconds(uint16_t * const apMaxIntervalCeilingSeconds) const { - return GetUnsignedInteger(kCsTag_MaxIntervalCeilingSeconds, apMaxIntervalCeilingSeconds); + return GetUnsignedInteger(to_underlying(Tag::kMaxIntervalCeilingSeconds), apMaxIntervalCeilingSeconds); } SubscribeResponseMessage::Builder & SubscribeResponseMessage::Builder::SubscriptionId(const uint64_t aSubscribeId) { if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_SubscriptionId), aSubscribeId); + mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kSubscriptionId)), aSubscribeId); } return *this; } @@ -127,7 +134,7 @@ SubscribeResponseMessage::Builder::MinIntervalFloorSeconds(const uint16_t aMinIn { if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_MinIntervalFloorSeconds), aMinIntervalFloorSeconds); + mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kMinIntervalFloorSeconds)), aMinIntervalFloorSeconds); } return *this; } @@ -137,14 +144,21 @@ SubscribeResponseMessage::Builder::MaxIntervalCeilingSeconds(const uint16_t aMax { if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_MaxIntervalCeilingSeconds), aMaxIntervalCeilingSeconds); + mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kMaxIntervalCeilingSeconds)), aMaxIntervalCeilingSeconds); } return *this; } SubscribeResponseMessage::Builder & SubscribeResponseMessage::Builder::EndOfSubscribeResponseMessage() { - EndOfContainer(); + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); + } return *this; } } // namespace app diff --git a/src/app/MessageDef/SubscribeResponseMessage.h b/src/app/MessageDef/SubscribeResponseMessage.h index 83c5739b14fa8f..68a94dd18f9383 100644 --- a/src/app/MessageDef/SubscribeResponseMessage.h +++ b/src/app/MessageDef/SubscribeResponseMessage.h @@ -17,8 +17,8 @@ #pragma once #include "EventPathIBs.h" -#include "StructBuilder.h" -#include "StructParser.h" +#include "MessageBuilder.h" +#include "MessageParser.h" #include #include #include @@ -29,14 +29,14 @@ namespace chip { namespace app { namespace SubscribeResponseMessage { -enum +enum class Tag : uint8_t { - kCsTag_SubscriptionId = 0, - kCsTag_MinIntervalFloorSeconds = 1, - kCsTag_MaxIntervalCeilingSeconds = 2, + kSubscriptionId = 0, + kMinIntervalFloorSeconds = 1, + kMaxIntervalCeilingSeconds = 2, }; -class Parser : public StructParser +class Parser : public MessageParser { public: #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK @@ -79,7 +79,7 @@ class Parser : public StructParser CHIP_ERROR GetMaxIntervalCeilingSeconds(uint16_t * const apMaxIntervalCeilingSeconds) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: /** diff --git a/src/app/MessageDef/TimedRequestMessage.cpp b/src/app/MessageDef/TimedRequestMessage.cpp index e922842bde0ebf..d2117efcf33479 100644 --- a/src/app/MessageDef/TimedRequestMessage.cpp +++ b/src/app/MessageDef/TimedRequestMessage.cpp @@ -23,7 +23,7 @@ namespace app { CHIP_ERROR TimedRequestMessage::Parser::CheckSchemaValidity() const { CHIP_ERROR err = CHIP_NO_ERROR; - int TagPresenceMask = 0; + int tagPresenceMask = 0; TLV::TLVReader reader; PRETTY_PRINT("TimedRequestMessage ="); PRETTY_PRINT("{"); @@ -34,11 +34,12 @@ CHIP_ERROR TimedRequestMessage::Parser::CheckSchemaValidity() const while (CHIP_NO_ERROR == (err = reader.Next())) { VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG); - switch (TLV::TagNumFromTag(reader.GetTag())) + uint32_t tagNum = TLV::TagNumFromTag(reader.GetTag()); + switch (tagNum) { case to_underlying(Tag::kTimeoutMs): - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kTimeoutMs))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kTimeoutMs)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kTimeoutMs))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kTimeoutMs)); VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { @@ -48,21 +49,28 @@ CHIP_ERROR TimedRequestMessage::Parser::CheckSchemaValidity() const } #endif // CHIP_DETAIL_LOGGING break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: - ReturnErrorOnFailure(CHIP_ERROR_INVALID_TLV_TAG); + 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::kTimeoutMs)); - if ((TagPresenceMask & RequiredFields) == RequiredFields) + if ((tagPresenceMask & RequiredFields) == RequiredFields) { err = CHIP_NO_ERROR; } + else + { + err = CHIP_ERROR_IM_MALFORMED_TIMED_REQUEST_MESSAGE; + } } ReturnErrorOnFailure(err); return reader.ExitContainer(mOuterContainerType); @@ -81,7 +89,14 @@ TimedRequestMessage::Builder & TimedRequestMessage::Builder::TimeoutMs(const uin { mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kTimeoutMs)), aTimeoutMs); } - EndOfContainer(); + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); + } return *this; } } // namespace app diff --git a/src/app/MessageDef/TimedRequestMessage.h b/src/app/MessageDef/TimedRequestMessage.h index 8873ec3d0f0050..1151bd21e2c43b 100644 --- a/src/app/MessageDef/TimedRequestMessage.h +++ b/src/app/MessageDef/TimedRequestMessage.h @@ -16,8 +16,8 @@ */ #pragma once -#include "StructBuilder.h" -#include "StructParser.h" +#include "MessageBuilder.h" +#include "MessageParser.h" #include #include #include @@ -33,7 +33,7 @@ enum class Tag : uint8_t kTimeoutMs = 0, }; -class Parser : public StructParser +class Parser : public MessageParser { public: #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK @@ -62,7 +62,7 @@ class Parser : public StructParser CHIP_ERROR GetTimeoutMs(uint16_t * const apTimeoutMs) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: /** diff --git a/src/app/MessageDef/WriteRequestMessage.cpp b/src/app/MessageDef/WriteRequestMessage.cpp index ace36b410f5538..de08b814c0251b 100644 --- a/src/app/MessageDef/WriteRequestMessage.cpp +++ b/src/app/MessageDef/WriteRequestMessage.cpp @@ -34,7 +34,7 @@ namespace app { CHIP_ERROR WriteRequestMessage::Parser::CheckSchemaValidity() const { CHIP_ERROR err = CHIP_NO_ERROR; - int TagPresenceMask = 0; + int tagPresenceMask = 0; TLV::TLVReader reader; PRETTY_PRINT("WriteRequestMessage ="); @@ -51,8 +51,8 @@ CHIP_ERROR WriteRequestMessage::Parser::CheckSchemaValidity() const { case to_underlying(Tag::kSuppressResponse): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kSuppressResponse))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kSuppressResponse)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kSuppressResponse))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kSuppressResponse)); #if CHIP_DETAIL_LOGGING { bool suppressResponse; @@ -64,8 +64,8 @@ CHIP_ERROR WriteRequestMessage::Parser::CheckSchemaValidity() const case to_underlying(Tag::kTimedRequest): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kTimedRequest))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kTimedRequest)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kTimedRequest))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kTimedRequest)); #if CHIP_DETAIL_LOGGING { bool timedRequest; @@ -76,8 +76,8 @@ CHIP_ERROR WriteRequestMessage::Parser::CheckSchemaValidity() const break; case to_underlying(Tag::kWriteRequests): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kWriteRequests))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kWriteRequests)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kWriteRequests))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kWriteRequests)); { AttributeDataIBs::Parser writeRequests; ReturnErrorOnFailure(writeRequests.Init(reader)); @@ -89,8 +89,8 @@ CHIP_ERROR WriteRequestMessage::Parser::CheckSchemaValidity() const break; case to_underlying(Tag::kMoreChunkedMessages): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kMoreChunkedMessages))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kMoreChunkedMessages)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kMoreChunkedMessages))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kMoreChunkedMessages)); #if CHIP_DETAIL_LOGGING { bool moreChunkedMessages; @@ -101,8 +101,8 @@ CHIP_ERROR WriteRequestMessage::Parser::CheckSchemaValidity() const break; case to_underlying(Tag::kIsFabricFiltered): // check if this tag has appeared before - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kIsFabricFiltered))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kIsFabricFiltered)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kIsFabricFiltered))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kIsFabricFiltered)); #if CHIP_DETAIL_LOGGING { bool isFabricFiltered; @@ -111,6 +111,9 @@ CHIP_ERROR WriteRequestMessage::Parser::CheckSchemaValidity() const } #endif // CHIP_DETAIL_LOGGING break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); break; @@ -125,7 +128,7 @@ CHIP_ERROR WriteRequestMessage::Parser::CheckSchemaValidity() const const int RequiredFields = (1 << to_underlying(Tag::kIsFabricFiltered)) | (1 << to_underlying(Tag::kTimedRequest)) | (1 << to_underlying(Tag::kWriteRequests)); - if ((TagPresenceMask & RequiredFields) == RequiredFields) + if ((tagPresenceMask & RequiredFields) == RequiredFields) { err = CHIP_NO_ERROR; } @@ -219,7 +222,14 @@ WriteRequestMessage::Builder & WriteRequestMessage::Builder::IsFabricFiltered(co WriteRequestMessage::Builder & WriteRequestMessage::Builder::EndOfWriteRequestMessage() { - EndOfContainer(); + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); + } return *this; } } // namespace app diff --git a/src/app/MessageDef/WriteRequestMessage.h b/src/app/MessageDef/WriteRequestMessage.h index 6af673a8342920..a914ab8546a64a 100644 --- a/src/app/MessageDef/WriteRequestMessage.h +++ b/src/app/MessageDef/WriteRequestMessage.h @@ -23,8 +23,8 @@ #pragma once #include "AttributeDataIBs.h" -#include "StructBuilder.h" -#include "StructParser.h" +#include "MessageBuilder.h" +#include "MessageParser.h" #include #include #include @@ -43,7 +43,7 @@ enum class Tag : uint8_t kIsFabricFiltered = 4, }; -class Parser : public StructParser +class Parser : public MessageParser { public: /** @@ -110,7 +110,7 @@ class Parser : public StructParser CHIP_ERROR GetIsFabricFiltered(bool * const apIsFabricFiltered) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: /** diff --git a/src/app/MessageDef/WriteResponseMessage.cpp b/src/app/MessageDef/WriteResponseMessage.cpp index 325a7a91573345..d0b70644037d6a 100644 --- a/src/app/MessageDef/WriteResponseMessage.cpp +++ b/src/app/MessageDef/WriteResponseMessage.cpp @@ -29,7 +29,7 @@ namespace app { CHIP_ERROR WriteResponseMessage::Parser::CheckSchemaValidity() const { CHIP_ERROR err = CHIP_NO_ERROR; - int TagPresenceMask = 0; + int tagPresenceMask = 0; TLV::TLVReader reader; AttributeStatusIBs::Parser writeResponses; PRETTY_PRINT("WriteResponseMessage ="); @@ -45,8 +45,8 @@ CHIP_ERROR WriteResponseMessage::Parser::CheckSchemaValidity() const switch (tagNum) { case to_underlying(Tag::kWriteResponses): - VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kWriteResponses))), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << to_underlying(Tag::kWriteResponses)); + VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kWriteResponses))), CHIP_ERROR_INVALID_TLV_TAG); + tagPresenceMask |= (1 << to_underlying(Tag::kWriteResponses)); VerifyOrReturnError(TLV::kTLVType_Array == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); ReturnErrorOnFailure(writeResponses.Init(reader)); @@ -54,6 +54,9 @@ CHIP_ERROR WriteResponseMessage::Parser::CheckSchemaValidity() const ReturnErrorOnFailure(writeResponses.CheckSchemaValidity()); PRETTY_PRINT_DECDEPTH(); break; + case kInteractionModelRevisionTag: + ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); + break; default: PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); break; @@ -67,7 +70,7 @@ CHIP_ERROR WriteResponseMessage::Parser::CheckSchemaValidity() const { const int RequiredFields = (1 << to_underlying(Tag::kWriteResponses)); - if ((TagPresenceMask & RequiredFields) == RequiredFields) + if ((tagPresenceMask & RequiredFields) == RequiredFields) { err = CHIP_NO_ERROR; } @@ -106,7 +109,14 @@ AttributeStatusIBs::Builder & WriteResponseMessage::Builder::GetWriteResponses() WriteResponseMessage::Builder & WriteResponseMessage::Builder::EndOfWriteResponseMessage() { - EndOfContainer(); + if (mError == CHIP_NO_ERROR) + { + mError = MessageBuilder::EncodeInteractionModelRevision(); + } + if (mError == CHIP_NO_ERROR) + { + EndOfContainer(); + } return *this; } } // namespace app diff --git a/src/app/MessageDef/WriteResponseMessage.h b/src/app/MessageDef/WriteResponseMessage.h index 632180ea11ced8..b3111f6225a2f1 100644 --- a/src/app/MessageDef/WriteResponseMessage.h +++ b/src/app/MessageDef/WriteResponseMessage.h @@ -18,9 +18,8 @@ #pragma once #include "AttributeStatusIBs.h" -#include "StructBuilder.h" - -#include "StructParser.h" +#include "MessageBuilder.h" +#include "MessageParser.h" #include #include #include @@ -35,7 +34,7 @@ enum class Tag : uint8_t kWriteResponses = 0, }; -class Parser : public StructParser +class Parser : public MessageParser { public: /** @@ -62,7 +61,7 @@ class Parser : public StructParser CHIP_ERROR GetWriteResponses(AttributeStatusIBs::Parser * const apWriteResponses) const; }; -class Builder : public StructBuilder +class Builder : public MessageBuilder { public: /** diff --git a/src/app/TimedRequest.cpp b/src/app/TimedRequest.cpp index fb47a375a2c0ae..1c325b62a19187 100644 --- a/src/app/TimedRequest.cpp +++ b/src/app/TimedRequest.cpp @@ -33,10 +33,10 @@ using namespace Messaging; CHIP_ERROR TimedRequest::Send(ExchangeContext * aExchangeContext, uint16_t aTimeoutMs) { // The payload is an anonymous struct (2 bytes) containing a single - // 16-bit integer with a context tag (1 control byte, 1 byte tag, at - // most 2 bytes for the integer). Use MessagePacketBuffer::New to - // account for other message-global overheads (MIC, etc). - System::PacketBufferHandle payload = MessagePacketBuffer::New(6); + // 16-bit integer with two context tag (1 control byte, 1 byte tag, at + // most 2 bytes for the timeout integer and 1 control byte, 1 byte tag, one byte for InteractionModelRevision). Use + // MessagePacketBuffer::New to account for other message-global overheads (MIC, etc). + System::PacketBufferHandle payload = MessagePacketBuffer::New(9); VerifyOrReturnError(!payload.IsNull(), CHIP_ERROR_NO_MEMORY); System::PacketBufferTLVWriter writer; diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index 426c28c7b60d23..402d8e6a1edc43 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -329,6 +329,10 @@ CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) // Reserved size for the MoreChunks boolean flag, which takes up 1 byte for the control tag and 1 byte for the context tag. const uint32_t kReservedSizeForMoreChunksFlag = 1 + 1; + // Reserved size for the uint8_t InteractionModelRevision flag, which takes up 1 byte for the control tag and 1 byte for the + // context tag, 1 byte for value + const uint32_t kReservedSizeForIMRevision = 1 + 1 + 1; + // Reserved size for the end of report message, which is an end-of-container (i.e 1 byte for the control tag). const uint32_t kReservedSizeForEndOfReportMessage = 1; @@ -362,7 +366,8 @@ CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) reportDataBuilder.SubscriptionId(subscriptionId); } - SuccessOrExit(err = reportDataWriter.ReserveBuffer(kReservedSizeForMoreChunksFlag + kReservedSizeForEndOfReportMessage)); + SuccessOrExit(err = reportDataWriter.ReserveBuffer(kReservedSizeForMoreChunksFlag + kReservedSizeForIMRevision + + kReservedSizeForEndOfReportMessage)); { bool hasMoreChunksForAttributes = false; @@ -388,7 +393,8 @@ CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) } SuccessOrExit(reportDataBuilder.GetError()); - SuccessOrExit(err = reportDataWriter.UnreserveBuffer(kReservedSizeForMoreChunksFlag + kReservedSizeForEndOfReportMessage)); + SuccessOrExit(err = reportDataWriter.UnreserveBuffer(kReservedSizeForMoreChunksFlag + kReservedSizeForIMRevision + + kReservedSizeForEndOfReportMessage)); if (hasMoreChunks) { reportDataBuilder.MoreChunkedMessages(true); diff --git a/src/lib/core/CHIPError.cpp b/src/lib/core/CHIPError.cpp index 285cdb379aa70e..ea22ad36e8c71e 100644 --- a/src/lib/core/CHIPError.cpp +++ b/src/lib/core/CHIPError.cpp @@ -692,6 +692,12 @@ bool FormatCHIPError(char * buf, uint16_t bufSize, CHIP_ERROR err) case CHIP_ERROR_IM_MALFORMED_DATA_VERSION_FILTER_IB.AsInteger(): desc = "Malformed Interaction Model Data Version Filter IB"; break; + case CHIP_ERROR_IM_MALFORMED_STATUS_RESPONSE_MESSAGE.AsInteger(): + desc = "Malformed Interaction Model Status Response Message"; + break; + case CHIP_ERROR_IM_MALFORMED_TIMED_REQUEST_MESSAGE.AsInteger(): + desc = "Malformed Interaction Model Timed Request Message"; + break; } #endif // !CHIP_CONFIG_SHORT_ERROR_STR diff --git a/src/lib/core/CHIPError.h b/src/lib/core/CHIPError.h index bf3febe81c9374..925bad6ffea63b 100644 --- a/src/lib/core/CHIPError.h +++ b/src/lib/core/CHIPError.h @@ -2389,6 +2389,24 @@ using CHIP_ERROR = ::chip::ChipError; */ #define CHIP_ERROR_IM_CONSTRAINT_ERROR CHIP_CORE_ERROR(0xd8) +/** + * @def CHIP_ERROR_IM_MALFORMED_STATUS_RESPONSE_MESSAGE + * + * @brief + * The Attribute DataElement is malformed: it either does not contain + * the required elements + */ +#define CHIP_ERROR_IM_MALFORMED_STATUS_RESPONSE_MESSAGE CHIP_CORE_ERROR(0xd9) + +/** + * @def CHIP_ERROR_IM_MALFORMED_TIMED_REQUEST_MESSAGE + * + * @brief + * The Attribute DataElement is malformed: it either does not contain + * the required elements + */ +#define CHIP_ERROR_IM_MALFORMED_TIMED_REQUEST_MESSAGE CHIP_CORE_ERROR(0xda) + /** * @} */ diff --git a/src/lib/core/DataModelTypes.h b/src/lib/core/DataModelTypes.h index 0630a7416c65eb..77989bd52c8845 100644 --- a/src/lib/core/DataModelTypes.h +++ b/src/lib/core/DataModelTypes.h @@ -42,6 +42,7 @@ typedef uint32_t FieldId; typedef uint16_t ListIndex; typedef uint32_t TransactionId; typedef uint16_t KeysetId; +typedef uint8_t InteractionModelRevision; constexpr FabricIndex kUndefinedFabricIndex = 0; constexpr EndpointId kInvalidEndpointId = 0xFFFF;