Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / app / InteractionModelEngine.cpp
1 /*
2  *
3  *    Copyright (c) 2020-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 objects for a CHIP Interaction Data model Engine which handle unsolicitied IM message, and
22  *      manage different kinds of IM client and handlers.
23  *
24  */
25
26 #include "InteractionModelEngine.h"
27 #include "Command.h"
28 #include "CommandHandler.h"
29 #include "CommandSender.h"
30 #include <cinttypes>
31
32 namespace chip {
33 namespace app {
34 InteractionModelEngine sInteractionModelEngine;
35
36 InteractionModelEngine::InteractionModelEngine() {}
37
38 InteractionModelEngine * InteractionModelEngine::GetInstance()
39 {
40     return &sInteractionModelEngine;
41 }
42
43 CHIP_ERROR InteractionModelEngine::Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate)
44 {
45     CHIP_ERROR err = CHIP_NO_ERROR;
46
47     mpExchangeMgr = apExchangeMgr;
48     mpDelegate    = apDelegate;
49
50     err = mpExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::InteractionModel::Id, this);
51     SuccessOrExit(err);
52
53 exit:
54     return err;
55 }
56
57 void InteractionModelEngine::Shutdown()
58 {
59     for (auto & commandSender : mCommandSenderObjs)
60     {
61         commandSender.Shutdown();
62     }
63
64     for (auto & commandHandler : mCommandHandlerObjs)
65     {
66         commandHandler.Shutdown();
67     }
68
69     for (auto & readClient : mReadClients)
70     {
71         readClient.Shutdown();
72     }
73
74     for (auto & readHandler : mReadHandlers)
75     {
76         readHandler.Shutdown();
77     }
78 }
79
80 CHIP_ERROR InteractionModelEngine::NewCommandSender(CommandSender ** const apCommandSender)
81 {
82     CHIP_ERROR err   = CHIP_ERROR_NO_MEMORY;
83     *apCommandSender = nullptr;
84
85     for (auto & commandSender : mCommandSenderObjs)
86     {
87         if (commandSender.IsFree())
88         {
89             *apCommandSender = &commandSender;
90             err              = commandSender.Init(mpExchangeMgr, mpDelegate);
91             if (CHIP_NO_ERROR != err)
92             {
93                 *apCommandSender = nullptr;
94                 ExitNow();
95             }
96             break;
97         }
98     }
99
100 exit:
101     return err;
102 }
103
104 CHIP_ERROR InteractionModelEngine::NewReadClient(ReadClient ** const apReadClient)
105 {
106     CHIP_ERROR err = CHIP_ERROR_NO_MEMORY;
107
108     for (auto & readClient : mReadClients)
109     {
110         if (readClient.IsFree())
111         {
112             *apReadClient = &readClient;
113             err           = readClient.Init(mpExchangeMgr, mpDelegate);
114             if (CHIP_NO_ERROR != err)
115             {
116                 *apReadClient = nullptr;
117             }
118             return err;
119         }
120     }
121
122     return err;
123 }
124
125 void InteractionModelEngine::OnUnknownMsgType(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
126                                               const PayloadHeader & aPayloadHeader, System::PacketBufferHandle aPayload)
127 {
128     CHIP_ERROR err = CHIP_NO_ERROR;
129
130     ChipLogDetail(DataManagement, "Msg type %d not supported", aPayloadHeader.GetMessageType());
131
132     // Todo: Add status report
133     // err = SendStatusReport(ec, kChipProfile_Common, kStatus_UnsupportedMessage);
134     // SuccessOrExit(err);
135
136     apExchangeContext->Close();
137     apExchangeContext = nullptr;
138
139     ChipLogFunctError(err);
140
141     // Todo: Fix the below check after the above status report is implemented.
142     if (nullptr != apExchangeContext)
143     {
144         apExchangeContext->Abort();
145     }
146 }
147
148 void InteractionModelEngine::OnInvokeCommandRequest(Messaging::ExchangeContext * apExchangeContext,
149                                                     const PacketHeader & aPacketHeader, const PayloadHeader & aPayloadHeader,
150                                                     System::PacketBufferHandle aPayload)
151 {
152     CHIP_ERROR err = CHIP_NO_ERROR;
153
154     for (auto & commandHandler : mCommandHandlerObjs)
155     {
156         if (commandHandler.IsFree())
157         {
158             err = commandHandler.Init(mpExchangeMgr, mpDelegate);
159             SuccessOrExit(err);
160             commandHandler.OnMessageReceived(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
161             apExchangeContext = nullptr;
162             break;
163         }
164     }
165
166 exit:
167     ChipLogFunctError(err);
168
169     if (nullptr != apExchangeContext)
170     {
171         apExchangeContext->Abort();
172     }
173 }
174
175 void InteractionModelEngine::OnReadRequest(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
176                                            const PayloadHeader & aPayloadHeader, System::PacketBufferHandle aPayload)
177 {
178     CHIP_ERROR err = CHIP_NO_ERROR;
179
180     ChipLogDetail(DataManagement, "Receive Read request");
181
182     for (auto & readHandler : mReadHandlers)
183     {
184         if (readHandler.IsFree())
185         {
186             err = readHandler.Init(mpDelegate);
187             SuccessOrExit(err);
188             err = readHandler.OnReadRequest(apExchangeContext, std::move(aPayload));
189             SuccessOrExit(err);
190             apExchangeContext = nullptr;
191             break;
192         }
193     }
194
195 exit:
196     ChipLogFunctError(err);
197
198     if (nullptr != apExchangeContext)
199     {
200         apExchangeContext->Abort();
201     }
202 }
203
204 void InteractionModelEngine::OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
205                                                const PayloadHeader & aPayloadHeader, System::PacketBufferHandle aPayload)
206 {
207     if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::InvokeCommandRequest))
208     {
209
210         OnInvokeCommandRequest(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
211     }
212     else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::ReadRequest))
213     {
214         OnReadRequest(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
215     }
216     else
217     {
218         OnUnknownMsgType(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
219     }
220 }
221
222 void InteractionModelEngine::OnResponseTimeout(Messaging::ExchangeContext * ec)
223 {
224     ChipLogProgress(DataManagement, "Time out! failed to receive echo response from Exchange: %d", ec->GetExchangeId());
225 }
226
227 // The default implementation to make compiler happy before codegen for this is ready.
228 // TODO: Remove this after codegen is ready.
229 void __attribute__((weak))
230 DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId,
231                              chip::TLV::TLVReader & aReader, Command * apCommandObj)
232 {
233     ChipLogDetail(DataManagement, "Received Cluster Command: Cluster=%" PRIx16 " Command=%" PRIx8 " Endpoint=%" PRIx8, aClusterId,
234                   aCommandId, aEndPointId);
235     ChipLogError(
236         DataManagement,
237         "Default DispatchSingleClusterCommand is called, this should be replaced by actual dispatched for cluster commands");
238 }
239
240 uint16_t InteractionModelEngine::GetReadClientArrayIndex(const ReadClient * const apReadClient) const
241 {
242     return static_cast<uint16_t>(apReadClient - mReadClients);
243 }
244 } // namespace app
245 } // namespace chip