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(std::shared_ptr< OC::OCResource > resource)
42 m_ocResource = resource;
43 m_enrolleeResource = std::make_shared<EnrolleeResource>(m_ocResource);
44 m_securityProvStatusCb = nullptr;
45 m_getConfigurationStatusCb = nullptr;
46 m_securityPinCb = nullptr;
47 m_secProvisioningDbPathCb = nullptr;
48 m_devicePropProvStatusCb = nullptr;
49 m_cloudPropProvStatusCb = nullptr;
51 m_deviceId = resource->sid();
55 ESResult RemoteEnrollee::registerSecurityCallbackHandler(SecurityPinCb securityPinCb,
56 SecProvisioningDbPathCb secProvisioningDbPathCb)
58 // No need to check NULL for m_secProvisioningDbPathCB as this is not a mandatory
59 // callback function. If m_secProvisioningDbPathCB is NULL, provisioning manager
60 // in security layer will try to find the PDM.db file in the local path.
61 // If PDM.db is found, the provisioning manager operations will succeed.
62 // Otherwise all the provisioning manager operations will fail.
63 m_secProvisioningDbPathCb = secProvisioningDbPathCb;
64 m_securityPinCb = securityPinCb;
67 #endif //__WITH_DTLS__
69 void RemoteEnrollee::securityStatusHandler(
70 std::shared_ptr< SecProvisioningStatus > status)
72 OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "easySetupStatusCallback status is, UUID = %s, "
73 "Status = %d", status->getDeviceUUID().c_str(),
74 status->getESResult());
76 if(status->getESResult() == ES_OK)
78 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are successful. "
79 "Continue with Network information provisioning");
81 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");
83 m_securityProvStatusCb(status);
87 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are fail");
89 m_securityProvStatusCb(status);
93 void RemoteEnrollee::getStatusHandler(std::shared_ptr< GetEnrolleeStatus > status)
95 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getStatusHandler");
97 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"getStatusHandler = %d", status->getESResult());
99 m_getStatusCb(status);
102 void RemoteEnrollee::getConfigurationStatusHandler (
103 std::shared_ptr< GetConfigurationStatus > status)
105 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getConfigurationStatusHandler");
107 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"GetConfigurationStatus = %d", status->getESResult());
109 m_getConfigurationStatusCb(status);
112 void RemoteEnrollee::devicePropProvisioningStatusHandler(
113 std::shared_ptr< DevicePropProvisioningStatus > status)
115 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering DevicePropProvisioningStatusHandler");
117 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", status->getESResult());
119 m_devicePropProvStatusCb(status);
124 void RemoteEnrollee::cloudPropProvisioningStatusHandler (
125 std::shared_ptr< CloudPropProvisioningStatus > status)
127 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering cloudPropProvisioningStatusHandler");
129 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d", status->getESCloudState());
131 m_cloudPropProvStatusCb(status);
135 ESResult RemoteEnrollee::ESDiscoveryTimeout(unsigned short waittime)
137 struct timespec startTime;
140 struct timespec currTime;
144 ESResult res = ES_OK;
145 #ifdef _POSIX_MONOTONIC_CLOCK
146 int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
148 int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
156 while (ES_OK == res || m_discoveryResponse == false)
158 #ifdef _POSIX_MONOTONIC_CLOCK
159 clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
161 clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
168 long elapsed = (currTime.tv_sec - startTime.tv_sec);
169 if (elapsed > waittime)
173 if (m_discoveryResponse)
181 void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
183 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered");
185 std::string resourceURI;
186 std::string hostAddress;
187 std::string hostDeviceID;
193 if(!(resource->connectivityType() & CT_ADAPTER_TCP))
195 // Get the resource URI
196 resourceURI = resource->uri();
197 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
198 "URI of the resource: %s", resourceURI.c_str());
200 // Get the resource host address
201 hostAddress = resource->host();
202 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
203 "Host address of the resource: %s", hostAddress.c_str());
205 hostDeviceID = resource->sid();
206 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
207 "Host DeviceID of the resource: %s", hostDeviceID.c_str());
209 if(!m_deviceId.empty() && m_deviceId == hostDeviceID)
211 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "Find matched CloudResource");
212 m_ocResource = resource;
213 m_discoveryResponse = true;
218 catch(std::exception& e)
220 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
221 "Exception in foundResource: %s", e.what());
225 ESResult RemoteEnrollee::discoverResource()
227 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Enter discoverResource");
229 std::string query("");
230 query.append(ES_BASE_RES_URI);
231 query.append("?rt=");
232 query.append(OC_RSRVD_ES_RES_TYPE_PROV);
234 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
236 m_discoveryResponse = false;
238 std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =
239 std::bind(&RemoteEnrollee::onDeviceDiscovered, this,
240 std::placeholders::_1);
241 OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,
242 onDeviceDiscoveredCb);
244 if (result != OCStackResult::OC_STACK_OK)
246 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
247 "Failed discoverResource");
251 ESResult foundResponse = ESDiscoveryTimeout (DISCOVERY_TIMEOUT);
253 if (foundResponse == ES_ERROR || !m_discoveryResponse)
255 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
256 "Failed discoverResource because timeout");
262 void RemoteEnrollee::provisionSecurity(SecurityProvStatusCb callback)
265 m_securityProvStatusCb = callback;
267 SecurityProvStatusCb securityProvStatusCb = std::bind(
268 &RemoteEnrollee::securityStatusHandler,
270 std::placeholders::_1);
271 //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
272 m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
274 m_enrolleeSecurity->registerCallbackHandler(securityProvStatusCb, m_securityPinCb, m_secProvisioningDbPathCb);
278 m_enrolleeSecurity->performOwnershipTransfer();
280 catch (OCException & e)
282 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
283 "Exception for performOwnershipTransfer : %s", e.reason().c_str());
285 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Fail performOwnershipTransfer");
286 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
287 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
288 m_securityProvStatusCb(securityProvisioningStatus);
292 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured.");
294 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
295 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
296 m_securityProvStatusCb(securityProvisioningStatus);
300 void RemoteEnrollee::getStatus(GetStatusCb callback)
304 throw ESInvalidParameterException("Callback is empty");
307 if (m_enrolleeResource == nullptr)
309 throw ESBadRequestException ("Device not created");
312 m_getStatusCb = callback;
314 GetStatusCb getStatusCb = std::bind(
315 &RemoteEnrollee::getStatusHandler, this, std::placeholders::_1);
316 m_enrolleeResource->registerGetStatusCallback(getStatusCb);
317 m_enrolleeResource->getStatus();
321 void RemoteEnrollee::getConfiguration(GetConfigurationStatusCb callback)
325 throw ESInvalidParameterException("Callback is empty");
328 if (m_enrolleeResource == nullptr)
330 throw ESBadRequestException ("Device not created");
333 m_getConfigurationStatusCb = callback;
335 GetConfigurationStatusCb getConfigurationStatusCb = std::bind(
336 &RemoteEnrollee::getConfigurationStatusHandler, this, std::placeholders::_1);
337 m_enrolleeResource->registerGetConfigurationStatusCallback(getConfigurationStatusCb);
338 m_enrolleeResource->getConfiguration();
341 void RemoteEnrollee::provisionDeviceProperties(const DeviceProp& devProp, DevicePropProvStatusCb callback)
343 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionDeviceProperties");
347 throw ESInvalidParameterException("Callback is empty");
350 m_devicePropProvStatusCb = callback;
352 if (m_enrolleeResource == nullptr)
354 throw ESBadRequestException ("Device not created");
357 if(devProp.WIFI.ssid.empty())
359 throw ESBadRequestException ("Invalid Provisiong Data.");
362 DevicePropProvStatusCb devicePropProvStatusCb = std::bind(
363 &RemoteEnrollee::devicePropProvisioningStatusHandler, this, std::placeholders::_1);
365 m_enrolleeResource->registerDevicePropProvStatusCallback(devicePropProvStatusCb);
366 m_enrolleeResource->provisionEnrollee(devProp);
369 void RemoteEnrollee::initCloudResource()
371 ESResult result = ES_ERROR;
373 if (m_cloudResource != nullptr)
375 throw ESBadRequestException ("Already created");
378 result = discoverResource();
380 if (result == ES_ERROR)
382 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
383 "Failed to create resource object using discoverResource");
384 throw ESBadRequestException ("Resource object not created");
389 if(m_ocResource != nullptr)
391 m_cloudResource = std::make_shared<CloudResource>(std::move(m_ocResource));
393 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
394 CloudPropProvisioningStatus >(ESResult::ES_OK, ESCloudProvState::ES_CLOUD_ENROLLEE_FOUND);
396 m_cloudPropProvStatusCb(provStatus);
400 throw ESBadGetException ("Resource handle is invalid");
406 void RemoteEnrollee::provisionCloudProperties(const CloudProp& cloudProp, CloudPropProvStatusCb callback)
408 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionCloudProperties");
410 ESResult result = ES_ERROR;
414 throw ESInvalidParameterException("Callback is empty");
417 m_cloudPropProvStatusCb = callback;
419 if(cloudProp.authCode.empty()
420 || cloudProp.authProvider.empty()
421 || cloudProp.ciServer.empty())
423 throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
431 catch (const std::exception& e)
433 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
434 "Exception caught in provisionCloudProperties = %s", e.what());
436 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
437 CloudPropProvisioningStatus >(ESResult::ES_ERROR, ESCloudProvState::ES_CLOUD_ENROLLEE_NOT_FOUND);
438 m_cloudPropProvStatusCb(provStatus);
441 if (m_cloudResource == nullptr)
443 throw ESBadRequestException ("Cloud Resource not created");
446 CloudPropProvStatusCb cloudPropProvStatusCb = std::bind(
447 &RemoteEnrollee::cloudPropProvisioningStatusHandler, this, std::placeholders::_1);
449 m_cloudResource->registerCloudPropProvisioningStatusCallback(cloudPropProvStatusCb);
450 m_cloudResource->provisionEnrollee(cloudProp);