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_securityProvStatusCb = 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::securityStatusHandler(
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(),
72 status->getESResult());
74 if(status->getESResult() == 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_securityProvStatusCb(status);
85 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are fail");
87 m_securityProvStatusCb(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->getESDataProvState() >= ESDataProvState::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;
194 if(!(resource->connectivityType() & CT_ADAPTER_TCP))
196 // Get the resource URI
197 resourceURI = resource->uri();
198 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
199 "URI of the resource: %s", resourceURI.c_str());
201 // Get the resource host address
202 hostAddress = resource->host();
203 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
204 "Host address of the resource: %s", hostAddress.c_str());
206 hostDeviceID = resource->sid();
207 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
208 "Host DeviceID of the resource: %s", hostDeviceID.c_str());
210 if(m_deviceId .empty())
213 * Easysetup is always performed with a single Enrollee device and
214 * in a private network (SoftAP or BLE), so the assumption is that
215 * only the intended device will respond for the discovery.
216 * With the above assumption the below two statements are written.
218 m_ocResource = resource;
219 m_deviceId = resource->sid();
220 m_discoveryResponse = true;
223 else if(!m_deviceId.empty() && m_deviceId == hostDeviceID)
225 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "Find matched CloudResource");
226 m_ocResource = resource;
227 m_discoveryResponse = true;
232 catch(std::exception& e)
234 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
235 "Exception in foundResource: %s", e.what());
239 ESResult RemoteEnrollee::discoverResource()
241 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Enter discoverResource");
243 if (m_ocResource != nullptr)
245 throw ESBadRequestException("resource is already created");
248 std::string query("");
249 query.append(ES_BASE_RES_URI);
250 query.append("?rt=");
251 query.append(OC_RSRVD_ES_RES_TYPE_PROV);
253 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
255 m_discoveryResponse = false;
257 std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =
258 std::bind(&RemoteEnrollee::onDeviceDiscovered, this,
259 std::placeholders::_1);
260 OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,
261 onDeviceDiscoveredCb);
263 if (result != OCStackResult::OC_STACK_OK)
265 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
266 "Failed discoverResource");
270 ESResult foundResponse = ESDiscoveryTimeout (DISCOVERY_TIMEOUT);
272 if (foundResponse == ES_ERROR || !m_discoveryResponse)
274 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
275 "Failed discoverResource because timeout");
281 void RemoteEnrollee::initRemoteEnrollee()
283 ESResult result = ES_ERROR;
285 if (m_enrolleeResource != nullptr)
287 throw ESBadRequestException ("Already created");
290 result = discoverResource();
292 if (result == ES_ERROR)
294 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
295 "Failed to create resource object using discoverResource");
296 throw ESBadRequestException ("Resource object not created");
301 if(m_ocResource != nullptr)
303 m_enrolleeResource = std::make_shared<EnrolleeResource>(std::move(m_ocResource));
307 throw ESBadGetException ("Resource handle is invalid");
312 void RemoteEnrollee::startSecurityProvisioning(SecurityProvStatusCb callback)
315 m_securityProvStatusCb = callback;
317 SecurityProvStatusCb securityProvStatusCb = std::bind(
318 &RemoteEnrollee::securityStatusHandler,
320 std::placeholders::_1);
321 //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
322 m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_enrolleeResource, "");
324 m_enrolleeSecurity->setTargetDevID(m_deviceId);
325 m_enrolleeSecurity->registerCallbackHandler(securityProvStatusCb, m_securityPinCb, m_secProvisioningDbPathCb);
329 m_enrolleeSecurity->performOwnershipTransfer();
331 catch (OCException & e)
333 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
334 "Exception for performOwnershipTransfer : %s", e.reason().c_str());
336 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Fail performOwnershipTransfer");
337 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
338 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
339 m_securityProvStatusCb(securityProvisioningStatus);
344 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured.");
346 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
347 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
348 m_securityProvStatusCb(securityProvisioningStatus);
352 void RemoteEnrollee::requestPropertyData(RequestPropertyDataStatusCb callback)
356 throw ESInvalidParameterException("Callback is empty");
359 m_requestPropertyDataStatusCb = callback;
361 if (m_enrolleeResource == nullptr)
363 throw ESBadRequestException ("Device not created");
366 RequestPropertyDataStatusCb RequestPropertyDataStatusCb = std::bind(
367 &RemoteEnrollee::RequestPropertyDataStatusHandler, this, std::placeholders::_1);
368 m_enrolleeResource->registerRequestPropertyDataStatusCallback(RequestPropertyDataStatusCb);
369 m_enrolleeResource->RequestPropertyData();
372 void RemoteEnrollee::startDataProvisioning(DataProvStatusCb callback)
374 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter startDataProvisioning");
378 throw ESInvalidParameterException("Callback is empty");
381 m_dataProvStatusCb = callback;
383 if (m_enrolleeResource == nullptr)
385 throw ESBadRequestException ("Device not created");
388 if(m_dataProvInfo.WIFI.ssid.empty())
390 throw ESBadRequestException ("Invalid Provisiong Data.");
393 m_dataProvStatusCb = callback;
395 DataProvStatusCb dataProvStatusCb = std::bind(
396 &RemoteEnrollee::dataProvisioningStatusHandler, this, std::placeholders::_1);
398 m_enrolleeResource->registerProvStatusCallback(dataProvStatusCb);
399 m_enrolleeResource->provisionEnrollee(m_dataProvInfo);
402 void RemoteEnrollee::initCloudResource()
404 ESResult result = ES_ERROR;
406 if (m_cloudResource != nullptr)
408 throw ESBadRequestException ("Already created");
411 result = discoverResource();
413 if (result == ES_ERROR)
415 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
416 "Failed to create resource object using discoverResource");
417 throw ESBadRequestException ("Resource object not created");
422 if(m_ocResource != nullptr)
424 m_cloudResource = std::make_shared<CloudResource>(std::move(m_ocResource));
426 std::shared_ptr< CloudProvisioningStatus > provStatus = std::make_shared<
427 CloudProvisioningStatus >(ESResult::ES_OK, ESCloudProvState::ES_CLOUD_ENROLLEE_FOUND);
429 m_cloudProvStatusCb(provStatus);
433 throw ESBadGetException ("Resource handle is invalid");
439 void RemoteEnrollee::startCloudProvisioning(CloudProvStatusCb callback)
441 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter startCloudProvisioning");
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;