replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / service / easy-setup / mediator / richsdk / src / RemoteEnrollee.cpp
index 89e0964..941239d 100755 (executable)
 #include "ESException.h"
 #include "logger.h"
 #include "OCResource.h"
+#include "oic_string.h"
 #ifdef __WITH_DTLS__
 #include "EnrolleeSecurity.h"
+#include "base64.h"
+#include "oic_malloc.h"
+#include "cacommon.h"
 #endif //__WITH_DTLS
 
 namespace OIC
@@ -35,9 +39,9 @@ namespace OIC
     {
         static const char ES_BASE_RES_URI[] = "/oic/res";
         #define ES_REMOTE_ENROLLEE_TAG "ES_REMOTE_ENROLLEE"
-        #define DISCOVERY_TIMEOUT 5
+        #define DISCOVERY_TIMEOUT 1
 
-        RemoteEnrollee::RemoteEnrollee(std::shared_ptr< OC::OCResource > resource)
+        RemoteEnrollee::RemoteEnrollee(const std::shared_ptr< OC::OCResource > resource)
         {
             m_ocResource = resource;
             m_enrolleeResource = std::make_shared<EnrolleeResource>(m_ocResource);
@@ -47,144 +51,215 @@ namespace OIC
             m_secProvisioningDbPathCb = nullptr;
             m_devicePropProvStatusCb = nullptr;
             m_cloudPropProvStatusCb = nullptr;
+            m_connectRequestStatusCb = nullptr;
 
             m_deviceId = resource->sid();
         }
 
-#ifdef __WITH_DTLS__
-        ESResult RemoteEnrollee::registerSecurityCallbackHandler(SecurityPinCb securityPinCb,
-                SecProvisioningDbPathCb secProvisioningDbPathCb)
+        void RemoteEnrollee::onSecurityStatusHandlerCallback(
+                const std::shared_ptr< SecProvisioningStatus > status,
+                std::weak_ptr<RemoteEnrollee> this_ptr)
         {
-            // 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;
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onSecurityStatusHandlerCallback");
+            std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
+            if(Ptr)
+            {
+                Ptr->securityStatusHandler(status);
+            }
         }
-#endif //__WITH_DTLS__
 
         void RemoteEnrollee::securityStatusHandler(
-                        std::shared_ptr< SecProvisioningStatus > status)
+                const std::shared_ptr< SecProvisioningStatus > status) const
         {
-            OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "easySetupStatusCallback status is, UUID = %s, "
-                    "Status = %d", status->getDeviceUUID().c_str(),
-                    status->getESResult());
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "securityStatusHandlr IN");
+            OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "UUID = %s", status->getDeviceUUID().c_str());
+            OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG, "ESResult = %d", status->getESResult());
 
             if(status->getESResult() == ES_OK)
             {
-                OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are successful. "
-                        "Continue with Network information provisioning");
-
-                OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");
-
+                OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "Ownership transfer is successfully done.");
                 m_securityProvStatusCb(status);
             }
             else
             {
-                OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are fail");
-
+                OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG, "Ownership transfer is failed.");
                 m_securityProvStatusCb(status);
             }
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "securityStatusHandlr OUT");
+        }
+
+        ESOwnershipTransferData RemoteEnrollee::onSecurityStatusWithOptionHandlerCallback(
+                const std::shared_ptr< SecProvisioningStatus > status,
+                std::weak_ptr<RemoteEnrollee> this_ptr)
+        {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onSecurityStatusWithOptionHandlerCallback");
+            std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
+            if(Ptr)
+            {
+                return Ptr->securityStatusWithOptionHandler(status);
+            }
+            return ESOwnershipTransferData();
         }
 
-        void RemoteEnrollee::getStatusHandler(std::shared_ptr< GetEnrolleeStatus > status)
+        ESOwnershipTransferData RemoteEnrollee::securityStatusWithOptionHandler(
+                const std::shared_ptr< SecProvisioningStatus > status) const
         {
-            OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getStatusHandler");
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "securityStatusWithOptionHandler IN");
+            OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "UUID = %s", status->getDeviceUUID().c_str());
+            OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG, "ESResult = %d", status->getESResult());
 
-            OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"getStatusHandler = %d", status->getESResult());
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "securityStatusWithOptionHandler OUT");
+            return m_securityProvStatusCbWithOption(status);
+        }
 
+        void RemoteEnrollee::onGetStatusHandlerCallback(
+                const std::shared_ptr< GetEnrolleeStatus > status,
+                std::weak_ptr<RemoteEnrollee> this_ptr)
+        {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onGetStatusHandlerCallback");
+            std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
+            if(Ptr)
+            {
+                Ptr->getStatusHandler(status);
+            }
+        }
+
+        void RemoteEnrollee::getStatusHandler(
+                const std::shared_ptr< GetEnrolleeStatus > status) const
+        {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatusHandler IN");
+
+            OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatusHandler = %d",
+                                                    status->getESResult());
             m_getStatusCb(status);
+
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatusHandler OUT");
         }
 
-        void RemoteEnrollee::getConfigurationStatusHandler (
-                std::shared_ptr< GetConfigurationStatus > status)
+        void RemoteEnrollee::onGetConfigurationStatusHandlerCallback(
+                const std::shared_ptr< GetConfigurationStatus > status,
+                std::weak_ptr<RemoteEnrollee> this_ptr)
         {
-            OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getConfigurationStatusHandler");
+            OIC_LOG(INFO,ES_REMOTE_ENROLLEE_TAG,"onGetConfigurationStatusHandlerCallback");
+            std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
+            if(Ptr)
+            {
+                Ptr->getConfigurationStatusHandler(status);
+            }
+        }
 
-            OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"GetConfigurationStatus = %d", status->getESResult());
+        void RemoteEnrollee::getConfigurationStatusHandler (
+                const std::shared_ptr< GetConfigurationStatus > status) const
+        {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getConfigurationStatusHandler IN");
 
+            OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG,"GetConfigurationStatus = %d",
+                                                    status->getESResult());
             m_getConfigurationStatusCb(status);
+
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getConfigurationStatusHandler OUT");
         }
 
-        void RemoteEnrollee::devicePropProvisioningStatusHandler(
-                std::shared_ptr< DevicePropProvisioningStatus > status)
+        void RemoteEnrollee::onDevicePropProvisioningStatusHandlerCallback(
+                const std::shared_ptr< DevicePropProvisioningStatus > status,
+                std::weak_ptr<RemoteEnrollee> this_ptr)
         {
-            OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering DevicePropProvisioningStatusHandler");
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onDevicePropProvisioningStatusHandlerCallback");
+            std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
+            if(Ptr)
+            {
+                Ptr->devicePropProvisioningStatusHandler(status);
+            }
+        }
 
-            OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", status->getESResult());
+        void RemoteEnrollee::devicePropProvisioningStatusHandler(
+                const std::shared_ptr< DevicePropProvisioningStatus > status) const
+        {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "devicePropProvisioningStatusHandler IN");
 
+            OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG, "DeviceProvStatus = %d", status->getESResult());
             m_devicePropProvStatusCb(status);
+#ifdef __WITH_DTLS__
+            if( m_ocResource.get() != nullptr &&
+                    !(m_ocResource->connectivityType() & CT_ADAPTER_GATT_BTLE) &&
+                    ES_OK == status->getESResult() )
+            {
+                // NOTE: Temporary patch
+                CAEndpoint_t endpoint = {.adapter = CA_ADAPTER_IP};
 
-            return;
+                OCDevAddr address = m_ocResource->getDevAddr();
+                OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE, address.addr);
+                endpoint.port = address.port;
+
+                OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "HOST = %s", endpoint.addr);
+                OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "PORT = %u", endpoint.port);
+                CAcloseSslSession(&endpoint);
+            }
+#endif
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "devicePropProvisioningStatusHandler OUT");
         }
 
-        void RemoteEnrollee::cloudPropProvisioningStatusHandler (
-                std::shared_ptr< CloudPropProvisioningStatus > status)
+        void RemoteEnrollee::onCloudPropProvisioningStatusHandlerCallback(
+                const std::shared_ptr< CloudPropProvisioningStatus > status,
+                std::weak_ptr<RemoteEnrollee> this_ptr)
         {
-            OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering cloudPropProvisioningStatusHandler");
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onCloudPropProvisioningStatusHandlerCallback");
+            std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
+            if(Ptr)
+            {
+                Ptr->cloudPropProvisioningStatusHandler(status);
+            }
+        }
 
-            OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d", status->getESCloudState());
+        void RemoteEnrollee::cloudPropProvisioningStatusHandler (
+                const std::shared_ptr< CloudPropProvisioningStatus > status) const
+        {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "cloudPropProvisioningStatusHandler IN");
 
+            OIC_LOG_V(INFO,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d",
+                                                    status->getESResult());
             m_cloudPropProvStatusCb(status);
-            return;
+
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "cloudPropProvisioningStatusHandler OUT");
         }
 
-        ESResult RemoteEnrollee::ESDiscoveryTimeout(unsigned short waittime)
+        void RemoteEnrollee::onConnectRequestStatusHandlerCallback(
+                const std::shared_ptr< ConnectRequestStatus > status,
+                std::weak_ptr<RemoteEnrollee> this_ptr)
         {
-            struct timespec startTime;
-            startTime.tv_sec=0;
-            startTime.tv_sec=0;
-            struct timespec currTime;
-            currTime.tv_sec=0;
-            currTime.tv_nsec=0;
-
-            ESResult res = ES_OK;
-            #ifdef _POSIX_MONOTONIC_CLOCK
-                int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
-            #else
-                int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
-            #endif
-
-            if (0 != clock_res)
+            OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"onConnectRequestStatusHandlerCallback");
+            std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
+            if(Ptr)
             {
-                return ES_ERROR;
+                Ptr->connectRequestStatusHandler(status);
             }
+        }
 
-            while (ES_OK == res || m_discoveryResponse == false)
-            {
-                #ifdef _POSIX_MONOTONIC_CLOCK
-                        clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
-                #else
-                        clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
-                #endif
+        void RemoteEnrollee::connectRequestStatusHandler(
+                const std::shared_ptr< ConnectRequestStatus > status) const
+        {
+            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connectRequestStatusHandler IN");
 
-                if (0 != clock_res)
-                {
-                    return ES_ERROR;
-                }
-                long elapsed = (currTime.tv_sec - startTime.tv_sec);
-                if (elapsed > waittime)
-                {
-                    return ES_OK;
-                }
-                if (m_discoveryResponse)
-                {
-                    res = ES_OK;
-                }
-             }
-             return res;
+            OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "RequestConnectStatus = %d", status->getESResult());
+            m_connectRequestStatusCb(status);
+
+            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connectRequestStatusHandler OUT");
         }
 
-        void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
+        void RemoteEnrollee::onDiscoveredCallback(const std::shared_ptr<OC::OCResource> resource,
+            std::weak_ptr<RemoteEnrollee> this_ptr)
         {
-            OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered");
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"onDiscoveredCallback()");
+            std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
+            if(Ptr)
+            {
+                Ptr->onDeviceDiscovered(resource);
+            }
+        }
 
-            std::string resourceURI;
-            std::string hostAddress;
-            std::string hostDeviceID;
+        void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
+        {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered IN");
 
             try
             {
@@ -192,113 +267,168 @@ namespace OIC
                 {
                     if(!(resource->connectivityType() & CT_ADAPTER_TCP))
                     {
+                        std::string resourceURI;
+                        std::string hostAddress;
+                        std::string hostDeviceID;
+
                         // Get the resource URI
                         resourceURI = resource->uri();
-                        OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
+                        OIC_LOG_V(INFO_PRIVATE, 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,
+                        OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG,
                                 "Host address of the resource: %s", hostAddress.c_str());
 
                         hostDeviceID = resource->sid();
-                        OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
+                        OIC_LOG_V(INFO_PRIVATE, 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");
+                            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "Find matched resource for cloud provisioning");
                             m_ocResource = resource;
                             m_discoveryResponse = true;
+                            m_cond.notify_all();
                         }
                     }
                 }
             }
             catch(std::exception& e)
             {
-                OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
+                OIC_LOG_V(INFO, ES_REMOTE_ENROLLEE_TAG,
                         "Exception in foundResource: %s", e.what());
             }
+
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered OUT");
         }
 
         ESResult RemoteEnrollee::discoverResource()
         {
-            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Enter discoverResource");
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "discoverResource IN");
 
             std::string query("");
             query.append(ES_BASE_RES_URI);
             query.append("?rt=");
-            query.append(OC_RSRVD_ES_RES_TYPE_PROV);
+            query.append(OC_RSRVD_ES_RES_TYPE_EASYSETUP);
 
-            OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
+            OIC_LOG_V(INFO, 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);
+            onDeviceDiscoveredCb cb = std::bind(&RemoteEnrollee::onDiscoveredCallback,
+                                                std::placeholders::_1,
+                                                shared_from_this());
+
+            OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT, cb);
 
             if (result != OCStackResult::OC_STACK_OK)
             {
-                OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
+                OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG,
                         "Failed discoverResource");
                 return ES_ERROR;
             }
 
-            ESResult foundResponse = ESDiscoveryTimeout (DISCOVERY_TIMEOUT);
+            std::unique_lock<std::mutex> lck(m_discoverymtx);
+            m_cond.wait_for(lck, std::chrono::seconds(DISCOVERY_TIMEOUT));
 
-            if (foundResponse == ES_ERROR || !m_discoveryResponse)
+            if (!m_discoveryResponse)
             {
-                OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
+                OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG,
                         "Failed discoverResource because timeout");
                 return ES_ERROR;
             }
+
             return ES_OK;
         }
 
-        void RemoteEnrollee::provisionSecurity(SecurityProvStatusCb callback)
+        void RemoteEnrollee::provisionSecurity(const SecurityProvStatusCb callback)
         {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity IN");
 #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);
+                    &RemoteEnrollee::onSecurityStatusHandlerCallback,
+                    std::placeholders::_1,
+                    shared_from_this());
             //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
-            m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
+            if(!m_localEnrolleeSecurity.get())
+            {
+                m_localEnrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource);
+            }
 
-            m_enrolleeSecurity->registerCallbackHandler(securityProvStatusCb, m_securityPinCb, m_secProvisioningDbPathCb);
+            res = m_localEnrolleeSecurity->provisionOwnership(NULL);
 
-            try
+            std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
+                            std::make_shared< SecProvisioningStatus >(m_localEnrolleeSecurity->getUUID(), res);
+            securityProvStatusCb(securityProvisioningStatus);
+#else
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured built.");
+
+            if(!callback)
             {
-                m_enrolleeSecurity->performOwnershipTransfer();
+                throw ESInvalidParameterException("Callback is empty");
             }
-            catch (OCException & e)
+            std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
+                     std::make_shared< SecProvisioningStatus >
+                                   ("", ESResult::ES_SEC_OPERATION_IS_NOT_SUPPORTED);
+            callback(securityProvisioningStatus);
+#endif
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity OUT");
+        }
+
+        void RemoteEnrollee::provisionSecurity(const SecurityProvStatusCbWithOption callback)
+        {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity IN");
+#ifdef __WITH_DTLS__
+            ESResult res = ESResult::ES_ERROR;
+            if(!callback)
             {
-                OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
-                        "Exception for performOwnershipTransfer : %s", e.reason().c_str());
+                throw ESInvalidParameterException("Callback is empty");
+            }
+            m_securityProvStatusCbWithOption = callback;
+
+            SecurityProvStatusCbWithOption securityProvStatusCbWithOption = std::bind(
+                                    &RemoteEnrollee::onSecurityStatusWithOptionHandlerCallback,
+                                    std::placeholders::_1,
+                                    shared_from_this());
 
-                OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Fail performOwnershipTransfer");
-                    std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
-                            std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
-                    m_securityProvStatusCb(securityProvisioningStatus);
-                return ;
+            if(!m_localEnrolleeSecurity.get())
+            {
+                m_localEnrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource);
             }
+
+            res = m_localEnrolleeSecurity->provisionOwnership(securityProvStatusCbWithOption);
+
+            std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
+                            std::make_shared< SecProvisioningStatus >(m_localEnrolleeSecurity->getUUID(), res);
+            securityProvStatusCbWithOption(securityProvisioningStatus);
 #else
-            OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured.");
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured built.");
 
+            if(!callback)
+            {
+                throw ESInvalidParameterException("Callback is empty");
+            }
             std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
-                     std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
-            m_securityProvStatusCb(securityProvisioningStatus);
+                     std::make_shared< SecProvisioningStatus >
+                                   ("", ESResult::ES_SEC_OPERATION_IS_NOT_SUPPORTED);
+            callback(securityProvisioningStatus);
 #endif
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity OUT");
         }
 
-        void RemoteEnrollee::getStatus(GetStatusCb callback)
+        void RemoteEnrollee::getStatus(const GetStatusCb callback)
         {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatus IN");
+
             if(!callback)
             {
                 throw ESInvalidParameterException("Callback is empty");
@@ -312,14 +442,20 @@ namespace OIC
             m_getStatusCb = callback;
 
             GetStatusCb getStatusCb = std::bind(
-                &RemoteEnrollee::getStatusHandler, this, std::placeholders::_1);
+                &RemoteEnrollee::onGetStatusHandlerCallback,
+                std::placeholders::_1,
+                shared_from_this());
+
             m_enrolleeResource->registerGetStatusCallback(getStatusCb);
             m_enrolleeResource->getStatus();
 
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getStatus OUT");
         }
 
-        void RemoteEnrollee::getConfiguration(GetConfigurationStatusCb callback)
+        void RemoteEnrollee::getConfiguration(const GetConfigurationStatusCb callback)
         {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getConfiguration IN");
+
             if(!callback)
             {
                 throw ESInvalidParameterException("Callback is empty");
@@ -333,14 +469,20 @@ namespace OIC
             m_getConfigurationStatusCb = callback;
 
             GetConfigurationStatusCb getConfigurationStatusCb = std::bind(
-                    &RemoteEnrollee::getConfigurationStatusHandler, this, std::placeholders::_1);
+                    &RemoteEnrollee::onGetConfigurationStatusHandlerCallback,
+                    std::placeholders::_1,
+                    shared_from_this());
+
             m_enrolleeResource->registerGetConfigurationStatusCallback(getConfigurationStatusCb);
             m_enrolleeResource->getConfiguration();
+
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "getConfiguration OUT");
         }
 
-        void RemoteEnrollee::provisionDeviceProperties(const DeviceProp& devProp, DevicePropProvStatusCb callback)
+        void RemoteEnrollee::provisionDeviceProperties(const DeviceProp& deviceProp,
+                                                            const DevicePropProvStatusCb callback)
         {
-            OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionDeviceProperties");
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionDeviceProperties IN");
 
             if(!callback)
             {
@@ -354,32 +496,28 @@ namespace OIC
                 throw ESBadRequestException ("Device not created");
             }
 
-            if(devProp.WIFI.ssid.empty())
-            {
-                throw ESBadRequestException ("Invalid Provisiong Data.");
-            }
-
             DevicePropProvStatusCb devicePropProvStatusCb = std::bind(
-                    &RemoteEnrollee::devicePropProvisioningStatusHandler, this, std::placeholders::_1);
+                    &RemoteEnrollee::onDevicePropProvisioningStatusHandlerCallback,
+                    std::placeholders::_1,
+                    shared_from_this());
 
             m_enrolleeResource->registerDevicePropProvStatusCallback(devicePropProvStatusCb);
-            m_enrolleeResource->provisionEnrollee(devProp);
+            m_enrolleeResource->provisionProperties(deviceProp);
+
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionDeviceProperties OUT");
         }
 
         void RemoteEnrollee::initCloudResource()
         {
-            ESResult result = ES_ERROR;
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "initCloudResource IN");
 
-            if (m_cloudResource != nullptr)
-            {
-                throw ESBadRequestException ("Already created");
-            }
+            ESResult result = ES_ERROR;
 
             result = discoverResource();
 
             if (result == ES_ERROR)
             {
-                OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
+                OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG,
                                     "Failed to create resource object using discoverResource");
                 throw ESBadRequestException ("Resource object not created");
             }
@@ -388,26 +526,32 @@ namespace OIC
             {
                 if(m_ocResource != nullptr)
                 {
-                    m_cloudResource = std::make_shared<CloudResource>(std::move(m_ocResource));
-
-                    std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
-                        CloudPropProvisioningStatus >(ESResult::ES_OK, ESCloudProvState::ES_CLOUD_ENROLLEE_FOUND);
-
-                    m_cloudPropProvStatusCb(provStatus);
+                    m_cloudResource = std::make_shared<CloudResource>(m_ocResource);
                 }
                 else
                 {
                     throw ESBadGetException ("Resource handle is invalid");
                 }
             }
-        }
 
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "initCloudResource OUT");
+        }
 
-        void RemoteEnrollee::provisionCloudProperties(const CloudProp& cloudProp, CloudPropProvStatusCb callback)
+        void RemoteEnrollee::provisionCloudProperties(const CloudProp& cloudProp,
+                                                            const CloudPropProvStatusCb callback)
         {
-            OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionCloudProperties");
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties w/o OCResource IN");
 
-            ESResult result = ES_ERROR;
+            provisionCloudProperties(NULL, cloudProp, callback);
+
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties w/o OCResource OUT");
+        }
+
+        void RemoteEnrollee::provisionCloudProperties(const std::shared_ptr< OC::OCResource > resource,
+                                                        const CloudProp& cloudProp,
+                                                        const CloudPropProvStatusCb callback)
+        {
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties IN");
 
             if(!callback)
             {
@@ -416,27 +560,93 @@ namespace OIC
 
             m_cloudPropProvStatusCb = callback;
 
-            if(cloudProp.authCode.empty()
-                || cloudProp.authProvider.empty()
-                || cloudProp.ciServer.empty())
+            if((cloudProp.getAuthCode().empty() && cloudProp.getAccessToken().empty()) ||
+                cloudProp.getAuthProvider().empty() ||
+                cloudProp.getCiServer().empty())
             {
                 throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
             }
 
-            try
+            if(resource)
             {
-                initCloudResource();
+                if(resource->getResourceTypes().at(0) != OC_RSRVD_ES_RES_TYPE_EASYSETUP ||
+                                resource->connectivityType() & CT_ADAPTER_TCP)
+                {
+                    OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG, "Given resource is not valid due to wrong rt or conntype");
+                    throw ESInvalidParameterException("A given OCResource is wrong");
+                }
+
+                auto interfaces = resource->getResourceInterfaces();
+                bool isFound = false;
+                for(auto interface : interfaces)
+                {
+                    if(interface.compare(BATCH_INTERFACE) == 0)
+                    {
+                        OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "RemoteEnrollee object is succeessfully created");
+                        OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "HOST: %s", resource->host().c_str());
+                        OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "URI: %s", resource->uri().c_str());
+                        OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "SID: %s", resource->sid().c_str());
+                        OIC_LOG_V(INFO_PRIVATE, ES_REMOTE_ENROLLEE_TAG, "CONNECTIVITY: %d", resource->connectivityType());
+                        isFound = true;
+                    }
+                }
+
+                if(!isFound)
+                {
+                    throw ESInvalidParameterException("A given OCResource has no batch interface");
+                }
             }
 
+            try
+            {
+                if(resource == NULL)
+                {
+                    initCloudResource();
+                }
+                else
+                {
+                    OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "Skip to find a provisioning resource");
+                    m_ocResource = resource;
+                    m_cloudResource = std::make_shared<CloudResource>(m_ocResource);
+                }
+            }
             catch (const std::exception& e)
             {
                 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_ERROR, ESCloudProvState::ES_CLOUD_ENROLLEE_NOT_FOUND);
+                        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;
+                if(!m_cloudEnrolleeSecurity.get())
+                {
+                    m_cloudEnrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource);
+                }
+
+
+                res = m_cloudEnrolleeSecurity->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
+            {
+                OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "ACL and Cert. provisioning are skipped.");
             }
+#endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)
 
             if (m_cloudResource == nullptr)
             {
@@ -444,10 +654,38 @@ namespace OIC
             }
 
             CloudPropProvStatusCb cloudPropProvStatusCb = std::bind(
-                    &RemoteEnrollee::cloudPropProvisioningStatusHandler, this, std::placeholders::_1);
+                    &RemoteEnrollee::onCloudPropProvisioningStatusHandlerCallback,
+                    std::placeholders::_1,
+                    shared_from_this());
 
             m_cloudResource->registerCloudPropProvisioningStatusCallback(cloudPropProvStatusCb);
-            m_cloudResource->provisionEnrollee(cloudProp);
+            m_cloudResource->provisionProperties(cloudProp);
+
+            OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties OUT");
+        }
+
+        void RemoteEnrollee::requestToConnect(const std::vector<ES_CONNECT_TYPE> &connectTypes, const ConnectRequestStatusCb callback)
+        {
+            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connect IN");
+
+            if(!callback)
+            {
+                throw ESInvalidParameterException("Callback is empty");
+            }
+
+            m_connectRequestStatusCb = callback;
+
+            ConnectRequestStatusCb connectRequestStatusCb = std::bind(
+                        &RemoteEnrollee::onConnectRequestStatusHandlerCallback,
+                        std::placeholders::_1,
+                        shared_from_this());
+
+            m_enrolleeResource->registerConnectRequestStatusCallback(connectRequestStatusCb);
+            m_enrolleeResource->requestToConnect(connectTypes);
+
+            OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connect OUT");
         }
     }
 }
+
+