3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2013-2017 Nest Labs, Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 * Declaration of CHIP Device Controller, a common class
23 * that implements connecting and messaging and will later
24 * be expanded to support discovery, pairing and
25 * provisioning of CHIP devices.
31 #include <controller/CHIPDevice.h>
32 #include <core/CHIPCore.h>
33 #include <core/CHIPPersistentStorageDelegate.h>
34 #include <core/CHIPTLV.h>
35 #include <messaging/ExchangeMgr.h>
36 #include <support/DLLUtil.h>
37 #include <support/SerializableIntegerSet.h>
38 #include <transport/AdminPairingTable.h>
39 #include <transport/RendezvousSession.h>
40 #include <transport/RendezvousSessionDelegate.h>
41 #include <transport/SecureSessionMgr.h>
42 #include <transport/TransportMgr.h>
43 #include <transport/raw/UDP.h>
47 namespace Controller {
49 constexpr uint16_t kNumMaxActiveDevices = 64;
50 constexpr uint16_t kNumMaxPairedDevices = 128;
52 struct ControllerInitParams
54 PersistentStorageDelegate * storageDelegate = nullptr;
55 System::Layer * systemLayer = nullptr;
56 Inet::InetLayer * inetLayer = nullptr;
59 class DLL_EXPORT DevicePairingDelegate
62 virtual ~DevicePairingDelegate() {}
66 * Called when the pairing reaches a certain stage.
68 * @param status Current status of pairing
70 virtual void OnStatusUpdate(RendezvousSessionDelegate::Status status) {}
74 * Called when the network credentials are needed for the remote device
76 * @param callback Callback delegate that provisions the network credentials
78 virtual void OnNetworkCredentialsRequested(RendezvousDeviceCredentialsDelegate * callback) = 0;
82 * Called when the operational credentials are needed for the remote device
84 * @param csr Certificate signing request from the device
85 * @param csr_length The length of CSR
86 * @param callback Callback delegate that provisions the operational credentials
88 virtual void OnOperationalCredentialsRequested(const char * csr, size_t csr_length,
89 RendezvousDeviceCredentialsDelegate * callback) = 0;
93 * Called when the pairing is complete (with success or error)
95 * @param error Error cause, if any
97 virtual void OnPairingComplete(CHIP_ERROR error) {}
101 * Called when the pairing is deleted (with success or error)
103 * @param error Error cause, if any
105 virtual void OnPairingDeleted(CHIP_ERROR error) {}
110 * Controller applications can use this class to communicate with already paired CHIP devices. The
111 * application is required to provide access to the persistent storage, where the paired device information
112 * is stored. This object of this class can be initialized with the data from the storage (List of devices,
113 * and device pairing information for individual devices). Alternatively, this class can retrieve the
114 * relevant information when the application tries to communicate with the device
116 class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public PersistentStorageResultDelegate
120 virtual ~DeviceController() {}
123 * Init function to be used when there exists a device layer that takes care of initializing
124 * System::Layer and InetLayer.
126 CHIP_ERROR Init(NodeId localDeviceId, ControllerInitParams params);
128 // Note: Future modifications should be made to ControllerInitParams
129 CHIP_ERROR Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate = nullptr,
130 System::Layer * systemLayer = nullptr, Inet::InetLayer * inetLayer = nullptr);
132 virtual CHIP_ERROR Shutdown();
136 * This function deserializes the provided deviceInfo object, and initializes and outputs the
137 * corresponding Device object. The lifetime of the output object is tied to that of the DeviceController
138 * object. The caller must not use the Device object If they free the DeviceController object, or
139 * after they call ReleaseDevice() on the returned device object.
141 * @param[in] deviceId Node ID for the CHIP device
142 * @param[in] deviceInfo Serialized device info for the device
143 * @param[out] device The output device object
145 * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code.
147 CHIP_ERROR GetDevice(NodeId deviceId, const SerializedDevice & deviceInfo, Device ** device);
151 * This function is similar to the other GetDevice object, except it reads the serialized object from
152 * the persistent storage.
154 * @param[in] deviceId Node ID for the CHIP device
155 * @param[out] device The output device object
157 * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code.
159 CHIP_ERROR GetDevice(NodeId deviceId, Device ** device);
161 CHIP_ERROR SetUdpListenPort(uint16_t listenPort);
163 virtual void ReleaseDevice(Device * device);
168 * Start the event loop task within the CHIP stack
169 * @return CHIP_ERROR The return status
171 CHIP_ERROR ServiceEvents();
175 * Allow the CHIP Stack to process any pending events
176 * This can be called in an event handler loop to tigger callbacks within the CHIP stack
177 * @return CHIP_ERROR The return status
179 CHIP_ERROR ServiceEventSignal();
190 /* A list of device objects that can be used for communicating with corresponding
191 CHIP devices. The list does not contain all the paired devices, but only the ones
192 which the controller application is currently accessing.
194 Device mActiveDevices[kNumMaxActiveDevices];
196 SerializableU64Set<kNumMaxPairedDevices> mPairedDevices;
197 bool mPairedDevicesInitialized;
199 NodeId mLocalDeviceId;
200 DeviceTransportMgr * mTransportMgr;
201 SecureSessionMgr * mSessionManager;
202 Messaging::ExchangeManager * mExchangeManager;
203 PersistentStorageDelegate * mStorageDelegate;
204 Inet::InetLayer * mInetLayer;
206 uint16_t mListenPort;
207 uint16_t GetInactiveDeviceIndex();
208 uint16_t FindDeviceIndex(SecureSessionHandle session);
209 uint16_t FindDeviceIndex(NodeId id);
210 void ReleaseDevice(uint16_t index);
211 void ReleaseDeviceById(NodeId remoteDeviceId);
212 CHIP_ERROR InitializePairedDeviceList();
213 CHIP_ERROR SetPairedDeviceList(const char * pairedDeviceSerializedSet);
214 ControllerDeviceInitParams GetControllerDeviceInitParams();
216 Transport::AdminId mAdminId = 0;
217 Transport::AdminPairingTable mAdmins;
220 //////////// SecureSessionMgrDelegate Implementation ///////////////
221 void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session,
222 System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr) override;
224 void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override;
225 void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) override;
227 //////////// PersistentStorageResultDelegate Implementation ///////////////
228 void OnPersistentStorageStatus(const char * key, Operation op, CHIP_ERROR err) override;
230 void ReleaseAllDevices();
232 System::Layer * mSystemLayer;
237 * The commissioner applications doesn't advertise itself as an available device for rendezvous
238 * process. This delegate class provides no-op functions for the advertisement delegate.
240 class DeviceCommissionerRendezvousAdvertisementDelegate : public RendezvousAdvertisementDelegate
245 * Starts advertisement of the device for rendezvous availability.
247 CHIP_ERROR StartAdvertisement() const override { return CHIP_NO_ERROR; }
251 * Stops advertisement of the device for rendezvous availability.
253 CHIP_ERROR StopAdvertisement() const override { return CHIP_NO_ERROR; }
258 * The commissioner applications can use this class to pair new/unpaired CHIP devices. The application is
259 * required to provide write access to the persistent storage, where the paired device information
262 class DLL_EXPORT DeviceCommissioner : public DeviceController, public RendezvousSessionDelegate
265 DeviceCommissioner();
266 ~DeviceCommissioner() {}
269 * Init function to be used when there exists a device layer that takes care of initializing
270 * System::Layer and InetLayer.
272 CHIP_ERROR Init(NodeId localDeviceId, ControllerInitParams params, DevicePairingDelegate * pairingDelegate = nullptr);
274 // Note: Future modifications should be made to ControllerInitParams
275 CHIP_ERROR Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate = nullptr,
276 DevicePairingDelegate * pairingDelegate = nullptr, System::Layer * systemLayer = nullptr,
277 Inet::InetLayer * inetLayer = nullptr);
279 void SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate) { mPairingDelegate = pairingDelegate; }
281 CHIP_ERROR Shutdown() override;
283 // ----- Connection Management -----
286 * Pair a CHIP device with the provided Rendezvous connection parameters.
287 * Use registered DevicePairingDelegate object to receive notifications on
288 * pairing status updates.
290 * Note: Pairing process requires that the caller has registered PersistentStorageDelegate
291 * in the Init() call.
293 * @param[in] remoteDeviceId The remote device Id.
294 * @param[in] params The Rendezvous connection parameters
296 CHIP_ERROR PairDevice(NodeId remoteDeviceId, RendezvousParameters & params);
298 [[deprecated("Available until Rendezvous is implemented")]] CHIP_ERROR
299 PairTestDeviceWithoutSecurity(NodeId remoteDeviceId, const Transport::PeerAddress & peerAddress, SerializedDevice & serialized);
303 * This function stops a pairing process that's in progress. It does not delete the pairing of a previously
306 * @param[in] remoteDeviceId The remote device Id.
308 * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error
310 CHIP_ERROR StopPairing(NodeId remoteDeviceId);
314 * Remove pairing for a paired device. If the device is currently being paired, it'll stop the pairing process.
316 * @param[in] remoteDeviceId The remote device Id.
318 * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error
320 CHIP_ERROR UnpairDevice(NodeId remoteDeviceId);
322 //////////// RendezvousSessionDelegate Implementation ///////////////
323 void OnRendezvousError(CHIP_ERROR err) override;
324 void OnRendezvousComplete() override;
325 void OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) override;
327 void RendezvousCleanup(CHIP_ERROR status);
329 void ReleaseDevice(Device * device) override;
332 DevicePairingDelegate * mPairingDelegate;
333 RendezvousSession * mRendezvousSession;
335 /* This field is an index in mActiveDevices list. The object at this index in the list
336 contains the device object that's tracking the state of the device that's being paired.
337 If no device is currently being paired, this value will be kNumMaxPairedDevices. */
338 uint16_t mDeviceBeingPaired;
340 /* TODO: BLE rendezvous and IP rendezvous should share the same procedure, so this is just a
341 workaround-like flag and should be removed in the future.
342 When using IP rendezvous, we need to disable network provisioning. In the future, network
343 provisioning will no longer be a part of rendezvous procedure. */
344 bool mIsIPRendezvous;
346 /* This field is true when device pairing information changes, e.g. a new device is paired, or
347 the pairing for a device is removed. The DeviceCommissioner uses this to decide when to
348 persist the device list */
349 bool mPairedDevicesUpdated;
351 DeviceCommissionerRendezvousAdvertisementDelegate mRendezvousAdvDelegate;
353 void PersistDeviceList();
355 void FreeRendezvousSession();
357 CHIP_ERROR LoadKeyId(PersistentStorageDelegate * delegate, uint16_t & out);
359 uint16_t mNextKeyId = 0;
362 } // namespace Controller