3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2018 Google LLC.
5 * Copyright (c) 2016-2017 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 * This file defines StatusElement parser and builder in CHIP interaction model
24 #include "StatusElement.h"
26 #include "MessageDefHelper.h"
33 using namespace chip::TLV;
37 CHIP_ERROR StatusElement::Parser::Init(const chip::TLV::TLVReader & aReader)
39 CHIP_ERROR err = CHIP_NO_ERROR;
41 // make a copy of the reader here
42 mReader.Init(aReader);
43 VerifyOrExit(chip::TLV::kTLVType_Array == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
45 // This is just a dummy, as we're not going to exit this container ever
46 chip::TLV::TLVType OuterContainerType;
47 err = mReader.EnterContainer(OuterContainerType);
50 ChipLogFunctError(err);
54 CHIP_ERROR StatusElement::Parser::DecodeStatusElement(Protocols::SecureChannel::GeneralStatusCode * apGeneralCode,
55 uint32_t * apProtocolId, uint16_t * apProtocolCode) const
57 CHIP_ERROR err = CHIP_NO_ERROR;
58 chip::TLV::TLVReader lReader;
61 lReader.Init(mReader);
65 VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
66 err = lReader.Get(generalCode);
68 *apGeneralCode = static_cast<Protocols::SecureChannel::GeneralStatusCode>(generalCode);
72 VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
73 err = lReader.Get(*apProtocolId);
78 VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
79 err = lReader.Get(*apProtocolCode);
83 ChipLogFunctError(err);
87 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
88 CHIP_ERROR StatusElement::Parser::CheckSchemaValidity() const
90 CHIP_ERROR err = CHIP_NO_ERROR;
91 uint16_t TagPresenceMask = 0;
92 chip::TLV::TLVReader reader;
94 PRETTY_PRINT("StatusElement =");
97 // make a copy of the reader
100 while (CHIP_NO_ERROR == (err = reader.Next()))
102 // This is an array; all elements are anonymous.
103 VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);
105 if (!(TagPresenceMask & (1 << kCsTag_GeneralCode)))
107 TagPresenceMask |= (1 << kCsTag_GeneralCode);
108 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
110 #if CHIP_DETAIL_LOGGING
112 uint16_t generalCode;
113 err = reader.Get(generalCode);
116 PRETTY_PRINT("\tGeneralCode = 0x%" PRIx16 ",", generalCode);
118 #endif // CHIP_DETAIL_LOGGING
120 else if (!(TagPresenceMask & (1 << kCsTag_ProtocolId)))
122 TagPresenceMask |= (1 << kCsTag_ProtocolId);
123 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
125 #if CHIP_DETAIL_LOGGING
127 uint32_t kCsTag_ProtocolId;
128 err = reader.Get(kCsTag_ProtocolId);
131 PRETTY_PRINT("\tProtocolId = 0x%" PRIx32 ",", kCsTag_ProtocolId);
133 #endif // CHIP_DETAIL_LOGGING
135 else if (!(TagPresenceMask & (1 << kCsTag_ProtocolCode)))
137 TagPresenceMask |= (1 << kCsTag_ProtocolCode);
138 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
140 #if CHIP_DETAIL_LOGGING
142 uint16_t protocolCode;
143 err = reader.Get(protocolCode);
146 PRETTY_PRINT("\tprotocolCode = 0x%" PRIx16 ",", protocolCode);
148 #endif // CHIP_DETAIL_LOGGING
152 PRETTY_PRINT("\tExtra element in StatusElement");
158 // if we have exhausted this container
159 if (CHIP_END_OF_TLV == err)
161 // check for required fields:
162 const uint16_t RequiredFields = (1 << kCsTag_GeneralCode) | (1 << kCsTag_ProtocolId) | (1 << kCsTag_ProtocolCode);
164 if ((TagPresenceMask & RequiredFields) == RequiredFields)
170 err = CHIP_ERROR_IM_MALFORMED_STATUS_CODE;
175 ChipLogFunctError(err);
179 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
181 CHIP_ERROR StatusElement::Builder::Init(chip::TLV::TLVWriter * const apWriter)
183 return ListBuilder::Init(apWriter);
186 CHIP_ERROR StatusElement::Builder::Init(chip::TLV::TLVWriter * const apWriter, const uint8_t aContextTagToUse)
188 return ListBuilder::Init(apWriter, aContextTagToUse);
191 StatusElement::Builder & StatusElement::Builder::EncodeStatusElement(const Protocols::SecureChannel::GeneralStatusCode aGeneralCode,
192 const uint32_t aProtocolId, const uint16_t aProtocolCode)
194 uint64_t tag = chip::TLV::AnonymousTag;
196 SuccessOrExit(mError);
198 mError = mpWriter->Put(tag, static_cast<uint16_t>(aGeneralCode));
199 SuccessOrExit(mError);
201 mError = mpWriter->Put(tag, aProtocolId);
202 SuccessOrExit(mError);
204 mError = mpWriter->Put(tag, aProtocolCode);
205 SuccessOrExit(mError);
208 ChipLogFunctError(mError);
212 StatusElement::Builder & StatusElement::Builder::EndOfStatusElement()