Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / controller / python / chip / internal / CommissionerImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2021 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17 #include <memory>
18
19 #include <controller/CHIPDeviceController.h>
20 #include <platform/CHIPDeviceLayer.h>
21 #include <platform/KeyValueStoreManager.h>
22 #include <support/logging/CHIPLogging.h>
23
24 #include "ChipThreadWork.h"
25
26 namespace {
27
28 class ServerStorageDelegate : public chip::PersistentStorageDelegate
29 {
30 public:
31     void SetStorageDelegate(chip::PersistentStorageResultDelegate * delegate) override { mAsyncDelegate = delegate; }
32
33     void AsyncSetKeyValue(const char * key, const char * value) override
34     {
35
36         CHIP_ERROR err = SyncSetKeyValue(key, value, strlen(value));
37
38         if (err != CHIP_NO_ERROR)
39         {
40             mAsyncDelegate->OnPersistentStorageStatus(key, chip::PersistentStorageResultDelegate::Operation::kSET, err);
41         }
42     }
43
44     CHIP_ERROR
45     SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override
46     {
47         return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size);
48     }
49
50     CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override
51     {
52         return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(key, value, size);
53     }
54
55     void AsyncDeleteKeyValue(const char * key) override { chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(key); }
56
57 private:
58     chip::PersistentStorageResultDelegate * mAsyncDelegate = nullptr;
59 };
60
61 // FIXME: implement this class
62 class ScriptDevicePairingDelegate final : public chip::Controller::DevicePairingDelegate
63 {
64 public:
65     using OnNetworkCredentialsRequestedCallback     = void (*)();
66     using OnOperationalCredentialsRequestedCallback = void (*)(const char * csr, size_t length);
67     using OnPairingCompleteCallback                 = void (*)(CHIP_ERROR err);
68
69     ~ScriptDevicePairingDelegate() = default;
70
71     void OnNetworkCredentialsRequested(chip::RendezvousDeviceCredentialsDelegate * callback) override
72     {
73         mCredentialsDelegate = callback;
74         if (mNetworkCredentialsRequested == nullptr)
75         {
76             ChipLogError(Controller, "Callback for network credentials is not defined.");
77             return;
78         }
79         mNetworkCredentialsRequested();
80     }
81
82     void OnOperationalCredentialsRequested(const char * csr, size_t csr_length,
83                                            chip::RendezvousDeviceCredentialsDelegate * callback) override
84     {
85         mCredentialsDelegate = callback;
86         if (mOperationalCredentialsRequested == nullptr)
87         {
88             ChipLogError(Controller, "Callback for operational credentials is not defined.");
89             return;
90         }
91
92         mOperationalCredentialsRequested(csr, csr_length);
93     }
94
95     void OnPairingComplete(CHIP_ERROR error) override
96     {
97         if (mPairingComplete == nullptr)
98         {
99             ChipLogError(Controller, "Callback for pairing coomplete is not defined.");
100             return;
101         }
102         mPairingComplete(error);
103     }
104
105     void SetNetworkCredentialsRequestedCallback(OnNetworkCredentialsRequestedCallback callback)
106     {
107         mNetworkCredentialsRequested = callback;
108     }
109
110     void SetOperatioonalCredentialsRequestedCallback(OnOperationalCredentialsRequestedCallback callback)
111     {
112         mOperationalCredentialsRequested = callback;
113     }
114
115     void SetPairingCompleteCallback(OnPairingCompleteCallback callback) { mPairingComplete = callback; }
116
117     void SetWifiCredentials(const char * ssid, const char * password)
118     {
119         if (mCredentialsDelegate == nullptr)
120         {
121             ChipLogError(Controller, "Wifi credentials received before delegate available.");
122             return;
123         }
124
125         mCredentialsDelegate->SendNetworkCredentials(ssid, password);
126     }
127
128     void SetThreadCredentials(const chip::DeviceLayer::Internal::DeviceNetworkInfo & threadData)
129     {
130         if (mCredentialsDelegate == nullptr)
131         {
132             ChipLogError(Controller, "Thread credentials received before delegate available.");
133             return;
134         }
135
136         mCredentialsDelegate->SendThreadCredentials(threadData);
137     }
138
139 private:
140     OnNetworkCredentialsRequestedCallback mNetworkCredentialsRequested         = nullptr;
141     OnOperationalCredentialsRequestedCallback mOperationalCredentialsRequested = nullptr;
142     OnPairingCompleteCallback mPairingComplete                                 = nullptr;
143
144     /// Delegate is set during request callbacks
145     chip::RendezvousDeviceCredentialsDelegate * mCredentialsDelegate = nullptr;
146 };
147
148 ServerStorageDelegate gServerStorage;
149 ScriptDevicePairingDelegate gPairingDelegate;
150
151 } // namespace
152
153 extern "C" void pychip_internal_PairingDelegate_SetWifiCredentials(const char * ssid, const char * password)
154 {
155     chip::python::ChipMainThreadScheduleAndWait([&]() { gPairingDelegate.SetWifiCredentials(ssid, password); });
156 }
157
158 extern "C" CHIP_ERROR pychip_internal_PairingDelegate_SetThreadCredentials(const void * data, uint32_t length)
159 {
160
161     // Openthread is OPAQUE by the spec, however current CHIP stack does not have any
162     // validation/support for opaque blobs. As a result, we try to do some
163     // pre-validation here
164
165     // TODO: there should be uniform 'BLOBL' support within the thread stack
166     if (length != sizeof(chip::DeviceLayer::Internal::DeviceNetworkInfo))
167     {
168         ChipLogError(Controller, "Received invalid thread credential blob. Expected size %u and got %u bytes instead",
169                      sizeof(chip::DeviceLayer::Internal::DeviceNetworkInfo), length);
170         return CHIP_ERROR_INVALID_ARGUMENT;
171     }
172
173     // unsure about alignment so copy into a properly aligned item
174     chip::DeviceLayer::Internal::DeviceNetworkInfo threadInfo;
175     memcpy(&threadInfo, data, sizeof(threadInfo));
176
177     // TODO: figure out a proper way to validate this or remove validation once
178     // thread credentials are assumed opaque throughout
179     if ((threadInfo.ThreadChannel != chip::DeviceLayer::Internal::kThreadChannel_NotSpecified) &&
180         ((threadInfo.ThreadChannel < 11) || (threadInfo.ThreadChannel > 26)))
181     {
182         ChipLogError(Controller, "Failed to validate thread info: channel %d is not valid", threadInfo.ThreadChannel);
183         return CHIP_ERROR_INVALID_ARGUMENT;
184     }
185
186     chip::python::ChipMainThreadScheduleAndWait([&]() { gPairingDelegate.SetThreadCredentials(threadInfo); });
187
188     return CHIP_NO_ERROR;
189 }
190
191 extern "C" void pychip_internal_PairingDelegate_SetNetworkCredentialsRequestedCallback(
192     ScriptDevicePairingDelegate::OnNetworkCredentialsRequestedCallback callback)
193 {
194     gPairingDelegate.SetNetworkCredentialsRequestedCallback(callback);
195 }
196
197 extern "C" void pychip_internal_PairingDelegate_SetOperationalCredentialsRequestedCallback(
198     ScriptDevicePairingDelegate::OnOperationalCredentialsRequestedCallback callback)
199 {
200     gPairingDelegate.SetOperatioonalCredentialsRequestedCallback(callback);
201 }
202
203 extern "C" void
204 pychip_internal_PairingDelegate_SetPairingCompleteCallback(ScriptDevicePairingDelegate::OnPairingCompleteCallback callback)
205 {
206     gPairingDelegate.SetPairingCompleteCallback(callback);
207 }
208
209 extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_New(uint64_t localDeviceId)
210 {
211     std::unique_ptr<chip::Controller::DeviceCommissioner> result;
212     CHIP_ERROR err;
213
214     chip::python::ChipMainThreadScheduleAndWait([&]() {
215         result = std::make_unique<chip::Controller::DeviceCommissioner>();
216
217         // System and Inet layers explicitly passed to indicate that the CHIP stack is
218         // already assumed initialized
219         err = result->Init(localDeviceId,
220                            chip::Controller::ControllerInitParams{
221                                .storageDelegate = &gServerStorage,
222                                .systemLayer     = &chip::DeviceLayer::SystemLayer,
223                                .inetLayer       = &chip::DeviceLayer::InetLayer,
224                            },
225                            &gPairingDelegate);
226     });
227
228     if (err != CHIP_NO_ERROR)
229     {
230         ChipLogError(Controller, "Commissioner initialization failed: %s", chip::ErrorStr(err));
231         return nullptr;
232     }
233
234     return result.release();
235 }
236
237 /// Returns CHIP_ERROR corresponding to an UnpairDevice call
238 extern "C" uint32_t pychip_internal_Commissioner_Unpair(chip::Controller::DeviceCommissioner * commissioner,
239                                                         uint64_t remoteDeviceId)
240 {
241     CHIP_ERROR err;
242
243     chip::python::ChipMainThreadScheduleAndWait([&]() { err = commissioner->UnpairDevice(remoteDeviceId); });
244
245     return err;
246 }
247
248 extern "C" uint32_t pychip_internal_Commissioner_BleConnectForPairing(chip::Controller::DeviceCommissioner * commissioner,
249                                                                       uint64_t remoteNodeId, uint32_t pinCode,
250                                                                       uint16_t discriminator)
251 {
252
253     CHIP_ERROR err;
254
255     chip::python::ChipMainThreadScheduleAndWait([&]() {
256         chip::RendezvousParameters params;
257
258         params.SetDiscriminator(discriminator).SetSetupPINCode(pinCode).SetRemoteNodeId(remoteNodeId);
259 #if CONFIG_NETWORK_LAYER_BLE
260         params.SetBleLayer(chip::DeviceLayer::ConnectivityMgr().GetBleLayer()).SetPeerAddress(chip::Transport::PeerAddress::BLE());
261 #endif
262
263         err = commissioner->PairDevice(remoteNodeId, params);
264     });
265
266     return err;
267 }