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;
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::getConfigurationStatusHandler (
92 std::shared_ptr< GetConfigurationStatus > status)
94 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getConfigurationStatusHandler");
96 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"GetConfigurationStatus = %d", status->getESResult());
98 m_getConfigurationStatusCb(status);
101 void RemoteEnrollee::devicePropProvisioningStatusHandler(
102 std::shared_ptr< DevicePropProvisioningStatus > status)
104 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering DevicePropProvisioningStatusHandler");
106 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", status->getESResult());
108 m_devicePropProvStatusCb(status);
113 void RemoteEnrollee::cloudPropProvisioningStatusHandler (
114 std::shared_ptr< CloudPropProvisioningStatus > status)
116 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering cloudPropProvisioningStatusHandler");
118 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d", status->getESCloudState());
120 m_cloudPropProvStatusCb(status);
124 ESResult RemoteEnrollee::ESDiscoveryTimeout(unsigned short waittime)
126 struct timespec startTime;
129 struct timespec currTime;
133 ESResult res = ES_OK;
134 #ifdef _POSIX_MONOTONIC_CLOCK
135 int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
137 int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
145 while (ES_OK == res || m_discoveryResponse == false)
147 #ifdef _POSIX_MONOTONIC_CLOCK
148 clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
150 clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
157 long elapsed = (currTime.tv_sec - startTime.tv_sec);
158 if (elapsed > waittime)
162 if (m_discoveryResponse)
170 void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
172 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered");
174 std::string resourceURI;
175 std::string hostAddress;
176 std::string hostDeviceID;
182 if(!(resource->connectivityType() & CT_ADAPTER_TCP))
184 // Get the resource URI
185 resourceURI = resource->uri();
186 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
187 "URI of the resource: %s", resourceURI.c_str());
189 // Get the resource host address
190 hostAddress = resource->host();
191 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
192 "Host address of the resource: %s", hostAddress.c_str());
194 hostDeviceID = resource->sid();
195 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
196 "Host DeviceID of the resource: %s", hostDeviceID.c_str());
198 if(!m_deviceId.empty() && m_deviceId == hostDeviceID)
200 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "Find matched CloudResource");
201 m_ocResource = resource;
202 m_discoveryResponse = true;
207 catch(std::exception& e)
209 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
210 "Exception in foundResource: %s", e.what());
214 ESResult RemoteEnrollee::discoverResource()
216 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Enter discoverResource");
218 std::string query("");
219 query.append(ES_BASE_RES_URI);
220 query.append("?rt=");
221 query.append(OC_RSRVD_ES_RES_TYPE_PROV);
223 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
225 m_discoveryResponse = false;
227 std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =
228 std::bind(&RemoteEnrollee::onDeviceDiscovered, this,
229 std::placeholders::_1);
230 OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,
231 onDeviceDiscoveredCb);
233 if (result != OCStackResult::OC_STACK_OK)
235 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
236 "Failed discoverResource");
240 ESResult foundResponse = ESDiscoveryTimeout (DISCOVERY_TIMEOUT);
242 if (foundResponse == ES_ERROR || !m_discoveryResponse)
244 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
245 "Failed discoverResource because timeout");
251 void RemoteEnrollee::configureSecurity(SecurityProvStatusCb callback)
254 m_securityProvStatusCb = callback;
256 SecurityProvStatusCb securityProvStatusCb = std::bind(
257 &RemoteEnrollee::securityStatusHandler,
259 std::placeholders::_1);
260 //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
261 m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
263 m_enrolleeSecurity->registerCallbackHandler(securityProvStatusCb, m_securityPinCb, m_secProvisioningDbPathCb);
267 m_enrolleeSecurity->performOwnershipTransfer();
269 catch (OCException & e)
271 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
272 "Exception for performOwnershipTransfer : %s", e.reason().c_str());
274 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Fail performOwnershipTransfer");
275 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
276 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
277 m_securityProvStatusCb(securityProvisioningStatus);
281 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured.");
283 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
284 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
285 m_securityProvStatusCb(securityProvisioningStatus);
289 void RemoteEnrollee::getConfiguration(GetConfigurationStatusCb callback)
293 throw ESInvalidParameterException("Callback is empty");
296 m_getConfigurationStatusCb = callback;
298 if (m_enrolleeResource == nullptr)
300 throw ESBadRequestException ("Device not created");
303 GetConfigurationStatusCb getConfigurationStatusCb = std::bind(
304 &RemoteEnrollee::getConfigurationStatusHandler, this, std::placeholders::_1);
305 m_enrolleeResource->registerGetConfigurationStatusCallback(getConfigurationStatusCb);
306 m_enrolleeResource->getConfiguration();
309 void RemoteEnrollee::provisionDeviceProperties(const DeviceProp& devProp, DevicePropProvStatusCb callback)
311 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionDeviceProperties");
315 throw ESInvalidParameterException("Callback is empty");
318 m_devicePropProvStatusCb = callback;
320 if (m_enrolleeResource == nullptr)
322 throw ESBadRequestException ("Device not created");
325 if(devProp.WIFI.ssid.empty())
327 throw ESBadRequestException ("Invalid Provisiong Data.");
330 DevicePropProvStatusCb devicePropProvStatusCb = std::bind(
331 &RemoteEnrollee::devicePropProvisioningStatusHandler, this, std::placeholders::_1);
333 m_enrolleeResource->registerDevicePropProvStatusCallback(devicePropProvStatusCb);
334 m_enrolleeResource->provisionEnrollee(devProp);
337 void RemoteEnrollee::initCloudResource()
339 ESResult result = ES_ERROR;
341 if (m_cloudResource != nullptr)
343 throw ESBadRequestException ("Already created");
346 result = discoverResource();
348 if (result == ES_ERROR)
350 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
351 "Failed to create resource object using discoverResource");
352 throw ESBadRequestException ("Resource object not created");
357 if(m_ocResource != nullptr)
359 m_cloudResource = std::make_shared<CloudResource>(std::move(m_ocResource));
361 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
362 CloudPropProvisioningStatus >(ESResult::ES_OK, ESCloudProvState::ES_CLOUD_ENROLLEE_FOUND);
364 m_cloudPropProvStatusCb(provStatus);
368 throw ESBadGetException ("Resource handle is invalid");
374 void RemoteEnrollee::provisionCloudProperties(const CloudProp& cloudProp, CloudPropProvStatusCb callback)
376 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionCloudProperties");
378 ESResult result = ES_ERROR;
382 throw ESInvalidParameterException("Callback is empty");
385 m_cloudPropProvStatusCb = callback;
387 if(cloudProp.authCode.empty()
388 || cloudProp.authProvider.empty()
389 || cloudProp.ciServer.empty())
391 throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
399 catch (const std::exception& e)
401 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
402 "Exception caught in provisionCloudProperties = %s", e.what());
404 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
405 CloudPropProvisioningStatus >(ESResult::ES_ERROR, ESCloudProvState::ES_CLOUD_ENROLLEE_NOT_FOUND);
406 m_cloudPropProvStatusCb(provStatus);
409 if (m_cloudResource == nullptr)
411 throw ESBadRequestException ("Cloud Resource not created");
414 CloudPropProvStatusCb cloudPropProvStatusCb = std::bind(
415 &RemoteEnrollee::cloudPropProvisioningStatusHandler, this, std::placeholders::_1);
417 m_cloudResource->registerCloudPropProvisioningStatusCallback(cloudPropProvStatusCb);
418 m_cloudResource->provisionEnrollee(cloudProp);
421 void RemoteEnrollee::setDevID(const std::string devId)