Add C++ API for OCUnlink / OCRemove CAPI to Provisioning Manager
[platform/upstream/iotivity.git] / resource / provisioning / src / OCProvisioningManager.cpp
1 /* *****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  * *****************************************************************/
20
21 #include "ocstack.h"
22 #include "base64.h"
23 #include "OCProvisioningManager.h"
24
25 namespace OC
26 {
27     OCStackResult OCSecure::provisionInit(const std::string& dbPath)
28     {
29         OCStackResult result;
30         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
31
32         if(cLock)
33         {
34             std::lock_guard<std::recursive_mutex> lock(*cLock);
35             result = OCInitPM(dbPath.c_str());
36         }
37         else
38         {
39             oclog() <<"Mutex not found";
40             result = OC_STACK_ERROR;
41         }
42
43         return result;
44     }
45
46     OCStackResult OCSecure::discoverUnownedDevices(unsigned short timeout,
47             DeviceList_t &list)
48     {
49         OCStackResult result;
50         OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
51         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
52         auto cLock = csdkLock.lock();
53
54         if(cLock)
55         {
56             std::lock_guard<std::recursive_mutex> lock(*cLock);
57             result = OCDiscoverUnownedDevices(timeout, &pDevList);
58             if (result == OC_STACK_OK)
59             {
60                 // Create DeviceList of OCSecureResource's
61                 pCurDev = pDevList;
62                 while (pCurDev)
63                 {
64                     tmp = pCurDev;
65                     list.push_back(std::shared_ptr<OCSecureResource>(
66                                 new OCSecureResource(csdkLock, pCurDev)));
67                     pCurDev = pCurDev->next;
68                     tmp->next = nullptr;
69                 }
70             }
71             else
72             {
73                 oclog() <<"Unowned device discovery failed!";
74             }
75         }
76         else
77         {
78             oclog() <<"Mutex not found";
79             result = OC_STACK_ERROR;
80         }
81
82         return result;
83     }
84
85     OCStackResult OCSecure::discoverOwnedDevices(unsigned short timeout,
86             DeviceList_t &list)
87     {
88         OCStackResult result;
89         OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
90         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
91         auto cLock = csdkLock.lock();
92
93         if(cLock)
94         {
95             std::lock_guard<std::recursive_mutex> lock(*cLock);
96             result = OCDiscoverOwnedDevices(timeout, &pDevList);
97             if (result == OC_STACK_OK)
98             {
99                 pCurDev = pDevList;
100                 while (pCurDev)
101                 {
102                     tmp = pCurDev;
103                     list.push_back(std::shared_ptr<OCSecureResource>(
104                                 new OCSecureResource(csdkLock, pCurDev)));
105                     pCurDev = pCurDev->next;
106                     tmp->next = nullptr;
107                 }
108             }
109             else
110             {
111                 oclog() <<"Owned device discovery failed!";
112             }
113         }
114         else
115         {
116             oclog() <<"Mutex not found";
117             result = OC_STACK_ERROR;
118         }
119
120         return result;
121     }
122
123     OCStackResult OCSecure::setOwnerTransferCallbackData(OicSecOxm_t oxm,
124             OTMCallbackData_t* callbackData, InputPinCallback inputPin)
125     {
126         if(NULL == callbackData || oxm >= OIC_OXM_COUNT)
127         {
128             oclog() <<"Invalid callbackData or OXM type";
129             return OC_STACK_INVALID_PARAM;
130         }
131
132         if((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin)
133         {
134             oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null";
135             return OC_STACK_INVALID_PARAM;
136         }
137
138         OCStackResult result;
139         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
140
141         if(cLock)
142         {
143             std::lock_guard<std::recursive_mutex> lock(*cLock);
144             result = OCSetOwnerTransferCallbackData(oxm, callbackData);
145             if(result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN & oxm))
146             {
147                 SetInputPinCB(inputPin);
148             }
149         }
150         else
151         {
152             oclog() <<"Mutex not found";
153             result = OC_STACK_ERROR;
154         }
155
156         return result;
157
158     }
159
160     OCStackResult OCSecure::getDevInfoFromNetwork(unsigned short timeout,
161             DeviceList_t &ownedDevList,
162             DeviceList_t &unownedDevList)
163     {
164         OCStackResult result = OC_STACK_OK;
165         OCProvisionDev_t *owned = nullptr, *unowned = nullptr, *tmp = nullptr, *dev = nullptr;
166         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
167         auto cLock = csdkLock.lock();
168
169         if(cLock)
170         {
171             std::lock_guard<std::recursive_mutex> lock(*cLock);
172
173             result = OCGetDevInfoFromNetwork(timeout, &owned, &unowned);
174
175             if (result == OC_STACK_OK)
176             {
177                 dev = owned;
178                 while (dev)
179                 {
180                     tmp = dev;
181                     ownedDevList.push_back(std::shared_ptr<OCSecureResource>(
182                                 new OCSecureResource(csdkLock, dev)));
183                     dev = dev->next;
184                     tmp->next = nullptr;
185                 }
186
187                 dev = unowned;
188                 while (dev)
189                 {
190                     tmp = dev;
191                     unownedDevList.push_back(std::shared_ptr<OCSecureResource>(
192                                 new OCSecureResource(csdkLock,  dev)));
193                     dev = dev->next;
194                     tmp->next = nullptr;
195                 }
196             }
197         }
198         else
199         {
200             oclog() <<"Mutex not found";
201             result = OC_STACK_ERROR;
202         }
203
204         return result;
205     }
206
207     void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
208     {
209         PMResultList_t *results = nullptr;
210         ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
211
212         results = new PMResultList_t;
213         for (int i = 0; i < nOfRes; i++)
214         {
215             results->push_back(arr[i]);
216         }
217
218         std::thread exec(context->callback, results, hasError);
219         exec.detach();
220
221         delete context;
222     }
223
224     OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
225                                         devPtr(nullptr)
226     {
227     }
228
229     OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
230             OCProvisionDev_t *dPtr)
231         :m_csdkLock(csdkLock), devPtr(dPtr)
232     {
233     }
234
235     OCSecureResource::~OCSecureResource()
236     {
237         if(devPtr)
238         {
239             OCDeleteDiscoveredDevices(devPtr);
240         }
241     }
242
243     OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
244     {
245         if(!resultCallback)
246         {
247             oclog() <<"Result callback can't be null";
248             return OC_STACK_INVALID_PARAM;
249         }
250
251         OCStackResult result;
252         auto cLock = m_csdkLock.lock();
253
254         if(cLock)
255         {
256             ProvisionContext* context = new ProvisionContext(resultCallback);
257
258             std::lock_guard<std::recursive_mutex> lock(*cLock);
259             result = OCDoOwnershipTransfer(static_cast<void*>(context),
260                     devPtr, &OCSecureResource::callbackWrapper);
261         }
262         else
263         {
264             oclog() <<"Mutex not found";
265             result = OC_STACK_ERROR;
266         }
267         return result;
268     }
269
270     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
271             ResultCallBack resultCallback)
272     {
273         if(!resultCallback || !acl)
274         {
275             oclog() <<"Result callback or ACL can't be null";
276             return OC_STACK_INVALID_PARAM;
277         }
278
279         OCStackResult result;
280         auto cLock = m_csdkLock.lock();
281
282         if(cLock)
283         {
284             ProvisionContext* context = new ProvisionContext(resultCallback);
285
286             std::lock_guard<std::recursive_mutex> lock(*cLock);
287             result = OCProvisionACL(static_cast<void*>(context),
288                     devPtr, const_cast<OicSecAcl_t*>(acl),
289                     &OCSecureResource::callbackWrapper);
290         }
291         else
292         {
293             oclog() <<"Mutex not found";
294             result = OC_STACK_ERROR;
295         }
296         return result;
297     }
298
299     OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
300             const OCSecureResource &device2, ResultCallBack resultCallback)
301     {
302         if(!resultCallback)
303         {
304             oclog() << "Result calback can't be null";
305             return OC_STACK_INVALID_PARAM;
306         }
307
308         OCStackResult result;
309         auto cLock = m_csdkLock.lock();
310
311         if(cLock)
312         {
313             ProvisionContext* context = new ProvisionContext(resultCallback);
314
315             std::lock_guard<std::recursive_mutex> lock(*cLock);
316             result = OCProvisionCredentials(static_cast<void*>(context),
317                     cred.getCredentialType(),
318                     cred.getCredentialKeySize(),
319                     devPtr, device2.getDevPtr(),
320                     &OCSecureResource::callbackWrapper);
321         }
322         else
323         {
324             oclog() <<"Mutex not found";
325             result = OC_STACK_ERROR;
326         }
327         return result;
328     }
329
330     OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
331             const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
332             ResultCallBack resultCallback)
333     {
334         if(!resultCallback)
335         {
336             oclog() << "Result calback can't be null";
337             return OC_STACK_INVALID_PARAM;
338         }
339
340         OCStackResult result;
341         auto cLock = m_csdkLock.lock();
342
343         if(cLock)
344         {
345             ProvisionContext* context = new ProvisionContext(resultCallback);
346
347             std::lock_guard<std::recursive_mutex> lock(*cLock);
348             result = OCProvisionPairwiseDevices(static_cast<void*>(context),
349                     cred.getCredentialType(),
350                     cred.getCredentialKeySize(),
351                     devPtr, const_cast<OicSecAcl_t*>(acl1),
352                     device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
353                     &OCSecureResource::callbackWrapper);
354         }
355         else
356         {
357             oclog() <<"Mutex not found";
358             result = OC_STACK_ERROR;
359         }
360         return result;
361     }
362
363     OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
364             ResultCallBack resultCallback)
365     {
366         if(!resultCallback)
367         {
368             oclog() << "Result calback can't be null";
369             return OC_STACK_INVALID_PARAM;
370         }
371
372         OCStackResult result;
373         auto cLock = m_csdkLock.lock();
374
375         if(cLock)
376         {
377             ProvisionContext* context = new ProvisionContext(resultCallback);
378
379             std::lock_guard<std::recursive_mutex> lock(*cLock);
380
381             result = OCUnlinkDevices(static_cast<void*>(context),
382                     devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
383         }
384         else
385         {
386             oclog() <<"Mutex not found";
387             result = OC_STACK_ERROR;
388         }
389         return result;
390     }
391
392     OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
393             ResultCallBack resultCallback)
394     {
395         if(!resultCallback)
396         {
397             oclog() << "Result calback can't be null";
398             return OC_STACK_INVALID_PARAM;
399         }
400
401         OCStackResult result;
402         auto cLock = m_csdkLock.lock();
403
404         if(cLock)
405         {
406             ProvisionContext* context = new ProvisionContext(resultCallback);
407
408             std::lock_guard<std::recursive_mutex> lock(*cLock);
409
410             result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
411                     devPtr, &OCSecureResource::callbackWrapper);
412         }
413         else
414         {
415             oclog() <<"Mutex not found";
416             result = OC_STACK_ERROR;
417         }
418         return result;
419     }
420
421     OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
422     {
423         OCStackResult result;
424         size_t numOfDevices = -1;
425         auto devUuid = devPtr->doxm->deviceID;
426         auto cLock = m_csdkLock.lock();
427
428         if(cLock)
429         {
430             std::lock_guard<std::recursive_mutex> lock(*cLock);
431
432             OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
433             result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
434             if (result == OC_STACK_OK)
435             {
436                 for (tmp = linkedDevs; tmp; tmp = tmp->next)
437                 {
438                     uuidList.push_back(tmp->dev);
439                 }
440                 OCDeleteUuidList(linkedDevs);
441             }
442         }
443         else
444         {
445             oclog() <<"Mutex not found";
446             result = OC_STACK_ERROR;
447         }
448         return result;
449     }
450
451     std::string OCSecureResource::getDeviceID()
452     {
453         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {0,};
454         uint32_t outLen = 0;
455         B64Result b64Ret = B64_OK;
456         std::ostringstream deviceId("");
457
458         validateSecureResource();
459         b64Ret = b64Encode(devPtr->doxm->deviceID.id, sizeof(devPtr->doxm->deviceID.id), base64Buff,
460                 sizeof(base64Buff), &outLen);
461
462         if (B64_OK == b64Ret)
463         {
464             deviceId << base64Buff;
465         }
466         return deviceId.str();
467     }
468
469     OCProvisionDev_t* OCSecureResource::getDevPtr() const
470     {
471         return devPtr;
472     }
473
474     std::string OCSecureResource::getDevAddr()
475     {
476         validateSecureResource();
477         std::string ipAddr(devPtr->endpoint.addr);
478         return ipAddr;
479     }
480
481     int OCSecureResource::getDeviceStatus()
482     {
483         validateSecureResource();
484         return (int)devPtr->devStatus;
485     }
486
487     bool OCSecureResource::getOwnedStatus()
488     {
489         validateSecureResource();
490         return devPtr->doxm->owned;
491     }
492
493     void OCSecureResource::validateSecureResource()
494     {
495         if (!devPtr)
496         {
497             throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
498         }
499     }
500 }