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::getConfigurationStatusHandler (
94 std::shared_ptr< GetConfigurationStatus > status)
96 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getConfigurationStatusHandler");
98 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"GetConfigurationStatus = %d", status->getESResult());
100 m_getConfigurationStatusCb(status);
103 void RemoteEnrollee::devicePropProvisioningStatusHandler(
104 std::shared_ptr< DevicePropProvisioningStatus > status)
106 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering DevicePropProvisioningStatusHandler");
108 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", status->getESResult());
110 m_devicePropProvStatusCb(status);
115 void RemoteEnrollee::cloudPropProvisioningStatusHandler (
116 std::shared_ptr< CloudPropProvisioningStatus > status)
118 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering cloudPropProvisioningStatusHandler");
120 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d", status->getESCloudState());
122 m_cloudPropProvStatusCb(status);
126 ESResult RemoteEnrollee::ESDiscoveryTimeout(unsigned short waittime)
128 struct timespec startTime;
131 struct timespec currTime;
135 ESResult res = ES_OK;
136 #ifdef _POSIX_MONOTONIC_CLOCK
137 int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
139 int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
147 while (ES_OK == res || m_discoveryResponse == false)
149 #ifdef _POSIX_MONOTONIC_CLOCK
150 clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
152 clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
159 long elapsed = (currTime.tv_sec - startTime.tv_sec);
160 if (elapsed > waittime)
164 if (m_discoveryResponse)
172 void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
174 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered");
176 std::string resourceURI;
177 std::string hostAddress;
178 std::string hostDeviceID;
184 if(!(resource->connectivityType() & CT_ADAPTER_TCP))
186 // Get the resource URI
187 resourceURI = resource->uri();
188 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
189 "URI of the resource: %s", resourceURI.c_str());
191 // Get the resource host address
192 hostAddress = resource->host();
193 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
194 "Host address of the resource: %s", hostAddress.c_str());
196 hostDeviceID = resource->sid();
197 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
198 "Host DeviceID of the resource: %s", hostDeviceID.c_str());
200 if(!m_deviceId.empty() && m_deviceId == hostDeviceID)
202 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "Find matched CloudResource");
203 m_ocResource = resource;
204 m_discoveryResponse = true;
209 catch(std::exception& e)
211 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
212 "Exception in foundResource: %s", e.what());
216 ESResult RemoteEnrollee::discoverResource()
218 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Enter discoverResource");
220 std::string query("");
221 query.append(ES_BASE_RES_URI);
222 query.append("?rt=");
223 query.append(OC_RSRVD_ES_RES_TYPE_PROV);
225 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
227 m_discoveryResponse = false;
229 std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =
230 std::bind(&RemoteEnrollee::onDeviceDiscovered, this,
231 std::placeholders::_1);
232 OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,
233 onDeviceDiscoveredCb);
235 if (result != OCStackResult::OC_STACK_OK)
237 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
238 "Failed discoverResource");
242 ESResult foundResponse = ESDiscoveryTimeout (DISCOVERY_TIMEOUT);
244 if (foundResponse == ES_ERROR || !m_discoveryResponse)
246 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
247 "Failed discoverResource because timeout");
253 void RemoteEnrollee::provisionSecurity(SecurityProvStatusCb callback)
256 m_securityProvStatusCb = callback;
258 SecurityProvStatusCb securityProvStatusCb = std::bind(
259 &RemoteEnrollee::securityStatusHandler,
261 std::placeholders::_1);
262 //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
263 m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
265 m_enrolleeSecurity->registerCallbackHandler(securityProvStatusCb, m_securityPinCb, m_secProvisioningDbPathCb);
269 m_enrolleeSecurity->performOwnershipTransfer();
271 catch (OCException & e)
273 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
274 "Exception for performOwnershipTransfer : %s", e.reason().c_str());
276 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Fail performOwnershipTransfer");
277 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
278 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
279 m_securityProvStatusCb(securityProvisioningStatus);
283 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured.");
285 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
286 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
287 m_securityProvStatusCb(securityProvisioningStatus);
291 void RemoteEnrollee::getConfiguration(GetConfigurationStatusCb callback)
295 throw ESInvalidParameterException("Callback is empty");
298 m_getConfigurationStatusCb = callback;
300 if (m_enrolleeResource == nullptr)
302 throw ESBadRequestException ("Device not created");
305 GetConfigurationStatusCb getConfigurationStatusCb = std::bind(
306 &RemoteEnrollee::getConfigurationStatusHandler, this, std::placeholders::_1);
307 m_enrolleeResource->registerGetConfigurationStatusCallback(getConfigurationStatusCb);
308 m_enrolleeResource->getConfiguration();
311 void RemoteEnrollee::provisionDeviceProperties(const DeviceProp& devProp, DevicePropProvStatusCb callback)
313 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionDeviceProperties");
317 throw ESInvalidParameterException("Callback is empty");
320 m_devicePropProvStatusCb = callback;
322 if (m_enrolleeResource == nullptr)
324 throw ESBadRequestException ("Device not created");
327 if(devProp.WIFI.ssid.empty())
329 throw ESBadRequestException ("Invalid Provisiong Data.");
332 DevicePropProvStatusCb devicePropProvStatusCb = std::bind(
333 &RemoteEnrollee::devicePropProvisioningStatusHandler, this, std::placeholders::_1);
335 m_enrolleeResource->registerDevicePropProvStatusCallback(devicePropProvStatusCb);
336 m_enrolleeResource->provisionEnrollee(devProp);
339 void RemoteEnrollee::initCloudResource()
341 ESResult result = ES_ERROR;
343 if (m_cloudResource != nullptr)
345 throw ESBadRequestException ("Already created");
348 result = discoverResource();
350 if (result == ES_ERROR)
352 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
353 "Failed to create resource object using discoverResource");
354 throw ESBadRequestException ("Resource object not created");
359 if(m_ocResource != nullptr)
361 m_cloudResource = std::make_shared<CloudResource>(std::move(m_ocResource));
363 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
364 CloudPropProvisioningStatus >(ESResult::ES_OK, ESCloudProvState::ES_CLOUD_ENROLLEE_FOUND);
366 m_cloudPropProvStatusCb(provStatus);
370 throw ESBadGetException ("Resource handle is invalid");
376 void RemoteEnrollee::provisionCloudProperties(const CloudProp& cloudProp, CloudPropProvStatusCb callback)
378 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionCloudProperties");
380 ESResult result = ES_ERROR;
384 throw ESInvalidParameterException("Callback is empty");
387 m_cloudPropProvStatusCb = callback;
389 if(cloudProp.authCode.empty()
390 || cloudProp.authProvider.empty()
391 || cloudProp.ciServer.empty())
393 throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
401 catch (const std::exception& e)
403 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
404 "Exception caught in provisionCloudProperties = %s", e.what());
406 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
407 CloudPropProvisioningStatus >(ESResult::ES_ERROR, ESCloudProvState::ES_CLOUD_ENROLLEE_NOT_FOUND);
408 m_cloudPropProvStatusCb(provStatus);
411 if (m_cloudResource == nullptr)
413 throw ESBadRequestException ("Cloud Resource not created");
416 CloudPropProvStatusCb cloudPropProvStatusCb = std::bind(
417 &RemoteEnrollee::cloudPropProvisioningStatusHandler, this, std::placeholders::_1);
419 m_cloudResource->registerCloudPropProvisioningStatusCallback(cloudPropProvStatusCb);
420 m_cloudResource->provisionEnrollee(cloudProp);