EasySetup:Applied "href" and "rep" to POST request
authorAbhishek Pandey <abhi.siso@samsung.com>
Thu, 14 Sep 2017 16:35:07 +0000 (22:05 +0530)
committerAbhishek Pandey <abhi.siso@samsung.com>
Fri, 15 Sep 2017 04:28:12 +0000 (09:58 +0530)
IOT-2713: https://jira.iotivity.org/browse/IOT-2713

- Applied "href" and "rep" to POST request using oic.if.b (batch interface).
- Updated the handling for provision wifi & cloud properties
- Verified Enrollee & Mediator on Linux with sample apps.
- Linux Unit tests verified locally.
- Also fixed on build warning in easysetup_x.c (sample app).

Change-Id: I5e5d7c495d45dd8eb41ca5bcce2af8e18fd53c71
Signed-off-by: Abhishek Pandey <abhi.siso@samsung.com>
service/easy-setup/enrollee/src/resourcehandler.c
service/easy-setup/mediator/richsdk/inc/ESRichCommon.h
service/easy-setup/mediator/richsdk/src/CloudResource.cpp
service/easy-setup/mediator/richsdk/src/CloudResource.h
service/easy-setup/mediator/richsdk/src/EnrolleeResource.cpp
service/easy-setup/mediator/richsdk/src/RemoteEnrollee.cpp
service/easy-setup/sampleapp/enrollee/linux/easysetup_x.c

index 6490462..9cfe46a 100644 (file)
@@ -53,6 +53,7 @@ OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest, OCRep
 OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest, OCRepPayload** payload);
 OCEntityHandlerResult ProcessPostRequest(OCEntityHandlerRequest *ehRequest, OCRepPayload** payload);
 void updateEasySetupResource(OCEntityHandlerRequest* ehRequest, OCRepPayload* input);
+void updateEasySetupConnectProperty(OCRepPayload* input);
 void updateWiFiConfResource(OCRepPayload* input);
 void updateCoapCloudConfResource(OCRepPayload* input);
 void updateDevConfResource(OCRepPayload* input);
@@ -341,6 +342,64 @@ void updateEasySetupResource(OCEntityHandlerRequest* ehRequest, OCRepPayload* in
 {
     OIC_LOG_V(DEBUG, ES_RH_TAG, "g_ESEasySetupResource.status %d", g_ESEasySetupResource.status);
 
+    // Below call is to allow cn update without 'rep' property.
+    // Can remove if no longer needed to support this way.
+    updateEasySetupConnectProperty(input);
+
+    if (ehRequest->query)
+    {
+        if (CompareResourceInterface(ehRequest->query, OC_RSRVD_INTERFACE_BATCH))
+        {
+            // When Provisioning resource has a POST with BatchInterface
+            // Parsing POST request on Batch Interface cosidering same format as GET using batch.
+            OCRepPayload *children = input;
+
+            while(children)
+            {
+                char* href = NULL;
+                OCRepPayloadGetPropString(children, OC_RSRVD_HREF, &href);
+                OIC_LOG_V(DEBUG, ES_RH_TAG, "href [%s]", href);
+                ///TODO: Check why href value is null even though available in payload
+
+                OCRepPayload *repPayload = NULL;
+                OCRepPayloadGetPropObject(children, OC_RSRVD_REPRESENTATION, &repPayload);
+
+                char* uri = children->uri;
+                OIC_LOG_V(DEBUG, ES_RH_TAG, "uri [%s]", uri);
+
+                if(NULL == uri || NULL == repPayload)
+                {
+                    children = children->next;
+                    continue;
+                }
+
+                if (0 == strcmp(uri, OC_RSRVD_ES_URI_EASYSETUP))
+                {
+                    updateEasySetupConnectProperty(repPayload);
+                }
+                else if (0 == strcmp(uri, OC_RSRVD_ES_URI_WIFICONF))
+                {
+                    updateWiFiConfResource(repPayload);
+                }
+                else if (0 == strcmp(uri, OC_RSRVD_ES_URI_COAPCLOUDCONF))
+                {
+                    updateCoapCloudConfResource(repPayload);
+                }
+                else if (0 == strcmp(uri, OC_RSRVD_ES_URI_DEVCONF))
+                {
+                    updateDevConfResource(repPayload);
+                }
+
+                children = children->next;
+                OCRepPayloadDestroy(repPayload);
+                OICFree(href);
+             }
+        }
+    }
+}
+
+void updateEasySetupConnectProperty(OCRepPayload* input)
+{
     int64_t *connect_req = NULL;
     size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
     if (OCRepPayloadGetIntArray(input, OC_RSRVD_ES_CONNECT, &connect_req, dimensions))
@@ -386,17 +445,6 @@ void updateEasySetupResource(OCEntityHandlerRequest* ehRequest, OCRepPayload* in
             }
         }
     }
-
-    if (ehRequest->query)
-    {
-        if (CompareResourceInterface(ehRequest->query, OC_RSRVD_INTERFACE_BATCH))
-        {
-            // When Provisioning resource has a POST with BatchInterface
-            updateCoapCloudConfResource(input);
-            updateWiFiConfResource(input);
-            updateDevConfResource(input);
-        }
-    }
 }
 
 void updateWiFiConfResource(OCRepPayload* input)
@@ -1296,7 +1344,6 @@ OCStackResult CreateEasySetupResources(bool isSecured, ESResourceMask resourceMa
             OIC_LOG_V(ERROR, ES_RH_TAG, "Bind WiFiConfResource result: %s", getResult(res));
             return res;
         }
-
     }
 
     if ((resourceMask & ES_COAPCLOUDCONF_RESOURCE) == ES_COAPCLOUDCONF_RESOURCE)
@@ -1595,6 +1642,7 @@ OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest * ehRequest,
 
     return ehResult;
 }
+
 /**
  * This is the entity handler for the registered resource.
  * This is invoked by OCStack whenever it recevies a request for this resource.
index 3604c62..da464ce 100644 (file)
@@ -45,6 +45,8 @@ using namespace OC;
 using namespace std;
 
 #define ES_RICH_COMMON_TAG "ES_MEDIATOR_COMMON"
+#define OCF_CONTENT_FORMAT_VERSION_OPTION_ID 2053
+#define OCF_CONTENT_FORMAT_VERSION_VALUE 2048
 
 #ifndef WITH_ARDUINO
 namespace OIC
@@ -316,6 +318,57 @@ namespace OIC
             {
                 return m_rep;
             }
+
+            /**
+             * Update Cloud property representation as per OCF Specification.
+             *
+             * Resource Schema for CloudConf resource is different in older Enrollee following
+             * OIC Spec compared to newer Enrollee following OCF Spec. This function updates
+             * the representation as per spec version.
+             */
+            void updateOCRepresentation(int specVersion)
+            {
+                if(0 == specVersion) // OIC Server does not contain CONTENT FORMAT VERSION
+                {
+                    // Representation is already stored as per older resource schemas.
+                    return;
+                }
+
+                // Representation should be updated as per OCF 1.3 Easy Setup resource schemas.
+                std::string authCode = m_rep.getValue<std::string>(OC_RSRVD_ES_AUTHCODE);
+                std::string authProvider = m_rep.getValue<std::string>(OC_RSRVD_ES_AUTHPROVIDER);
+                std::string ciServer = m_rep.getValue<std::string>(OC_RSRVD_ES_CISERVER);
+
+                std::string accessToken = m_rep.getValue<std::string>(OC_RSRVD_ES_ACCESSTOKEN);
+                OAUTH_TOKENTYPE accessTokenType = static_cast<OAUTH_TOKENTYPE>(
+                                m_rep.getValue<int>(OC_RSRVD_ES_ACCESSTOKEN_TYPE));
+
+                OCRepresentation rootRep;
+                rootRep.setUri(OC_RSRVD_ES_URI_EASYSETUP);
+
+                OCRepresentation cloudDataRep;
+
+                if(authCode.length() > 0)
+                    cloudDataRep.setValue(OC_RSRVD_ES_AUTHCODE, authCode);
+
+                if(accessToken.length() > 0)
+                {
+                    cloudDataRep.setValue(OC_RSRVD_ES_ACCESSTOKEN, accessToken);
+                    cloudDataRep.setValue(OC_RSRVD_ES_ACCESSTOKEN_TYPE, accessTokenType);
+                }
+
+                cloudDataRep.setValue(OC_RSRVD_ES_AUTHPROVIDER, authProvider);
+                cloudDataRep.setValue(OC_RSRVD_ES_CISERVER, ciServer);
+
+                OCRepresentation cloudconfRep;
+                cloudconfRep.setUri(OC_RSRVD_ES_URI_COAPCLOUDCONF);
+                cloudconfRep.setValue(OC_RSRVD_HREF, std::string(OC_RSRVD_ES_URI_COAPCLOUDCONF));
+                cloudconfRep.setValue(OC_RSRVD_REPRESENTATION, cloudDataRep);
+
+                rootRep.addChild(cloudconfRep);
+                m_rep = rootRep;
+            }
+
         protected:
             OCRepresentation m_rep;
             std::string m_cloudID;
@@ -448,13 +501,11 @@ namespace OIC
             }
 
             /**
-             * Get OCRepresentation object
+             * Update Device and Wi-Fi representation as per OCF Specification.
              *
              * Resource Schema for WiFiConf resource is different in older Enrollee following
              * OIC Spec compared to newer Enrollee following OCF Spec. This function updates
              * the representation as per spec version.
-             *
-             * Update representation as per OCF Specification.
              */
             void updateOCRepresentation(int specVersion)
             {
@@ -468,8 +519,22 @@ namespace OIC
                 WIFI_AUTHTYPE authtype = static_cast<WIFI_AUTHTYPE> (m_rep.getValue<int>(OC_RSRVD_ES_AUTHTYPE));
                 WIFI_ENCTYPE enctype = static_cast<WIFI_ENCTYPE> (m_rep.getValue<int>(OC_RSRVD_ES_ENCTYPE));
 
-                m_rep.setValue(OC_RSRVD_ES_AUTHTYPE, getAuthTypeAsString(authtype));
-                m_rep.setValue(OC_RSRVD_ES_ENCTYPE, getEncTypeAsString(enctype));
+                OCRepresentation rootRep;
+                rootRep.setUri(OC_RSRVD_ES_URI_EASYSETUP);
+
+                OCRepresentation wifiDataRep;
+                wifiDataRep.setValue(OC_RSRVD_ES_SSID, m_rep.getValue<std::string>(OC_RSRVD_ES_SSID));
+                wifiDataRep.setValue(OC_RSRVD_ES_CRED, m_rep.getValue<std::string>(OC_RSRVD_ES_CRED));
+                wifiDataRep.setValue(OC_RSRVD_ES_AUTHTYPE, getAuthTypeAsString(authtype));
+                wifiDataRep.setValue(OC_RSRVD_ES_ENCTYPE, getEncTypeAsString(enctype));
+
+                OCRepresentation wificonfRep;
+                wificonfRep.setUri(OC_RSRVD_ES_URI_WIFICONF);
+                wificonfRep.setValue(OC_RSRVD_HREF, std::string(OC_RSRVD_ES_URI_WIFICONF));
+                wificonfRep.setValue(OC_RSRVD_REPRESENTATION, wifiDataRep);
+
+                rootRep.addChild(wificonfRep);
+                m_rep = rootRep;
             }
 
         protected:
index 70b99cc..4ee377c 100644 (file)
@@ -54,12 +54,59 @@ namespace OIC
             }
         }
 
+        int CloudResource::GetOCFServerVersion()
+        {
+            OIC_LOG (DEBUG, ES_CLOUD_RES_TAG, "GetOCFServerVersion IN");
+
+            HeaderOptions headerOptions = m_ocResource->getServerHeaderOptions();
+            if (headerOptions.size() == 0)
+            {
+                OIC_LOG (ERROR, ES_CLOUD_RES_TAG, "No header option exists");
+            }
+            else
+            {
+                for (auto it = headerOptions.begin(); it != headerOptions.end(); ++it)
+                {
+                   if (it->getOptionID() == OCF_CONTENT_FORMAT_VERSION_OPTION_ID) // OPTION_CONTENT_VERSION
+                   {
+                        size_t dataLength = it->getOptionData().length();
+                        if (dataLength == 0)
+                        {
+                            OIC_LOG (ERROR, ES_CLOUD_RES_TAG,
+                                "GetOCFServerVersion: version value not found!");
+
+                            // Content Format Version Header Option ID exist but not value.
+                            // As OIC server don't use this header option ID, assuming as OCF Server.
+                            return 1;
+                        }
+
+                        int version = (it->getOptionData().c_str()[0]) * 256;
+                        OIC_LOG_V (INFO, ES_CLOUD_RES_TAG, "GetOCFServerVersion: Version [%d]", version);
+
+                        if(OCF_CONTENT_FORMAT_VERSION_VALUE == version)
+                        {
+                            OIC_LOG_V (DEBUG, ES_CLOUD_RES_TAG,
+                                "GetOCFServerVersion: Version matches OCF 1.0");
+                        }
+
+                        return version;
+                   }
+                }
+            }
+
+            OIC_LOG (DEBUG, ES_CLOUD_RES_TAG, "GetOCFServerVersion OUT version option not found");
+            return 0;
+        }
 
         void CloudResource::provisionProperties(const CloudProp& cloudProp)
         {
             OIC_LOG(DEBUG, ES_CLOUD_RES_TAG, "provisionProperties IN");
 
-            OCRepresentation provisioningRepresentation = cloudProp.toOCRepresentation();
+            int version = GetOCFServerVersion();
+            CloudProp cloudPropCopy = cloudProp;
+            cloudPropCopy.updateOCRepresentation(version);
+
+            OCRepresentation provisioningRepresentation = cloudPropCopy.toOCRepresentation();
 
             ESCloudResourceCb cb = std::bind(&CloudResource::onCloudProvResponseSafetyCb,
                             std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
index 9f116fb..8c1f6c1 100644 (file)
@@ -63,6 +63,9 @@ namespace OIC
                                                 const OCRepresentation& rep,
                                                 const int eCode);
 
+            // Determine Specification Version Enrollee follows using header options from discovered resource
+            int GetOCFServerVersion();
+
         private:
             std::shared_ptr< OC::OCResource > m_ocResource;
             CloudPropProvStatusCb m_cloudPropProvStatusCb;
index 64e4cc9..a256304 100644 (file)
@@ -32,8 +32,6 @@ namespace OIC
     namespace Service
     {
         #define ES_REMOTE_ENROLLEE_RES_TAG "ES_ENROLLEE_RESOURCE"
-        #define OCF_CONTENT_FORMAT_VERSION_OPTION_ID 2053
-        #define OCF_CONTENT_FORMAT_VERSION_VALUE 2048
 
         EnrolleeResource::EnrolleeResource(std::shared_ptr< OC::OCResource > resource)
         {
index 8f943bd..dd59616 100644 (file)
@@ -622,7 +622,6 @@ namespace OIC
                     m_cloudEnrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource);
                 }
 
-
                 res = m_cloudEnrolleeSecurity->provisionSecurityForCloudServer(cloudProp.getCloudID(),
                                                                           cloudProp.getCredID());
 
index 669fc38..bf104a9 100644 (file)
@@ -58,7 +58,7 @@ void ReadUserdataCb(OCRepPayload* payload, char* resourceType, void** userdata)
                     *userdata = (void*)OICMalloc(sizeof(UserProperties));
                     ((UserProperties*)(*userdata))->userValue_int = value;
                 }
-                OIC_LOG_V(INFO, ESX_ENROLLEE_TAG, "[User specific property] %s : %ld",
+                OIC_LOG_V(INFO, ESX_ENROLLEE_TAG, "[User specific property] %s : %lld",
                                                                             USERPROPERTY_KEY_INT, value);
                 g_userProperties.userValue_int = value;
             }