1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "RemoteEnrollee.h"
22 #include "EnrolleeResource.h"
23 #include "CloudResource.h"
24 #include "OCPlatform.h"
25 #include "ESException.h"
27 #include "OCResource.h"
29 #include "EnrolleeSecurity.h"
36 static const char ES_BASE_RES_URI[] = "/oic/res";
37 #define ES_REMOTE_ENROLLEE_TAG "ES_REMOTE_ENROLLEE"
38 #define DISCOVERY_TIMEOUT 5
40 RemoteEnrollee::RemoteEnrollee()
42 m_enrolleeSecStatusCb = nullptr;
43 m_RequestPropertyDataStatusCb = nullptr;
44 m_securityPinCb = nullptr;
45 m_secProvisioningDbPathCb = nullptr;
46 m_dataProvStatusCb = nullptr;
47 m_cloudProvStatusCb = nullptr;
49 //m_deviceId = nullptr;
53 ESResult RemoteEnrollee::registerSecurityCallbackHandler(SecurityPinCb securityPinCb,
54 SecProvisioningDbPathCb secProvisioningDbPathCb)
56 // No need to check NULL for m_secProvisioningDbPathCB as this is not a mandatory
57 // callback function. If m_secProvisioningDbPathCB is NULL, provisioning manager
58 // in security layer will try to find the PDM.db file in the local path.
59 // If PDM.db is found, the provisioning manager operations will succeed.
60 // Otherwise all the provisioning manager operations will fail.
61 m_secProvisioningDbPathCb = secProvisioningDbPathCb;
62 m_securityPinCb = securityPinCb;
65 #endif //__WITH_DTLS__
67 void RemoteEnrollee::easySetupSecurityStatusCallback(
68 std::shared_ptr< SecProvisioningStatus > status)
70 OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "easySetupStatusCallback status is, UUID = %s, "
71 "Status = %d", status->getDeviceUUID().c_str(),
74 if(status->getResult() == ES_OK)
76 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are successful. "
77 "Continue with Network information provisioning");
79 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");
81 m_enrolleeSecStatusCb(status);
85 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are fail");
87 m_enrolleeSecStatusCb(status);
91 void RemoteEnrollee::RequestPropertyDataStatusHandler (
92 std::shared_ptr< RequestPropertyDataStatus > status)
94 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering RequestPropertyDataStatusHandler");
96 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"RequestPropertyDataStatus = %d", status->getESResult());
98 if(status->getESResult() == ES_OK)
100 m_propertyData = status->getPropertyData();
103 m_RequestPropertyDataStatusCb(status);
106 void RemoteEnrollee::dataProvisioningStatusHandler(
107 std::shared_ptr< DataProvisioningStatus > status)
109 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering dataProvisioningStatusHandler");
111 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", status->getESResult());
113 if (status->getESResult() == ES_OK)
115 if (status->getESState() >= ESState::ES_PROVISIONED_ALREADY)
117 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", status->getESResult());
120 m_dataProvStatusCb(status);
125 void RemoteEnrollee::cloudProvisioningStatusHandler (
126 std::shared_ptr< CloudProvisioningStatus > status)
128 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering cloudProvisioningStatusHandler");
130 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d", status->getESCloudState());
132 m_cloudProvStatusCb(status);
136 ESResult RemoteEnrollee::ESDiscoveryTimeout(unsigned short waittime)
138 struct timespec startTime;
141 struct timespec currTime;
145 ESResult res = ES_OK;
146 #ifdef _POSIX_MONOTONIC_CLOCK
147 int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
149 int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
157 while (ES_OK == res || m_discoveryResponse == false)
159 #ifdef _POSIX_MONOTONIC_CLOCK
160 clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
162 clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
169 long elapsed = (currTime.tv_sec - startTime.tv_sec);
170 if (elapsed > waittime)
174 if (m_discoveryResponse)
182 void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
184 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered");
186 std::string resourceURI;
187 std::string hostAddress;
188 std::string hostDeviceID;
193 // Get the resource URI
194 resourceURI = resource->uri();
195 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
196 "URI of the resource: %s", resourceURI.c_str());
198 // Get the resource host address
199 hostAddress = resource->host();
200 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
201 "Host address of the resource: %s", hostAddress.c_str());
203 hostDeviceID = resource->sid();
204 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
205 "Host DeviceID of the resource: %s", hostDeviceID.c_str());
207 if(m_deviceId .empty())
210 * Easysetup is always performed with a single Enrollee device and
211 * in a private network (SoftAP or BLE), so the assumption is that
212 * only the intended device will respond for the discovery.
213 * With the above assumption the below two statements are written.
215 m_ocResource = resource;
216 m_deviceId = resource->sid();
217 m_discoveryResponse = true;
220 else if(!m_deviceId.empty() && m_deviceId == hostDeviceID)
222 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "Find matched CloudResource");
223 m_ocResource = resource;
224 m_discoveryResponse = true;
228 catch(std::exception& e)
230 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
231 "Exception in foundResource: %s", e.what());
235 ESResult RemoteEnrollee::discoverResource()
237 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Enter discoverResource");
239 if (m_ocResource != nullptr)
241 throw ESBadRequestException("resource is already created");
244 std::string query("");
245 query.append(ES_BASE_RES_URI);
246 query.append("?rt=");
247 query.append(OC_RSRVD_ES_PROV_RES_TYPE);
249 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
251 m_discoveryResponse = false;
253 std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =
254 std::bind(&RemoteEnrollee::onDeviceDiscovered, this,
255 std::placeholders::_1);
256 OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,
257 onDeviceDiscoveredCb);
259 if (result != OCStackResult::OC_STACK_OK)
261 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
262 "Failed discoverResource");
266 ESResult foundResponse = ESDiscoveryTimeout (DISCOVERY_TIMEOUT);
268 if (foundResponse == ES_ERROR || !m_discoveryResponse)
270 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
271 "Failed discoverResource because timeout");
277 void RemoteEnrollee::initRemoteEnrollee()
279 ESResult result = ES_ERROR;
281 if (m_enrolleeResource != nullptr)
283 throw ESBadRequestException ("Already created");
286 result = discoverResource();
288 if (result == ES_ERROR)
290 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
291 "Failed to create resource object using discoverResource");
292 throw ESBadRequestException ("Resource object not created");
297 if(m_ocResource != nullptr)
299 m_enrolleeResource = std::make_shared<EnrolleeResource>(std::move(m_ocResource));
303 throw ESBadGetException ("Resource handle is invalid");
308 void RemoteEnrollee::startSecurityProvisioning(EnrolleeSecStatusCb callback)
312 m_enrolleeSecStatusCb = callback;
314 EnrolleeSecStatusCb securityProvStatusCb = std::bind(
315 &RemoteEnrollee::easySetupSecurityStatusCallback,
317 std::placeholders::_1);
318 //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
319 m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_enrolleeResource, "");
321 m_enrolleeSecurity->registerCallbackHandler(securityProvStatusCb,
322 m_securityPinCb, m_secProvisioningDbPathCb);
326 if (!m_enrolleeSecurity->performOwnershipTransfer())
328 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Fail performOwnershipTransfer");
329 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
330 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
331 m_enrolleeSecStatusCb(securityProvisioningStatus);
335 catch (OCException & e)
337 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
338 "Exception for performOwnershipTransfer : %s", e.reason().c_str());
342 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured.");
344 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
345 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
346 m_enrolleeSecStatusCb(securityProvisioningStatus);
350 void RemoteEnrollee::requestPropertyData(RequestPropertyDataStatusCb callback)
354 throw ESInvalidParameterException("Callback is empty");
357 m_RequestPropertyDataStatusCb = callback;
359 if (m_enrolleeResource == nullptr)
361 throw ESBadRequestException ("Device not created");
364 RequestPropertyDataStatusCb RequestPropertyDataStatusCb = std::bind(
365 &RemoteEnrollee::RequestPropertyDataStatusHandler, this, std::placeholders::_1);
366 m_enrolleeResource->registerRequestPropertyDataStatusCallback(RequestPropertyDataStatusCb);
367 m_enrolleeResource->RequestPropertyData();
370 void RemoteEnrollee::startDataProvisioning(DataProvStatusCb callback)
372 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter startDataProvisioning");
376 throw ESInvalidParameterException("Callback is empty");
379 m_dataProvStatusCb = callback;
381 if (m_enrolleeResource == nullptr)
383 throw ESBadRequestException ("Device not created");
386 if(m_dataProvInfo.WIFI.ssid.empty())
388 throw ESBadRequestException ("Invalid Provisiong Data.");
391 m_dataProvStatusCb = callback;
393 DataProvStatusCb dataProvStatusCb = std::bind(
394 &RemoteEnrollee::dataProvisioningStatusHandler, this, std::placeholders::_1);
396 m_enrolleeResource->registerProvStatusCallback(dataProvStatusCb);
397 m_enrolleeResource->provisionEnrollee(m_dataProvInfo);
400 void RemoteEnrollee::initCloudResource()
402 ESResult result = ES_ERROR;
404 if (m_cloudResource != nullptr)
406 throw ESBadRequestException ("Already created");
409 result = discoverResource();
411 if (result == ES_ERROR)
413 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
414 "Failed to create resource object using discoverResource");
415 throw ESBadRequestException ("Resource object not created");
420 if(m_ocResource != nullptr)
422 m_cloudResource = std::make_shared<CloudResource>(std::move(m_ocResource));
424 std::shared_ptr< CloudProvisioningStatus > provStatus = std::make_shared<
425 CloudProvisioningStatus >(ESResult::ES_ERROR, ESCloudProvState::ES_CLOUD_ENROLLEE_FOUND);
427 m_cloudProvStatusCb(provStatus);
431 throw ESBadGetException ("Resource handle is invalid");
437 void RemoteEnrollee::startCloudProvisioning(CloudProvStatusCb callback)
439 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter startCloudProvisioning");
441 ESResult result = ES_ERROR;
445 throw ESInvalidParameterException("Callback is empty");
448 m_cloudProvStatusCb = callback;
455 catch (const std::exception& e)
457 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
458 "Exception caught in startCloudProvisioning = %s", e.what());
460 std::shared_ptr< CloudProvisioningStatus > provStatus = std::make_shared<
461 CloudProvisioningStatus >(ESResult::ES_ERROR, ESCloudProvState::ES_CLOUD_ENROLLEE_NOT_FOUND);
462 m_cloudProvStatusCb(provStatus);
465 if (m_cloudResource == nullptr)
467 throw ESBadRequestException ("Cloud Resource not created");
470 if(m_cloudProvInfo.authCode.empty()
471 || m_cloudProvInfo.authProvider.empty()
472 || m_cloudProvInfo.ciServer.empty())
474 throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
477 CloudProvStatusCb cloudProvStatusCb = std::bind(
478 &RemoteEnrollee::cloudProvisioningStatusHandler, this, std::placeholders::_1);
480 m_cloudResource->registerCloudProvisioningStatusCallback(cloudProvStatusCb);
481 m_cloudResource->provisionEnrollee(m_cloudProvInfo);
484 void RemoteEnrollee::setDataProvInfo(const DataProvInfo& dataProvInfo)
486 m_dataProvInfo = dataProvInfo;
489 void RemoteEnrollee::setCloudProvInfo(const CloudProvInfo& cloudProvInfo)
491 m_cloudProvInfo = cloudProvInfo;
494 DataProvInfo RemoteEnrollee::getDataProvInfo()
496 return m_dataProvInfo;