Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / app / ReadClient.cpp
1 /*
2  *
3  *    Copyright (c) 2021 Project CHIP Authors
4  *    All rights reserved.
5  *
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 /**
20  *    @file
21  *      This file defines the initiator side of a CHIP Read Interaction.
22  *
23  */
24
25 #include <app/InteractionModelEngine.h>
26 #include <app/ReadClient.h>
27
28 namespace chip {
29 namespace app {
30
31 CHIP_ERROR ReadClient::Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate)
32 {
33     CHIP_ERROR err = CHIP_NO_ERROR;
34     // Error if already initialized.
35     VerifyOrExit(apExchangeMgr != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
36     VerifyOrExit(mpExchangeMgr == nullptr, err = CHIP_ERROR_INCORRECT_STATE);
37     VerifyOrExit(mpExchangeCtx == nullptr, err = CHIP_ERROR_INCORRECT_STATE);
38
39     mpExchangeMgr = apExchangeMgr;
40     mpExchangeCtx = nullptr;
41     mpDelegate    = apDelegate;
42     mState        = ClientState::Initialized;
43
44 exit:
45     ChipLogFunctError(err);
46     return err;
47 }
48
49 void ReadClient::Shutdown()
50 {
51     ClearExistingExchangeContext();
52     mpExchangeMgr = nullptr;
53     mpDelegate    = nullptr;
54     MoveToState(ClientState::Uninitialized);
55 }
56
57 const char * ReadClient::GetStateStr() const
58 {
59 #if CHIP_DETAIL_LOGGING
60     switch (mState)
61     {
62     case ClientState::Uninitialized:
63         return "UNINIT";
64     case ClientState::Initialized:
65         return "INIT";
66     case ClientState::AwaitingResponse:
67         return "AwaitingResponse";
68     }
69 #endif // CHIP_DETAIL_LOGGING
70     return "N/A";
71 }
72
73 void ReadClient::MoveToState(const ClientState aTargetState)
74 {
75     mState = aTargetState;
76     ChipLogDetail(DataManagement, "Client[%u] moving to [%s]", InteractionModelEngine::GetInstance()->GetReadClientArrayIndex(this),
77                   GetStateStr());
78 }
79
80 CHIP_ERROR ReadClient::SendReadRequest(NodeId aNodeId, Transport::AdminId aAdminId, EventPathParams * apEventPathParamsList,
81                                        size_t aEventPathParamsListSize)
82 {
83     CHIP_ERROR err = CHIP_NO_ERROR;
84     System::PacketBufferHandle msgBuf;
85     ChipLogDetail(DataManagement, "%s: Client[%u] [%5.5s]", __func__,
86                   InteractionModelEngine::GetInstance()->GetReadClientArrayIndex(this), GetStateStr());
87     VerifyOrExit(ClientState::Initialized == mState, err = CHIP_ERROR_INCORRECT_STATE);
88     VerifyOrExit(mpDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
89     VerifyOrExit(mpExchangeCtx == nullptr, err = CHIP_ERROR_INCORRECT_STATE);
90
91     {
92         System::PacketBufferTLVWriter writer;
93         ReadRequest::Builder request;
94
95         msgBuf = System::PacketBufferHandle::New(kMaxSecureSduLengthBytes);
96         VerifyOrExit(!msgBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
97
98         writer.Init(std::move(msgBuf));
99
100         err = request.Init(&writer);
101         SuccessOrExit(err);
102
103         if (aEventPathParamsListSize != 0 && apEventPathParamsList != nullptr)
104         {
105             // TODO: fill to construct event paths
106         }
107         request.EndOfReadRequest();
108         SuccessOrExit(request.GetError());
109
110         err = writer.Finalize(&msgBuf);
111         SuccessOrExit(err);
112     }
113
114     mpExchangeCtx = mpExchangeMgr->NewContext({ aNodeId, 0, aAdminId }, this);
115     VerifyOrExit(mpExchangeCtx != nullptr, err = CHIP_ERROR_NO_MEMORY);
116     mpExchangeCtx->SetResponseTimeout(kImMessageTimeoutMsec);
117
118     err = mpExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::ReadRequest, std::move(msgBuf),
119                                      Messaging::SendFlags(Messaging::SendMessageFlags::kExpectResponse));
120     SuccessOrExit(err);
121     MoveToState(ClientState::AwaitingResponse);
122
123 exit:
124     ChipLogFunctError(err);
125     return err;
126 }
127
128 void ReadClient::OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
129                                    const PayloadHeader & aPayloadHeader, System::PacketBufferHandle aPayload)
130 {
131     CHIP_ERROR err = CHIP_NO_ERROR;
132     VerifyOrExit(aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::ReportData),
133                  err = CHIP_ERROR_INVALID_MESSAGE_TYPE);
134     VerifyOrExit(apExchangeContext == mpExchangeCtx, err = CHIP_ERROR_INCORRECT_STATE);
135     err = ProcessReportData(std::move(aPayload));
136
137 exit:
138     ChipLogFunctError(err);
139     if (err != CHIP_NO_ERROR && mpDelegate != nullptr)
140     {
141         mpDelegate->ReportError(this, err);
142     }
143     ClearExistingExchangeContext();
144     MoveToState(ClientState::Initialized);
145     return;
146 }
147
148 CHIP_ERROR ReadClient::ClearExistingExchangeContext()
149 {
150     if (mpExchangeCtx != nullptr)
151     {
152         mpExchangeCtx->Abort();
153         mpExchangeCtx = nullptr;
154     }
155
156     return CHIP_NO_ERROR;
157 }
158
159 CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle aPayload)
160 {
161     CHIP_ERROR err = CHIP_NO_ERROR;
162     ReportData::Parser report;
163
164     bool isEventListPresent  = false;
165     bool suppressResponse    = false;
166     bool moreChunkedMessages = false;
167
168     System::PacketBufferTLVReader reader;
169
170     reader.Init(std::move(aPayload));
171     reader.Next();
172
173     err = report.Init(reader);
174     SuccessOrExit(err);
175
176     err = report.CheckSchemaValidity();
177     SuccessOrExit(err);
178
179     err = report.GetSuppressResponse(&suppressResponse);
180     if (CHIP_END_OF_TLV == err)
181     {
182         err = CHIP_NO_ERROR;
183     }
184     SuccessOrExit(err);
185
186     err = report.GetMoreChunkedMessages(&moreChunkedMessages);
187     if (CHIP_END_OF_TLV == err)
188     {
189         err = CHIP_NO_ERROR;
190     }
191     SuccessOrExit(err);
192
193     {
194         EventList::Parser eventList;
195
196         err = report.GetEventDataList(&eventList);
197         if (CHIP_NO_ERROR == err)
198         {
199             isEventListPresent = true;
200         }
201         else if (CHIP_END_OF_TLV == err)
202         {
203             isEventListPresent = false;
204             err                = CHIP_NO_ERROR;
205         }
206         SuccessOrExit(err);
207
208         if (isEventListPresent && nullptr != mpDelegate && !moreChunkedMessages)
209         {
210             chip::TLV::TLVReader eventListReader;
211             eventList.GetReader(&eventListReader);
212             err = mpDelegate->EventStreamReceived(mpExchangeCtx, &eventListReader);
213             SuccessOrExit(err);
214         }
215     }
216
217     if (!suppressResponse)
218     {
219         // TODO: Add status report support and correspond handler in ReadHandler, particular for situation when there
220         // are multiple reports
221     }
222     if (nullptr != mpDelegate && !moreChunkedMessages)
223     {
224         err = mpDelegate->ReportProcessed(this);
225     }
226
227 exit:
228     ChipLogFunctError(err);
229     return err;
230 }
231
232 void ReadClient::OnResponseTimeout(Messaging::ExchangeContext * apExchangeContext)
233 {
234     ChipLogProgress(DataManagement, "Time out! failed to receive report data from Exchange: %d",
235                     apExchangeContext->GetExchangeId());
236     ClearExistingExchangeContext();
237     MoveToState(ClientState::Initialized);
238     if (nullptr != mpDelegate)
239     {
240         mpDelegate->ReportError(this, CHIP_ERROR_TIMEOUT);
241     }
242 }
243 }; // namespace app
244 }; // namespace chip