Refresh IM Invoke encoding with latest spec (#11169)
diff --git a/src/app/MessageDef/InvokeResponseMessage.cpp b/src/app/MessageDef/InvokeResponseMessage.cpp new file mode 100644 index 0000000..62d008d --- /dev/null +++ b/src/app/MessageDef/InvokeResponseMessage.cpp
@@ -0,0 +1,138 @@ +/** + * + * 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 <inttypes.h> +#include <stdarg.h> +#include <stdio.h> + +#include "InvokeResponseMessage.h" +#include "MessageDefHelper.h" + +#include <app/AppBuildConfig.h> + +namespace chip { +namespace app { +#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK +CHIP_ERROR InvokeResponseMessage::Parser::CheckSchemaValidity() const +{ + CHIP_ERROR err = CHIP_NO_ERROR; + int TagPresenceMask = 0; + TLV::TLVReader reader; + + PRETTY_PRINT("InvokeResponseMessage ="); + 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::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)); +#if CHIP_DETAIL_LOGGING + { + bool suppressResponse; + ReturnErrorOnFailure(reader.Get(suppressResponse)); + PRETTY_PRINT("\tsuppressResponse = %s, ", suppressResponse ? "true" : "false"); + } +#endif // CHIP_DETAIL_LOGGING + 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)); + { + InvokeResponses::Parser invokeResponses; + ReturnErrorOnFailure(invokeResponses.Init(reader)); + + PRETTY_PRINT_INCDEPTH(); + ReturnErrorOnFailure(invokeResponses.CheckSchemaValidity()); + PRETTY_PRINT_DECDEPTH(); + } + 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::kSuppressResponse)) | (1 << to_underlying(Tag::kInvokeResponses)); + + if ((TagPresenceMask & RequiredFields) == RequiredFields) + { + err = CHIP_NO_ERROR; + } + else + { + err = CHIP_ERROR_IM_MALFORMED_INVOKE_RESPONSE_MESSAGE; + } + } + + ReturnErrorOnFailure(err); + ReturnErrorOnFailure(reader.ExitContainer(mOuterContainerType)); + return CHIP_NO_ERROR; +} +#endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK + +CHIP_ERROR InvokeResponseMessage::Parser::GetSuppressResponse(bool * const apSuppressResponse) const +{ + return GetSimpleValue(to_underlying(Tag::kSuppressResponse), TLV::kTLVType_Boolean, apSuppressResponse); +} + +CHIP_ERROR InvokeResponseMessage::Parser::GetInvokeResponses(InvokeResponses::Parser * const apStatus) const +{ + TLV::TLVReader reader; + ReturnErrorOnFailure(mReader.FindElementWithTag(TLV::ContextTag(to_underlying(Tag::kInvokeResponses)), reader)); + ReturnErrorOnFailure(apStatus->Init(reader)); + return CHIP_NO_ERROR; +} + +InvokeResponseMessage::Builder & InvokeResponseMessage::Builder::SuppressResponse(const bool aSuppressResponse) +{ + if (mError == CHIP_NO_ERROR) + { + mError = mpWriter->PutBoolean(TLV::ContextTag(to_underlying(Tag::kSuppressResponse)), aSuppressResponse); + } + return *this; +} + +InvokeResponses::Builder & InvokeResponseMessage::Builder::CreateInvokeResponses() +{ + if (mError == CHIP_NO_ERROR) + { + mError = mInvokeResponses.Init(mpWriter, to_underlying(Tag::kInvokeResponses)); + } + return mInvokeResponses; +} + +InvokeResponseMessage::Builder & InvokeResponseMessage::Builder::EndOfInvokeResponseMessage() +{ + EndOfContainer(); + return *this; +} +} // namespace app +} // namespace chip