Line data Source code
1 : /**
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : */
16 :
17 : #include <inttypes.h>
18 : #include <stdarg.h>
19 : #include <stdio.h>
20 :
21 : #include "InvokeResponseMessage.h"
22 : #include "MessageDefHelper.h"
23 :
24 : #include <app/AppConfig.h>
25 :
26 : namespace chip {
27 : namespace app {
28 : #if CHIP_CONFIG_IM_PRETTY_PRINT
29 28 : CHIP_ERROR InvokeResponseMessage::Parser::PrettyPrint() const
30 : {
31 28 : CHIP_ERROR err = CHIP_NO_ERROR;
32 28 : TLV::TLVReader reader;
33 :
34 28 : PRETTY_PRINT("InvokeResponseMessage =");
35 28 : PRETTY_PRINT("{");
36 :
37 : // make a copy of the reader
38 28 : reader.Init(mReader);
39 :
40 113 : while (CHIP_NO_ERROR == (err = reader.Next()))
41 : {
42 85 : if (!TLV::IsContextTag(reader.GetTag()))
43 : {
44 0 : continue;
45 : }
46 85 : uint32_t tagNum = TLV::TagNumFromTag(reader.GetTag());
47 85 : switch (tagNum)
48 : {
49 28 : case to_underlying(Tag::kSuppressResponse):
50 : #if CHIP_DETAIL_LOGGING
51 : {
52 : bool suppressResponse;
53 28 : ReturnErrorOnFailure(reader.Get(suppressResponse));
54 28 : PRETTY_PRINT("\tsuppressResponse = %s, ", suppressResponse ? "true" : "false");
55 : }
56 : #endif // CHIP_DETAIL_LOGGING
57 28 : break;
58 28 : case to_underlying(Tag::kInvokeResponses): {
59 28 : InvokeResponseIBs::Parser invokeResponses;
60 28 : ReturnErrorOnFailure(invokeResponses.Init(reader));
61 :
62 28 : PRETTY_PRINT_INCDEPTH();
63 28 : ReturnErrorOnFailure(invokeResponses.PrettyPrint());
64 28 : PRETTY_PRINT_DECDEPTH();
65 : }
66 28 : break;
67 1 : case to_underlying(Tag::kMoreChunkedMessages):
68 : #if CHIP_DETAIL_LOGGING
69 : {
70 : bool moreChunkedMessages;
71 1 : ReturnErrorOnFailure(reader.Get(moreChunkedMessages));
72 1 : PRETTY_PRINT("\tmoreChunkedMessages = %s, ", moreChunkedMessages ? "true" : "false");
73 : }
74 : #endif // CHIP_DETAIL_LOGGING
75 1 : break;
76 28 : case Revision::kInteractionModelRevisionTag:
77 28 : ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader));
78 28 : break;
79 0 : default:
80 0 : PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum);
81 0 : break;
82 : }
83 : }
84 :
85 28 : PRETTY_PRINT("},");
86 28 : PRETTY_PRINT_BLANK_LINE();
87 :
88 28 : if (CHIP_END_OF_TLV == err)
89 : {
90 28 : err = CHIP_NO_ERROR;
91 : }
92 :
93 28 : ReturnErrorOnFailure(err);
94 28 : return reader.ExitContainer(mOuterContainerType);
95 : }
96 : #endif // CHIP_CONFIG_IM_PRETTY_PRINT
97 :
98 28 : CHIP_ERROR InvokeResponseMessage::Parser::GetSuppressResponse(bool * const apSuppressResponse) const
99 : {
100 28 : return GetSimpleValue(to_underlying(Tag::kSuppressResponse), TLV::kTLVType_Boolean, apSuppressResponse);
101 : }
102 :
103 27 : CHIP_ERROR InvokeResponseMessage::Parser::GetInvokeResponses(InvokeResponseIBs::Parser * const apStatus) const
104 : {
105 27 : TLV::TLVReader reader;
106 27 : ReturnErrorOnFailure(mReader.FindElementWithTag(TLV::ContextTag(Tag::kInvokeResponses), reader));
107 27 : return apStatus->Init(reader);
108 : }
109 :
110 27 : CHIP_ERROR InvokeResponseMessage::Parser::GetMoreChunkedMessages(bool * const apMoreChunkedMessages) const
111 : {
112 27 : return GetSimpleValue(to_underlying(Tag::kMoreChunkedMessages), TLV::kTLVType_Boolean, apMoreChunkedMessages);
113 : }
114 :
115 51 : CHIP_ERROR InvokeResponseMessage::Builder::InitWithEndBufferReserved(TLV::TLVWriter * const apWriter)
116 : {
117 51 : ReturnErrorOnFailure(Init(apWriter));
118 51 : ReturnErrorOnFailure(GetWriter()->ReserveBuffer(GetSizeToEndInvokeResponseMessage()));
119 51 : mIsEndBufferReserved = true;
120 51 : return CHIP_NO_ERROR;
121 : }
122 :
123 53 : InvokeResponseMessage::Builder & InvokeResponseMessage::Builder::SuppressResponse(const bool aSuppressResponse)
124 : {
125 53 : if (mError == CHIP_NO_ERROR)
126 : {
127 53 : mError = mpWriter->PutBoolean(TLV::ContextTag(Tag::kSuppressResponse), aSuppressResponse);
128 : }
129 53 : return *this;
130 : }
131 :
132 54 : InvokeResponseIBs::Builder & InvokeResponseMessage::Builder::CreateInvokeResponses(const bool aReserveEndBuffer)
133 : {
134 54 : if (mError == CHIP_NO_ERROR)
135 : {
136 54 : if (aReserveEndBuffer)
137 : {
138 49 : mError = mInvokeResponses.InitWithEndBufferReserved(mpWriter, to_underlying(Tag::kInvokeResponses));
139 : }
140 : else
141 : {
142 5 : mError = mInvokeResponses.Init(mpWriter, to_underlying(Tag::kInvokeResponses));
143 : }
144 : }
145 54 : return mInvokeResponses;
146 : }
147 :
148 5 : InvokeResponseMessage::Builder & InvokeResponseMessage::Builder::MoreChunkedMessages(const bool aMoreChunkedMessages)
149 : {
150 : // If any changes are made to how we encoded MoreChunkedMessage that involves how many
151 : // bytes are needed, a corresponding change to GetSizeForMoreChunkResponses indicating
152 : // the new size that will be required.
153 :
154 : // skip if error has already been set
155 5 : SuccessOrExit(mError);
156 :
157 5 : if (mIsMoreChunkMessageBufferReserved)
158 : {
159 4 : mError = GetWriter()->UnreserveBuffer(GetSizeForMoreChunkResponses());
160 4 : SuccessOrExit(mError);
161 4 : mIsMoreChunkMessageBufferReserved = false;
162 : }
163 :
164 5 : mError = mpWriter->PutBoolean(TLV::ContextTag(Tag::kMoreChunkedMessages), aMoreChunkedMessages);
165 5 : exit:
166 5 : return *this;
167 : }
168 :
169 11 : CHIP_ERROR InvokeResponseMessage::Builder::ReserveSpaceForMoreChunkedMessages()
170 : {
171 11 : ReturnErrorOnFailure(GetWriter()->ReserveBuffer(GetSizeForMoreChunkResponses()));
172 11 : mIsMoreChunkMessageBufferReserved = true;
173 11 : return CHIP_NO_ERROR;
174 : }
175 :
176 47 : CHIP_ERROR InvokeResponseMessage::Builder::EndOfInvokeResponseMessage()
177 : {
178 : // If any changes are made to how we end the invoke response message that involves how many
179 : // bytes are needed, a corresponding change to GetSizeToEndInvokeResponseMessage indicating
180 : // the new size that will be required.
181 47 : ReturnErrorOnFailure(mError);
182 47 : if (mIsEndBufferReserved)
183 : {
184 42 : ReturnErrorOnFailure(GetWriter()->UnreserveBuffer(GetSizeToEndInvokeResponseMessage()));
185 42 : mIsEndBufferReserved = false;
186 : }
187 47 : if (mError == CHIP_NO_ERROR)
188 : {
189 47 : mError = MessageBuilder::EncodeInteractionModelRevision();
190 : }
191 47 : if (mError == CHIP_NO_ERROR)
192 : {
193 47 : EndOfContainer();
194 : }
195 47 : return GetError();
196 : }
197 :
198 15 : uint32_t InvokeResponseMessage::Builder::GetSizeForMoreChunkResponses()
199 : {
200 : // MoreChunkedMessages() encodes a uint8_t with context tag 0x02. This means 1 control byte,
201 : // 1 byte for the tag. For booleans the value is encoded in control byte.
202 15 : uint32_t kEncodeMoreChunkedMessages = 1 + 1;
203 :
204 15 : return kEncodeMoreChunkedMessages;
205 : }
206 :
207 93 : uint32_t InvokeResponseMessage::Builder::GetSizeToEndInvokeResponseMessage()
208 : {
209 : // EncodeInteractionModelRevision() encodes a uint8_t with context tag 0xFF. This means 1 control byte,
210 : // 1 byte for the tag, 1 byte for the value.
211 93 : uint32_t kEncodeInteractionModelSize = 1 + 1 + 1;
212 93 : uint32_t kEndOfContainerSize = 1;
213 :
214 93 : return kEncodeInteractionModelSize + kEndOfContainerSize;
215 : }
216 : } // namespace app
217 : } // namespace chip
|