Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / app / MessageDef / StatusElement.cpp
1 /**
2  *
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
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18 /**
19  *    @file
20  *      This file defines StatusElement parser and builder in CHIP interaction model
21  *
22  */
23
24 #include "StatusElement.h"
25
26 #include "MessageDefHelper.h"
27
28 #include <inttypes.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31
32 using namespace chip;
33 using namespace chip::TLV;
34
35 namespace chip {
36 namespace app {
37 CHIP_ERROR StatusElement::Parser::Init(const chip::TLV::TLVReader & aReader)
38 {
39     CHIP_ERROR err = CHIP_NO_ERROR;
40
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);
44
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);
48
49 exit:
50     ChipLogFunctError(err);
51     return err;
52 }
53
54 CHIP_ERROR StatusElement::Parser::DecodeStatusElement(Protocols::SecureChannel::GeneralStatusCode * apGeneralCode,
55                                                       uint32_t * apProtocolId, uint16_t * apProtocolCode) const
56 {
57     CHIP_ERROR err = CHIP_NO_ERROR;
58     chip::TLV::TLVReader lReader;
59
60     uint16_t generalCode;
61     lReader.Init(mReader);
62
63     err = lReader.Next();
64     SuccessOrExit(err);
65     VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
66     err = lReader.Get(generalCode);
67     SuccessOrExit(err);
68     *apGeneralCode = static_cast<Protocols::SecureChannel::GeneralStatusCode>(generalCode);
69
70     err = lReader.Next();
71     SuccessOrExit(err);
72     VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
73     err = lReader.Get(*apProtocolId);
74     SuccessOrExit(err);
75
76     err = lReader.Next();
77     SuccessOrExit(err);
78     VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
79     err = lReader.Get(*apProtocolCode);
80     SuccessOrExit(err);
81
82 exit:
83     ChipLogFunctError(err);
84     return err;
85 }
86
87 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
88 CHIP_ERROR StatusElement::Parser::CheckSchemaValidity() const
89 {
90     CHIP_ERROR err           = CHIP_NO_ERROR;
91     uint16_t TagPresenceMask = 0;
92     chip::TLV::TLVReader reader;
93
94     PRETTY_PRINT("StatusElement =");
95     PRETTY_PRINT("{");
96
97     // make a copy of the reader
98     reader.Init(mReader);
99
100     while (CHIP_NO_ERROR == (err = reader.Next()))
101     {
102         // This is an array; all elements are anonymous.
103         VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);
104
105         if (!(TagPresenceMask & (1 << kCsTag_GeneralCode)))
106         {
107             TagPresenceMask |= (1 << kCsTag_GeneralCode);
108             VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
109
110 #if CHIP_DETAIL_LOGGING
111             {
112                 uint16_t generalCode;
113                 err = reader.Get(generalCode);
114                 SuccessOrExit(err);
115
116                 PRETTY_PRINT("\tGeneralCode = 0x%" PRIx16 ",", generalCode);
117             }
118 #endif // CHIP_DETAIL_LOGGING
119         }
120         else if (!(TagPresenceMask & (1 << kCsTag_ProtocolId)))
121         {
122             TagPresenceMask |= (1 << kCsTag_ProtocolId);
123             VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
124
125 #if CHIP_DETAIL_LOGGING
126             {
127                 uint32_t kCsTag_ProtocolId;
128                 err = reader.Get(kCsTag_ProtocolId);
129                 SuccessOrExit(err);
130
131                 PRETTY_PRINT("\tProtocolId = 0x%" PRIx32 ",", kCsTag_ProtocolId);
132             }
133 #endif // CHIP_DETAIL_LOGGING
134         }
135         else if (!(TagPresenceMask & (1 << kCsTag_ProtocolCode)))
136         {
137             TagPresenceMask |= (1 << kCsTag_ProtocolCode);
138             VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
139
140 #if CHIP_DETAIL_LOGGING
141             {
142                 uint16_t protocolCode;
143                 err = reader.Get(protocolCode);
144                 SuccessOrExit(err);
145
146                 PRETTY_PRINT("\tprotocolCode = 0x%" PRIx16 ",", protocolCode);
147             }
148 #endif // CHIP_DETAIL_LOGGING
149         }
150         else
151         {
152             PRETTY_PRINT("\tExtra element in StatusElement");
153         }
154     }
155
156     PRETTY_PRINT("},");
157     PRETTY_PRINT("");
158     // if we have exhausted this container
159     if (CHIP_END_OF_TLV == err)
160     {
161         // check for required fields:
162         const uint16_t RequiredFields = (1 << kCsTag_GeneralCode) | (1 << kCsTag_ProtocolId) | (1 << kCsTag_ProtocolCode);
163
164         if ((TagPresenceMask & RequiredFields) == RequiredFields)
165         {
166             err = CHIP_NO_ERROR;
167         }
168         else
169         {
170             err = CHIP_ERROR_IM_MALFORMED_STATUS_CODE;
171         }
172     }
173
174 exit:
175     ChipLogFunctError(err);
176
177     return err;
178 }
179 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
180
181 CHIP_ERROR StatusElement::Builder::Init(chip::TLV::TLVWriter * const apWriter)
182 {
183     return ListBuilder::Init(apWriter);
184 }
185
186 CHIP_ERROR StatusElement::Builder::Init(chip::TLV::TLVWriter * const apWriter, const uint8_t aContextTagToUse)
187 {
188     return ListBuilder::Init(apWriter, aContextTagToUse);
189 }
190
191 StatusElement::Builder & StatusElement::Builder::EncodeStatusElement(const Protocols::SecureChannel::GeneralStatusCode aGeneralCode,
192                                                                      const uint32_t aProtocolId, const uint16_t aProtocolCode)
193 {
194     uint64_t tag = chip::TLV::AnonymousTag;
195
196     SuccessOrExit(mError);
197
198     mError = mpWriter->Put(tag, static_cast<uint16_t>(aGeneralCode));
199     SuccessOrExit(mError);
200
201     mError = mpWriter->Put(tag, aProtocolId);
202     SuccessOrExit(mError);
203
204     mError = mpWriter->Put(tag, aProtocolCode);
205     SuccessOrExit(mError);
206
207 exit:
208     ChipLogFunctError(mError);
209     return *this;
210 }
211
212 StatusElement::Builder & StatusElement::Builder::EndOfStatusElement()
213 {
214     EndOfContainer();
215     return *this;
216 }
217
218 }; // namespace app
219 }; // namespace chip