Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / controller / CHIPDevice.h
1 /*
2  *
3  *    Copyright (c) 2020 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 contains definitions for Device class. The objects of this
22  *    class will be used by Controller applications to interact with CHIP
23  *    devices. The class provides mechanism to construct, send and receive
24  *    messages to and from the corresponding CHIP devices.
25  */
26
27 #pragma once
28
29 #include <app/CommandSender.h>
30 #include <app/InteractionModelEngine.h>
31 #include <app/util/CHIPDeviceCallbacksMgr.h>
32 #include <app/util/basic-types.h>
33 #include <core/CHIPCallback.h>
34 #include <core/CHIPCore.h>
35 #include <setup_payload/SetupPayload.h>
36 #include <support/Base64.h>
37 #include <support/DLLUtil.h>
38 #include <transport/PASESession.h>
39 #include <transport/SecureSessionMgr.h>
40 #include <transport/TransportMgr.h>
41 #include <transport/raw/MessageHeader.h>
42 #include <transport/raw/UDP.h>
43
44 namespace chip {
45 namespace Controller {
46
47 class DeviceController;
48 class DeviceStatusDelegate;
49 struct SerializedDevice;
50
51 using DeviceTransportMgr = TransportMgr<Transport::UDP /* IPv6 */
52 #if INET_CONFIG_ENABLE_IPV4
53                                         ,
54                                         Transport::UDP /* IPv4 */
55 #endif
56                                         >;
57
58 struct ControllerDeviceInitParams
59 {
60     DeviceTransportMgr * transportMgr = nullptr;
61     SecureSessionMgr * sessionMgr     = nullptr;
62     Inet::InetLayer * inetLayer       = nullptr;
63 };
64
65 class DLL_EXPORT Device
66 {
67 public:
68     ~Device()
69     {
70         if (mCommandSender != nullptr)
71         {
72             mCommandSender->Shutdown();
73             mCommandSender = nullptr;
74         }
75     }
76
77     enum class PairingWindowOption
78     {
79         kOriginalSetupCode,
80         kTokenWithRandomPIN,
81         kTokenWithProvidedPIN,
82     };
83
84     /**
85      * @brief
86      *   Set the delegate object which will be called when a message is received.
87      *   The user of this Device object must reset the delegate (by calling
88      *   SetDelegate(nullptr)) before releasing their delegate object.
89      *
90      * @param[in] delegate   The pointer to the delegate object.
91      */
92     void SetDelegate(DeviceStatusDelegate * delegate) { mStatusDelegate = delegate; }
93
94     // ----- Messaging -----
95     /**
96      * @brief
97      *   Send the provided message to the device
98      *
99      * @param[in] message   The message to be sent.
100      *
101      * @return CHIP_ERROR   CHIP_NO_ERROR on success, or corresponding error
102      */
103     CHIP_ERROR SendMessage(System::PacketBufferHandle message);
104
105     /**
106      * @brief
107      *   Send the command in internal command sender.
108      */
109     CHIP_ERROR SendCommands();
110
111     /**
112      * @brief
113      *   Initialize internal command sender, required for sending commands over interaction model.
114      */
115     void InitCommandSender()
116     {
117         if (mCommandSender != nullptr)
118         {
119             mCommandSender->Shutdown();
120             mCommandSender = nullptr;
121         }
122 #if CHIP_ENABLE_INTERACTION_MODEL
123         chip::app::InteractionModelEngine::GetInstance()->NewCommandSender(&mCommandSender);
124 #endif
125     }
126     app::CommandSender * GetCommandSender() { return mCommandSender; }
127
128     /**
129      * @brief Get the IP address and port assigned to the device.
130      *
131      * @param[out] addr   IP address of the device.
132      * @param[out] port   Port number of the device.
133      *
134      * @return true, if the IP address and port were filled in the out parameters, false otherwise
135      */
136     bool GetAddress(Inet::IPAddress & addr, uint16_t & port) const;
137
138     /**
139      * @brief
140      *   Initialize the device object with secure session manager and inet layer object
141      *   references. This variant of function is typically used when the device object
142      *   is created from a serialized device information. The other parameters (address, port,
143      *   interface etc) are part of the serialized device, so those are not required to be
144      *   initialized.
145      *
146      *   Note: The lifetime of session manager and inet layer objects must be longer than
147      *   that of this device object. If these objects are freed, while the device object is
148      *   still using them, it can lead to unknown behavior and crashes.
149      *
150      * @param[in] params       Wrapper object for transport manager etc.
151      * @param[in] listenPort   Port on which controller is listening (typically CHIP_PORT)
152      * @param[in] admin        Local administrator that's initializing this device object
153      */
154     void Init(ControllerDeviceInitParams params, uint16_t listenPort, Transport::AdminId admin)
155     {
156         mTransportMgr   = params.transportMgr;
157         mSessionManager = params.sessionMgr;
158         mInetLayer      = params.inetLayer;
159         mListenPort     = listenPort;
160         mAdminId        = admin;
161     }
162
163     /**
164      * @brief
165      *   Initialize a new device object with secure session manager, inet layer object,
166      *   and other device specific parameters. This variant of function is typically used when
167      *   a new device is paired, and the corresponding device object needs to updated with
168      *   all device specifc parameters (address, port, interface etc).
169      *
170      *   This is not done as part of constructor so that the controller can have a list of
171      *   uninitialzed/unpaired device objects. The object is initialized only when the device
172      *   is actually paired.
173      *
174      * @param[in] params       Wrapper object for transport manager etc.
175      * @param[in] listenPort   Port on which controller is listening (typically CHIP_PORT)
176      * @param[in] deviceId     Node ID of the device
177      * @param[in] peerAddress  The location of the peer. MUST be of type Transport::Type::kUdp
178      * @param[in] admin        Local administrator that's initializing this device object
179      */
180     void Init(ControllerDeviceInitParams params, uint16_t listenPort, NodeId deviceId, const Transport::PeerAddress & peerAddress,
181               Transport::AdminId admin)
182     {
183         Init(params, mListenPort, admin);
184         mDeviceId = deviceId;
185         mState    = ConnectionState::Connecting;
186
187         if (peerAddress.GetTransportType() != Transport::Type::kUdp)
188         {
189             ChipLogError(Controller, "Invalid peer address received in chip device initialization. Expected a UDP address.");
190             chipDie();
191         }
192         else
193         {
194             mDeviceUdpAddress = peerAddress;
195         }
196     }
197
198     /** @brief Serialize the Pairing Session to a string. It's guaranteed that the string
199      *         will be null terminated, and there won't be any embedded null characters.
200      *
201      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
202      **/
203     CHIP_ERROR Serialize(SerializedDevice & output);
204
205     /** @brief Deserialize the Pairing Session from the string. It's expected that the string
206      *         will be null terminated, and there won't be any embedded null characters.
207      *
208      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
209      **/
210     CHIP_ERROR Deserialize(const SerializedDevice & input);
211
212     /**
213      * @brief
214      *   Called when a new pairing is being established
215      *
216      * @param session A handle to the secure session
217      * @param mgr     A pointer to the SecureSessionMgr
218      */
219     void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr);
220
221     /**
222      * @brief
223      *   Called when a connection is closing.
224      *
225      *   The receiver should release all resources associated with the connection.
226      *
227      * @param session A handle to the secure session
228      * @param mgr     A pointer to the SecureSessionMgr
229      */
230     void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr);
231
232     /**
233      * @brief
234      *   This function is called when a message is received from the corresponding CHIP
235      *   device. The message ownership is transferred to the function, and it is expected
236      *   to release the message buffer before returning.
237      *
238      * @param[in] header        Reference to common packet header of the received message
239      * @param[in] payloadHeader Reference to payload header in the message
240      * @param[in] session       A handle to the secure session
241      * @param[in] msgBuf        The message buffer
242      * @param[in] mgr           Pointer to secure session manager which received the message
243      */
244     void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session,
245                            System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr);
246
247     /**
248      * @brief
249      *   Trigger a paired device to re-enter the pairing mode. If an onboarding token is provided, the device will use
250      *   the provided setup PIN code and the discriminator to advertise itself for pairing availability. If the token
251      *   is not provided, the device will use the manufacturer assigned setup PIN code and discriminator.
252      *
253      *   The device will exit the pairing mode after a successful pairing, or after the given `timeout` time.
254      *
255      * @param[in] timeout         The pairing mode should terminate after this much time.
256      * @param[in] option          The pairing window can be opened using the original setup code, or an
257      *                            onboarding token can be generated using a random setup PIN code (or with
258      *                            the PIN code provied in the setupPayload). This argument selects one of these
259      *                            methods.
260      * @param[out] setupPayload   The setup payload corresponding to the generated onboarding token.
261      *
262      * @return CHIP_ERROR               CHIP_NO_ERROR on success, or corresponding error
263      */
264     CHIP_ERROR OpenPairingWindow(uint32_t timeout, PairingWindowOption option, SetupPayload & setupPayload);
265
266     /**
267      * @brief
268      *   Update address of the device.
269      *
270      *   This function will set new IP address and port of the device. Since the device settings might
271      *   have been moved from RAM to the persistent storage, the function will load the device settings
272      *   first, before making the changes.
273      *
274      * @param[in] addr   Address of the device to be set.
275      *
276      * @return CHIP_NO_ERROR if the address has been updated, an error code otherwise.
277      */
278     CHIP_ERROR UpdateAddress(const Transport::PeerAddress & addr);
279     /**
280      * @brief
281      *   Return whether the current device object is actively associated with a paired CHIP
282      *   device. An active object can be used to communicate with the corresponding device.
283      */
284     bool IsActive() const { return mActive; }
285
286     void SetActive(bool active) { mActive = active; }
287
288     bool IsSecureConnected() const { return IsActive() && mState == ConnectionState::SecureConnected; }
289
290     void Reset()
291     {
292         SetActive(false);
293         mState          = ConnectionState::NotConnected;
294         mSessionManager = nullptr;
295         mStatusDelegate = nullptr;
296         mInetLayer      = nullptr;
297     }
298
299     NodeId GetDeviceId() const { return mDeviceId; }
300
301     bool MatchesSession(SecureSessionHandle session) const { return mSecureSession == session; }
302
303     void SetAddress(const Inet::IPAddress & deviceAddr) { mDeviceUdpAddress.SetIPAddress(deviceAddr); }
304
305     PASESessionSerializable & GetPairing() { return mPairing; }
306
307     uint8_t GetNextSequenceNumber() { return mSequenceNumber++; };
308     void AddResponseHandler(uint8_t seqNum, Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback);
309     void AddReportHandler(EndpointId endpoint, ClusterId cluster, AttributeId attribute, Callback::Cancelable * onReportCallback);
310
311 private:
312     enum class ConnectionState
313     {
314         NotConnected,
315         Connecting,
316         SecureConnected,
317     };
318
319     enum class ResetTransport
320     {
321         kYes,
322         kNo,
323     };
324     /* Node ID assigned to the CHIP device */
325     NodeId mDeviceId;
326
327     /** Address used to communicate with the device. MUST be Type::kUDP
328      *  in the current implementation.
329      */
330     Transport::PeerAddress mDeviceUdpAddress = Transport::PeerAddress::UDP(Inet::IPAddress::Any);
331
332     Inet::InetLayer * mInetLayer = nullptr;
333
334     bool mActive           = false;
335     ConnectionState mState = ConnectionState::NotConnected;
336
337     PASESessionSerializable mPairing;
338
339     DeviceStatusDelegate * mStatusDelegate = nullptr;
340
341     SecureSessionMgr * mSessionManager = nullptr;
342
343     DeviceTransportMgr * mTransportMgr = nullptr;
344
345     app::CommandSender * mCommandSender = nullptr;
346
347     SecureSessionHandle mSecureSession = {};
348
349     uint8_t mSequenceNumber = 0;
350
351     app::CHIPDeviceCallbacksMgr & mCallbacksMgr = app::CHIPDeviceCallbacksMgr::GetInstance();
352
353     /**
354      * @brief
355      *   This function loads the secure session object from the serialized operational
356      *   credentials corresponding to the device. This is typically done when the device
357      *   does not have an active secure channel.
358      *
359      * @param[in] resetNeeded   Does the underlying network socket require a reset
360      */
361     CHIP_ERROR LoadSecureSessionParameters(ResetTransport resetNeeded);
362
363     /**
364      * @brief
365      *   This function loads the secure session object from the serialized operational
366      *   credentials corresponding if needed, based on the current state of the device and
367      *   underlying transport object.
368      *
369      * @param[out] didLoad   Were the secure session params loaded by the call to this function.
370      */
371     CHIP_ERROR LoadSecureSessionParametersIfNeeded(bool & didLoad);
372
373     CHIP_ERROR SendMessage(System::PacketBufferHandle message, PayloadHeader & payloadHeader);
374
375     uint16_t mListenPort;
376
377     Transport::AdminId mAdminId = Transport::kUndefinedAdminId;
378 };
379
380 /**
381  * This class defines an interface for an object that the user of Device
382  * can register as a delegate. The delegate object will be called by the
383  * Device when a new message or status update is received from the corresponding
384  * CHIP device.
385  */
386 class DLL_EXPORT DeviceStatusDelegate
387 {
388 public:
389     virtual ~DeviceStatusDelegate() {}
390
391     /**
392      * @brief
393      *   Called when a message is received from the device.
394      *
395      * @param[in] msg Received message buffer.
396      */
397     virtual void OnMessage(System::PacketBufferHandle msg) = 0;
398
399     /**
400      * @brief
401      *   Called when response to OpenPairingWindow is received from the device.
402      *
403      * @param[in] status CHIP_NO_ERROR on success, or corresponding error.
404      */
405     virtual void OnPairingWindowOpenStatus(CHIP_ERROR status){};
406
407     /**
408      * @brief
409      *   Called when device status is updated.
410      *
411      */
412     virtual void OnStatusChange(void){};
413 };
414
415 #ifdef IFNAMSIZ
416 constexpr uint16_t kMaxInterfaceName = IFNAMSIZ;
417 #else
418 constexpr uint16_t kMaxInterfaceName = 32;
419 #endif
420
421 typedef struct SerializableDevice
422 {
423     PASESessionSerializable mOpsCreds;
424     uint64_t mDeviceId; /* This field is serialized in LittleEndian byte order */
425     uint8_t mDeviceAddr[INET6_ADDRSTRLEN];
426     uint16_t mDevicePort; /* This field is serialized in LittleEndian byte order */
427     uint16_t mAdminId;    /* This field is serialized in LittleEndian byte order */
428     uint8_t mInterfaceName[kMaxInterfaceName];
429 } SerializableDevice;
430
431 typedef struct SerializedDevice
432 {
433     // Extra uint64_t to account for padding bytes (NULL termination, and some decoding overheads)
434     // The encoder may not include a NULL character, and there are maximum 2 bytes of padding.
435     // So extra 8 bytes should be sufficient to absorb this overhead.
436     uint8_t inner[BASE64_ENCODED_LEN(sizeof(SerializableDevice) + sizeof(uint64_t))];
437 } SerializedDevice;
438
439 } // namespace Controller
440 } // namespace chip