Coverage Report

Created: 2026-04-09 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/connectedhomeip/src/app/MessageDef/InvokeResponseMessage.cpp
Line
Count
Source
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
CHIP_ERROR InvokeResponseMessage::Parser::PrettyPrint() const
30
0
{
31
0
    CHIP_ERROR err = CHIP_NO_ERROR;
32
0
    TLV::TLVReader reader;
33
34
0
    PRETTY_PRINT("InvokeResponseMessage =");
35
0
    PRETTY_PRINT("{");
36
37
    // make a copy of the reader
38
0
    reader.Init(mReader);
39
40
0
    while (CHIP_NO_ERROR == (err = reader.Next()))
41
0
    {
42
0
        if (!TLV::IsContextTag(reader.GetTag()))
43
0
        {
44
0
            continue;
45
0
        }
46
0
        uint32_t tagNum = TLV::TagNumFromTag(reader.GetTag());
47
0
        switch (tagNum)
48
0
        {
49
0
        case to_underlying(Tag::kSuppressResponse):
50
0
#if CHIP_DETAIL_LOGGING
51
0
        {
52
0
            bool suppressResponse;
53
0
            ReturnErrorOnFailure(reader.Get(suppressResponse));
54
0
            PRETTY_PRINT("\tsuppressResponse = %s, ", suppressResponse ? "true" : "false");
55
0
        }
56
0
#endif // CHIP_DETAIL_LOGGING
57
0
        break;
58
0
        case to_underlying(Tag::kInvokeResponses): {
59
0
            InvokeResponseIBs::Parser invokeResponses;
60
0
            ReturnErrorOnFailure(invokeResponses.Init(reader));
61
62
0
            PRETTY_PRINT_INCDEPTH();
63
0
            ReturnErrorOnFailure(invokeResponses.PrettyPrint());
64
0
            PRETTY_PRINT_DECDEPTH();
65
0
        }
66
0
        break;
67
0
        case to_underlying(Tag::kMoreChunkedMessages):
68
0
#if CHIP_DETAIL_LOGGING
69
0
        {
70
0
            bool moreChunkedMessages;
71
0
            ReturnErrorOnFailure(reader.Get(moreChunkedMessages));
72
0
            PRETTY_PRINT("\tmoreChunkedMessages = %s, ", moreChunkedMessages ? "true" : "false");
73
0
        }
74
0
#endif // CHIP_DETAIL_LOGGING
75
0
        break;
76
0
        case Revision::kInteractionModelRevisionTag:
77
0
            ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader));
78
0
            break;
79
0
        default:
80
0
            PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum);
81
0
            break;
82
0
        }
83
0
    }
84
85
0
    PRETTY_PRINT("},");
86
0
    PRETTY_PRINT_BLANK_LINE();
87
88
0
    if (CHIP_END_OF_TLV == err)
89
0
    {
90
0
        err = CHIP_NO_ERROR;
91
0
    }
92
93
0
    ReturnErrorOnFailure(err);
94
0
    return reader.ExitContainer(mOuterContainerType);
95
0
}
96
#endif // CHIP_CONFIG_IM_PRETTY_PRINT
97
98
CHIP_ERROR InvokeResponseMessage::Parser::GetSuppressResponse(bool * const apSuppressResponse) const
99
0
{
100
0
    return GetSimpleValue(to_underlying(Tag::kSuppressResponse), TLV::kTLVType_Boolean, apSuppressResponse);
101
0
}
102
103
CHIP_ERROR InvokeResponseMessage::Parser::GetInvokeResponses(InvokeResponseIBs::Parser * const apStatus) const
104
0
{
105
0
    TLV::TLVReader reader;
106
0
    ReturnErrorOnFailure(mReader.FindElementWithTag(TLV::ContextTag(Tag::kInvokeResponses), reader));
107
0
    return apStatus->Init(reader);
108
0
}
109
110
CHIP_ERROR InvokeResponseMessage::Parser::GetMoreChunkedMessages(bool * const apMoreChunkedMessages) const
111
0
{
112
0
    return GetSimpleValue(to_underlying(Tag::kMoreChunkedMessages), TLV::kTLVType_Boolean, apMoreChunkedMessages);
113
0
}
114
115
CHIP_ERROR InvokeResponseMessage::Builder::InitWithEndBufferReserved(TLV::TLVWriter * const apWriter)
116
0
{
117
0
    ReturnErrorOnFailure(Init(apWriter));
118
0
    ReturnErrorOnFailure(GetWriter()->ReserveBuffer(GetSizeToEndInvokeResponseMessage()));
119
0
    mIsEndBufferReserved = true;
120
0
    return CHIP_NO_ERROR;
121
0
}
122
123
InvokeResponseMessage::Builder & InvokeResponseMessage::Builder::SuppressResponse(const bool aSuppressResponse)
124
0
{
125
0
    if (mError == CHIP_NO_ERROR)
126
0
    {
127
0
        mError = mpWriter->PutBoolean(TLV::ContextTag(Tag::kSuppressResponse), aSuppressResponse);
128
0
    }
129
0
    return *this;
130
0
}
131
132
InvokeResponseIBs::Builder & InvokeResponseMessage::Builder::CreateInvokeResponses(const bool aReserveEndBuffer)
133
0
{
134
0
    if (mError == CHIP_NO_ERROR)
135
0
    {
136
0
        if (aReserveEndBuffer)
137
0
        {
138
0
            mError = mInvokeResponses.InitWithEndBufferReserved(mpWriter, to_underlying(Tag::kInvokeResponses));
139
0
        }
140
0
        else
141
0
        {
142
0
            mError = mInvokeResponses.Init(mpWriter, to_underlying(Tag::kInvokeResponses));
143
0
        }
144
0
    }
145
0
    return mInvokeResponses;
146
0
}
147
148
InvokeResponseMessage::Builder & InvokeResponseMessage::Builder::MoreChunkedMessages(const bool aMoreChunkedMessages)
149
0
{
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
0
    SuccessOrExit(mError);
156
157
0
    if (mIsMoreChunkMessageBufferReserved)
158
0
    {
159
0
        mError = GetWriter()->UnreserveBuffer(GetSizeForMoreChunkResponses());
160
0
        SuccessOrExit(mError);
161
0
        mIsMoreChunkMessageBufferReserved = false;
162
0
    }
163
164
0
    mError = mpWriter->PutBoolean(TLV::ContextTag(Tag::kMoreChunkedMessages), aMoreChunkedMessages);
165
0
exit:
166
0
    return *this;
167
0
}
168
169
CHIP_ERROR InvokeResponseMessage::Builder::ReserveSpaceForMoreChunkedMessages()
170
0
{
171
0
    ReturnErrorOnFailure(GetWriter()->ReserveBuffer(GetSizeForMoreChunkResponses()));
172
0
    mIsMoreChunkMessageBufferReserved = true;
173
0
    return CHIP_NO_ERROR;
174
0
}
175
176
CHIP_ERROR InvokeResponseMessage::Builder::EndOfInvokeResponseMessage()
177
0
{
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
0
    ReturnErrorOnFailure(mError);
182
0
    if (mIsEndBufferReserved)
183
0
    {
184
0
        ReturnErrorOnFailure(GetWriter()->UnreserveBuffer(GetSizeToEndInvokeResponseMessage()));
185
0
        mIsEndBufferReserved = false;
186
0
    }
187
0
    if (mError == CHIP_NO_ERROR)
188
0
    {
189
0
        mError = MessageBuilder::EncodeInteractionModelRevision();
190
0
    }
191
0
    if (mError == CHIP_NO_ERROR)
192
0
    {
193
0
        EndOfContainer();
194
0
    }
195
0
    return GetError();
196
0
}
197
198
uint32_t InvokeResponseMessage::Builder::GetSizeForMoreChunkResponses()
199
0
{
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
0
    uint32_t kEncodeMoreChunkedMessages = 1 + 1;
203
204
0
    return kEncodeMoreChunkedMessages;
205
0
}
206
207
uint32_t InvokeResponseMessage::Builder::GetSizeToEndInvokeResponseMessage()
208
0
{
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
0
    uint32_t kEncodeInteractionModelSize = 1 + 1 + 1;
212
0
    uint32_t kEndOfContainerSize         = 1;
213
214
0
    return kEncodeInteractionModelSize + kEndOfContainerSize;
215
0
}
216
} // namespace app
217
} // namespace chip