[easysetup] Easysetup Justworks bug fix and sample application bug fix when security...
authorlankamadan <lanka.madan@samsung.com>
Thu, 24 Dec 2015 11:06:48 +0000 (20:06 +0900)
committerMadan Lanka <lanka.madan@samsung.com>
Thu, 24 Dec 2015 12:43:37 +0000 (12:43 +0000)
- Bug when security is enabled is fixed

Change-Id: Ifb96ee5a57622fab7216a46946d904e237317641
Signed-off-by: lankamadan <lanka.madan@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/4723
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
service/easy-setup/sampleapp/mediator/linux/mediator_cpp.cpp
service/easy-setup/sdk/common/escommon.h
service/easy-setup/sdk/mediator/include/RemoteEnrollee.h
service/easy-setup/sdk/mediator/src/EnrolleeSecurity.cpp
service/easy-setup/sdk/mediator/src/EnrolleeSecurity.h
service/easy-setup/sdk/mediator/src/RemoteEnrollee.cpp
service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.cpp
service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.h

index 91d0aed..9e5125d 100755 (executable)
@@ -93,7 +93,7 @@ void initEasySetup()
 
     easySetupIntance = EasySetup::getInstance();
 
-    ipaddress = "192.168.0.150";
+    ipaddress = "10.113.64.106";
     //std::cout << "Enter the target enrollee ipv4 address ";
 
 
index 67d628f..520990a 100755 (executable)
@@ -240,18 +240,34 @@ namespace OIC
         /**
          * Security Provisioning Status
          */
-        typedef struct {
-            /// UUID of the target device
-            std::string devUUID;
-            /// EasySetup result
-            ESResult res;
-        } SecProvisioningResult;
+        class SecProvisioningResult
+        {
+        public:
+            std::shared_ptr< SecProvisioningResult > shared_ptr;
+            SecProvisioningResult(std::string deviceUUID, ESResult result) :
+                m_devUUID(deviceUUID), m_result(result)
+            {
+
+            }
+
+            std::string getDeviceUUID()
+            {
+                return m_devUUID;
+            }
 
+            ESResult getResult()
+            {
+                return m_result;
+            }
+        private:
+            std::string m_devUUID;
+            ESResult m_result;
+        };
 
         /**
          * Callback function definition for providing Enrollee security status .
          */
-        typedef std::function< void(SecProvisioningResult) > EnrolleeSecStatusCb;
+        typedef std::function< void(std::shared_ptr<SecProvisioningResult>) > EnrolleeSecStatusCb;
 
         /**
          * Callback definition to be invoked when the security stack expects a pin from application.
index 485626a..fbd273d 100755 (executable)
@@ -66,7 +66,6 @@ namespace OIC
             /**\r
              * Register Security status and other information callback handlers.\r
              *\r
-             * @param enrolleeSecStatusCb Callback to get security status callbacks.\r
              * @param secProvisioningDbCb Callback to be invoked when the stack expects a\r
              *        path for the provisioning db.\r
              * @param securityPinCb Callback to get security pin during pin based ownership transfer.\r
@@ -76,8 +75,8 @@ namespace OIC
              *\r
              * @see SecProvisioningResult\r
              */\r
-            ESResult registerSecurityCallbackHandler(EnrolleeSecStatusCb enrolleeSecStatusCb,\r
-                    SecurityPinCb securityPinCb, SecProvisioningDbPathCb secProvisioningDbPathCb);\r
+            ESResult registerSecurityCallbackHandler(SecurityPinCb securityPinCb,\r
+                    SecProvisioningDbPathCb secProvisioningDbPathCb);\r
 #endif //__WITH_DTLS__\r
 \r
             /**\r
@@ -134,6 +133,8 @@ namespace OIC
             bool m_needSecuredEasysetup;\r
 \r
             void provisioningStatusHandler (std::shared_ptr< ProvisioningStatus > provStatus);\r
+            void easySetupSecurityStatusCallback(\r
+            std::shared_ptr< SecProvisioningResult > secProvisioningResult);\r
         };\r
     }\r
 }\r
index 219d429..2446a3d 100755 (executable)
@@ -18,6 +18,8 @@
 //\r
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
 \r
+#include "base64.h"\r
+\r
 #include "EnrolleeSecurity.h"\r
 #include "oxmjustworks.h"\r
 #include "oxmrandompin.h"\r
 #include "logger.h"\r
 #include "ESException.h"\r
 #include "oic_malloc.h"\r
+#include "oic_string.h"\r
 \r
 namespace OIC\r
 {\r
     namespace Service\r
     {\r
+        #define MAX_PERMISSION_LENGTH (5)\r
+        #define CREATE (1)\r
+        #define READ (2)\r
+        #define UPDATE (4)\r
+        #define DELETE (8)\r
+        #define NOTIFY (16)\r
+        #define DASH '-'\r
+\r
         //TODO : Currently discovery timeout for owned and unowned devices is fixed as 5\r
         // The value should be accepted from the application as a parameter during ocplatform\r
         // config call\r
-        #define ES_SEC_DISCOVERY_TIMEOUT 5\r
+#define ES_SEC_DISCOVERY_TIMEOUT 5\r
 \r
         EnrolleeSecurity::EnrolleeSecurity(\r
-                std::shared_ptr< RemoteEnrolleeResource > remoteEnrolleeResource,\r
-                std::string secDbPath)\r
+        std::shared_ptr< RemoteEnrolleeResource > remoteEnrolleeResource,\r
+        std::string secDbPath)\r
         {\r
             m_enrolleeSecState = EnrolleeSecState::ES_SEC_UNKNOWN;\r
+            m_remoteEnrolleeResource = remoteEnrolleeResource;\r
 \r
             //Initializing the provisioning client stack using the db path provided by the\r
             // application.\r
@@ -52,9 +64,8 @@ namespace OIC
             }\r
         }\r
 \r
-        ESResult EnrolleeSecurity::registerCallbackHandler(\r
-                EnrolleeSecStatusCb enrolleeSecStatusCb, SecurityPinCb securityPinCb,\r
-                SecProvisioningDbPathCb secProvisioningDbPathCb)\r
+        ESResult EnrolleeSecurity::registerCallbackHandler(EnrolleeSecStatusCb enrolleeSecStatusCb,\r
+                SecurityPinCb securityPinCb, SecProvisioningDbPathCb secProvisioningDbPathCb)\r
 \r
         {\r
             m_enrolleeSecStatusCb = enrolleeSecStatusCb;\r
@@ -70,10 +81,9 @@ namespace OIC
             for (unsigned int i = 0; i < list.size(); i++)\r
             {\r
                 OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Device %d ID %s ", i + 1,\r
-                        list[i]->getDeviceID().c_str());\r
-                OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s", list[i]->getDevAddr().c_str());\r
+                        list[i]->getDeviceID().c_str());OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s", list[i]->getDevAddr().c_str());\r
 \r
-                if(list[i]->getDevAddr() == host)\r
+                if (list[i]->getDevAddr() == host)\r
                 {\r
                     return list[i];\r
                 }\r
@@ -82,22 +92,64 @@ namespace OIC
             return nullptr;\r
         }\r
 \r
+        void EnrolleeSecurity::convertUUIDToString(OicUuid_t uuid, std::string& uuidString)\r
+        {\r
+            char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] =\r
+            { 0, };\r
+            uint32_t outLen = 0;\r
+            B64Result b64Ret = B64_OK;\r
+            std::ostringstream deviceId("");\r
+\r
+            b64Ret = b64Encode(uuid.id, sizeof(uuid.id),\r
+                    base64Buff, sizeof(base64Buff), &outLen);\r
+\r
+            if (B64_OK == b64Ret)\r
+            {\r
+                deviceId << base64Buff;\r
+            }\r
+            uuidString =  deviceId.str();\r
+        }\r
+\r
         void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)\r
         {\r
             if (hasError)\r
             {\r
                 OC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in OwnershipTransfer");\r
+\r
+                std::shared_ptr< SecProvisioningResult > securityProvisioningStatus = nullptr;\r
+                std::string uuid;\r
+                convertUUIDToString(result->at(0).deviceId, uuid);\r
+                securityProvisioningStatus = std::make_shared< SecProvisioningResult >(uuid,\r
+                        ES_ERROR);\r
+\r
+                m_enrolleeSecStatusCb(securityProvisioningStatus);\r
+                return;\r
             }\r
             else\r
             {\r
                 OC_LOG(DEBUG, ENROLEE_SECURITY_TAG,"Transferred Ownership successfuly for device : ");\r
-                OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",result->at(0).deviceId.id);\r
-\r
-                delete result;\r
+                std::string uuid;\r
+                convertUUIDToString(result->at(0).deviceId, uuid);\r
+                OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",uuid.c_str());\r
 \r
                 //TODO : Decide if we have to manage the owned/unowned devices.\r
                 //pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]);\r
                 //pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);\r
+\r
+                OC_LOG(DEBUG, ENROLEE_SECURITY_TAG,\r
+                        "Ownership transfer success success. Continuing with provisioning ACL");\r
+\r
+                if (provisionAcl() == ES_ERROR)\r
+                {\r
+                    OC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in provisionAcl");\r
+                    std::shared_ptr< SecProvisioningResult > securityProvisioningStatus = nullptr;\r
+                    std::string uuid;\r
+                    convertUUIDToString(result->at(0).deviceId, uuid);\r
+                    securityProvisioningStatus = std::make_shared< SecProvisioningResult >(uuid,\r
+                            ES_ERROR);\r
+                }\r
+\r
+                delete result;\r
             }\r
         }\r
 \r
@@ -111,37 +163,114 @@ namespace OIC
         {\r
             if (hasError)\r
             {\r
-                OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error in provisioning operation!");\r
+                OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionCb : Error in provisioning operation!");\r
             }\r
             else\r
             {\r
-                OC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received provisioning results: ");\r
+                OC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionCb : Received provisioning results: ");\r
                 for (unsigned int i = 0; i < result->size(); i++)\r
                 {\r
-                    OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res); OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",result->at(0).deviceId.id);\r
+                    OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res);\r
+                    std::string uuid;\r
+                    convertUUIDToString(result->at(0).deviceId, uuid);\r
+\r
+                    OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",uuid.c_str());\r
+                    std::shared_ptr< SecProvisioningResult > securityProvisioningStatus = nullptr;\r
+                    securityProvisioningStatus = std::make_shared< SecProvisioningResult >(uuid,\r
+                            ES_OK);\r
+\r
+                    m_enrolleeSecStatusCb(securityProvisioningStatus);\r
+                    return;\r
                 }\r
 \r
                 delete result;\r
             }\r
         }\r
 \r
-        ESResult EnrolleeSecurity::performOwnershipTransfer()\r
+        /**\r
+         * Calculate ACL permission from string to bit\r
+         *\r
+         * @param[in] temp_psm    Input data of ACL permission string\r
+         * @param[in,out] pms    The pointer of ACL permission value\r
+         * @return  0 on success otherwise -1.\r
+         */\r
+        int EnrolleeSecurity::CalculateAclPermission(const char *temp_pms, uint16_t *pms)\r
         {\r
-            ESResult res = ES_ERROR;\r
+            int i = 0;\r
+\r
+            if (NULL == temp_pms || NULL == pms)\r
+            {\r
+                return -1;\r
+            }\r
+            *pms = 0;\r
+            while (temp_pms[i] != '\0')\r
+            {\r
+                switch (temp_pms[i])\r
+                {\r
+                    case 'C':\r
+                        {\r
+                            *pms += CREATE;\r
+                            i++;\r
+                            break;\r
+                        }\r
+                    case 'R':\r
+                        {\r
+                            *pms += READ;\r
+                            i++;\r
+                            break;\r
+                        }\r
+                    case 'U':\r
+                        {\r
+                            *pms += UPDATE;\r
+                            i++;\r
+                            break;\r
+                        }\r
+                    case 'D':\r
+                        {\r
+                            *pms += DELETE;\r
+                            i++;\r
+                            break;\r
+                        }\r
+                    case 'N':\r
+                        {\r
+                            *pms += NOTIFY;\r
+                            i++;\r
+                            break;\r
+                        }\r
+                    case '_':\r
+                        {\r
+                            i++;\r
+                            break;\r
+                        }\r
+                    default:\r
+                        {\r
+                            return -1;\r
+                        }\r
+                }\r
+            }\r
+            return 0;\r
+        }\r
+\r
+        EasySetupState EnrolleeSecurity::performOwnershipTransfer()\r
+        {\r
+            EasySetupState ownershipStatus = DEVICE_NOT_OWNED;\r
 \r
             OC::DeviceList_t pUnownedDevList, pOwnedDevList;\r
 \r
             pOwnedDevList.clear();\r
             pUnownedDevList.clear();\r
 \r
-            OCStackResult result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,\r
+            OCStackResult result;\r
+\r
+            result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,\r
                     pOwnedDevList);\r
             if (result != OC_STACK_OK)\r
             {\r
                 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");\r
-                res = ES_ERROR;\r
-\r
-                return res;\r
+                ownershipStatus = DEVICE_NOT_OWNED;\r
+                //Throw exception\r
+                throw ESPlatformException(result);\r
+                return ownershipStatus;\r
             }\r
             else if (pOwnedDevList.size())\r
             {\r
@@ -149,40 +278,40 @@ namespace OIC
                         pOwnedDevList.size());\r
                 std::shared_ptr< OC::OCSecureResource > ownedDevice =\r
                         findEnrollee(\r
-                                m_remoteEnrolleeResource->m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress,\r
+                                std::string(\r
+                                        m_remoteEnrolleeResource->m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress),\r
                                 pOwnedDevList);\r
-                if(ownedDevice)\r
+                if (ownedDevice)\r
                 {\r
-                    res = ES_OK;\r
+                    ownershipStatus = DEVICE_OWNED;\r
+                    return ownershipStatus;\r
                 }\r
             }\r
             else\r
             {\r
-                OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No Secure devices found.");\r
-                res = ES_ERROR;\r
-\r
-                return res;\r
+                OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No owned devices found.");\r
+                ownershipStatus = DEVICE_NOT_OWNED;\r
             }\r
 \r
-            result = OCSecure::discoverUnownedDevices(ES_SEC_DISCOVERY_TIMEOUT,\r
-                    pUnownedDevList);\r
+            result = OCSecure::discoverUnownedDevices(ES_SEC_DISCOVERY_TIMEOUT, pUnownedDevList);\r
             if (result != OC_STACK_OK)\r
             {\r
                 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "UnOwned Discovery failed.");\r
-                res = ES_ERROR;\r
-\r
-                return res;\r
+                ownershipStatus = DEVICE_NOT_OWNED;\r
+                //Throw exception\r
+                throw ESPlatformException(result);\r
+                return ownershipStatus;\r
             }\r
             else if (pUnownedDevList.size())\r
             {\r
                 OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found Unowned devices. Count =%d",\r
                         pUnownedDevList.size());\r
 \r
-                std::shared_ptr< OC::OCSecureResource > unownedDevice =\r
+                m_unownedDevice =\r
                         findEnrollee(\r
                                 m_remoteEnrolleeResource->m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress,\r
                                 pUnownedDevList);\r
-                if (unownedDevice)\r
+                if (m_unownedDevice)\r
                 {\r
                     OTMCallbackData_t justWorksCBData;\r
                     justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;\r
@@ -193,60 +322,100 @@ namespace OIC
                     OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);\r
 \r
                     OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",\r
-                            unownedDevice->getDeviceID().c_str());\r
+                            m_unownedDevice->getDeviceID().c_str());\r
 \r
                     OC::ResultCallBack ownershipTransferCb = std::bind(\r
                             &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,\r
                             std::placeholders::_2);\r
 \r
-                    if (unownedDevice->doOwnershipTransfer(ownershipTransferCb) != OC_STACK_OK)\r
+                    if (m_unownedDevice->doOwnershipTransfer(ownershipTransferCb) != OC_STACK_OK)\r
                     {\r
                         OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransferCallback is failed");\r
-                        res = ES_ERROR;\r
-                    }\r
-                    else\r
-                    {\r
-                        if(provisionCreds() == ES_OK)\r
-                        {\r
-                            OC_LOG(DEBUG, ENROLEE_SECURITY_TAG,\r
-                                    "provisionCreds success. Continuing with provisioning ACL");\r
-\r
-                            if (provisionAcl() == ES_OK)\r
-                            {\r
-                                OC_LOG(DEBUG, ENROLEE_SECURITY_TAG,\r
-                                        "provisionAcl success.");\r
-\r
-                                //returning success;\r
-                                res = ES_OK;\r
-                            }\r
-                            else\r
-                            {\r
-                                OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionAcl failed.");\r
-                                res = ES_ERROR;\r
-                            }\r
-                        }\r
-                        else\r
-                        {\r
-                            OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionCreds failed.");\r
-                            res = ES_ERROR;\r
-                        }\r
+                        ownershipStatus = DEVICE_NOT_OWNED;\r
+                        //Throw exception\r
+                        throw ESPlatformException(result);\r
                     }\r
+                    ownershipStatus = DEVICE_NOT_OWNED;\r
                 }\r
             }\r
             else\r
             {\r
-                OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No Secure devices found.");\r
-                res = ES_ERROR;\r
+                OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No unSecure devices found.");\r
+                ownershipStatus = DEVICE_NOT_OWNED;\r
+\r
+                return ownershipStatus;\r
+            }\r
+\r
+            return ownershipStatus;\r
+        }\r
+\r
+        ESResult EnrolleeSecurity::createProvisiongResourceACL(OicSecAcl_t *acl)\r
+        {\r
+            //TODO : Have to accept subject id of the mediator from application during easysetup\r
+            // initialization.\r
+            char temp_id[UUID_LENGTH+1] = {"admindeviceUUID0"};\r
+            for (int i = 0, j = 0; temp_id[i] != '\0'; i++)\r
+            {\r
+                acl->subject.id[j++] = temp_id[i];\r
+            }\r
+\r
+            //Always resource length is 1. /oic/prov is the only resource for which needs ACL\r
+            // permission has to be set\r
+            acl->resourcesLen = 1;\r
+            acl->resources = (char **) OICCalloc(acl->resourcesLen, sizeof(char *));\r
+            if (NULL == acl->resources)\r
+            {\r
+                OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while memory allocation");\r
+                return ES_ERROR;\r
+            }\r
+\r
+            char temp_rsc[MAX_URI_LENGTH] = {OC_RSRVD_ES_URI_PROV};\r
+\r
+            for (size_t i = 0; i < acl->resourcesLen; i++)\r
+            {\r
+                acl->resources[i] = OICStrdup(temp_rsc);\r
+                if (NULL == acl->resources[i])\r
+                {\r
+                    OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while memory allocation");\r
+                    return ES_ERROR;\r
+                }\r
+            }\r
+            // Set Permission\r
+            char temp_pms[MAX_PERMISSION_LENGTH+1]={"CRUDN"};\r
+            int ret;\r
+            do\r
+            {\r
+                ret = CalculateAclPermission(temp_pms, &(acl->permission));\r
+            } while (0 != ret);\r
 \r
-                return res;\r
+            //TODO : Have to accept subject id of the mediator from application during easysetup\r
+            // initialization.\r
+            for (int i = 0, j = 0; temp_id[i] != '\0'; i++)\r
+            {\r
+                acl->subject.id[j++] = temp_id[i];\r
             }\r
 \r
-            return res;\r
+            // Set Rowner\r
+            acl->ownersLen = 1;//Always resource owner is only one, which is the mediator\r
+            acl->owners = (OicUuid_t *) OICCalloc(acl->ownersLen, sizeof(OicUuid_t));\r
+            if (NULL == acl->owners)\r
+            {\r
+                OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while memory allocation");\r
+                return ES_ERROR;\r
+            }\r
+            for (size_t i = 0; i < acl->ownersLen; i++)\r
+            {\r
+                for (int k = 0, j = 0; temp_id[k] != '\0'; k++)\r
+                {\r
+                    acl->owners[i].id[j++] = temp_id[k];\r
+                }\r
+            }\r
+            return ES_OK;\r
         }\r
 \r
         ESResult EnrolleeSecurity::provisionAcl()\r
         {\r
-            // TODO : Currently device id is hardcoded, but this id has to be obtained from the\r
+            // TODO : Currently device uuid is hardcoded, but this id has to be obtained from the\r
             // application\r
             OicSecAcl_t *acl = nullptr;\r
 \r
@@ -257,50 +426,21 @@ namespace OIC
                 return ES_ERROR;\r
             }\r
 \r
-//            std::cout << "Please input ACL for selected device: " << std::endl;\r
-//            if (0 != InputACL(acl1))\r
-//            {\r
-//                break;\r
-//            }\r
+            if ( createProvisiongResourceACL (acl) == ES_ERROR)\r
+            {\r
+               return ES_ERROR;\r
+            }\r
+\r
 \r
             OC::ResultCallBack provisioningCb = std::bind(&EnrolleeSecurity::provisionCb, this,\r
-                    std::placeholders::_1, std::placeholders::_2);\r
+            std::placeholders::_1, std::placeholders::_2);\r
 \r
-            if (m_securedResource->provisionACL(acl, provisioningCb) != OC_STACK_OK)\r
+            if (m_unownedDevice->provisionACL(acl, provisioningCb) != OC_STACK_OK)\r
             {\r
                 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionACL is failed");\r
+                return ES_ERROR;\r
             }\r
-            return ES_ERROR;\r
-        }\r
-\r
-        ESResult EnrolleeSecurity::provisionCreds()\r
-        {\r
-//            int devices[2];\r
-//\r
-//            if (0 != readDeviceNumber(pOwnedDevList, 2, devices))\r
-//                break;\r
-//\r
-//            int first = devices[0];\r
-//            int second = devices[1];\r
-//\r
-//            std::cout << "Provision Credentials to devices: "\r
-//                    << pOwnedDevList[first]->getDeviceID();\r
-//            std::cout << " and " << pOwnedDevList[second]->getDeviceID() << std::endl;\r
-//\r
-//            Credential cred(NO_SECURITY_MODE, 0);\r
-//            std::cout << "Please input credentials for selected devices: " << std::endl;\r
-//            if (0 != InputCredentials(cred))\r
-//                break;\r
-//\r
-//            ask = 0;\r
-//\r
-//            if (pOwnedDevList[first]->provisionCredentials(cred, *pOwnedDevList[second].get(),\r
-//                    provisionCB) != OC_STACK_OK)\r
-//            {\r
-//                ask = 1;\r
-//                std::cout << "provisionCredentials is failed" << std::endl;\r
-//            }\r
-            return ES_ERROR;\r
+            return ES_OK;\r
         }\r
     }\r
 }\r
index 8adb9d5..2fba49e 100755 (executable)
@@ -30,7 +30,7 @@ namespace OIC
 {\r
     namespace Service\r
     {\r
-        #define ENROLEE_SECURITY_TAG "ENROLEE_SECURITY"\r
+#define ENROLEE_SECURITY_TAG "ENROLEE_SECURITY"\r
 \r
         class RemoteEnrolleeResource;\r
         class OCSecureResource;\r
@@ -44,31 +44,33 @@ namespace OIC
         {\r
         public:\r
             EnrolleeSecurity(std::shared_ptr< RemoteEnrolleeResource > remoteEnrolleeResource,\r
-                    std::string secDbPath);\r
+            std::string secDbPath);\r
 \r
             ESResult registerCallbackHandler(EnrolleeSecStatusCb enrolleeSecStatusCb,\r
                     SecurityPinCb securityPinCb, SecProvisioningDbPathCb secProvisioningDbPathCb);\r
 \r
-\r
-            ESResult performOwnershipTransfer();\r
+            EasySetupState performOwnershipTransfer();\r
 \r
             ESResult provisionCreds();\r
 \r
             ESResult provisionAcl();\r
 \r
         private:\r
-            std::shared_ptr < RemoteEnrolleeResource > m_remoteEnrolleeResource;\r
+            std::shared_ptr< RemoteEnrolleeResource > m_remoteEnrolleeResource;\r
             EnrolleeSecStatusCb m_enrolleeSecStatusCb;\r
             SecurityPinCb m_securityPinCb;\r
             SecProvisioningDbPathCb m_secProvisioningDbPathCb;\r
+            std::shared_ptr< OC::OCSecureResource > m_unownedDevice;\r
 \r
-            EnrolleeSecState m_enrolleeSecState;\r
-            std::shared_ptr < OC::OCSecureResource > m_securedResource;\r
+            EnrolleeSecState m_enrolleeSecState;std::shared_ptr< OC::OCSecureResource > m_securedResource;\r
 \r
             std::shared_ptr< OC::OCSecureResource > findEnrollee(std::string host,\r
                     OC::DeviceList_t &list);\r
             void provisionCb(OC::PMResultList_t *result, int hasError);\r
             void ownershipTransferCb(OC::PMResultList_t *result, int hasError);\r
+            void convertUUIDToString(OicUuid_t uuid, std::string& uuidString);\r
+            ESResult createProvisiongResourceACL(OicSecAcl_t *acl);\r
+            int CalculateAclPermission(const char *temp_pms, uint16_t *pms);\r
         };\r
     }\r
 }\r
index 4365a93..3ef1f94 100755 (executable)
@@ -42,8 +42,7 @@ namespace OIC
         }\r
 \r
 #ifdef __WITH_DTLS__\r
-        ESResult RemoteEnrollee::registerSecurityCallbackHandler(\r
-                EnrolleeSecStatusCb enrolleeSecStatusCb, SecurityPinCb securityPinCb,\r
+        ESResult RemoteEnrollee::registerSecurityCallbackHandler(SecurityPinCb securityPinCb,\r
                 SecProvisioningDbPathCb secProvisioningDbPathCb)\r
         {\r
             // No need to check NULL for m_secProvisioningDbPathCB as this is not a mandatory\r
@@ -52,7 +51,6 @@ namespace OIC
             // If PDM.db is found, the provisioning manager operations will succeed.\r
             // Otherwise all the provisioning manager operations will fail.\r
             m_secProvisioningDbPathCb = secProvisioningDbPathCb;\r
-            m_enrolleeSecStatusCb = enrolleeSecStatusCb;\r
             m_securityPinCb = securityPinCb;\r
             return ES_OK;\r
         }\r
@@ -75,8 +73,48 @@ namespace OIC
                 m_easySetupStatusCb = callback;\r
 \r
                 m_remoteResource = std::make_shared< RemoteEnrolleeResource >(m_enrolleeNWProvInfo);\r
+            }\r
+        }\r
+\r
+        void RemoteEnrollee::easySetupSecurityStatusCallback(\r
+                        std::shared_ptr< SecProvisioningResult > secProvisioningResult)\r
+        {\r
+            OC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "easySetupStatusCallback status is, UUID = %s, "\r
+                    "Status = %d", secProvisioningResult->getDeviceUUID().c_str(),\r
+                    secProvisioningResult->getResult());\r
+\r
+            if(secProvisioningResult->getResult() == ES_OK)\r
+            {\r
+                OC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are successful. "\r
+                        "Continue with Network information provisioning");\r
+\r
+                m_currentESState = CurrentESState::ES_OWNED;\r
 \r
-                m_remoteResource->constructResourceObject();\r
+                OC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");\r
+\r
+                RemoteEnrolleeResource::ProvStatusCb provStatusCb = std::bind(\r
+                        &RemoteEnrollee::provisioningStatusHandler, this, std::placeholders::_1);\r
+\r
+                m_remoteResource->registerProvStatusCallback(provStatusCb);\r
+                m_remoteResource->provisionEnrollee();\r
+            }\r
+            else\r
+            {\r
+                OC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are successful");\r
+                std::shared_ptr< EasySetupStatus > easySetupStatus = nullptr;\r
+                easySetupStatus = std::make_shared< EasySetupStatus >(DEVICE_NOT_PROVISIONED,\r
+                                            m_enrolleeNWProvInfo);\r
+                if (m_easySetupStatusCb)\r
+                {\r
+                    if (easySetupStatus)\r
+                    {\r
+                        m_easySetupStatusCb(easySetupStatus);\r
+                    }\r
+                    else\r
+                    {\r
+                        m_easySetupStatusCb(nullptr);\r
+                    }\r
+                }\r
             }\r
         }\r
 \r
@@ -163,38 +201,74 @@ namespace OIC
             {\r
                 throw ESBadRequestException ("Device not created");\r
             }\r
-            else\r
+\r
+            ESResult result = ES_ERROR;\r
+\r
+            result = m_remoteResource->constructResourceObject();\r
+\r
+            if (result == ES_ERROR)\r
             {\r
-                m_currentESState = CurrentESState::ES_ONBOARDED;\r
+                OC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,\r
+                                    "Failed to create device using constructResourceObject");\r
+                throw ESBadRequestException ("Device not created");\r
+            }\r
+\r
+            m_currentESState = CurrentESState::ES_ONBOARDED;\r
 \r
 #ifdef __WITH_DTLS__\r
-                if (m_needSecuredEasysetup && m_currentESState < CurrentESState::ES_OWNED)\r
-                {\r
-                    //TODO : DBPath is passed empty as of now. Need to take dbpath from application.\r
-                    m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_remoteResource, "");\r
+            if (m_needSecuredEasysetup && m_currentESState < CurrentESState::ES_OWNED)\r
+            {\r
+                EnrolleeSecStatusCb securityProvStatusCb = std::bind(\r
+                        &RemoteEnrollee::easySetupSecurityStatusCallback,\r
+                        this,\r
+                        std::placeholders::_1);\r
+                //TODO : DBPath is passed empty as of now. Need to take dbpath from application.\r
+                m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_remoteResource, "");\r
 \r
-                    m_enrolleeSecurity->registerCallbackHandler(m_enrolleeSecStatusCb,\r
-                            m_securityPinCb, m_secProvisioningDbPathCb);\r
+                m_enrolleeSecurity->registerCallbackHandler(securityProvStatusCb,\r
+                        m_securityPinCb, m_secProvisioningDbPathCb);\r
 \r
-                    if (m_enrolleeSecurity->performOwnershipTransfer() == ES_ERROR)\r
+                try\r
+                {\r
+                    EasySetupState easySetupState = m_enrolleeSecurity->performOwnershipTransfer();\r
+                    if (easySetupState == DEVICE_NOT_OWNED)\r
                     {\r
-                        std::shared_ptr< EasySetupStatus > easySetupStatus = nullptr;\r
-\r
-                        easySetupStatus = std::make_shared < EasySetupStatus\r
-                        > (DEVICE_NOT_OWNED, m_enrolleeNWProvInfo);\r
+                        OC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG,\r
+                                "performOwnershipTransfer returned : %d",\r
+                                easySetupState);\r
                         return;\r
                     }\r
-                }\r
-#endif\r
-\r
-                OC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");\r
+                    else if (easySetupState == DEVICE_OWNED)\r
+                    {\r
+                        OC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG,\r
+                                "performOwnershipTransfer returned : %d",\r
+                                easySetupState);\r
+                        OC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");\r
 \r
-                RemoteEnrolleeResource::ProvStatusCb provStatusCb = std::bind(\r
-                        &RemoteEnrollee::provisioningStatusHandler, this, std::placeholders::_1);\r
+                        RemoteEnrolleeResource::ProvStatusCb provStatusCb = std::bind(\r
+                                &RemoteEnrollee::provisioningStatusHandler,\r
+                                this, std::placeholders::_1);\r
 \r
-                m_remoteResource->registerProvStatusCallback(provStatusCb);\r
-                m_remoteResource->provisionEnrollee();\r
+                        m_remoteResource->registerProvStatusCallback(provStatusCb);\r
+                        m_remoteResource->provisionEnrollee();\r
+                    }\r
+                }\r
+                catch (OCException & e)\r
+                {\r
+                    OC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,\r
+                            "Exception for performOwnershipTransfer : %s", e.reason().c_str());\r
+                    return ;\r
+                }\r
             }\r
+#else\r
+            OC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");\r
+\r
+            RemoteEnrolleeResource::ProvStatusCb provStatusCb = std::bind(\r
+                    &RemoteEnrollee::provisioningStatusHandler, this, std::placeholders::_1);\r
+\r
+            m_remoteResource->registerProvStatusCallback(provStatusCb);\r
+            m_remoteResource->provisionEnrollee();\r
+#endif\r
         }\r
 \r
         void RemoteEnrollee::stopProvisioning()\r
index 7fc4180..a4118aa 100755 (executable)
@@ -19,6 +19,7 @@
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
 \r
 #include <functional>\r
+#include <time.h>\r
 \r
 #include "RemoteEnrolleeResource.h"\r
 \r
@@ -31,25 +32,29 @@ namespace OIC
 {\r
     namespace Service\r
     {\r
-        #define ES_REMOTE_ENROLLEE_TAG "ES_REMOTE_ENROLLEE"\r
-        static const char ES_PROV_RES_URI[]  = "/oic/prov";\r
+        #define ES_REMOTE_ENROLLEE_RES_TAG "ES_REMOTE_ENROLLEE_RES"\r
+        #define DISCOVERY_TIMEOUT 5\r
+\r
+        static const char ES_BASE_RES_URI[] = "/oic/res";\r
+        static const char ES_PROV_RES_URI[] = "/oic/prov";\r
         static const char ES_PROV_RES_TYPE[] = "oic.r.prov";\r
 \r
         RemoteEnrolleeResource::RemoteEnrolleeResource(EnrolleeNWProvInfo enrolleeNWProvInfo)\r
         {\r
             m_enrolleeNWProvInfo = enrolleeNWProvInfo;\r
+            m_discoveryResponse = false;\r
         }\r
 \r
         void RemoteEnrolleeResource::checkProvInformationCb(const HeaderOptions& /*headerOptions*/,\r
                 const OCRepresentation& rep, const int eCode)\r
         {\r
-            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "checkProvInformationCb : %s, eCode = %d",\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "checkProvInformationCb : %s, eCode = %d",\r
                     rep.getUri().c_str(),\r
                     eCode);\r
 \r
-            if(eCode != 0)\r
+            if (eCode != 0)\r
             {\r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
                         "checkProvInformationCb : Provisioning is failed ");\r
                 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<\r
                         ProvisioningStatus >(ESResult::ES_ERROR, ESState::ES_PROVISIONING_ERROR);\r
@@ -65,28 +70,30 @@ namespace OIC
             rep.getValue(OC_RSRVD_ES_TNN, tnn);\r
             rep.getValue(OC_RSRVD_ES_CD, cd);\r
 \r
-            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "checkProvInformationCb : ps - %d", ps);\r
-            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "checkProvInformationCb : tnn - %s", tnn.c_str());\r
-            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "checkProvInformationCb : cd - %s", cd.c_str());\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "checkProvInformationCb : ps - %d", ps);\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
+                    "checkProvInformationCb : tnn - %s", tnn.c_str());\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
+                    "checkProvInformationCb : cd - %s", cd.c_str());\r
 \r
             //Provisioning status check\r
             if (ps == ES_PS_PROVISIONING_COMPLETED)\r
             {\r
-                if(tnn != std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.ssid))\r
+                if (tnn != std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.ssid))\r
                 {\r
-                    OC_LOG_V (ERROR, ES_REMOTE_ENROLLEE_TAG,\r
+                    OC_LOG_V (ERROR, ES_REMOTE_ENROLLEE_RES_TAG,\r
                             "checkProvInformationCb : Network SSID is not the same as the "\r
                             "SSID provisioned");\r
                     std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<\r
                             ProvisioningStatus >(ESResult::ES_ERROR,\r
                             ESState::ES_PROVISIONING_ERROR);\r
-                            m_provStatusCb(provStatus);\r
+                    m_provStatusCb(provStatus);\r
                     return;\r
                 }\r
 \r
-                if(cd != std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.pwd))\r
+                if (cd != std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.pwd))\r
                 {\r
-                    OC_LOG_V (ERROR, ES_REMOTE_ENROLLEE_TAG,\r
+                    OC_LOG_V (ERROR, ES_REMOTE_ENROLLEE_RES_TAG,\r
                             "checkProvInformationCb : Network PWD is not the same as the "\r
                             "PWD provisioned");\r
                     std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<\r
@@ -96,7 +103,7 @@ namespace OIC
                     return;\r
                 }\r
 \r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
                         "checkProvInformationCb : Provisioning is success ");\r
                 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<\r
                         ProvisioningStatus >(ESResult::ES_OK, ESState::ES_PROVISIONING_SUCCESS);\r
@@ -105,7 +112,7 @@ namespace OIC
             }\r
             else\r
             {\r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
                         "checkProvInformationCb : Provisioning is failed ");\r
                 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<\r
                         ProvisioningStatus >(ESResult::ES_ERROR, ESState::ES_PROVISIONING_ERROR);\r
@@ -115,17 +122,16 @@ namespace OIC
         }\r
 \r
         void RemoteEnrolleeResource::getProvStatusResponse(const HeaderOptions& /*headerOptions*/,\r
-                                                    const OCRepresentation& rep,\r
-                                                    const int eCode)\r
+                const OCRepresentation& rep, const int eCode)\r
         {\r
-            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "getProvStatusResponse : %s, eCode = %d",\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : %s, eCode = %d",\r
                     rep.getUri().c_str(),\r
                     eCode);\r
 \r
             if (eCode != 0)\r
             {\r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,\r
-                                            "getProvStatusResponse : Provisioning is failed ");\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
+                        "getProvStatusResponse : Provisioning is failed ");\r
                 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<\r
                         ProvisioningStatus >(ESResult::ES_ERROR, ESState::ES_PROVISIONING_ERROR);\r
                 m_provStatusCb(provStatus);\r
@@ -140,38 +146,38 @@ namespace OIC
             rep.getValue(OC_RSRVD_ES_TNN, tnn);\r
             rep.getValue(OC_RSRVD_ES_CD, cd);\r
 \r
-            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "getProvStatusResponse : ps - %d",\r
-                                ps);\r
-            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "getProvStatusResponse : tnn - %s",\r
-                                            tnn.c_str());\r
-            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "getProvStatusResponse : cd - %s",\r
-                                            cd.c_str());\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : ps - %d",\r
+                    ps);\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : tnn - %s",\r
+                    tnn.c_str());\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : cd - %s",\r
+                    cd.c_str());\r
 \r
             if (ps == ES_PS_NEED_PROVISIONING) //Indicates the need for provisioning\r
             {\r
                 OCRepresentation provisioningRepresentation;\r
 \r
                 provisioningRepresentation.setValue(OC_RSRVD_ES_TNN,\r
-                        std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.ssid));\r
+                std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.ssid));\r
                 provisioningRepresentation.setValue(OC_RSRVD_ES_CD,\r
-                        std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.pwd));\r
+                std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.pwd));\r
 \r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "getProvStatusResponse : ssid - %s",\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : ssid - %s",\r
                         m_enrolleeNWProvInfo.netAddressInfo.WIFI.ssid);\r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "getProvStatusResponse : pwd - %s",\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : pwd - %s",\r
                         m_enrolleeNWProvInfo.netAddressInfo.WIFI.pwd);\r
 \r
                 m_ocResource->put(provisioningRepresentation, QueryParamsMap(),\r
                         std::function<\r
                                 void(const HeaderOptions& headerOptions,\r
                                         const OCRepresentation& rep, const int eCode) >(\r
-                                std::bind(&RemoteEnrolleeResource::checkProvInformationCb, this,\r
-                                        std::placeholders::_1, std::placeholders::_2,\r
-                                        std::placeholders::_3)));\r
+                        std::bind(&RemoteEnrolleeResource::checkProvInformationCb, this,\r
+                        std::placeholders::_1, std::placeholders::_2,\r
+                        std::placeholders::_3)));\r
             }\r
-            else if(ps == ES_PS_PROVISIONING_COMPLETED) //Indicates that provisioning is completed\r
+            else if (ps == ES_PS_PROVISIONING_COMPLETED) //Indicates that provisioning is completed\r
             {\r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
                         "getProvStatusResponse : Provisioning is successful");\r
                 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<\r
                         ProvisioningStatus >(ESResult::ES_OK, ESState::ES_PROVISIONED_ALREADY);\r
@@ -179,35 +185,138 @@ namespace OIC
             }\r
         }\r
 \r
-        void RemoteEnrolleeResource::registerProvStatusCallback (ProvStatusCb provStatusCb)\r
+        void RemoteEnrolleeResource::registerProvStatusCallback(ProvStatusCb provStatusCb)\r
         {\r
             m_provStatusCb = provStatusCb;\r
         }\r
 \r
-        void RemoteEnrolleeResource::constructResourceObject()\r
+        ESResult RemoteEnrolleeResource::ESDiscoveryTimeout(unsigned short waittime)\r
+        {\r
+            struct timespec startTime;\r
+            startTime.tv_sec=0;\r
+            startTime.tv_sec=0;\r
+            struct timespec currTime;\r
+            currTime.tv_sec=0;\r
+            currTime.tv_nsec=0;\r
+\r
+            ESResult res = ES_OK;\r
+            #ifdef _POSIX_MONOTONIC_CLOCK\r
+                int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);\r
+            #else\r
+                int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);\r
+            #endif\r
+\r
+            if (0 != clock_res)\r
+            {\r
+                return ES_ERROR;\r
+            }\r
+\r
+            while (ES_OK == res || m_discoveryResponse == false)\r
+            {\r
+                #ifdef _POSIX_MONOTONIC_CLOCK\r
+                        clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);\r
+                #else\r
+                        clock_res = clock_gettime(CLOCK_REALTIME, &currTime);\r
+                #endif\r
+\r
+                if (0 != clock_res)\r
+                {\r
+                    return ES_ERROR;\r
+                }\r
+                long elapsed = (currTime.tv_sec - startTime.tv_sec);\r
+                if (elapsed > waittime)\r
+                {\r
+                    return ES_OK;\r
+                }\r
+                if (m_discoveryResponse)\r
+                {\r
+                    res = ES_OK;\r
+                }\r
+             }\r
+             return res;\r
+        }\r
+\r
+        void RemoteEnrolleeResource::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)\r
+        {\r
+            OC_LOG (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "onDeviceDiscovered");\r
+\r
+            std::string resourceURI;\r
+            std::string hostAddress;\r
+            try\r
+            {\r
+                if(resource)\r
+                {\r
+                    // Get the resource URI\r
+                    resourceURI = resource->uri();\r
+                    OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
+                            "URI of the resource: %s", resourceURI.c_str());\r
+\r
+                    // Get the resource host address\r
+                    hostAddress = resource->host();\r
+                    OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
+                            "Host address of the resource: %s", hostAddress.c_str());\r
+\r
+                    std::size_t foundIP =\r
+                        hostAddress.find(\r
+                                std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress));\r
+\r
+                    if(resourceURI == ES_PROV_RES_URI && foundIP!=std::string::npos)\r
+                    {\r
+                        m_ocResource = resource;\r
+                        m_discoveryResponse = true;\r
+\r
+                        OC_LOG (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
+                                "Found the device with the resource");\r
+\r
+                        return;\r
+                    }\r
+                    else\r
+                    {\r
+                        OC_LOG (ERROR, ES_REMOTE_ENROLLEE_RES_TAG, "NOT the intended resource.");\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    OC_LOG (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "Resource is invalid");\r
+                }\r
+\r
+            }\r
+            catch(std::exception& e)\r
+            {\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
+                        "Exception in foundResource: %s", e.what());\r
+            }\r
+        }\r
+\r
+\r
+        ESResult RemoteEnrolleeResource::constructResourceObject()\r
         {\r
             if (m_ocResource != nullptr)\r
             {\r
                 throw ESBadRequestException("Remote resource is already created");\r
             }\r
 \r
+#ifdef REMOTE_ARDUINO_ENROLEE\r
+            //This process will create OCResource with port 55555 which is specific\r
+            // to Arduino WiFi enrollee\r
             try\r
             {\r
-
-                std::vector< std::string > m_if = { DEFAULT_INTERFACE };\r
-                std::vector< std::string > m_resTypes = {ES_PROV_RES_TYPE};\r
 \r
+                std::vector< std::string > interface =\r
+                {   DEFAULT_INTERFACE};\r
+                std::vector< std::string > resTypes =\r
+                {   ES_PROV_RES_TYPE};\r
 \r
-                OC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Before OCPlatform::constructResourceObject");\r
+                OC_LOG(DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "Before OCPlatform::constructResourceObject");\r
 \r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "m_host = %s",\r
-                                    m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress);\r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "ES_PROV_RES_URI = %s", ES_PROV_RES_URI);\r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "m_connectivityType = %d",\r
-                                    m_enrolleeNWProvInfo.connType);\r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "m_resTypes = %s",\r
-                                    m_resTypes.at(0).c_str());\r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "m_if = %s", m_if.at(0).c_str());\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "m_host = %s",\r
+                        m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress);\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "ES_PROV_RES_URI = %s", ES_PROV_RES_URI);\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "m_connectivityType = %d",\r
+                        m_enrolleeNWProvInfo.connType);\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "resTypes = %s",\r
+                        resTypes.at(0).c_str());\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "interface = %s", interface.at(0).c_str());\r
 \r
                 std::string host;\r
                 if(m_enrolleeNWProvInfo.needSecuredEasysetup)\r
@@ -232,36 +341,99 @@ namespace OIC
                     host.append(":55555");\r
                 }\r
 \r
-                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "HOST = %s", host.c_str());\r
+                OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "HOST = %s", host.c_str());\r
 \r
                 m_ocResource = OC::OCPlatform::constructResourceObject(host,\r
-                                                                   ES_PROV_RES_URI,\r
-                                                                   m_enrolleeNWProvInfo.connType,\r
-                                                                   true,\r
-                                                                   m_resTypes,\r
-                                                                   m_if);\r
-                OC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG,\r
+                        ES_PROV_RES_URI,\r
+                        m_enrolleeNWProvInfo.connType,\r
+                        true,\r
+                        resTypes,\r
+                        interface);\r
+                OC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,\r
                         "created OCResource : %s", m_ocResource->uri().c_str());\r
+\r
+                return ES_OK;\r
             }\r
             catch (OCException & e)\r
             {\r
-                OC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,\r
+                OC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_RES_TAG,\r
                         "Exception for constructResourceObject : %s", e.reason().c_str());\r
             }\r
+\r
+#else\r
+            std::string host("");\r
+            std::string query("");\r
+\r
+            if (m_enrolleeNWProvInfo.needSecuredEasysetup)\r
+            {\r
+                host.append("coaps://");\r
+            }\r
+            else\r
+            {\r
+                host.append("coap://");\r
+            }\r
+\r
+            if (m_enrolleeNWProvInfo.connType == CT_ADAPTER_IP)\r
+            {\r
+                // TODO : RemoteEnrollee is current handling easysetup on IP transport.\r
+                // WiFiRemoteEnrollee need to extend RemoteEnrollee for providing IP specific\r
+                // Enrollee easysetup.\r
+\r
+                host.append(m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress);\r
+            }\r
+\r
+            query.append(ES_BASE_RES_URI);\r
+            query.append("?rt=");\r
+            query.append(ES_PROV_RES_TYPE);\r
+\r
+            OC_LOG(DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "Before OCPlatform::constructResourceObject");\r
+\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "host = %s",\r
+                    host.c_str());\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "query = %s", query.c_str());\r
+            OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "m_connectivityType = %d",\r
+                    m_enrolleeNWProvInfo.connType);\r
+\r
+            m_discoveryResponse = false;\r
+            std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =\r
+                    std::bind(&RemoteEnrolleeResource::onDeviceDiscovered, this,\r
+                                                    std::placeholders::_1);\r
+            OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,\r
+                    onDeviceDiscoveredCb);\r
+\r
+            if (result != OCStackResult::OC_STACK_OK)\r
+            {\r
+                OC_LOG(ERROR,ES_REMOTE_ENROLLEE_RES_TAG,\r
+                        "Failed to create device using constructResourceObject");\r
+                return ES_ERROR;\r
+            }\r
+\r
+\r
+            ESResult foundResponse = ESDiscoveryTimeout (DISCOVERY_TIMEOUT);\r
+\r
+            if (!m_discoveryResponse)\r
+            {\r
+                OC_LOG(ERROR,ES_REMOTE_ENROLLEE_RES_TAG,\r
+                        "Failed to create device using constructResourceObject");\r
+                return ES_ERROR;\r
+            }\r
+\r
+            return ES_OK;\r
+#endif\r
         }\r
 \r
         void RemoteEnrolleeResource::provisionEnrollee()\r
 \r
         {\r
-            if(m_ocResource == nullptr)\r
+            if (m_ocResource == nullptr)\r
             {\r
-                throw ESBadRequestException ("Resource is not initialized");\r
+                throw ESBadRequestException("Resource is not initialized");\r
             }\r
 \r
             OC::QueryParamsMap query;\r
             OC::OCRepresentation rep;\r
 \r
-            std::function <OCStackResult(void)> getProvisioingStatus = [&]\r
+            std::function< OCStackResult(void) > getProvisioingStatus = [&]\r
             {   return m_ocResource->get(m_ocResource->getResourceTypes().at(0),\r
                         m_ocResource->getResourceInterfaces().at(0), query,\r
                         std::function<\r
@@ -299,9 +471,9 @@ namespace OIC
                     std::function<\r
                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,\r
                                     const int eCode) >(\r
-                            std::bind(&RemoteEnrolleeResource::checkProvInformationCb, this,\r
-                                    std::placeholders::_1, std::placeholders::_2,\r
-                                    std::placeholders::_3)));\r
+                    std::bind(&RemoteEnrolleeResource::checkProvInformationCb, this,\r
+                    std::placeholders::_1, std::placeholders::_2,\r
+                    std::placeholders::_3)));\r
         }\r
     }\r
 }\r
index 8e41c28..69a4f65 100755 (executable)
@@ -83,7 +83,7 @@ namespace OIC
              *\r
              * @see ProvisioningStatus\r
              */\r
-            void constructResourceObject();\r
+            ESResult constructResourceObject();\r
 \r
             /**\r
              * Function for provisioning of Remote Enrollee resource using the information provided.\r
@@ -106,12 +106,17 @@ namespace OIC
             std::mutex m_mutex;\r
             ProvStatusCb m_provStatusCb;\r
             EnrolleeNWProvInfo m_enrolleeNWProvInfo;\r
+            bool m_discoveryResponse;\r
 \r
             void getProvStatusResponse(const HeaderOptions& headerOptions, const OCRepresentation& rep,\r
                     const int eCode);\r
 \r
             void checkProvInformationCb(const HeaderOptions& headerOptions, const OCRepresentation& rep,\r
                     const int eCode);\r
+\r
+            ESResult ESDiscoveryTimeout(unsigned short waittime);\r
+\r
+            void onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource);\r
         };\r
     }\r
 }\r