#include "RemoteEnrollee.h"
#include "EnrolleeResource.h"
+#include "CloudResource.h"
+#include "OCPlatform.h"
#include "ESException.h"
#include "logger.h"
+#include "OCResource.h"
#ifdef __WITH_DTLS__
#include "EnrolleeSecurity.h"
+#include "base64.h"
+#include "oic_malloc.h"
#endif //__WITH_DTLS
namespace OIC
{
- #define ES_REMOTE_ENROLLEE_TAG "ES_REMOTE_ENROLLEE"
-
namespace Service
{
- RemoteEnrollee::RemoteEnrollee(const WiFiOnboadingConnection& wifiOnboardingconn) :
- m_wifiOnboardingconn(wifiOnboardingconn)
- {
- m_requestCapabilityStatusCb = nullptr;
- m_currentESState = CurrentESState::ES_ONBOARDED;
- m_isSecured = m_wifiOnboardingconn.isSecured;
-
- m_remoteResource = std::make_shared< EnrolleeResource >(m_wifiOnboardingconn);
-
- OIC_LOG ( DEBUG, ES_REMOTE_ENROLLEE_TAG, "Inside RemoteEnrollee constr");
- }
+ static const char ES_BASE_RES_URI[] = "/oic/res";
+ #define ES_REMOTE_ENROLLEE_TAG "ES_REMOTE_ENROLLEE"
+ #define DISCOVERY_TIMEOUT 5
-#ifdef __WITH_DTLS__
- ESResult RemoteEnrollee::registerSecurityCallbackHandler(SecurityPinCb securityPinCb,
- SecProvisioningDbPathCb secProvisioningDbPathCb)
+ RemoteEnrollee::RemoteEnrollee(const std::shared_ptr< OC::OCResource > resource)
{
- // No need to check NULL for m_secProvisioningDbPathCB as this is not a mandatory
- // callback function. If m_secProvisioningDbPathCB is NULL, provisioning manager
- // in security layer will try to find the PDM.db file in the local path.
- // If PDM.db is found, the provisioning manager operations will succeed.
- // Otherwise all the provisioning manager operations will fail.
- m_secProvisioningDbPathCb = secProvisioningDbPathCb;
- m_securityPinCb = securityPinCb;
- return ES_OK;
+ m_ocResource = resource;
+ m_enrolleeResource = std::make_shared<EnrolleeResource>(m_ocResource);
+ m_securityProvStatusCb = nullptr;
+ m_getConfigurationStatusCb = nullptr;
+ m_securityPinCb = nullptr;
+ m_secProvisioningDbPathCb = nullptr;
+ m_devicePropProvStatusCb = nullptr;
+ m_cloudPropProvStatusCb = nullptr;
+
+ m_deviceId = resource->sid();
}
-#endif //__WITH_DTLS__
- void RemoteEnrollee::easySetupSecurityStatusCallback(
- std::shared_ptr< SecProvisioningStatus > secProvisioningStatus)
+ void RemoteEnrollee::securityStatusHandler(
+ const std::shared_ptr< SecProvisioningStatus > status) const
{
- OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "easySetupStatusCallback status is, UUID = %s, "
- "Status = %d", secProvisioningStatus->getDeviceUUID().c_str(),
- secProvisioningStatus->getResult());
+ OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "easySetupStatusCallback status is, UUID = %s,"
+ "Status = %d", status->getDeviceUUID().c_str(),
+ status->getESResult());
- if(secProvisioningStatus->getResult() == ES_OK)
+ if(status->getESResult() == ES_OK)
{
OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are successful. "
"Continue with Network information provisioning");
- m_currentESState = CurrentESState::ES_OWNED;
-
- OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");
+ OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before provisionProperties");
- m_enrolleeSecStatusCb(secProvisioningStatus);
+ m_securityProvStatusCb(status);
}
else
{
OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are fail");
- m_enrolleeSecStatusCb(secProvisioningStatus);
+ m_securityProvStatusCb(status);
}
}
- void RemoteEnrollee::InitRemoteEnrolleeStatusHandler (
- std::shared_ptr< InitRemoteEnrolleeStatus > initRemoteEnrolleeStatus)
+ void RemoteEnrollee::getStatusHandler(
+ const std::shared_ptr< GetEnrolleeStatus > status) const
{
- OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering InitRemoteEnrolleeStatusHandler");
+ OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getStatusHandler");
- OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"initRemoteEnrolleeStatus = %d", initRemoteEnrolleeStatus->getESResult());
+ OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"getStatusHandler = %d", status->getESResult());
- m_initRemoteEnrolleeStatusCb(initRemoteEnrolleeStatus);
+ m_getStatusCb(status);
}
- void RemoteEnrollee::requestCapabilityStatusHandler (
- std::shared_ptr< RequestCapabilityStatus > requestCapabilityStatus)
+ void RemoteEnrollee::getConfigurationStatusHandler (
+ const std::shared_ptr< GetConfigurationStatus > status) const
{
- OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering requestCapabilityStatusHandler");
+ OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getConfigurationStatusHandler");
- OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"requestCapabilityStatus = %d", requestCapabilityStatus->getESResult());
+ OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"GetConfigurationStatus = %d",
+ status->getESResult());
- m_requestCapabilityStatusCb(requestCapabilityStatus);
+ m_getConfigurationStatusCb(status);
}
- void RemoteEnrollee::dataProvisioningStatusHandler(
- std::shared_ptr< ProvisioningStatus > provStatus)
+ void RemoteEnrollee::devicePropProvisioningStatusHandler(
+ const std::shared_ptr< DevicePropProvisioningStatus > status) const
{
- OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering dataprovisioningStatusHandler");
+ OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering DevicePropProvisioningStatusHandler");
- OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", provStatus->getESResult());
+ OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", status->getESResult());
- if (provStatus->getESResult() == ES_OK)
- {
- if (provStatus->getESState() >= ESState::ES_PROVISIONED_ALREADY)
- {
- OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", provStatus->getESResult());
- m_currentESState = CurrentESState::ES_PROVISIONED;
- }
- }
- m_dataProvStatusCb(provStatus);
+ m_devicePropProvStatusCb(status);
return;
}
- void RemoteEnrollee::initRemoteEnrollee(InitRemoteEnrolleeStatusCb callback)
+ void RemoteEnrollee::cloudPropProvisioningStatusHandler (
+ const std::shared_ptr< CloudPropProvisioningStatus > status) const
{
- ESResult result = ES_ERROR;
+ OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering cloudPropProvisioningStatusHandler");
- if(!callback)
+ OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d",
+ status->getESResult());
+
+ m_cloudPropProvStatusCb(status);
+ return;
+ }
+
+ void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
+ {
+ OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered");
+
+ std::string resourceURI;
+ std::string hostAddress;
+ std::string hostDeviceID;
+
+ try
{
- throw ESInvalidParameterException("Callback is empty");
+ if(resource)
+ {
+ if(!(resource->connectivityType() & CT_ADAPTER_TCP))
+ {
+ // Get the resource URI
+ resourceURI = resource->uri();
+ OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
+ "URI of the resource: %s", resourceURI.c_str());
+
+ // Get the resource host address
+ hostAddress = resource->host();
+ OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
+ "Host address of the resource: %s", hostAddress.c_str());
+
+ hostDeviceID = resource->sid();
+ OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
+ "Host DeviceID of the resource: %s", hostDeviceID.c_str());
+
+ if(!m_deviceId.empty() && m_deviceId == hostDeviceID)
+ {
+ OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "Find matched CloudResource");
+ m_ocResource = resource;
+ m_discoveryResponse = true;
+ m_cond.notify_all();
+ }
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
+ "Exception in foundResource: %s", e.what());
}
+ }
+
+ ESResult RemoteEnrollee::discoverResource()
+ {
+ OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Enter discoverResource");
- m_initRemoteEnrolleeStatusCb = callback;
+ std::string query("");
+ query.append(ES_BASE_RES_URI);
+ query.append("?rt=");
+ query.append(OC_RSRVD_ES_RES_TYPE_PROV);
- if (m_remoteResource != nullptr)
+ OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
+
+ m_discoveryResponse = false;
+
+ std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =
+ std::bind(&RemoteEnrollee::onDeviceDiscovered, this,
+ std::placeholders::_1);
+ OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,
+ onDeviceDiscoveredCb);
+
+ if (result != OCStackResult::OC_STACK_OK)
{
- throw ESBadRequestException ("Already created");
+ OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
+ "Failed discoverResource");
+ return ES_ERROR;
}
- InitRemoteEnrolleeStatusCb initRemoteEnrolleeStatusCb = std::bind(
- &RemoteEnrollee::InitRemoteEnrolleeStatusHandler, this, std::placeholders::_1);
- m_remoteResource->registerInitRemoteEnrolleeStatusCallback(initRemoteEnrolleeStatusCb);
+ std::unique_lock<std::mutex> lck(m_discoverymtx);
+ m_cond.wait_for(lck, std::chrono::seconds(DISCOVERY_TIMEOUT));
- result = m_remoteResource->constructResourceObject();
-
- if (result == ES_ERROR)
+ if (!m_discoveryResponse)
{
OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
- "Failed to create device using constructResourceObject");
- throw ESBadRequestException ("Device not created");
+ "Failed discoverResource because timeout");
+ return ES_ERROR;
}
+ return ES_OK;
}
- void RemoteEnrollee::startSecurityProvisioning(EnrolleeSecStatusCb callback)
+ void RemoteEnrollee::provisionSecurity(const SecurityProvStatusCb callback)
{
#ifdef __WITH_DTLS__
+ ESResult res = ESResult::ES_ERROR;
+ if(!callback)
+ {
+ throw ESInvalidParameterException("Callback is empty");
+ }
+ m_securityProvStatusCb = callback;
+
+ SecurityProvStatusCb securityProvStatusCb = std::bind(
+ &RemoteEnrollee::securityStatusHandler,
+ this,
+ std::placeholders::_1);
+ //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
+ m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
+
+ res = m_enrolleeSecurity->provisionOwnership();
+
+ std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
+ std::make_shared< SecProvisioningStatus >(m_enrolleeSecurity->getUUID(), res);
+ m_securityProvStatusCb(securityProvisioningStatus);
+#else
+ OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured.");
+ if(!callback)
+ {
+ throw ESInvalidParameterException("Callback is empty");
+ }
+ std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
+ std::make_shared< SecProvisioningStatus >
+ ("", ESResult::ES_SEC_OPERATION_IS_NOT_SUPPORTED);
+ callback(securityProvisioningStatus);
+#endif
+ }
- m_enrolleeSecStatusCb = callback;
+ void RemoteEnrollee::getStatus(const GetStatusCb callback)
+ {
+ if(!callback)
+ {
+ throw ESInvalidParameterException("Callback is empty");
+ }
- if (m_isSecured && m_currentESState < CurrentESState::ES_OWNED)
+ if (m_enrolleeResource == nullptr)
{
- EnrolleeSecStatusCb securityProvStatusCb = std::bind(
- &RemoteEnrollee::easySetupSecurityStatusCallback,
- this,
- std::placeholders::_1);
- //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
- m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_remoteResource, "");
+ throw ESBadRequestException ("Device not created");
+ }
- m_enrolleeSecurity->registerCallbackHandler(securityProvStatusCb,
- m_securityPinCb, m_secProvisioningDbPathCb);
+ m_getStatusCb = callback;
- try
- {
- EasySetupState easySetupState = m_enrolleeSecurity->performOwnershipTransfer();
- if (easySetupState == DEVICE_NOT_OWNED)
- {
- OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG,
- "performOwnershipTransfer returned : %d",
- easySetupState);
- return;
- }
- else if (easySetupState == DEVICE_OWNED)
- {
- OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG,
- "performOwnershipTransfer returned : %d",
- easySetupState);
- OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");
- }
- }
- catch (OCException & e)
- {
- OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
- "Exception for performOwnershipTransfer : %s", e.reason().c_str());
- return ;
- }
+ GetStatusCb getStatusCb = std::bind(
+ &RemoteEnrollee::getStatusHandler, this, std::placeholders::_1);
+ m_enrolleeResource->registerGetStatusCallback(getStatusCb);
+ m_enrolleeResource->getStatus();
+
+ }
+
+ void RemoteEnrollee::getConfiguration(const GetConfigurationStatusCb callback)
+ {
+ if(!callback)
+ {
+ throw ESInvalidParameterException("Callback is empty");
}
-#endif
+
+ if (m_enrolleeResource == nullptr)
+ {
+ throw ESBadRequestException ("Device not created");
+ }
+
+ m_getConfigurationStatusCb = callback;
+
+ GetConfigurationStatusCb getConfigurationStatusCb = std::bind(
+ &RemoteEnrollee::getConfigurationStatusHandler, this, std::placeholders::_1);
+ m_enrolleeResource->registerGetConfigurationStatusCallback(getConfigurationStatusCb);
+ m_enrolleeResource->getConfiguration();
}
- void RemoteEnrollee::getCapabilityData(RequestCapabilityStatusCb callback)
+ void RemoteEnrollee::provisionDeviceProperties(const DeviceProp& deviceProp,
+ const DevicePropProvStatusCb callback)
{
- ESResult result = ES_ERROR;
+ OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionDeviceProperties");
if(!callback)
{
throw ESInvalidParameterException("Callback is empty");
}
- m_requestCapabilityStatusCb = callback;
+ m_devicePropProvStatusCb = callback;
- if (m_remoteResource == nullptr)
+ if (m_enrolleeResource == nullptr)
{
throw ESBadRequestException ("Device not created");
}
- RequestCapabilityStatusCb requestCapabilityStatusCb = std::bind(
- &RemoteEnrollee::requestCapabilityStatusHandler, this, std::placeholders::_1);
- m_remoteResource->registerCapabilityStatusCallback(requestCapabilityStatusCb);
- m_remoteResource->getCapabilityData();
+ if(deviceProp.getSsid().empty())
+ {
+ throw ESBadRequestException ("Invalid Provisiong Data.");
+ }
+
+ DevicePropProvStatusCb devicePropProvStatusCb = std::bind(
+ &RemoteEnrollee::devicePropProvisioningStatusHandler,
+ this, std::placeholders::_1);
+
+ m_enrolleeResource->registerDevicePropProvStatusCallback(devicePropProvStatusCb);
+ m_enrolleeResource->provisionProperties(deviceProp);
}
- void RemoteEnrollee::startDataProvisioning(const ProvConfig& dataProvConfig, DataProvStatusCb callback)
+ void RemoteEnrollee::initCloudResource()
{
- OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");
+ ESResult result = ES_ERROR;
- m_ProvConfig = dataProvConfig;
- m_dataProvStatusCb = callback;
+ result = discoverResource();
- DataProvStatusCb dataProvStatusCb = std::bind(
- &RemoteEnrollee::dataProvisioningStatusHandler, this, std::placeholders::_1);
+ if (result == ES_ERROR)
+ {
+ OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
+ "Failed to create resource object using discoverResource");
+ throw ESBadRequestException ("Resource object not created");
+ }
- m_remoteResource->registerProvStatusCallback(dataProvStatusCb);
- m_remoteResource->provisionEnrollee();
+ else
+ {
+ if(m_ocResource != nullptr)
+ {
+ m_cloudResource = std::make_shared<CloudResource>(m_ocResource);
+ }
+ else
+ {
+ throw ESBadGetException ("Resource handle is invalid");
+ }
+ }
}
- void RemoteEnrollee::stopProvisioning()
+ void RemoteEnrollee::provisionCloudProperties(const CloudProp& cloudProp,
+ const CloudPropProvStatusCb callback)
{
- m_currentESState = CurrentESState::ES_UNKNOWN;
+ OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionCloudProperties");
- m_remoteResource->unprovisionEnrollee();
- }
+ if(!callback)
+ {
+ throw ESInvalidParameterException("Callback is empty");
+ }
- bool RemoteEnrollee::isEnrolleeProvisioned()
- {
- if(m_currentESState >= CurrentESState::ES_PROVISIONED)
+ m_cloudPropProvStatusCb = callback;
+
+ if(cloudProp.getAuthCode().empty() ||
+ cloudProp.getAuthProvider().empty() ||
+ cloudProp.getCiServer().empty())
+ {
+ throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
+ }
+
+ try
+ {
+ initCloudResource();
+ }
+
+ catch (const std::exception& e)
{
- return true;
+ OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
+ "Exception caught in provisionCloudProperties = %s", e.what());
+
+ std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
+ CloudPropProvisioningStatus >(ESResult::ES_ENROLLEE_DISCOVERY_FAILURE);
+ m_cloudPropProvStatusCb(provStatus);
+ return;
+ }
+#if defined(__WITH_DTLS__) && defined(__WITH_TLS__)
+ if(!(cloudProp.getCloudID().empty() && cloudProp.getCredID() <= 0))
+ {
+ ESResult res = ESResult::ES_ERROR;
+ m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
+
+ res = m_enrolleeSecurity->provisionSecurityForCloudServer(cloudProp.getCloudID(),
+ cloudProp.getCredID());
+
+ if(res != ESResult::ES_OK)
+ {
+ m_cloudResource = nullptr;
+ std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
+ CloudPropProvisioningStatus >(res);
+ m_cloudPropProvStatusCb(provStatus);
+ return;
+ }
}
else
{
- return false;
+ OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "ACL and Cert. provisioning are skipped.");
}
- }
+#endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)
- ProvConfig RemoteEnrollee::getProvConfig ()
- {
- return m_ProvConfig;
- }
+ if (m_cloudResource == nullptr)
+ {
+ throw ESBadRequestException ("Cloud Resource not created");
+ }
- WiFiOnboadingConnection RemoteEnrollee::getOnboardConn()
- {
- return m_wifiOnboardingconn;
- }
+ CloudPropProvStatusCb cloudPropProvStatusCb = std::bind(
+ &RemoteEnrollee::cloudPropProvisioningStatusHandler,
+ this, std::placeholders::_1);
+ m_cloudResource->registerCloudPropProvisioningStatusCallback(cloudPropProvStatusCb);
+ m_cloudResource->provisionProperties(cloudProp);
+ }
}
}