Added thread for security and cloud provisioning.
[platform/upstream/iotivity.git] / service / easy-setup / mediator / richsdk / src / RemoteEnrollee.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 "RemoteEnrollee.h"
22 #include "EnrolleeResource.h"
23 #include "CloudResource.h"
24 #include "OCPlatform.h"
25 #include "ESException.h"
26 #include "logger.h"
27 #include "OCResource.h"
28 #include "oic_string.h"
29 #ifdef __WITH_DTLS__
30 #include "EnrolleeSecurity.h"
31 #include "base64.h"
32 #include "oic_malloc.h"
33 #include "cacommon.h"
34 #endif //__WITH_DTLS
35
36 namespace OIC
37 {
38     namespace Service
39     {
40         static const char ES_BASE_RES_URI[] = "/oic/res";
41         #define ES_REMOTE_ENROLLEE_TAG "ES_REMOTE_ENROLLEE"
42         #define DISCOVERY_TIMEOUT 1
43
44         RemoteEnrollee::RemoteEnrollee(const std::shared_ptr< OC::OCResource > resource)
45         {
46             m_ocResource = resource;
47             m_enrolleeResource = std::make_shared<EnrolleeResource>(m_ocResource);
48             m_securityProvStatusCb = nullptr;
49             m_getConfigurationStatusCb = nullptr;
50             m_securityPinCb = nullptr;
51             m_secProvisioningDbPathCb = nullptr;
52             m_devicePropProvStatusCb = nullptr;
53             m_cloudPropProvStatusCb = nullptr;
54             m_connectRequestStatusCb = nullptr;
55
56             m_deviceId = resource->sid();
57         }
58
59         void RemoteEnrollee::onSecurityStatusHandlerCallback(
60                 const std::shared_ptr< SecProvisioningStatus > status,
61                 std::weak_ptr<RemoteEnrollee> this_ptr)
62         {
63             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onSecurityStatusHandlerCallback");
64             std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
65             if(Ptr)
66             {
67                 Ptr->securityStatusHandler(status);
68             }
69         }
70
71         void RemoteEnrollee::securityStatusHandler(
72                 const std::shared_ptr< SecProvisioningStatus > status) const
73         {
74             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "securityStatusHandlr IN");
75             OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "UUID = %s", status->getDeviceUUID().c_str());
76             OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG, "ESResult = %d", status->getESResult());
77
78             if(status->getESResult() == ES_OK)
79             {
80                 OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "Ownership transfer is successfully done.");
81                 m_securityProvStatusCb(status);
82             }
83             else
84             {
85                 OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG, "Ownership transfer is failed.");
86                 m_securityProvStatusCb(status);
87             }
88             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "securityStatusHandlr OUT");
89         }
90
91         ESOwnershipTransferData RemoteEnrollee::onSecurityStatusWithOptionHandlerCallback(
92                 const std::shared_ptr< SecProvisioningStatus > status,
93                 std::weak_ptr<RemoteEnrollee> this_ptr)
94         {
95             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onSecurityStatusWithOptionHandlerCallback");
96             std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
97             if(Ptr)
98             {
99                 return Ptr->securityStatusWithOptionHandler(status);
100             }
101             return ESOwnershipTransferData();
102         }
103
104         ESOwnershipTransferData RemoteEnrollee::securityStatusWithOptionHandler(
105                 const std::shared_ptr< SecProvisioningStatus > status) const
106         {
107             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "securityStatusWithOptionHandler IN");
108             OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "UUID = %s", status->getDeviceUUID().c_str());
109             OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG, "ESResult = %d", status->getESResult());
110
111             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "securityStatusWithOptionHandler OUT");
112             return m_securityProvStatusCbWithOption(status);
113         }
114
115         void RemoteEnrollee::onGetStatusHandlerCallback(
116                 const std::shared_ptr< GetEnrolleeStatus > status,
117                 std::weak_ptr<RemoteEnrollee> this_ptr)
118         {
119             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onGetStatusHandlerCallback");
120             std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
121             if(Ptr)
122             {
123                 Ptr->getStatusHandler(status);
124             }
125         }
126
127         void RemoteEnrollee::getStatusHandler(
128                 const std::shared_ptr< GetEnrolleeStatus > status) const
129         {
130             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatusHandler IN");
131
132             OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatusHandler = %d",
133                                                     status->getESResult());
134             m_getStatusCb(status);
135
136             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatusHandler OUT");
137         }
138
139         void RemoteEnrollee::onGetConfigurationStatusHandlerCallback(
140                 const std::shared_ptr< GetConfigurationStatus > status,
141                 std::weak_ptr<RemoteEnrollee> this_ptr)
142         {
143             OIC_LOG(INFO,ES_REMOTE_ENROLLEE_TAG,"onGetConfigurationStatusHandlerCallback");
144             std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
145             if(Ptr)
146             {
147                 Ptr->getConfigurationStatusHandler(status);
148             }
149         }
150
151         void RemoteEnrollee::getConfigurationStatusHandler (
152                 const std::shared_ptr< GetConfigurationStatus > status) const
153         {
154             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getConfigurationStatusHandler IN");
155
156             OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG,"GetConfigurationStatus = %d",
157                                                     status->getESResult());
158             m_getConfigurationStatusCb(status);
159
160             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getConfigurationStatusHandler OUT");
161         }
162
163         void RemoteEnrollee::onDevicePropProvisioningStatusHandlerCallback(
164                 const std::shared_ptr< DevicePropProvisioningStatus > status,
165                 std::weak_ptr<RemoteEnrollee> this_ptr)
166         {
167             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onDevicePropProvisioningStatusHandlerCallback");
168             std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
169             if(Ptr)
170             {
171                 Ptr->devicePropProvisioningStatusHandler(status);
172             }
173         }
174
175         void RemoteEnrollee::devicePropProvisioningStatusHandler(
176                 const std::shared_ptr< DevicePropProvisioningStatus > status) const
177         {
178             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "devicePropProvisioningStatusHandler IN");
179
180             OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG, "DeviceProvStatus = %d", status->getESResult());
181             m_devicePropProvStatusCb(status);
182 #ifdef __WITH_DTLS__
183             if( m_ocResource.get() != nullptr &&
184                     !(m_ocResource->connectivityType() & CT_ADAPTER_GATT_BTLE) &&
185                     ES_OK == status->getESResult() )
186             {
187                 // NOTE: Temporary patch
188                 CAEndpoint_t endpoint = {
189                     .adapter = CA_ADAPTER_IP,
190                     .flags = CA_DEFAULT_FLAGS,
191                     .port = 0,
192                     .addr = {0},
193                     .ifindex = 0,
194                     .remoteId = {0},
195 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
196                     .routeData = {0}
197 #endif
198                 };
199                 OCDevAddr address = m_ocResource->getDevAddr();
200                 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE, address.addr);
201                 endpoint.port = address.port;
202
203                 OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "HOST = %s", endpoint.addr);
204                 OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "PORT = %u", endpoint.port);
205                 CAcloseSslSession(&endpoint);
206             }
207 #endif
208             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "devicePropProvisioningStatusHandler OUT");
209         }
210
211         void RemoteEnrollee::onCloudPropProvisioningStatusHandlerCallback(
212                 const std::shared_ptr< CloudPropProvisioningStatus > status,
213                 std::weak_ptr<RemoteEnrollee> this_ptr)
214         {
215             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onCloudPropProvisioningStatusHandlerCallback");
216             std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
217             if(Ptr)
218             {
219                 Ptr->cloudPropProvisioningStatusHandler(status);
220             }
221         }
222
223         void RemoteEnrollee::cloudPropProvisioningStatusHandler (
224                 const std::shared_ptr< CloudPropProvisioningStatus > status) const
225         {
226             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "cloudPropProvisioningStatusHandler IN");
227
228             OIC_LOG_V(INFO,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d",
229                                                     status->getESResult());
230             m_cloudPropProvStatusCb(status);
231
232             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "cloudPropProvisioningStatusHandler OUT");
233         }
234
235         void RemoteEnrollee::onConnectRequestStatusHandlerCallback(
236                 const std::shared_ptr< ConnectRequestStatus > status,
237                 std::weak_ptr<RemoteEnrollee> this_ptr)
238         {
239             OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"onConnectRequestStatusHandlerCallback");
240             std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
241             if(Ptr)
242             {
243                 Ptr->connectRequestStatusHandler(status);
244             }
245         }
246
247         void RemoteEnrollee::connectRequestStatusHandler(
248                 const std::shared_ptr< ConnectRequestStatus > status) const
249         {
250             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connectRequestStatusHandler IN");
251
252             OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "RequestConnectStatus = %d", status->getESResult());
253             m_connectRequestStatusCb(status);
254
255             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connectRequestStatusHandler OUT");
256         }
257
258         void RemoteEnrollee::onDiscoveredCallback(const std::shared_ptr<OC::OCResource> resource,
259             std::weak_ptr<RemoteEnrollee> this_ptr)
260         {
261             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onDiscoveredCallback()");
262             std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
263             if(Ptr)
264             {
265                 Ptr->onDeviceDiscovered(resource);
266             }
267         }
268
269         void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
270         {
271             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered IN");
272
273             try
274             {
275                 if(resource)
276                 {
277                     if(!(resource->connectivityType() & CT_ADAPTER_TCP))
278                     {
279                         std::string resourceURI;
280                         std::string hostAddress;
281                         std::string hostDeviceID;
282
283                         // Get the resource URI
284                         resourceURI = resource->uri();
285                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG,
286                                 "URI of the resource: %s", resourceURI.c_str());
287
288                         // Get the resource host address
289                         hostAddress = resource->host();
290                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG,
291                                 "Host address of the resource: %s", hostAddress.c_str());
292
293                         hostDeviceID = resource->sid();
294                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG,
295                                 "Host DeviceID of the resource: %s", hostDeviceID.c_str());
296
297                         if(!m_deviceId.empty() && m_deviceId == hostDeviceID)
298                         {
299                             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "Find matched resource for cloud provisioning");
300                             m_ocResource = resource;
301                             m_discoveryResponse = true;
302                             m_cond.notify_all();
303                         }
304                     }
305                 }
306             }
307             catch(std::exception& e)
308             {
309                 OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG,
310                         "Exception in foundResource: %s", e.what());
311             }
312
313             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered OUT");
314         }
315
316         ESResult RemoteEnrollee::discoverResource()
317         {
318             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "discoverResource IN");
319
320             std::string query("");
321             query.append(ES_BASE_RES_URI);
322             query.append("?rt=");
323             query.append(OC_RSRVD_ES_RES_TYPE_EASYSETUP);
324
325             OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
326
327             m_discoveryResponse = false;
328
329             onDeviceDiscoveredCb cb = std::bind(&RemoteEnrollee::onDiscoveredCallback,
330                                                 std::placeholders::_1,
331                                                 shared_from_this());
332
333             OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT, cb);
334
335             if (result != OCStackResult::OC_STACK_OK)
336             {
337                 OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG,
338                         "Failed discoverResource");
339                 return ES_ERROR;
340             }
341
342             std::unique_lock<std::mutex> lck(m_discoverymtx);
343             m_cond.wait_for(lck, std::chrono::seconds(DISCOVERY_TIMEOUT));
344
345             if (!m_discoveryResponse)
346             {
347                 OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG,
348                         "Failed discoverResource because timeout");
349                 return ES_ERROR;
350             }
351
352             return ES_OK;
353         }
354
355         void RemoteEnrollee::provisionSecurity(const SecurityProvStatusCb callback)
356         {
357             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity IN");
358 #ifdef __WITH_DTLS__
359             ESResult res = ESResult::ES_ERROR;
360             if(!callback)
361             {
362                 throw ESInvalidParameterException("Callback is empty");
363             }
364             m_securityProvStatusCb = callback;
365
366             SecurityProvStatusCb securityProvStatusCb = std::bind(
367                     &RemoteEnrollee::onSecurityStatusHandlerCallback,
368                     std::placeholders::_1,
369                     shared_from_this());
370             //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
371             if(!m_localEnrolleeSecurity.get())
372             {
373                 m_localEnrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource);
374             }
375
376 #ifdef __TIZEN__
377             /* NOTE: Execute cloud resource discovery and secure resource discovery in
378                 different thread to avoid blocking of main event loop of Tizen */
379             std::thread secProvThread = std::thread([this, securityProvStatusCb](void)
380                 {
381                     OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"provisionSecurity - thread IN");
382                     ESResult res = m_localEnrolleeSecurity->provisionOwnership(NULL);
383
384                     std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
385                                     std::make_shared< SecProvisioningStatus >(m_localEnrolleeSecurity->getUUID(), res);
386                     securityProvStatusCb(securityProvisioningStatus);
387                     OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"provisionSecurity - thread OUT");
388                 });
389
390             // TODO: Join thread
391             secProvThread.detach();
392 #else
393             res = m_localEnrolleeSecurity->provisionOwnership(NULL);
394
395             std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
396                             std::make_shared< SecProvisioningStatus >(m_localEnrolleeSecurity->getUUID(), res);
397             securityProvStatusCb(securityProvisioningStatus);
398 #endif
399 #else
400             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured built.");
401
402             if(!callback)
403             {
404                 throw ESInvalidParameterException("Callback is empty");
405             }
406             std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
407                      std::make_shared< SecProvisioningStatus >
408                                    ("", ESResult::ES_SEC_OPERATION_IS_NOT_SUPPORTED);
409             callback(securityProvisioningStatus);
410 #endif
411             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity OUT");
412         }
413
414         void RemoteEnrollee::provisionSecurity(const SecurityProvStatusCbWithOption callback)
415         {
416             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity IN");
417 #ifdef __WITH_DTLS__
418             ESResult res = ESResult::ES_ERROR;
419             if(!callback)
420             {
421                 throw ESInvalidParameterException("Callback is empty");
422             }
423             m_securityProvStatusCbWithOption = callback;
424
425             SecurityProvStatusCbWithOption securityProvStatusCbWithOption = std::bind(
426                                     &RemoteEnrollee::onSecurityStatusWithOptionHandlerCallback,
427                                     std::placeholders::_1,
428                                     shared_from_this());
429
430             if(!m_localEnrolleeSecurity.get())
431             {
432                 m_localEnrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource);
433             }
434 #ifdef __TIZEN__
435             /* NOTE: Execute cloud resource discovery and secure resource discovery in
436                 different thread to avoid blocking of main event loop of Tizen */
437             std::thread secProvThread = std::thread([this, securityProvStatusCbWithOption](void)
438                 {
439                     OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"provisionSecurity - thread IN");
440                     ESResult res = m_localEnrolleeSecurity->provisionOwnership(securityProvStatusCbWithOption);
441
442                     std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
443                                     std::make_shared< SecProvisioningStatus >(m_localEnrolleeSecurity->getUUID(), res);
444                     securityProvStatusCbWithOption(securityProvisioningStatus);
445                     OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"provisionSecurity - thread OUT");
446                 });
447
448             // TODO: Join thread
449             secProvThread.detach();
450 #else
451             res = m_localEnrolleeSecurity->provisionOwnership(securityProvStatusCbWithOption);
452
453             std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
454                             std::make_shared< SecProvisioningStatus >(m_localEnrolleeSecurity->getUUID(), res);
455             securityProvStatusCbWithOption(securityProvisioningStatus);
456 #endif
457 #else
458             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured built.");
459
460             if(!callback)
461             {
462                 throw ESInvalidParameterException("Callback is empty");
463             }
464             std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
465                      std::make_shared< SecProvisioningStatus >
466                                    ("", ESResult::ES_SEC_OPERATION_IS_NOT_SUPPORTED);
467             callback(securityProvisioningStatus);
468 #endif
469             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity OUT");
470         }
471
472         void RemoteEnrollee::getStatus(const GetStatusCb callback)
473         {
474             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatus IN");
475
476             if(!callback)
477             {
478                 throw ESInvalidParameterException("Callback is empty");
479             }
480
481             if (m_enrolleeResource == nullptr)
482             {
483                 throw ESBadRequestException ("Device not created");
484             }
485
486             m_getStatusCb = callback;
487
488             GetStatusCb getStatusCb = std::bind(
489                 &RemoteEnrollee::onGetStatusHandlerCallback,
490                 std::placeholders::_1,
491                 shared_from_this());
492
493             m_enrolleeResource->registerGetStatusCallback(getStatusCb);
494             m_enrolleeResource->getStatus();
495
496             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatus OUT");
497         }
498
499         void RemoteEnrollee::getConfiguration(const GetConfigurationStatusCb callback)
500         {
501             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getConfiguration IN");
502
503             if(!callback)
504             {
505                 throw ESInvalidParameterException("Callback is empty");
506             }
507
508             if (m_enrolleeResource == nullptr)
509             {
510                 throw ESBadRequestException ("Device not created");
511             }
512
513             m_getConfigurationStatusCb = callback;
514
515             GetConfigurationStatusCb getConfigurationStatusCb = std::bind(
516                     &RemoteEnrollee::onGetConfigurationStatusHandlerCallback,
517                     std::placeholders::_1,
518                     shared_from_this());
519
520             m_enrolleeResource->registerGetConfigurationStatusCallback(getConfigurationStatusCb);
521             m_enrolleeResource->getConfiguration();
522
523             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getConfiguration OUT");
524         }
525
526         void RemoteEnrollee::provisionDeviceProperties(const DeviceProp& deviceProp,
527                                                             const DevicePropProvStatusCb callback)
528         {
529             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionDeviceProperties IN");
530
531             if(!callback)
532             {
533                 throw ESInvalidParameterException("Callback is empty");
534             }
535
536             m_devicePropProvStatusCb = callback;
537
538             if (m_enrolleeResource == nullptr)
539             {
540                 throw ESBadRequestException ("Device not created");
541             }
542
543             DevicePropProvStatusCb devicePropProvStatusCb = std::bind(
544                     &RemoteEnrollee::onDevicePropProvisioningStatusHandlerCallback,
545                     std::placeholders::_1,
546                     shared_from_this());
547
548             m_enrolleeResource->registerDevicePropProvStatusCallback(devicePropProvStatusCb);
549             m_enrolleeResource->provisionProperties(deviceProp);
550
551             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionDeviceProperties OUT");
552         }
553
554         void RemoteEnrollee::initCloudResource()
555         {
556             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "initCloudResource IN");
557
558             ESResult result = ES_ERROR;
559
560             result = discoverResource();
561
562             if (result == ES_ERROR)
563             {
564                 OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG,
565                                     "Failed to create resource object using discoverResource");
566                 throw ESBadRequestException ("Resource object not created");
567             }
568
569             else
570             {
571                 if(m_ocResource != nullptr)
572                 {
573                     m_cloudResource = std::make_shared<CloudResource>(m_ocResource);
574                 }
575                 else
576                 {
577                     throw ESBadGetException ("Resource handle is invalid");
578                 }
579             }
580
581             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "initCloudResource OUT");
582         }
583
584         void RemoteEnrollee::provisionCloudProperties(const CloudProp& cloudProp,
585                                                             const CloudPropProvStatusCb callback)
586         {
587             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties w/o OCResource IN");
588
589             provisionCloudProperties(NULL, cloudProp, callback);
590
591             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties w/o OCResource OUT");
592         }
593
594 #ifndef __TIZEN__
595         void RemoteEnrollee::provisionCloudProperties(const std::shared_ptr< OC::OCResource > resource,
596                                                         const CloudProp& cloudProp,
597                                                         const CloudPropProvStatusCb callback)
598         {
599             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties IN");
600
601             if(!callback)
602             {
603                 throw ESInvalidParameterException("Callback is empty");
604             }
605
606             m_cloudPropProvStatusCb = callback;
607
608             if((cloudProp.getAuthCode().empty() && cloudProp.getAccessToken().empty()) ||
609                 cloudProp.getAuthProvider().empty() ||
610                 cloudProp.getCiServer().empty())
611             {
612                 throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
613             }
614
615             if(resource)
616             {
617                 if(resource->getResourceTypes().at(0) != OC_RSRVD_ES_RES_TYPE_EASYSETUP ||
618                                 resource->connectivityType() & CT_ADAPTER_TCP)
619                 {
620                     OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG, "Given resource is not valid due to wrong rt or conntype");
621                     throw ESInvalidParameterException("A given OCResource is wrong");
622                 }
623
624                 auto interfaces = resource->getResourceInterfaces();
625                 bool isFound = false;
626                 for(auto interface : interfaces)
627                 {
628                     if(interface.compare(BATCH_INTERFACE) == 0)
629                     {
630                         OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "RemoteEnrollee object is succeessfully created");
631                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "HOST: %s", resource->host().c_str());
632                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "URI: %s", resource->uri().c_str());
633                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "SID: %s", resource->sid().c_str());
634                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "CONNECTIVITY: %d", resource->connectivityType());
635                         isFound = true;
636                     }
637                 }
638
639                 if(!isFound)
640                 {
641                     throw ESInvalidParameterException("A given OCResource has no batch interface");
642                 }
643             }
644
645             try
646             {
647                 if(resource == NULL)
648                 {
649                     initCloudResource();
650                 }
651                 else
652                 {
653                     OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "Skip to find a provisioning resource");
654                     m_ocResource = resource;
655                     m_cloudResource = std::make_shared<CloudResource>(m_ocResource);
656                 }
657             }
658             catch (const std::exception& e)
659             {
660                 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
661                     "Exception caught in provisionCloudProperties = %s", e.what());
662
663                 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
664                         CloudPropProvisioningStatus >(ESResult::ES_ENROLLEE_DISCOVERY_FAILURE);
665                 m_cloudPropProvStatusCb(provStatus);
666                 return;
667             }
668 #if defined(__WITH_DTLS__) && defined(__WITH_TLS__)
669             if(!(cloudProp.getCloudID().empty() && cloudProp.getCredID() <= 0))
670             {
671                 ESResult res = ESResult::ES_ERROR;
672                 if(!m_cloudEnrolleeSecurity.get())
673                 {
674                     m_cloudEnrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource);
675                 }
676
677
678                 res = m_cloudEnrolleeSecurity->provisionSecurityForCloudServer(cloudProp.getCloudID(),
679                                                                           cloudProp.getCredID());
680
681                 if(res != ESResult::ES_OK)
682                 {
683                     m_cloudResource = nullptr;
684                     std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
685                             CloudPropProvisioningStatus >(res);
686                     m_cloudPropProvStatusCb(provStatus);
687                     return;
688                 }
689             }
690             else
691             {
692                 OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "ACL and Cert. provisioning are skipped.");
693             }
694 #endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)
695
696             if (m_cloudResource == nullptr)
697             {
698                 throw ESBadRequestException ("Cloud Resource not created");
699             }
700
701             CloudPropProvStatusCb cloudPropProvStatusCb = std::bind(
702                     &RemoteEnrollee::onCloudPropProvisioningStatusHandlerCallback,
703                     std::placeholders::_1,
704                     shared_from_this());
705
706             m_cloudResource->registerCloudPropProvisioningStatusCallback(cloudPropProvStatusCb);
707             m_cloudResource->provisionProperties(cloudProp);
708
709             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties OUT");
710         }
711 #else
712         void RemoteEnrollee::provisionCloudProperties(const std::shared_ptr< OC::OCResource > resource,
713                                                         const CloudProp& cloudProp,
714                                                         const CloudPropProvStatusCb callback)
715         {
716             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties IN");
717
718             if(!callback)
719             {
720                 throw ESInvalidParameterException("Callback is empty");
721             }
722
723             m_cloudPropProvStatusCb = callback;
724
725             if((cloudProp.getAuthCode().empty() && cloudProp.getAccessToken().empty()) ||
726                 cloudProp.getAuthProvider().empty() ||
727                 cloudProp.getCiServer().empty())
728             {
729                 throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
730             }
731
732             if(resource)
733             {
734                 if(resource->getResourceTypes().at(0) != OC_RSRVD_ES_RES_TYPE_EASYSETUP ||
735                                 resource->connectivityType() & CT_ADAPTER_TCP)
736                 {
737                     OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG, "Given resource is not valid due to wrong rt or conntype");
738                     throw ESInvalidParameterException("A given OCResource is wrong");
739                 }
740
741                 auto interfaces = resource->getResourceInterfaces();
742                 bool isFound = false;
743                 for(auto interface : interfaces)
744                 {
745                     if(interface.compare(BATCH_INTERFACE) == 0)
746                     {
747                         OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "RemoteEnrollee object is succeessfully created");
748                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "HOST: %s", resource->host().c_str());
749                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "URI: %s", resource->uri().c_str());
750                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "SID: %s", resource->sid().c_str());
751                         OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "CONNECTIVITY: %d", resource->connectivityType());
752                         isFound = true;
753                     }
754                 }
755
756                 if(!isFound)
757                 {
758                     throw ESInvalidParameterException("A given OCResource has no batch interface");
759                 }
760
761                 OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "Skip to find a provisioning resource");
762                 m_ocResource = resource;
763                 m_cloudResource = std::make_shared<CloudResource>(m_ocResource);
764                 if (m_cloudResource == nullptr)
765                 {
766                     throw ESBadRequestException ("Cloud Resource not created");
767                 }
768             }
769
770             /* NOTE: Execute cloud resource discovery and secure resource discovery in
771                 different thread to avoid blocking of main event loop of Tizen */
772             std::thread cloudProvThread = std::thread([this, cloudProp]()
773                 {
774                     OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties - thread IN");
775                     try
776                     {
777                         // Discover easy-setup resource only if it is not provided by API caller
778                         if(!m_cloudResource)
779                         {
780                             initCloudResource();
781                             if (m_cloudResource == nullptr)
782                             {
783                                 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG, "Cloud resource is not created");
784                                 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
785                                         CloudPropProvisioningStatus >(ESResult::ES_ENROLLEE_DISCOVERY_FAILURE);
786                                 m_cloudPropProvStatusCb(provStatus);
787                                 return;
788                             }
789                         }
790                     }
791                     catch (const std::exception& e)
792                     {
793                         OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
794                             "Exception caught in provisionCloudProperties = %s", e.what());
795
796                         std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
797                                 CloudPropProvisioningStatus >(ESResult::ES_ENROLLEE_DISCOVERY_FAILURE);
798                         m_cloudPropProvStatusCb(provStatus);
799                         return;
800                     }
801
802 #if defined(__WITH_DTLS__) && defined(__WITH_TLS__)
803                     if(!(cloudProp.getCloudID().empty() && cloudProp.getCredID() <= 0))
804                     {
805                         ESResult res = ESResult::ES_ERROR;
806                         if(!m_cloudEnrolleeSecurity.get())
807                         {
808                             m_cloudEnrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource);
809                         }
810
811
812                         res = m_cloudEnrolleeSecurity->provisionSecurityForCloudServer(cloudProp.getCloudID(),
813                                                                                   cloudProp.getCredID());
814
815                         if(res != ESResult::ES_OK)
816                         {
817                             m_cloudResource = nullptr;
818                             std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
819                                     CloudPropProvisioningStatus >(res);
820                             m_cloudPropProvStatusCb(provStatus);
821                             return;
822                         }
823                     }
824                     else
825                     {
826                         OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "ACL and Cert. provisioning are skipped.");
827                     }
828 #endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)
829
830                     CloudPropProvStatusCb cloudPropProvStatusCb = std::bind(
831                             &RemoteEnrollee::onCloudPropProvisioningStatusHandlerCallback,
832                             std::placeholders::_1,
833                             shared_from_this());
834
835                     m_cloudResource->registerCloudPropProvisioningStatusCallback(cloudPropProvStatusCb);
836                     m_cloudResource->provisionProperties(cloudProp);
837                     OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties - thread OUT");
838                 });
839
840             // TODO: Join thread
841             cloudProvThread.detach();
842             OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties OUT");
843         }
844 #endif
845         void RemoteEnrollee::requestToConnect(const std::vector<ES_CONNECT_TYPE> &connectTypes, const ConnectRequestStatusCb callback)
846         {
847             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connect IN");
848
849             if(!callback)
850             {
851                 throw ESInvalidParameterException("Callback is empty");
852             }
853
854             m_connectRequestStatusCb = callback;
855
856             ConnectRequestStatusCb connectRequestStatusCb = std::bind(
857                         &RemoteEnrollee::onConnectRequestStatusHandlerCallback,
858                         std::placeholders::_1,
859                         shared_from_this());
860
861             m_enrolleeResource->registerConnectRequestStatusCallback(connectRequestStatusCb);
862             m_enrolleeResource->requestToConnect(connectTypes);
863
864             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connect OUT");
865         }
866     }
867 }
868
869