[IOT-2430] add eps from OCLinksPayloadValueCreate
authoruzchoi <uzchoi@samsung.com>
Mon, 26 Jun 2017 09:18:07 +0000 (18:18 +0900)
committerAshok Babu Channa <ashok.channa@samsung.com>
Thu, 24 Aug 2017 06:03:19 +0000 (06:03 +0000)
Previous OCLinksPayloadValueCreate function just create the payload
without eps info in links parameter and with tls and tcp port info
for cbor as media format request.
If user input the OCEntityHandleRequest from entity handler callback,
this function will parse whether this is request from vnd.ocf/cbor or
cbor media format using newly created function OCRequestIsOCFContentFormat
here, and create the links payload accordingly with eps info for vnd.ocf
media format request and tls/tcp for legacy cbor type request.

This patch has the seperated handling logic according to ll interface
and baseline interface in HandleLinkListInterface function.
ll interface requires links array payload instead of object with links.

OCLinksPayloadValueCreate API is changed as below.
:return type has PayloadValue to align to other create API.
:ehRequest is added as param. to receive the request media format and so on.

This change also include the fix to exclude the parent node from links
and the fix for tcp and tls property fill-in logic in vnd.ocf/cbor case.

This change add CreateEndpointPayloadList API change to add *epCount
param to return the count of endpoint.

Change-Id: I8f4c5905f35a7ed2286514926385921e407ff674
Signed-off-by: uzchoi <uzchoi@samsung.com>
Signed-off-by: Uze <uzchoi@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/20987
Reviewed-by: Todd Malsbary <todd.malsbary@intel.com>
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
Reviewed-by: Ashok Babu Channa <ashok.channa@samsung.com>
resource/csdk/stack/include/internal/occollection.h
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/include/ocpayload.h
resource/csdk/stack/src/occollection.c
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/test/stacktests.cpp

index 9d5cece..acb96fe 100644 (file)
@@ -29,7 +29,20 @@ uint8_t GetNumOfResourcesInCollection(const OCResource *resource);
 OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                                               OCEntityHandlerRequest *entityHandlerRequest);
 
-OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri,
-                           OCRepPayloadValue** linksRepPayloadValue, OCDevAddr* devAddr);
+/**
+ * This function creates the payloadValue for links parameter of collection resource.
+ * @param[in] resourceUri Resource uri (this should be a collection resource)
+ * @param[out] linksRepPayloadValue The payloadValue for links parameter of collection
+ * @param[in] devAddr Structure pointing to the address. (from OCEntityHandlerRequest)
+ * @param[in] isOCFVer true if AcceptedVersion is OCF1.0 or higher
+ *            otherwise false in case OIC1.1 (from OCEntityHandlerRequest)
+ *
+ * @note: The destroy of OCRepPayloadValue is not supported. Instead, use
+ *        OCRepPayloadDestroy(...) to destroy RepPayload of the collection Resource
+ *
+ * @return ::true if successful otherwise false.
+ */
+bool BuildCollectionLinksPayloadValue(const char* resourceUri,
+                    OCRepPayloadValue** linksRepPayloadValue, bool isOCFContentFormat, OCDevAddr* devAddr);
 
 #endif //OC_COLLECTION_H
index afb9d4e..697132e 100644 (file)
@@ -373,13 +373,23 @@ OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured);
  * @param[in] devAddr devAddr Structure pointing to the address.
  * @param[in] networkInfo array of CAEndpoint_t
  * @param[in] infoSize size of array
- * @param[in] listHead pointer to HeadNode pointer
+ * @param[out] listHead pointer to HeadNode pointer
+ * @param[out] epSize size of array
  *
  * @return if success return pointer else NULL
  */
 OCEndpointPayload* CreateEndpointPayloadList(OCTpsSchemeFlags endpointType,
     const OCDevAddr *devAddr, CAEndpoint_t *networkInfo,
-    size_t infoSize, OCEndpointPayload **listHead);
+    size_t infoSize, OCEndpointPayload **listHead, size_t* epSize);
+
+/*
+* This function returns to destroy endpoint payload
+*
+*/
+void OC_CALL OCEndpointPayloadDestroy(OCEndpointPayload* payload);
+
+// Check on Accept Version option.
+bool OCRequestIsOCFContentFormat(OCEntityHandlerRequest *ehRequest, bool* isOCFContentFormat);
 
 #ifdef __cplusplus
 }
index 23a37f9..049f774 100644 (file)
@@ -302,18 +302,18 @@ char* OC_CALL OCCreateString(const OCStringLL* ll);
 bool OC_CALL OCByteStringCopy(OCByteString *dest, const OCByteString *source);
 
 /**
-* This function creates the payloadValue for links parameter of collection resource.
-* @param[in] resourceUri Resource uri (this should be a collection resource)
-* @param[out] linksRepPayloadValue The payloadValue for links parameter of collection
-* @param[in] devAddr Structure pointing to the address. (from OCEntityHandlerRequest)
-*
-* @note: The destroy of OCRepPayloadValue is not supported. Instead, use
-*        OCRepPayloadDestroy(...) to destroy RepPayload of the collection Resource
-*
-* @return ::OC_STACK_OK if successful or else other value.
-*/
-OCStackResult OC_CALL OCLinksPayloadValueCreate(const char *resourceUri,
-                      OCRepPayloadValue **linksRepPayloadValue, OCDevAddr *devAddr);
+ * This function creates the payloadValue for links parameter of collection resource.
+ * @param[in] resourceUri Resource uri (this should be a collection resource)
+ * @param[out] linksRepPayloadValue The payloadValue for links parameter of collection
+ * @param[in] ehRequest parameter received from Entity Handler for client request
+ *
+ * @note: The destroy of OCRepPayloadValue is not supported. Instead, use
+ *        OCRepPayloadDestroy(...) to destroy RepPayload of the collection Resource
+ *
+ * @return ::true if successful otherwise false.
+ **/
+bool OC_CALL OCLinksPayloadValueCreate(const char *resourceUri,
+              OCRepPayloadValue **linksRepPayloadValue, OCEntityHandlerRequest *ehRequest);
 
 #ifdef __cplusplus
 }
index 13d44d8..893f641 100644 (file)
 
 #include "occollection.h"
 #include "ocpayload.h"
+#include "ocendpoint.h"
 #include "ocstack.h"
 #include "ocstackinternal.h"
 #include "oicgroup.h"
 #include "oic_string.h"
 #include "payload_logging.h"
-
+#include "cainterface.h"
 #define TAG "OIC_RI_COLLECTION"
 
 static bool AddRTSBaslinePayload(OCRepPayload **linkArray, int size, OCRepPayload **colPayload)
@@ -149,12 +150,30 @@ static OCStackResult HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest
         }
     }
 
+    if (size < 1)
+    {
+        ret = OC_STACK_NO_RESOURCE;
+        goto exit;
+    }
+
     if (ret == OC_STACK_OK)
     {
         colPayload = OCRepPayloadCreate();
         if (colPayload)
         {
-            if (0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, ifQueryParam))
+            bool isOCFContentFormat = true;
+            OCRequestIsOCFContentFormat(ehRequest, &isOCFContentFormat);
+            // from the OCF1.0 linklist specification, ll has array of links
+            if ((0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL) && isOCFContentFormat))
+            {
+                for (int n = 0 ; n < (int)size - 1 ; n++)
+                {
+                    linkArr[n]->next = linkArr[n + 1];
+                }
+                colPayload = linkArr[0];
+                goto exit;
+            }
+            else if (0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, ifQueryParam))
             {
                 //TODO : Add resource type filtering once collections
                 // start supporting queries.
@@ -186,6 +205,7 @@ exit:
         ehResult = (ret == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR;
     }
     ret = SendResponse(colPayload, ehRequest, collResource, ehResult);
+    OIC_LOG_V(INFO, TAG, "Send Response result from HandleLinkedListInterface = %d", (int)ret);
     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)colPayload);
     OCRepPayloadDestroy(colPayload);
     return ret;
@@ -316,67 +336,123 @@ exit:
     return result;
 }
 
-static OCRepPayload* addPolicyPayload(OCResourceHandle* resourceHandle, OCDevAddr* devAddr)
+static bool addPolicyPayload(OCResourceHandle* resourceHandle, OCDevAddr* devAddr,
+                             bool isOCFContentFormat, OCRepPayload** outPolicy)
 {
+    if (resourceHandle == NULL || devAddr == NULL || outPolicy == NULL) return false;
+
     OCResourceProperty p = OCGetResourceProperties(resourceHandle);
     OCRepPayload* policy = OCRepPayloadCreate();
     if (policy)
     {
         OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
-        OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
-
-        if (p & OC_SECURE)
+        if (!isOCFContentFormat)
         {
-            uint16_t securePort = 0;
-            if (devAddr)
+            OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
+
+            if (p & OC_SECURE)
             {
-                if (devAddr->adapter == OC_ADAPTER_IP)
+                uint16_t securePort = 0;
+                if (devAddr)
                 {
-                    if (devAddr->flags & OC_IP_USE_V6)
+                    if (devAddr->adapter == OC_ADAPTER_IP)
                     {
-                        securePort = caglobals.ip.u6s.port;
-                    }
-                    else if (devAddr->flags & OC_IP_USE_V4)
-                    {
-                        securePort = caglobals.ip.u4s.port;
+                        if (devAddr->flags & OC_IP_USE_V6)
+                        {
+                            securePort = caglobals.ip.u6s.port;
+                        }
+                        else if (devAddr->flags & OC_IP_USE_V4)
+                        {
+                            securePort = caglobals.ip.u4s.port;
+                        }
                     }
                 }
-            }
-            OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
+                OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
 
+#if defined(TCP_ADAPTER) && defined(__WITH_TLS__)
+                // tls
+                if (devAddr)
+                {
+                    uint16_t tlsPort = 0;
+                    GetTCPPortInfo(devAddr, &tlsPort, true);
+                    OCRepPayloadSetPropInt(policy, OC_RSRVD_TLS_PORT, tlsPort);
+                }
+#endif
+            }
 #ifdef TCP_ADAPTER
-#ifdef __WITH_TLS__
-            // tls
-            if (devAddr)
+#ifdef  __WITH_TLS__
+            if (!(p & OC_SECURE))
             {
-                uint16_t tlsPort = 0;
-                GetTCPPortInfo(devAddr, &tlsPort, true);
-                OCRepPayloadSetPropInt(policy, OC_RSRVD_TLS_PORT, tlsPort);
+#endif
+                // tcp
+                if (devAddr)
+                {
+                    uint16_t tcpPort = 0;
+                    GetTCPPortInfo(devAddr, &tcpPort, false);
+                    OCRepPayloadSetPropInt(policy, OC_RSRVD_TCP_PORT, tcpPort);
+                }
+#ifdef  __WITH_TLS__
             }
-#else
-        }
-        // tcp
-        if (devAddr)
-        {
-            uint16_t tcpPort = 0;
-            GetTCPPortInfo(devAddr, &tcpPort, false);
-            OCRepPayloadSetPropInt(policy, OC_RSRVD_TCP_PORT, tcpPort);
 #endif
 #endif
         }
     }
-    return policy;
+    else
+    {
+        return false;
+    }
+
+    *outPolicy = policy;
+    return true;
 }
 
-OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPayloadValue** linksRepPayloadValue,
-    OCDevAddr* devAddr)
+static bool translateEndpointsPayload(OCEndpointPayload* epPayloadOrg,
+                                      size_t size, OCRepPayload*** outArrayPayload)
 {
-    OCStackResult result = OC_STACK_ERROR;
+    bool result = false;
+    OCRepPayload** arrayPayload = (OCRepPayload**)OICMalloc(sizeof(OCRepPayload*) * (size));
+    VERIFY_PARAM_NON_NULL(TAG, arrayPayload, "Failed creating arrayPayload");
+    VERIFY_PARAM_NON_NULL(TAG, epPayloadOrg, "Invalid Parameter epPayload");
+    VERIFY_PARAM_NON_NULL(TAG, outArrayPayload, "Invalid Parameter outArrayPayload");
+    OCEndpointPayload* epPayload = epPayloadOrg;
+
+    for (size_t i = 0; (i < size) && (epPayload != NULL) ; i++)
+    {
+        arrayPayload[i] = OCRepPayloadCreate();
+        if (!arrayPayload[i])
+        {
+            for (size_t j = 0; j < i; j++)
+            {
+                OCRepPayloadDestroy(arrayPayload[j]);
+            }
+            result = false;
+            goto exit;
+        }
+        char* createdEPStr = OCCreateEndpointString(epPayload);
+        OIC_LOG_V(DEBUG, TAG, " OCCreateEndpointString() = %s", createdEPStr);
+        OCRepPayloadSetPropString(arrayPayload[i], OC_RSRVD_ENDPOINT, createdEPStr);
+
+        // in case of pri as 1, skip set property
+        if (epPayload->pri != 1 )
+            OCRepPayloadSetPropInt(arrayPayload[i], OC_RSRVD_PRIORITY, epPayload->pri);
+
+        epPayload = epPayload->next;
+        result = true;
+    }
+    *outArrayPayload = arrayPayload;
+exit:
+    OCEndpointPayloadDestroy(epPayloadOrg);
+    if (result == false) OICFree(arrayPayload);
+    return result;
+}
 
+bool BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPayloadValue** linksRepPayloadValue,
+    bool isOCFContentFormat, OCDevAddr* devAddr)
+{
     OCRepPayloadValue* createdPayloadValue = (OCRepPayloadValue*)OICCalloc(1, sizeof(OCRepPayloadValue));
     if (!createdPayloadValue)
     {
-        return result;
+        return false;
     }
     createdPayloadValue->name = OC_RSRVD_LINKS;
     createdPayloadValue->type = OCREP_PROP_ARRAY;
@@ -386,7 +462,7 @@ OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPay
     {
         //in case input resource is not registered resource.
         OICFree(createdPayloadValue);
-        return result;
+        return false;
     }
 
     const OCChildResource* childResource = ((OCResource*)colResourceHandle)->rsrcChildResourcesHead;
@@ -394,7 +470,7 @@ OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPay
     {
         //in case input resource is not collection resource.
         OICFree(createdPayloadValue);
-        return result;
+        return false;
     }
 
     //children resources count calculation
@@ -405,15 +481,15 @@ OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPay
         childCountResource = childCountResource->next;
     } while (childCountResource);
 
-    OCRepPayload** arrayPayload = (OCRepPayload** )OICMalloc(sizeof(OCRepPayload*) * (childCount + 1));
+    OCRepPayload** arrayPayload = (OCRepPayload** )OICMalloc(sizeof(OCRepPayload*) * (childCount));
     if (!arrayPayload)
     {
         OICFree(createdPayloadValue);
-        return result;
+        return false;
     }
 
-    OCResource* iterResource = (OCResource*) colResourceHandle;
-    for (size_t i = 0; i < childCount + 1; i++)
+    OCResource* iterResource = childResource->rsrcResource;
+    for (size_t i = 0; i < childCount; i++)
     {
         arrayPayload[i] = OCRepPayloadCreate();
         if (!arrayPayload[i])
@@ -427,7 +503,7 @@ OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPay
 
             OICFree(arrayPayload);
 
-            return result;
+            return false;
         }
 
         OCRepPayloadSetUri(arrayPayload[i], iterResource->uri);
@@ -444,12 +520,15 @@ OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPay
             OCRepPayloadAddInterface(arrayPayload[i], resInterface->name);
         }
 
-        //@todo selectively fill in the data between Policy Map for OIC and EP Array for OCF
-        if (!OCRepPayloadSetPropObjectAsOwner(arrayPayload[i], OC_RSRVD_POLICY,
-                             addPolicyPayload((OCResourceHandle*)iterResource, devAddr)))
+        OCRepPayload* outPolicy = NULL;
+        //Policy Map will have tls and tcp properties for legacy support,
+        // in case contents format is cbor instead of vnd.ocf/cbor
+        if (!addPolicyPayload((OCResourceHandle*)iterResource, devAddr, isOCFContentFormat,
+                               &outPolicy) ||
+            !OCRepPayloadSetPropObjectAsOwner(arrayPayload[i], OC_RSRVD_POLICY, outPolicy))
         {
             OICFree(createdPayloadValue);
-
+            OCRepPayloadDestroy(outPolicy);
             for (size_t j = 0; j <= i; j++)
             {
                 OCRepPayloadDestroy(arrayPayload[j]);
@@ -457,27 +536,64 @@ OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPay
 
             OICFree(arrayPayload);
 
-            return result;
+            return false;
         }
 
-        if (i == 0)
+        //EP is added in case contents format is vnd.ocf/cbor
+        if (isOCFContentFormat)
         {
-            iterResource = childResource->rsrcResource;
-        }
-        else
-        {
-            childResource = childResource->next;
-            if (childResource)
+            CAEndpoint_t *info = NULL;
+            size_t networkSize = 0;
+            size_t epSize = 0;
+            CAGetNetworkInformation(&info, &networkSize);
+            OIC_LOG_V(DEBUG, TAG, "Network Information size = %d", networkSize);
+
+            OCEndpointPayload *listHead = NULL;
+            CreateEndpointPayloadList(((OCResource*)colResourceHandle)->endpointType,
+                devAddr, info, networkSize, &listHead, &epSize);
+            OICFree(info);
+            OIC_LOG_V(DEBUG, TAG, "Result of CreateEndpointPayloadList() = %s",
+                                  listHead ? "true":"false");
+
+            OCRepPayload** epArrayPayload = NULL;
+            size_t epsDim[MAX_REP_ARRAY_DEPTH] = { epSize, 0, 0 };
+
+            if (!translateEndpointsPayload(listHead, epSize, &epArrayPayload) ||
+                !OCRepPayloadSetPropObjectArrayAsOwner(arrayPayload[i],
+                            OC_RSRVD_ENDPOINTS, epArrayPayload, epsDim))
             {
-                iterResource = childResource->rsrcResource;
+                if (epArrayPayload)
+                {
+                    for (size_t j = 0; j < epSize; j++)
+                    {
+                        OCRepPayloadDestroy(epArrayPayload[j]);
+                    }
+                    OICFree(epArrayPayload);
+                }
+
+                OICFree(createdPayloadValue);
+
+                for (size_t j = 0; j <= i; j++)
+                {
+                    OCRepPayloadDestroy(arrayPayload[j]);
+                }
+                OICFree(arrayPayload);
+
+                return false;
             }
         }
+
+        childResource = childResource->next;
+        if (childResource)
+        {
+            iterResource = childResource->rsrcResource;
+        }
     }
 
     //create OCRepPayloadValue internal structure and pass
     //createdPayloadValue:OCRepPayloadValue.createdPayloadValueArray:arr->arrayPayload:objArray
     OCRepPayloadValueArray* createdPayloadValueArray = &createdPayloadValue->arr;
-    size_t linkDim[MAX_REP_ARRAY_DEPTH] = { childCount + 1, 0, 0 };
+    size_t linkDim[MAX_REP_ARRAY_DEPTH] = { childCount, 0, 0 };
     OC_STATIC_ASSERT(sizeof(createdPayloadValueArray->dimensions) == sizeof(linkDim), "Array size mismatch!");
     memcpy(createdPayloadValueArray->dimensions, linkDim, sizeof(linkDim));
     createdPayloadValueArray->type = OCREP_PROP_OBJECT;
@@ -485,6 +601,5 @@ OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPay
 
     *linksRepPayloadValue = createdPayloadValue;
 
-    result = OC_STACK_OK;
-    return result;
+    return true;
 }
index 41c6bd0..159f8d0 100644 (file)
@@ -1803,9 +1803,9 @@ void OC_CALL OCResourcePayloadAddNewEndpoint(OCResourcePayload* payload, OCEndpo
     }
 }
 
-OCEndpointPayload* CreateEndpointPayloadList(OCTpsSchemeFlags endpointType,
-                                             const OCDevAddr *devAddr, CAEndpoint_t *networkInfo,
-                                             size_t infoSize, OCEndpointPayload **listHead)
+OCEndpointPayload* CreateEndpointPayloadList(OCTpsSchemeFlags endpointType, const OCDevAddr *devAddr,
+                                            CAEndpoint_t *networkInfo, size_t infoSize,
+                                            OCEndpointPayload **listHead, size_t* epSize)
 {
     OCEndpointPayload *headNode = NULL;
     OCEndpointPayload *lastNode = NULL;
@@ -1813,6 +1813,7 @@ OCEndpointPayload* CreateEndpointPayloadList(OCTpsSchemeFlags endpointType,
     VERIFY_PARAM_NON_NULL(TAG, devAddr, "Invalid devAddr parameter");
     VERIFY_PARAM_NON_NULL(TAG, networkInfo, "Invalid networkInfo parameter");
     VERIFY_PARAM_NON_NULL(TAG, listHead, "Invalid listHead parameter");
+       if (epSize != NULL) *epSize = 0;
 
     if ((OC_ADAPTER_IP | OC_ADAPTER_TCP) & (devAddr->adapter))
     {
@@ -1829,6 +1830,7 @@ OCEndpointPayload* CreateEndpointPayloadList(OCTpsSchemeFlags endpointType,
                                                         info->flags,
                                                         &matchedTps))
                 {
+                    OIC_LOG_V(ERROR, TAG, "OCGetMatchedTpsFlags err");
                     goto exit;
                 }
 
@@ -1838,12 +1840,14 @@ OCEndpointPayload* CreateEndpointPayloadList(OCTpsSchemeFlags endpointType,
                         OICCalloc(1, sizeof(OCEndpointPayload));
                     if (!tmpNode)
                     {
+                        OIC_LOG_V(ERROR, TAG, "Fail creating tmpNode->addr");
                         goto exit;
                     }
 
                     OCStackResult ret = OCConvertTpsToString(matchedTps, &(tmpNode->tps));
                     if (ret != OC_STACK_OK)
                     {
+                        OIC_LOG_V(DEBUG, TAG, "OCConvertTpsToString(%s) is false", tmpNode->tps);
                         OCDiscoveryEndpointDestroy(tmpNode);
                         goto exit;
                     }
@@ -1851,6 +1855,7 @@ OCEndpointPayload* CreateEndpointPayloadList(OCTpsSchemeFlags endpointType,
                     tmpNode->addr = (char*)OICCalloc(MAX_ADDR_STR_SIZE, sizeof(char));
                     if (!tmpNode->addr)
                     {
+                        OIC_LOG_V(ERROR, TAG, "Fail creating tmpNode->addr");
                         OCDiscoveryEndpointDestroy(tmpNode);
                         goto exit;
                     }
@@ -1872,8 +1877,13 @@ OCEndpointPayload* CreateEndpointPayloadList(OCTpsSchemeFlags endpointType,
                         lastNode->next = tmpNode;
                         lastNode = tmpNode;
                     }
+                    if (epSize != NULL) (*epSize)++;
                 }
             }
+            else
+            {
+                OIC_LOG_V(DEBUG, TAG, "CATransportAdapter_t value = %d", info->adapter);
+            }
         }
     }
 
@@ -1902,7 +1912,8 @@ static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t secureP
     OCEndpointPayload *selfEp = NULL;
     if (networkInfo && infoSize && devAddr)
     {
-        if(!CreateEndpointPayloadList(res->endpointType, devAddr, networkInfo, infoSize, &(pl->eps)))
+        if(!CreateEndpointPayloadList(res->endpointType, devAddr, networkInfo, infoSize,
+                                      &(pl->eps), NULL))
         {
             return NULL;
         }
@@ -2216,14 +2227,58 @@ void OC_CALL OCDiagnosticPayloadDestroy(OCDiagnosticPayload* payload)
     OICFree(payload);
 }
 
-OCStackResult OC_CALL OCLinksPayloadValueCreate(const char* resourceUri, OCRepPayloadValue** linksRepPayloadValue,
-    OCDevAddr* devAddr)
+void OC_CALL OCEndpointPayloadDestroy(OCEndpointPayload* payload)
+{
+    if (!payload)
+    {
+        return;
+    }
+    OICFree(payload->tps);
+    OICFree(payload->addr);
+    OCEndpointPayloadDestroy(payload->next);
+    OICFree(payload);
+}
+
+bool OC_CALL OCLinksPayloadValueCreate(const char* resourceUri,
+    OCRepPayloadValue** linksRepPayloadValue, OCEntityHandlerRequest *ehRequest)
 {
     OIC_LOG(DEBUG, TAG, "OCLinksPayloadValueCreate");
-    OCStackResult result = OC_STACK_ERROR;
-    if ((resourceUri != NULL) & (linksRepPayloadValue != NULL) )
+    bool result = false;
+    if ((resourceUri != NULL) && (linksRepPayloadValue != NULL) && (ehRequest != NULL))
     {
-        result = BuildCollectionLinksPayloadValue(resourceUri, linksRepPayloadValue, devAddr);
+        bool isOCFContentFormat = false;
+        if (!OCRequestIsOCFContentFormat(ehRequest, &isOCFContentFormat))
+            return result;
+        result = BuildCollectionLinksPayloadValue(resourceUri, linksRepPayloadValue,
+                 isOCFContentFormat, &ehRequest->devAddr);
+        OIC_LOG_V(DEBUG, TAG, "return value of BuildCollectionLinksPayloadValue() = %s",
+                  result ? "true" : "false");
     }
     return result;
 }
+
+// Check on Content Version option whether request has vnd.ocf+cbor format instead of cbor
+bool OCRequestIsOCFContentFormat(OCEntityHandlerRequest *ehRequest, bool* isOCFContentFormat)
+{
+    if ((ehRequest == NULL)||(isOCFContentFormat == NULL))
+        return false;
+
+    OCServerRequest* serverRequest = (OCServerRequest*) ehRequest->requestHandle;
+
+    if (OC_FORMAT_VND_OCF_CBOR == serverRequest->acceptFormat)
+    {
+        *isOCFContentFormat = true;
+        OIC_LOG_V(INFO, TAG, "Content format is application/vnd.ocf+cbor");
+    }
+    else if (OC_FORMAT_CBOR == serverRequest->acceptFormat)
+    {
+        *isOCFContentFormat = false;
+        OIC_LOG_V(INFO, TAG, "Content format is application/cbor");
+    }
+    else
+    {
+        OIC_LOG_V(ERROR, TAG, "Content format is neither application/vnd.ocf+cbor nor /cbor");
+        return false;
+    }
+    return true;
+}
index da4ee3d..79ac4d8 100644 (file)
@@ -29,6 +29,7 @@ extern "C"
     #include "oic_string.h"
     #include "oic_time.h"
     #include "ocresourcehandler.h"
+    #include "occollection.h"
 }
 
 #include <gtest/gtest.h>
@@ -2979,17 +2980,17 @@ TEST(StackZoneId, getZoneIdWithInvalidParams)
 }
 #endif
 
-TEST(LinksPayloadValue, createLinksPayloadValue)
+TEST(LinksPayloadValue, BuildCollectionLinksPayloadValue)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
     OIC_LOG(INFO, TAG, "Starting createLinksPayloadValue test");
     InitStack(OC_SERVER);
 
     size_t numResources = 0;
-    uint8_t inBitmap[3] = { OC_DISCOVERABLE | OC_OBSERVABLE,
-                            OC_DISCOVERABLE | OC_OBSERVABLE,
+    uint8_t parentBitmap = OC_DISCOVERABLE | OC_OBSERVABLE;
+    uint8_t inBitmap[2] = { OC_DISCOVERABLE | OC_OBSERVABLE,
                             OC_DISCOVERABLE };
-    int64_t outBitmap[3] = {0};
+    int64_t outBitmap[2] = { 0 };
 
     OCResourceHandle containerHandle;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle,
@@ -2998,8 +2999,7 @@ TEST(LinksPayloadValue, createLinksPayloadValue)
         "/a/kitchen",
         0,
         NULL,
-        inBitmap[0]));
-    ++numResources;
+        parentBitmap));
 
     OCResourceHandle handle0;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
@@ -3008,7 +3008,7 @@ TEST(LinksPayloadValue, createLinksPayloadValue)
         "/a/led0",
         0,
         NULL,
-        inBitmap[1]));
+        inBitmap[0]));
     ++numResources;
 
     OCResourceHandle handle1;
@@ -3018,7 +3018,7 @@ TEST(LinksPayloadValue, createLinksPayloadValue)
         "/a/led1",
         0,
         NULL,
-        inBitmap[2]));
+        inBitmap[1]));
     ++numResources;
 
     EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle0));
@@ -3028,11 +3028,23 @@ TEST(LinksPayloadValue, createLinksPayloadValue)
     EXPECT_EQ(handle1, OCGetResourceHandleFromCollection(containerHandle, 1));
 
     OCRepPayloadValue* linksRepPayloadValue;
-    OCDevAddr* devAddr = NULL;
-    EXPECT_EQ(OC_STACK_OK, OCLinksPayloadValueCreate("/a/kitchen", &linksRepPayloadValue, devAddr));
+    OCRepPayload *collectionPayload = NULL;
+    OCRepPayload *policyMap = NULL;
+    OCRepPayload **linksMap = NULL;
+
+    OCDevAddr* devAddr = (OCDevAddr*)OICCalloc(1, sizeof(OCDevAddr));
+    devAddr->adapter = OC_ADAPTER_IP;
+    CAEndpoint_t *info = NULL;
+    size_t size = 0;
+    CAGetNetworkInformation(&info, &size);
+    devAddr->ifindex = info->ifindex;
+
+    //check for OIC1.1 logic
+    ASSERT_TRUE(BuildCollectionLinksPayloadValue("/a/kitchen", 
+                           &linksRepPayloadValue, false, devAddr));
     ASSERT_TRUE(NULL != linksRepPayloadValue);
 
-    OCRepPayload *collectionPayload = OCRepPayloadCreate();
+    collectionPayload = OCRepPayloadCreate();
     ASSERT_TRUE(NULL != collectionPayload);
 
     size_t dim[MAX_REP_ARRAY_DEPTH] = { numResources, 0, 0 };
@@ -3040,8 +3052,6 @@ TEST(LinksPayloadValue, createLinksPayloadValue)
     ASSERT_TRUE(OCRepPayloadSetPropObjectArrayAsOwner(collectionPayload, OC_RSRVD_LINKS,
                                               linksRepPayloadValue->arr.objArray, dim));
 
-    OCRepPayload *policyMap = NULL;
-    OCRepPayload **linksMap = NULL;
     ASSERT_TRUE(OCRepPayloadGetPropObjectArray(collectionPayload, OC_RSRVD_LINKS, &linksMap, dim));
 
     for (size_t i = 0; i < numResources; i++)
@@ -3054,14 +3064,29 @@ TEST(LinksPayloadValue, createLinksPayloadValue)
         {
 #ifdef TCP_ADAPTER
 #ifdef __WITH_TLS__
-            // tls
-            int64_t outTlsPort = 0;
-            ASSERT_TRUE(OCRepPayloadGetPropInt(policyMap, OC_RSRVD_TLS_PORT, &outTlsPort));
+            bool isSecure = false;
+            ASSERT_TRUE(OCRepPayloadGetPropBool(policyMap, OC_RSRVD_SECURE, &isSecure));
+            if (isSecure)
+            {
+                // tls
+                int64_t outTlsPort = 0;
+                ASSERT_TRUE(OCRepPayloadGetPropInt(policyMap, OC_RSRVD_TLS_PORT, &outTlsPort));
 
-            uint16_t tlsPort = 0;
-            GetTCPPortInfo(devAddr, &tlsPort, true);
+                uint16_t tlsPort = 0;
+                GetTCPPortInfo(devAddr, &tlsPort, true);
+                EXPECT_EQ(tlsPort, outTlsPort);
+            }
+            else
+            {
+                // tcp
+                int64_t outTcpPort = 0;
+                ASSERT_TRUE(OCRepPayloadGetPropInt(policyMap, OC_RSRVD_TCP_PORT, &outTcpPort));
+
+                uint16_t tcpPort = 0;
+                GetTCPPortInfo(devAddr, &tcpPort, false);
 
-            EXPECT_EQ(tlsPort, outTlsPort);
+                EXPECT_EQ(tcpPort, outTcpPort);
+            }
 #else
             // tcp
             int64_t outTcpPort = 0;
@@ -3081,6 +3106,76 @@ TEST(LinksPayloadValue, createLinksPayloadValue)
     OCRepPayloadDestroy(policyMap);
     OCRepPayloadDestroy(collectionPayload);
 
+    //check for OCF1.0 logic
+    ASSERT_TRUE(BuildCollectionLinksPayloadValue("/a/kitchen",
+                           &linksRepPayloadValue, true, devAddr));
+    ASSERT_TRUE(NULL != linksRepPayloadValue);
+
+    collectionPayload = OCRepPayloadCreate();
+    ASSERT_TRUE(NULL != collectionPayload);
+
+    dim[1] = dim[2] = 0;
+
+    ASSERT_TRUE(OCRepPayloadSetPropObjectArrayAsOwner(collectionPayload, OC_RSRVD_LINKS,
+        linksRepPayloadValue->arr.objArray, dim));
+
+    ASSERT_TRUE(OCRepPayloadGetPropObjectArray(collectionPayload, OC_RSRVD_LINKS, &linksMap, dim));
+
+    for (size_t i = 0; i < numResources; i++)
+    {
+        ASSERT_TRUE(OCRepPayloadGetPropObject(linksMap[i], OC_RSRVD_POLICY, &policyMap));
+        ASSERT_TRUE(OCRepPayloadGetPropInt(policyMap, OC_RSRVD_BITMAP, &outBitmap[i]));
+        EXPECT_EQ(inBitmap[i], outBitmap[i]);
+
+        size_t epsDim[MAX_REP_ARRAY_DEPTH] = { 0 };
+        OCRepPayload **epsMap = NULL;
+        ASSERT_TRUE(OCRepPayloadGetPropObjectArray(linksMap[i], OC_RSRVD_ENDPOINTS, &epsMap, epsDim));
+
+        size_t count = calcDimTotal(epsDim);
+        size_t coap_scheme_cnt[4] = { 0, 0, 0, 0 };
+        const char* coap_scheme[4] = { "coap", "coaps://", "coap+tcp://", "coaps+tcp://" };
+        char* outUri;
+        for (size_t k = 0; k < count; k++)
+        {
+            ASSERT_TRUE(OCRepPayloadGetPropString(epsMap[k], OC_RSRVD_ENDPOINT, &outUri));
+
+            if (!strncmp(outUri, coap_scheme[3], strlen(coap_scheme[3])))
+                coap_scheme_cnt[3]++;
+            else if (!strncmp(outUri, coap_scheme[2], strlen(coap_scheme[2])))
+                coap_scheme_cnt[2]++;
+            else if (!strncmp(outUri, coap_scheme[1], strlen(coap_scheme[1])))
+                coap_scheme_cnt[1]++;
+            else if (!strncmp(outUri, coap_scheme[0], strlen(coap_scheme[0])))
+                coap_scheme_cnt[0]++;
+            else
+            {
+                ASSERT_TRUE(false);
+                OIC_LOG_V(ERROR, TAG, "ep uri = %s \n", outUri);
+            }
+
+            OCRepPayloadDestroy(epsMap[k]);
+        }
+
+        ASSERT_GE(coap_scheme_cnt[0], (size_t) 1);
+#ifdef __WITH_TLS__
+        ASSERT_GE(coap_scheme_cnt[1], (size_t) 1);
+#ifdef TCP_ADAPTER
+        ASSERT_GE(coap_scheme_cnt[3], (size_t) 1);
+#endif
+#else
+#ifdef TCP_ADAPTER
+        ASSERT_GE(coap_scheme_cnt[2], (size_t) 1);
+#endif
+#endif
+
+        OCRepPayloadDestroy(linksMap[i]);
+        OICFree(epsMap);
+    }
+
+    OICFree(linksMap);
+    OCRepPayloadDestroy(policyMap);
+    OCRepPayloadDestroy(collectionPayload);
+
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }