Add support for application/vnd.ocf+cbor to resource directory.
authorTodd Malsbary <todd.malsbary@intel.com>
Wed, 1 Mar 2017 19:52:54 +0000 (11:52 -0800)
committerDan Mihai <Daniel.Mihai@microsoft.com>
Mon, 27 Mar 2017 21:37:38 +0000 (21:37 +0000)
- Add support to RD for publishing and storing endpoints.  Only
  publish secure or non-secure eps depending on resource properties.
- When creating application/cbor response to discovery, create
  separate links with the fully-qualified URI containing the supported
  endpoints.

Change-Id: Ifc370825103a73335eddccb4bbde4225d0a0a736
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/17631
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
12 files changed:
resource/csdk/resource-directory/include/rd_database.h
resource/csdk/resource-directory/src/internal/rd_database.c
resource/csdk/resource-directory/src/rd_client.c
resource/csdk/resource-directory/src/rd_server.c
resource/csdk/resource-directory/unittests/SConscript
resource/csdk/resource-directory/unittests/rddatabase.cpp
resource/csdk/resource-directory/unittests/rdtests.cpp
resource/csdk/stack/include/internal/ocendpoint.h
resource/csdk/stack/src/ocendpoint.c
resource/csdk/stack/src/ocpayloadconvert.c
resource/csdk/stack/src/ocpayloadparse.c
resource/csdk/stack/src/oicresourcedirectory.c

index a8285da..01c19f6 100644 (file)
@@ -38,11 +38,10 @@ OCStackResult OCRDDatabaseInit();
  * Stores in database the published resource.
  *
  * @param payload is the the published resource payload.
- * @param address provide information about endpoint connectivity details.
  *
  * @return ::OC_STACK_OK in case of success or else other value.
  */
-OCStackResult OCRDDatabaseStoreResources(const OCRepPayload *payload, const OCDevAddr *address);
+OCStackResult OCRDDatabaseStoreResources(const OCRepPayload *payload);
 
 /**
  * Delete the RD resources
index 3e3ed87..4b13774 100644 (file)
@@ -57,23 +57,20 @@ static sqlite3 *gRDDB = NULL;
 #define RD_TABLE \
     "create table RD_DEVICE_LIST(ID INTEGER PRIMARY KEY AUTOINCREMENT, " \
     XSTR(OC_RSRVD_DEVICE_ID) " UNIQUE NOT NULL, " \
-    XSTR(OC_RSRVD_TTL) " NOT NULL, " \
-    "ADDRESS NOT NULL);"
+    XSTR(OC_RSRVD_TTL) " NOT NULL);"
 
 #define RD_LL_TABLE  \
     "create table RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)" INTEGER PRIMARY KEY AUTOINCREMENT, " \
-    XSTR(OC_RSRVD_HREF)  "," \
-    XSTR(OC_RSRVD_REL)   ","  \
-    XSTR(OC_RSRVD_TITLE) "," \
-    XSTR(OC_RSRVD_BITMAP)"," \
-    XSTR(OC_RSRVD_TTL)   "," \
-    XSTR(OC_RSRVD_MEDIA_TYPE) "," \
+    XSTR(OC_RSRVD_HREF) "," \
+    XSTR(OC_RSRVD_REL) ","  \
+    XSTR(OC_RSRVD_URI) "," \
+    XSTR(OC_RSRVD_BITMAP) "," \
     "DEVICE_ID INT NOT NULL, " \
-    "FOREIGN KEY(DEVICE_ID) REFERENCES RD_DEVICE_LIST(ID) ON DELETE CASCADE );"
+    "FOREIGN KEY(DEVICE_ID) REFERENCES RD_DEVICE_LIST(ID) ON DELETE CASCADE);"
 
 #define RD_RT_TABLE \
     "create table RD_LINK_RT(" XSTR(OC_RSRVD_RESOURCE_TYPE) " NOT NULL, " \
-    "LINK_ID INT NOT NULL, "\
+    "LINK_ID INT NOT NULL, " \
     "FOREIGN KEY("XSTR(LINK_ID)") REFERENCES RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)") " \
     "ON DELETE CASCADE);"
 
@@ -83,6 +80,13 @@ static sqlite3 *gRDDB = NULL;
     "FOREIGN KEY("XSTR(LINK_ID)") REFERENCES RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)") " \
     "ON DELETE CASCADE);"
 
+#define RD_EP_TABLE \
+    "create table RD_LINK_EP(" XSTR(OC_RSRVD_ENDPOINT) " NOT NULL, " \
+    XSTR(OC_RSRVD_PRIORITY) " INT NOT NULL, " \
+    "LINK_ID INT NOT NULL, "\
+    "FOREIGN KEY("XSTR(LINK_ID)") REFERENCES RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)") " \
+    "ON DELETE CASCADE);"
+
 static void errorCallback(void *arg, int errCode, const char *errMsg)
 {
     OC_UNUSED(arg);
@@ -120,6 +124,9 @@ OCStackResult OCRDDatabaseInit()
 
             VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_IF_TABLE, NULL, NULL, NULL));
             OIC_LOG(DEBUG, TAG, "RD created RD_LINK_IF table.");
+
+            VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_EP_TABLE, NULL, NULL, NULL));
+            OIC_LOG(DEBUG, TAG, "RD created RD_LINK_EP table.");
             sqlRet = SQLITE_OK;
         }
     }
@@ -233,6 +240,55 @@ static int storeInterfaceType(char **interfaceTypes, size_t size, sqlite3_int64
     return res;
 }
 
+static int storeEndpoints(OCRepPayload **eps, size_t size, sqlite3_int64 rowid)
+{
+    int res = 1;
+    VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
+
+    const char *deleteEp = "DELETE FROM RD_LINK_EP WHERE LINK_ID=@id";
+    const char *insertEp = "INSERT INTO RD_LINK_EP VALUES(@ep, @pri, @id)";
+    sqlite3_stmt *stmt = 0;
+
+    VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, deleteEp, strlen(deleteEp) + 1, &stmt, NULL));
+    VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
+    res = sqlite3_step(stmt);
+    VERIFY_SQLITE(sqlite3_finalize(stmt));
+    if (res != SQLITE_DONE)
+    {
+        sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
+        return res;
+    }
+
+    for (size_t i = 0; i < size; i++)
+    {
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertEp, strlen(insertEp) + 1, &stmt, NULL));
+        char *ep;
+        if (OCRepPayloadGetPropString(eps[i], OC_RSRVD_ENDPOINT, &ep))
+        {
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@ep"),
+                                            ep, strlen(ep), SQLITE_STATIC));
+        }
+        sqlite3_int64 pri;
+        if (OCRepPayloadGetPropInt(eps[i], OC_RSRVD_PRIORITY, (int64_t *) &pri))
+        {
+            VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@pri"), pri));
+        }
+        VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
+        res = sqlite3_step(stmt);
+        VERIFY_SQLITE(sqlite3_finalize(stmt));
+        if (res != SQLITE_DONE)
+        {
+            sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
+            return res;
+        }
+        OICFree(ep);
+    }
+
+    VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
+    res = SQLITE_OK;
+    return res;
+}
+
 static int storeLinkPayload(OCRepPayload *rdPayload, sqlite3_int64 rowid)
 {
     int res = 1 ;
@@ -258,7 +314,7 @@ static int storeLinkPayload(OCRepPayload *rdPayload, sqlite3_int64 rowid)
     {
         const char *insertDeviceLLList = "INSERT OR IGNORE INTO RD_DEVICE_LINK_LIST (ins, href, DEVICE_ID) "
             "VALUES((SELECT ins FROM RD_DEVICE_LINK_LIST WHERE DEVICE_ID=@id AND href=@uri),@uri,@id)";
-        const char *updateDeviceLLList = "UPDATE RD_DEVICE_LINK_LIST SET bm=@bm,type=@mediaType "
+        const char *updateDeviceLLList = "UPDATE RD_DEVICE_LINK_LIST SET anchor=@anchor,bm=@bm "
             "WHERE DEVICE_ID=@id AND href=@uri";
 
         sqlite3_stmt *stmt = 0;
@@ -292,22 +348,21 @@ static int storeLinkPayload(OCRepPayload *rdPayload, sqlite3_int64 rowid)
                 VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
                                                 uri, strlen(uri), SQLITE_STATIC));
             }
+            char *anchor;
+            if (OCRepPayloadGetPropString(link, OC_RSRVD_URI, &anchor))
+            {
+                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@anchor"),
+                                                anchor, strlen(anchor), SQLITE_STATIC));
+            }
             OCRepPayload *p = NULL;
             if (OCRepPayloadGetPropObject(link, OC_RSRVD_POLICY, &p))
             {
                 sqlite3_int64 bm = 0;
-                if (OCRepPayloadGetPropInt(p, OC_RSRVD_BITMAP, &bm))
+                if (OCRepPayloadGetPropInt(p, OC_RSRVD_BITMAP, (int64_t *) &bm))
                 {
                     VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@bm"), bm));
                 }
             }
-            size_t mtDim[MAX_REP_ARRAY_DEPTH] = {0};
-            char **mediaType = NULL;
-            if (OCRepPayloadGetStringArray(link, OC_RSRVD_MEDIA_TYPE, &mediaType, mtDim))
-            {
-                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@mediaType"),
-                                                mediaType[0], strlen(mediaType[0]), SQLITE_STATIC));
-            }
             if (sqlite3_step(stmt) != SQLITE_DONE)
             {
                 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
@@ -321,6 +376,8 @@ static int storeLinkPayload(OCRepPayload *rdPayload, sqlite3_int64 rowid)
             size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
             char **itf = NULL;
             size_t itfDim[MAX_REP_ARRAY_DEPTH] = {0};
+            OCRepPayload** eps = NULL;
+            size_t epsDim[MAX_REP_ARRAY_DEPTH] = {0};
             const char *input = "SELECT ins FROM RD_DEVICE_LINK_LIST WHERE DEVICE_ID=@id AND href=@uri";
             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
             VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
@@ -332,7 +389,7 @@ static int storeLinkPayload(OCRepPayload *rdPayload, sqlite3_int64 rowid)
             res = sqlite3_step(stmt);
             if (res == SQLITE_ROW || res == SQLITE_DONE)
             {
-                int64_t ins = sqlite3_column_int64(stmt, 0);
+                sqlite3_int64 ins = sqlite3_column_int64(stmt, 0);
                 VERIFY_SQLITE(sqlite3_finalize(stmt));
                 if (!OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins))
                 {
@@ -341,8 +398,10 @@ static int storeLinkPayload(OCRepPayload *rdPayload, sqlite3_int64 rowid)
                 }
                 OCRepPayloadGetStringArray(link, OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
                 OCRepPayloadGetStringArray(link, OC_RSRVD_INTERFACE, &itf, itfDim);
+                OCRepPayloadGetPropObjectArray(link, OC_RSRVD_ENDPOINTS, &eps, epsDim);
                 VERIFY_SQLITE(storeResourceType(rt, rtDim[0], ins));
                 VERIFY_SQLITE(storeInterfaceType(itf, itfDim[0], ins));
+                VERIFY_SQLITE(storeEndpoints(eps, epsDim[0], ins));
             }
             else
             {
@@ -351,11 +410,6 @@ static int storeLinkPayload(OCRepPayload *rdPayload, sqlite3_int64 rowid)
 
             OICFree(uri);
             OCPayloadDestroy((OCPayload *)p);
-            for (j = 0; j < mtDim[0]; j++)
-            {
-                OICFree(mediaType[j]);
-            }
-            OICFree(mediaType);
             for (j = 0; j < rtDim[0]; j++)
             {
                 OICFree(rt[j]);
@@ -373,24 +427,21 @@ static int storeLinkPayload(OCRepPayload *rdPayload, sqlite3_int64 rowid)
     return res;
 }
 
-OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr *address)
+OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload)
 {
     CHECK_DATABASE_INIT;
 
     char *deviceId = NULL;
     OCRepPayloadGetPropString(payload, OC_RSRVD_DEVICE_ID, &deviceId);
-    int64_t ttl = 0;
-    OCRepPayloadGetPropInt(payload, OC_RSRVD_DEVICE_TTL, &ttl);
-    char rdAddress[MAX_URI_LENGTH];
-    snprintf(rdAddress, MAX_URI_LENGTH, "%s:%d", address->addr, address->port);
-    OIC_LOG_V(DEBUG, TAG, "Address: %s", rdAddress);
+    sqlite3_int64 ttl = 0;
+    OCRepPayloadGetPropInt(payload, OC_RSRVD_DEVICE_TTL, (int64_t *) &ttl);
 
     /* INSERT OR IGNORE then UPDATE to update or insert the row without triggering the cascading deletes */
     VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
 
     sqlite3_stmt *stmt = 0;
-    const char *insertDeviceList = "INSERT OR IGNORE INTO RD_DEVICE_LIST (ID, di, ttl, ADDRESS) "
-        "VALUES ((SELECT ID FROM RD_DEVICE_LIST WHERE di=@deviceId), @deviceId, @ttl, @rdAddress)";
+    const char *insertDeviceList = "INSERT OR IGNORE INTO RD_DEVICE_LIST (ID, di, ttl) "
+        "VALUES ((SELECT ID FROM RD_DEVICE_LIST WHERE di=@deviceId), @deviceId, @ttl)";
     VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertDeviceList, strlen(insertDeviceList) + 1, &stmt, NULL));
 
     if (deviceId)
@@ -402,8 +453,6 @@ OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr
     {
         VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@ttl"), ttl));
     }
-    VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@rdAddress"),
-                                    rdAddress, strlen(rdAddress), SQLITE_STATIC));
     if (sqlite3_step(stmt) != SQLITE_DONE)
     {
         sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
@@ -412,7 +461,7 @@ OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr
     }
     VERIFY_SQLITE(sqlite3_finalize(stmt));
 
-    const char *updateDeviceList = "UPDATE RD_DEVICE_LIST SET ttl=@ttl,ADDRESS=@rdAddress WHERE di=@deviceId";
+    const char *updateDeviceList = "UPDATE RD_DEVICE_LIST SET ttl=@ttl WHERE di=@deviceId";
     VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, updateDeviceList, strlen(updateDeviceList) + 1,
                                      &stmt, NULL));
     if (deviceId)
@@ -424,8 +473,6 @@ OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr
     {
         VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@ttl"), ttl));
     }
-    VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@rdAddress"),
-                                    rdAddress, strlen(rdAddress), SQLITE_STATIC));
     if (sqlite3_step(stmt) != SQLITE_DONE)
     {
         sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
@@ -447,7 +494,7 @@ OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr
     int res = sqlite3_step(stmt);
     if (res == SQLITE_ROW || res == SQLITE_DONE)
     {
-        int64_t rowid = sqlite3_column_int64(stmt, 0);
+        sqlite3_int64 rowid = sqlite3_column_int64(stmt, 0);
         VERIFY_SQLITE(sqlite3_finalize(stmt));
         VERIFY_SQLITE(storeLinkPayload(payload, rowid));
     }
index 730819c..18f6912 100644 (file)
@@ -19,6 +19,7 @@
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 #include "rd_client.h"
 
+#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -27,7 +28,9 @@
 #include "octypes.h"
 #include "ocstack.h"
 #include "ocpayload.h"
+#include "ocendpoint.h"
 #include "payload_logging.h"
+#include "cainterface.h"
 
 #define TAG "OIC_RD_CLIENT"
 
@@ -137,130 +140,185 @@ OCStackResult OCRDPublish(OCDoHandle *handle, const char *host,
 }
 
 static OCRepPayload *RDPublishPayloadCreate(const unsigned char *id,
-                                            const OCResourceHandle *resourceHandles, uint8_t nHandles)
+        const OCResourceHandle *resourceHandles, uint8_t nHandles)
 {
-    OCRepPayload *rdPayload =  (OCRepPayload *)OCRepPayloadCreate();
+    assert(id);
+
+    OCStackResult result = OC_STACK_ERROR;
+    OCRepPayload *rdPayload = NULL;
+    size_t dim[MAX_REP_ARRAY_DEPTH] = {0};
+    CAEndpoint_t *caEps = NULL;
+    size_t nCaEps = 0;
+    OCRepPayload **eps = NULL;
+
+    rdPayload =  (OCRepPayload *)OCRepPayloadCreate();
     if (!rdPayload)
     {
-        return NULL;
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        goto exit;
     }
 
-    if (id)
+    // Common properties
+    dim[0] = 1;
+    char **rts = (char **)OICCalloc(dim[0], sizeof(char *));
+    if (!rts)
     {
-        OCRepPayloadSetPropString(rdPayload, OC_RSRVD_DEVICE_ID, (const char*) id);
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        goto exit;
     }
+    rts[0] = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
+    OCRepPayloadSetStringArrayAsOwner(rdPayload, OC_RSRVD_RESOURCE_TYPE, rts, dim);
 
-    char *deviceName = NULL;
-    OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **) &deviceName);
-    if (deviceName)
+    dim[0] = 2;
+    char **ifs = (char **)OICCalloc(dim[0], sizeof(char *));
+    if (!ifs)
     {
-        OCRepPayloadSetPropString(rdPayload, OC_RSRVD_DEVICE_NAME, deviceName);
-        OICFree(deviceName);
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        goto exit;
     }
+    ifs[0] = OICStrdup(OC_RSRVD_INTERFACE_LL);
+    ifs[1] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
+    OCRepPayloadSetStringArrayAsOwner(rdPayload, OC_RSRVD_INTERFACE, ifs, dim);
 
-    char *platformModelName = NULL;
-    OCGetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, (void **) &platformModelName);
-    if (platformModelName)
+    char *n;
+    OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **) &n);
+    if (n)
     {
-        OCRepPayloadSetPropString(rdPayload, OC_DATA_MODEL_NUMBER, platformModelName);
-        OICFree(platformModelName);
+        OCRepPayloadSetPropStringAsOwner(rdPayload, OC_RSRVD_DEVICE_NAME, n);
     }
 
+    // oic.wk.rdpub properties
+    OCRepPayloadSetPropString(rdPayload, OC_RSRVD_DEVICE_ID, (const char*) id);
     OCRepPayloadSetPropInt(rdPayload, OC_RSRVD_DEVICE_TTL, OIC_RD_PUBLISH_TTL);
 
-    OCRepPayload **linkArr = (OCRepPayload**)OICCalloc(nHandles, sizeof(OCRepPayload *));
-    if (!linkArr)
+    dim[0] = nHandles;
+    OCRepPayload **links = (OCRepPayload **)OICCalloc(dim[0], sizeof(OCRepPayload *));
+    if (!links)
     {
-        OCRepPayloadDestroy(rdPayload);
-        return NULL;
+        goto exit;
     }
-
-    size_t dimensions[MAX_REP_ARRAY_DEPTH] = {nHandles, 0, 0};
+    OCRepPayloadSetPropObjectArrayAsOwner(rdPayload, OC_RSRVD_LINKS, links, dim);
     for (uint8_t j = 0; j < nHandles; j++)
     {
         OCResourceHandle handle = resourceHandles[j];
         if (handle)
         {
-            OCRepPayload *link = OCRepPayloadCreate();
+            links[j] = OCRepPayloadCreate();
 
             const char *uri = OCGetResourceUri(handle);
             if (uri)
             {
-                OCRepPayloadSetPropString(link, OC_RSRVD_HREF, uri);
+                OCRepPayloadSetPropString(links[j], OC_RSRVD_HREF, uri);
             }
 
-            uint8_t numElement = 0;
-            if (OC_STACK_OK == OCGetNumberOfResourceTypes(handle, &numElement))
+            uint8_t n;
+            if (OC_STACK_OK == OCGetNumberOfResourceTypes(handle, &n))
             {
-                size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
-                char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
-                for (uint8_t i = 0; i < numElement; ++i)
+                dim[0] = n;
+                char **rts = (char **)OICCalloc(n, sizeof(char *));
+                for (uint8_t i = 0; i < n; i++)
                 {
-                    const char *value = OCGetResourceTypeName(handle, i);
-                    OIC_LOG_V(DEBUG, TAG, "value: %s", value);
-                    rt[i] = OICStrdup(value);
+                    rts[i] = OICStrdup(OCGetResourceTypeName(handle, i));
+                    OIC_LOG_V(DEBUG, TAG, "value: %s", rts[i]);
                 }
-                OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_RESOURCE_TYPE, rt, rtDim);
+                OCRepPayloadSetStringArrayAsOwner(links[j], OC_RSRVD_RESOURCE_TYPE, rts, dim);
             }
 
-            numElement = 0;
-            if (OC_STACK_OK == OCGetNumberOfResourceInterfaces(handle, &numElement))
+            if (OC_STACK_OK == OCGetNumberOfResourceInterfaces(handle, &n))
             {
-                size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
-                char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
-                for (uint8_t i = 0; i < numElement; ++i)
+                dim[0] = n;
+                char **ifs = (char **)OICCalloc(n, sizeof(char *));
+                for (uint8_t i = 0; i < n; i++)
                 {
-                    const char *value = OCGetResourceInterfaceName(handle, i);
-                    OIC_LOG_V(DEBUG, TAG, "value: %s", value);
-                    itf[i] = OICStrdup(value);
+                    ifs[i] = OICStrdup(OCGetResourceInterfaceName(handle, i));
+                    OIC_LOG_V(DEBUG, TAG, "value: %s", ifs[i]);
                 }
-                OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_INTERFACE, itf, ifDim);
+                OCRepPayloadSetStringArrayAsOwner(links[j], OC_RSRVD_INTERFACE, ifs, dim);
             }
 
-            int64_t ins = 0;
+            // rel is always the default ("hosts")
+
+            char anchor[MAX_URI_LENGTH];
+            snprintf(anchor, MAX_URI_LENGTH, "ocf://%s", id);
+            OCRepPayloadSetPropString(links[j], OC_RSRVD_URI, anchor);
+
+            int64_t ins;
             if (OC_STACK_OK == OCGetResourceIns(handle, &ins))
             {
-                OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins);
+                OCRepPayloadSetPropInt(links[j], OC_RSRVD_INS, ins);
             }
 
-            size_t mtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
-            char **mediaType = (char **)OICMalloc(sizeof(char *) * 1);
-            if (!mediaType)
+            OCResourceProperty p = OCGetResourceProperties(handle);
+            bool isSecure = (p & OC_SECURE);
+            p &= (OC_DISCOVERABLE | OC_OBSERVABLE);
+            OCRepPayload *policy = OCRepPayloadCreate();
+            if (!policy)
             {
                 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+                goto exit;
+            }
+            OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, p);
+            OCRepPayloadSetPropObjectAsOwner(links[j], OC_RSRVD_POLICY, policy);
 
-                for(uint8_t i = 0; i < nHandles; i++)
+            CAResult_t caResult = CAGetNetworkInformation(&caEps, &nCaEps);
+            if (CA_STATUS_FAILED == caResult)
+            {
+                OIC_LOG(ERROR, TAG, "CAGetNetworkInformation failed!");
+                goto exit;
+            }
+            if (nCaEps)
+            {
+                dim[0] = 0;
+                for (uint32_t i = 0; i < nCaEps; i++)
                 {
-                    OCRepPayloadDestroy(linkArr[i]);
+                    if (isSecure == (bool)(caEps[i].flags & OC_FLAG_SECURE))
+                    {
+                        ++dim[0];
+                    }
+                }
+                eps = (OCRepPayload **)OICCalloc(dim[0], sizeof(OCRepPayload *));
+                if (!eps)
+                {
+                    OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+                    goto exit;
+                }
+                OCRepPayloadSetPropObjectArrayAsOwner(links[j], OC_RSRVD_ENDPOINTS, eps, dim);
+                uint32_t k = 0;
+                for (uint32_t i = 0; i < nCaEps; i++)
+                {
+                    if (isSecure == (bool)(caEps[i].flags & OC_FLAG_SECURE))
+                    {
+                        eps[k] = OCRepPayloadCreate();
+                        if (!eps[k])
+                        {
+                            OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+                            break;
+                        }
+                        char *epStr = OCCreateEndpointStringFromCA(&caEps[i]);
+                        if (!epStr)
+                        {
+                            OIC_LOG(ERROR, TAG, "Create endpoint string failed!");
+                            break;
+                        }
+                        OCRepPayloadSetPropStringAsOwner(eps[k], OC_RSRVD_ENDPOINT, epStr);
+                        OCRepPayloadSetPropInt(eps[k], OC_RSRVD_PRIORITY, 1);
+                        ++k;
+                    }
                 }
-                OICFree(linkArr);
-                OCRepPayloadDestroy(rdPayload);
-                return NULL;
             }
-
-            mediaType[0] = OICStrdup(OC_MEDIA_TYPE_APPLICATION_JSON);
-            OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_MEDIA_TYPE, mediaType,
-            mtDim);
-
-            OCResourceProperty p = OCGetResourceProperties(handle);
-            p = (OCResourceProperty) ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE));
-            OCRepPayload *policy = OCRepPayloadCreate();
-            OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, p);
-            OCRepPayloadSetPropObjectAsOwner(link, OC_RSRVD_POLICY, policy);
-
-            linkArr[j] = link;
         }
     }
 
-    OCRepPayloadSetPropObjectArray(rdPayload, OC_RSRVD_LINKS, (const OCRepPayload **)linkArr, dimensions);
     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload);
+    result = OC_STACK_OK;
 
-    for (uint8_t i = 0; i < nHandles; i++)
+exit:
+    OICFree(caEps);
+    if (OC_STACK_OK != result)
     {
-        OCRepPayloadDestroy(linkArr[i]);
+        OCRepPayloadDestroy(rdPayload);
+        rdPayload = NULL;
     }
-    OICFree(linkArr);
-
     return rdPayload;
 }
 
@@ -323,8 +381,13 @@ OCStackResult OCRDPublishWithDeviceId(OCDoHandle *handle, const char *host,
     rdPublishCbData.context = rdPublishContext;
     rdPublishCbData.cb = RDPublishCallback;
     rdPublishCbData.cd = RDPublishContextDeleter;
+    OCHeaderOption options[2];
+    size_t numOptions = 0;
+    uint16_t format = COAP_MEDIATYPE_APPLICATION_VND_OCF_CBOR;
+    OCSetHeaderOption(options, &numOptions, CA_OPTION_CONTENT_FORMAT, &format, sizeof(format));
+    OCSetHeaderOption(options, &numOptions, CA_OPTION_ACCEPT, &format, sizeof(format));
     return OCDoResource(handle, OC_REST_POST, targetUri, NULL, (OCPayload *)rdPayload,
-                        connectivityType, qos, &rdPublishCbData, NULL, 0);
+                        connectivityType, qos, &rdPublishCbData, options, numOptions);
 }
 
 OCStackResult OCRDDelete(OCDoHandle *handle, const char *host,
index 05d2369..d587632 100644 (file)
@@ -116,7 +116,7 @@ static OCEntityHandlerResult handlePublishRequest(const OCEntityHandlerRequest *
         OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) payload);
         if (OC_STACK_OK == OCRDDatabaseInit(NULL))
         {
-            if (OC_STACK_OK == OCRDDatabaseStoreResources(payload, &ehRequest->devAddr))
+            if (OC_STACK_OK == OCRDDatabaseStoreResources(payload))
             {
                 OIC_LOG_V(DEBUG, TAG, "Stored resources.");
                 resPayload = payload;
index 560fa5c..a5a6f9f 100644 (file)
@@ -60,6 +60,8 @@ rd_test_env.AppendUnique(
                 src_dir + '/extlibs/hippomocks-master',
                 '../include',
                 src_dir + '/resource/include',
+                src_dir + '/resource/csdk/connectivity/api',
+                src_dir + '/resource/csdk/connectivity/lib/libcoap-4.1.1/include',
                 src_dir + '/resource/csdk/include',
                 src_dir + '/resource/csdk/stack/include',
                 src_dir + '/resource/csdk/security/include',
index 5fafd74..613e4fd 100644 (file)
@@ -91,7 +91,6 @@ typedef struct Resource
     const char *uri;
     const char *rt;
     const char *itf;
-    const char *mt;
     uint8_t bm;
 } Resource;
 
@@ -112,6 +111,9 @@ static OCRepPayload *CreateRDPublishPayload(const char *deviceId,
     {
         OCRepPayload *link = OCRepPayloadCreate();
         OCRepPayloadSetPropString(link, OC_RSRVD_HREF, resources[i].uri);
+        char anchor[MAX_URI_LENGTH];
+        snprintf(anchor, MAX_URI_LENGTH, "ocf://%s", deviceId);
+        OCRepPayloadSetPropString(link, OC_RSRVD_URI, anchor);
         size_t rtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
         char **rt = (char **)OICMalloc(sizeof(char *) * 1);
         rt[0] = OICStrdup(resources[i].rt);
@@ -122,14 +124,18 @@ static OCRepPayload *CreateRDPublishPayload(const char *deviceId,
         itf[0] = OICStrdup(resources[i].itf);
         OCRepPayloadSetStringArray(link, OC_RSRVD_INTERFACE, (const char **)itf,
                                    itfDim);
-        size_t mtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
-        char **mt = (char **)OICMalloc(sizeof(char *) * 1);
-        mt[0] = OICStrdup(resources[i].mt);
-        OCRepPayloadSetStringArray(link, OC_RSRVD_MEDIA_TYPE, (const char **)mt,
-                                   mtDim);
         OCRepPayload *policy = OCRepPayloadCreate();
         OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, resources[i].bm);
         OCRepPayloadSetPropObjectAsOwner(link, OC_RSRVD_POLICY, policy);
+        size_t epsDim[MAX_REP_ARRAY_DEPTH] = {2, 0, 0};
+        OCRepPayload *eps[2];
+        eps[0] = OCRepPayloadCreate();
+        OCRepPayloadSetPropString(eps[0], OC_RSRVD_ENDPOINT, "coap://127.0.0.1:1234");
+        OCRepPayloadSetPropInt(eps[0], OC_RSRVD_PRIORITY, 1);
+        eps[1] = OCRepPayloadCreate();
+        OCRepPayloadSetPropString(eps[1], OC_RSRVD_ENDPOINT, "coaps://[::1]:5678");
+        OCRepPayloadSetPropInt(eps[1], OC_RSRVD_PRIORITY, 1);
+        OCRepPayloadSetPropObjectArray(link, OC_RSRVD_ENDPOINTS, (const OCRepPayload **)eps, epsDim);
         linkArr[i] = link;
     }
 
@@ -139,11 +145,26 @@ static OCRepPayload *CreateRDPublishPayload(const char *deviceId,
     return repPayload;
 }
 
+static void EndpointsVerify(const OCEndpointPayload *eps)
+{
+    EXPECT_STREQ(eps->tps, "coap");
+    EXPECT_STREQ(eps->addr, "127.0.0.1");
+    EXPECT_EQ(eps->family, OC_IP_USE_V4);
+    EXPECT_EQ(eps->port, 1234);
+    EXPECT_EQ(eps->pri, 1);
+    EXPECT_STREQ(eps->next->tps, "coaps");
+    EXPECT_STREQ(eps->next->addr, "::1");
+    EXPECT_EQ(eps->next->family, (OC_FLAG_SECURE | OC_IP_USE_V6));
+    EXPECT_EQ(eps->next->port, 5678);
+    EXPECT_EQ(eps->next->pri, 1);
+    EXPECT_TRUE(eps->next->next == NULL);
+}
+
 static OCRepPayload *CreateResources(const char *deviceId)
 {
     Resource resources[] = {
-        { "/a/thermostat", "core.thermostat", OC_RSRVD_INTERFACE_DEFAULT, OC_MEDIA_TYPE_APPLICATION_JSON, OC_DISCOVERABLE },
-        { "/a/light", "core.light", OC_RSRVD_INTERFACE_DEFAULT, OC_MEDIA_TYPE_APPLICATION_JSON, OC_DISCOVERABLE }
+        { "/a/thermostat", "core.thermostat", OC_RSRVD_INTERFACE_DEFAULT, OC_DISCOVERABLE },
+        { "/a/light", "core.light", OC_RSRVD_INTERFACE_DEFAULT, OC_DISCOVERABLE }
     };
     return CreateRDPublishPayload(deviceId, resources, 2);
 }
@@ -158,11 +179,8 @@ TEST_F(RDDatabaseTests, StoreResources)
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
     const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
     OCRepPayload *repPayload = CreateResources(deviceId);
-    OCDevAddr address;
-    address.port = 54321;
-    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
 
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload));
 
     OCDiscoveryPayload *discPayload = NULL;
     EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDiscoveryPayloadCreate(NULL, "core.light", &discPayload));
@@ -185,19 +203,16 @@ TEST_F(RDDatabaseTests, AddResources)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
     const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
-    OCDevAddr address;
-    address.port = 54321;
-    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
 
     OCRepPayload *repPayload = CreateResources(deviceId);
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload));
     OCPayloadDestroy((OCPayload *)repPayload);
 
     Resource resources[] = {
-        { "/a/light2", "core.light", OC_RSRVD_INTERFACE_DEFAULT, OC_MEDIA_TYPE_APPLICATION_JSON, OC_DISCOVERABLE }
+        { "/a/light2", "core.light", OC_RSRVD_INTERFACE_DEFAULT, OC_DISCOVERABLE }
     };
     repPayload = CreateRDPublishPayload(deviceId, resources, 1);
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload));
     OCPayloadDestroy((OCPayload *)repPayload);
 
     OCDiscoveryPayload *discPayload = NULL;
@@ -225,29 +240,24 @@ TEST_F(RDDatabaseTests, AddResources)
     EXPECT_TRUE(foundLight2);
     OCDiscoveryPayloadDestroy(discPayload);
     discPayload = NULL;
-
-    OCPayloadDestroy((OCPayload *)repPayload);
 }
 
 TEST_F(RDDatabaseTests, UpdateResources)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
-    const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
-    OCDevAddr address;
-    address.port = 54321;
-    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
+    const char *anchor = "ocf://7a960f46-a52e-4837-bd83-460b1a6dd56b";
+    const char *deviceId = &anchor[6];
 
     OCRepPayload *repPayload = CreateResources(deviceId);
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload));
     OCPayloadDestroy((OCPayload *)repPayload);
 
     Resource resources[] = {
-        { "/a/thermostat", "x.core.r.thermostat", "x.core.if.thermostat", "application/cbor", OC_DISCOVERABLE | OC_OBSERVABLE },
-        { "/a/light", "x.core.r.light", "x.core.if.light", "application/cbor", OC_DISCOVERABLE | OC_OBSERVABLE }
+        { "/a/thermostat", "x.core.r.thermostat", "x.core.if.thermostat", OC_DISCOVERABLE | OC_OBSERVABLE },
+        { "/a/light", "x.core.r.light", "x.core.if.light", OC_DISCOVERABLE | OC_OBSERVABLE }
     };
     repPayload = CreateRDPublishPayload(deviceId, resources, 2);
-    address.port = 12345;
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload));
     OCPayloadDestroy((OCPayload *)repPayload);
 
     OCDiscoveryPayload *discPayload = NULL;
@@ -264,6 +274,8 @@ TEST_F(RDDatabaseTests, UpdateResources)
             EXPECT_STREQ("x.core.if.thermostat", resource->interfaces->value);
             EXPECT_TRUE(resource->interfaces->next == NULL);
             EXPECT_EQ(OC_DISCOVERABLE | OC_OBSERVABLE, resource->bitmap);
+            EXPECT_STREQ(anchor, resource->anchor);
+            EndpointsVerify(resource->eps);
         }
         else if (!strcmp("/a/light", resource->uri))
         {
@@ -273,36 +285,33 @@ TEST_F(RDDatabaseTests, UpdateResources)
             EXPECT_STREQ("x.core.if.light", resource->interfaces->value);
             EXPECT_TRUE(resource->interfaces->next == NULL);
             EXPECT_EQ(OC_DISCOVERABLE | OC_OBSERVABLE, resource->bitmap);
+            EXPECT_STREQ(anchor, resource->anchor);
+            EndpointsVerify(resource->eps);
         }
     }
     EXPECT_TRUE(foundThermostat);
     EXPECT_TRUE(foundLight);
     OCDiscoveryPayloadDestroy(discPayload);
     discPayload = NULL;
-
-    OCPayloadDestroy((OCPayload *)repPayload);
 }
 
 TEST_F(RDDatabaseTests, AddAndUpdateResources)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
-    const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
-    OCDevAddr address;
-    address.port = 54321;
-    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
+    const char *anchor = "ocf://7a960f46-a52e-4837-bd83-460b1a6dd56b";
+    const char *deviceId = &anchor[6];
 
     OCRepPayload *repPayload = CreateResources(deviceId);
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload));
     OCPayloadDestroy((OCPayload *)repPayload);
 
     Resource resources[] = {
-        { "/a/thermostat", "x.core.r.thermostat", "x.core.if.thermostat", "application/cbor", OC_DISCOVERABLE | OC_OBSERVABLE },
-        { "/a/light", "x.core.r.light", "x.core.if.light", "application/cbor", OC_DISCOVERABLE | OC_OBSERVABLE },
-        { "/a/light2", "core.light", OC_RSRVD_INTERFACE_DEFAULT, OC_MEDIA_TYPE_APPLICATION_JSON, OC_DISCOVERABLE }
+        { "/a/thermostat", "x.core.r.thermostat", "x.core.if.thermostat", OC_DISCOVERABLE | OC_OBSERVABLE },
+        { "/a/light", "x.core.r.light", "x.core.if.light", OC_DISCOVERABLE | OC_OBSERVABLE },
+        { "/a/light2", "core.light", OC_RSRVD_INTERFACE_DEFAULT, OC_DISCOVERABLE }
     };
     repPayload = CreateRDPublishPayload(deviceId, resources, 3);
-    address.port = 12345;
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload));
     OCPayloadDestroy((OCPayload *)repPayload);
 
     OCDiscoveryPayload *discPayload = NULL;
@@ -320,6 +329,8 @@ TEST_F(RDDatabaseTests, AddAndUpdateResources)
             EXPECT_STREQ("x.core.if.thermostat", resource->interfaces->value);
             EXPECT_TRUE(resource->interfaces->next == NULL);
             EXPECT_EQ(OC_DISCOVERABLE | OC_OBSERVABLE, resource->bitmap);
+            EXPECT_STREQ(anchor, resource->anchor);
+            EndpointsVerify(resource->eps);
         }
         else if (!strcmp("/a/light", resource->uri))
         {
@@ -329,6 +340,8 @@ TEST_F(RDDatabaseTests, AddAndUpdateResources)
             EXPECT_STREQ("x.core.if.light", resource->interfaces->value);
             EXPECT_TRUE(resource->interfaces->next == NULL);
             EXPECT_EQ(OC_DISCOVERABLE | OC_OBSERVABLE, resource->bitmap);
+            EXPECT_STREQ(anchor, resource->anchor);
+            EndpointsVerify(resource->eps);
         }
         else if (!strcmp("/a/light2", resource->uri))
         {
@@ -338,6 +351,8 @@ TEST_F(RDDatabaseTests, AddAndUpdateResources)
             EXPECT_STREQ(OC_RSRVD_INTERFACE_DEFAULT, resource->interfaces->value);
             EXPECT_TRUE(resource->interfaces->next == NULL);
             EXPECT_EQ(OC_DISCOVERABLE, resource->bitmap);
+            EXPECT_STREQ(anchor, resource->anchor);
+            EndpointsVerify(resource->eps);
         }
     }
     EXPECT_TRUE(foundThermostat);
@@ -345,8 +360,6 @@ TEST_F(RDDatabaseTests, AddAndUpdateResources)
     EXPECT_TRUE(foundLight2);
     OCDiscoveryPayloadDestroy(discPayload);
     discPayload = NULL;
-
-    OCPayloadDestroy((OCPayload *)repPayload);
 }
 
 TEST_F(RDDatabaseTests, DeleteResourcesDevice)
@@ -360,11 +373,8 @@ TEST_F(RDDatabaseTests, DeleteResourcesDevice)
     OCRepPayload *payloads[2];
     payloads[0] = CreateResources(deviceIds[0]);
     payloads[1] = CreateResources(deviceIds[1]);
-    OCDevAddr address;
-    address.port = 54321;
-    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(payloads[0], &address));
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(payloads[1], &address));
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(payloads[0]));
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(payloads[1]));
 
     EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDeleteResources(deviceIds[0], NULL, 0));
 
index 919510f..35c5f54 100644 (file)
@@ -28,6 +28,8 @@ extern "C"
     #include "oic_malloc.h"
     #include "oic_string.h"
     #include "payload_logging.h"
+    #include "cacommon.h"
+    #include "coap/pdu.h"
 }
 
 #include "gtest/gtest.h"
@@ -298,12 +300,15 @@ TEST_F(RDTests, RDDeleteSpecificResource)
 #endif
 
 #if (defined(RD_SERVER) && defined(RD_CLIENT))
-class RDDiscoverTests : public testing::Test
+class RDDiscoverTests : public ::testing::TestWithParam<uint16_t>
 {
     protected:
         virtual void SetUp()
         {
             remove("RD.db");
+            numOptions = 0;
+            uint16_t format = GetParam();
+            OCSetHeaderOption(options, &numOptions, CA_OPTION_ACCEPT, &format, sizeof(format));
             EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER));
             EXPECT_EQ(OC_STACK_OK, OCRDStart());
         }
@@ -315,6 +320,8 @@ class RDDiscoverTests : public testing::Test
         }
     public:
         static const unsigned char *di[3];
+        OCHeaderOption options[1];
+        size_t numOptions;
 };
 const unsigned char *RDDiscoverTests::di[3] =
 {
@@ -323,6 +330,17 @@ const unsigned char *RDDiscoverTests::di[3] =
     (const unsigned char *) "9338c0b2-2373-4324-ba78-17c0ef79506d"
 };
 
+static bool EndsWith(const char *str, const char *suffix)
+{
+    size_t len = strlen(str);
+    size_t suffixLen = strlen(suffix);
+    if (len < suffixLen)
+    {
+        return false;
+    }
+    return !strcmp(&str[len - suffixLen], suffix);
+}
+
 static OCStackApplicationResult DiscoverAllResourcesVerify(void *ctx,
         OCDoHandle handle,
         OCClientResponse *response)
@@ -345,13 +363,13 @@ static OCStackApplicationResult DiscoverAllResourcesVerify(void *ctx,
                 foundId = true;
                 for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
                 {
-                    if (!strcmp("/a/light", resource->uri))
+                    if (EndsWith(resource->uri, "/a/light2"))
                     {
-                        foundLight = true;
+                        foundLight2 = true;
                     }
-                    if (!strcmp("/a/light2", resource->uri))
+                    else if (EndsWith(resource->uri, "/a/light"))
                     {
-                        foundLight2 = true;
+                        foundLight = true;
                     }
                 }
             }
@@ -363,7 +381,7 @@ static OCStackApplicationResult DiscoverAllResourcesVerify(void *ctx,
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, DiscoverAllResources)
+TEST_P(RDDiscoverTests, DiscoverAllResources)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -381,7 +399,7 @@ TEST_F(RDDiscoverTests, DiscoverAllResources)
 
     itst::Callback discoverCB(&DiscoverAllResourcesVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res", NULL, 0, CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -401,10 +419,9 @@ static OCStackApplicationResult ResourceQueryMatchesLocalAndRemoteVerify(void *c
              payload = payload->next)
         {
             EXPECT_TRUE(payload->resources != NULL);
-            if (payload->resources)
+            for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
             {
-                EXPECT_TRUE(payload->resources->next == NULL);
-                EXPECT_STREQ("/a/light", payload->resources->uri);
+                EXPECT_TRUE(EndsWith(payload->resources->uri, "/a/light"));
                 EXPECT_STREQ("core.light", payload->resources->types->value);
                 EXPECT_TRUE(payload->resources->types->next == NULL);
             }
@@ -413,7 +430,7 @@ static OCStackApplicationResult ResourceQueryMatchesLocalAndRemoteVerify(void *c
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, ResourceQueryMatchesLocalAndRemote)
+TEST_P(RDDiscoverTests, ResourceQueryMatchesLocalAndRemote)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -428,8 +445,7 @@ TEST_F(RDDiscoverTests, ResourceQueryMatchesLocalAndRemote)
 
     itst::Callback discoverCB(&ResourceQueryMatchesLocalAndRemoteVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=core.light", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -451,7 +467,7 @@ static OCStackApplicationResult ResourceQueryMatchesLocalOnlyVerify(void *ctx,
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, ResourceQueryMatchesLocalOnly)
+TEST_P(RDDiscoverTests, ResourceQueryMatchesLocalOnly)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -471,8 +487,7 @@ TEST_F(RDDiscoverTests, ResourceQueryMatchesLocalOnly)
 
     itst::Callback discoverCB(&ResourceQueryMatchesLocalOnlyVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=core.light", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -502,7 +517,7 @@ static void SetStringArray(OCRepPayload *payload, const char *name, const char *
     OCRepPayloadSetStringArray(payload, name, (const char **)ss, dim);
 }
 
-TEST_F(RDDiscoverTests, ResourceQueryMatchesRemoteOnly)
+TEST_P(RDDiscoverTests, ResourceQueryMatchesRemoteOnly)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -541,13 +556,12 @@ TEST_F(RDDiscoverTests, ResourceQueryMatchesRemoteOnly)
 
     itst::Callback publishCB(&handlePublishCB);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_POST, "127.0.0.1/oic/rd?rt=oic.wk.rdpub", NULL,
-                                        (OCPayload *)repPayload, CT_DEFAULT, OC_HIGH_QOS, publishCB, NULL, 0));
+                    (OCPayload *)repPayload, CT_DEFAULT, OC_HIGH_QOS, publishCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, publishCB.Wait(100));
 
     itst::Callback discoverCB(&ResourceQueryMatchesRemoteOnlyVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=core.light2", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT,OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -568,7 +582,7 @@ static OCStackApplicationResult DatabaseHas0ResourceQueryMatchesVerify(void *ctx
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, DatabaseHas0ResourceQueryMatches)
+TEST_P(RDDiscoverTests, DatabaseHas0ResourceQueryMatches)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -600,8 +614,7 @@ TEST_F(RDDiscoverTests, DatabaseHas0ResourceQueryMatches)
 
     itst::Callback discoverCB(&DatabaseHas0ResourceQueryMatchesVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=core.light", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT,OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -622,10 +635,9 @@ static OCStackApplicationResult DatabaseHas1ResourceQueryMatchVerify(void *ctx,
         {
             payload = payload->next;
             EXPECT_TRUE(payload->resources != NULL);
-            if (payload->resources)
+            for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
             {
-                EXPECT_TRUE(payload->resources->next == NULL);
-                EXPECT_STREQ("/a/light2", payload->resources->uri);
+                EXPECT_TRUE(EndsWith(payload->resources->uri, "/a/light2"));
                 EXPECT_STREQ("core.light2", payload->resources->types->value);
                 EXPECT_TRUE(payload->resources->types->next == NULL);
             }
@@ -636,7 +648,7 @@ static OCStackApplicationResult DatabaseHas1ResourceQueryMatchVerify(void *ctx,
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, DatabaseHas1ResourceQueryMatch)
+TEST_P(RDDiscoverTests, DatabaseHas1ResourceQueryMatch)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -668,8 +680,7 @@ TEST_F(RDDiscoverTests, DatabaseHas1ResourceQueryMatch)
 
     itst::Callback discoverCB(&DatabaseHas1ResourceQueryMatchVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=core.light2", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -692,9 +703,8 @@ static OCStackApplicationResult DatabaseHasNResourceQueryMatchesVerify(void *ctx
             for (int i = 0; i < 3; ++i)
             {
                 EXPECT_TRUE(payload->resources != NULL);
-                if (payload->resources)
+                for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
                 {
-                    EXPECT_TRUE(payload->resources->next == NULL);
                     EXPECT_STREQ("core.light", payload->resources->types->value);
                     EXPECT_TRUE(payload->resources->types->next == NULL);
                 }
@@ -706,7 +716,7 @@ static OCStackApplicationResult DatabaseHasNResourceQueryMatchesVerify(void *ctx
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, DatabaseHasNResourceQueryMatches)
+TEST_P(RDDiscoverTests, DatabaseHasNResourceQueryMatches)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -738,8 +748,7 @@ TEST_F(RDDiscoverTests, DatabaseHasNResourceQueryMatches)
 
     itst::Callback discoverCB(&DatabaseHasNResourceQueryMatchesVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=core.light", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -760,7 +769,7 @@ static OCStackApplicationResult DatabaseHas0InterfaceQueryMatchesVerify(void *ct
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, DatabaseHas0InterfaceQueryMatches)
+TEST_P(RDDiscoverTests, DatabaseHas0InterfaceQueryMatches)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -792,8 +801,7 @@ TEST_F(RDDiscoverTests, DatabaseHas0InterfaceQueryMatches)
 
     itst::Callback discoverCB(&DatabaseHas0InterfaceQueryMatchesVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?if=oic.if.one", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -816,10 +824,9 @@ static OCStackApplicationResult DatabaseHas1InterfaceQueryMatchVerify(void *ctx,
             for (int i = 0; i < 1; ++i)
             {
                 EXPECT_TRUE(payload->resources != NULL);
-                if (payload->resources)
+                for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
                 {
-                    EXPECT_TRUE(payload->resources->next == NULL);
-                    EXPECT_STREQ("/a/light2", payload->resources->uri);
+                    EXPECT_TRUE(EndsWith(payload->resources->uri, "/a/light2"));
                     bool foundInterface = false;
                     for (OCStringLL *iface = payload->resources->interfaces; iface; iface = iface->next)
                     {
@@ -838,7 +845,7 @@ static OCStackApplicationResult DatabaseHas1InterfaceQueryMatchVerify(void *ctx,
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, DatabaseHas1InterfaceQueryMatch)
+TEST_P(RDDiscoverTests, DatabaseHas1InterfaceQueryMatch)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -870,8 +877,7 @@ TEST_F(RDDiscoverTests, DatabaseHas1InterfaceQueryMatch)
 
     itst::Callback discoverCB(&DatabaseHas1InterfaceQueryMatchVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?if=oic.if.two", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -894,9 +900,8 @@ static OCStackApplicationResult DatabaseHasNInterfaceQueryMatchesVerify(void *ct
             for (int i = 0; i < 3; ++i)
             {
                 EXPECT_TRUE(payload->resources != NULL);
-                if (payload->resources)
+                for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
                 {
-                    EXPECT_TRUE(payload->resources->next == NULL);
                     bool foundInterface = false;
                     for (OCStringLL *iface = payload->resources->interfaces; iface; iface = iface->next)
                     {
@@ -915,7 +920,7 @@ static OCStackApplicationResult DatabaseHasNInterfaceQueryMatchesVerify(void *ct
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, DatabaseHasNInterfaceQueryMatches)
+TEST_P(RDDiscoverTests, DatabaseHasNInterfaceQueryMatches)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -947,8 +952,7 @@ TEST_F(RDDiscoverTests, DatabaseHasNInterfaceQueryMatches)
 
     itst::Callback discoverCB(&DatabaseHasNInterfaceQueryMatchesVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?if=oic.if.a", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -971,10 +975,9 @@ static OCStackApplicationResult ResourceAndInterfaceQueryMatchVerify(void *ctx,
             for (int i = 0; i < 1; ++i)
             {
                 EXPECT_TRUE(payload->resources != NULL);
-                if (payload->resources)
+                for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
                 {
-                    EXPECT_TRUE(payload->resources->next == NULL);
-                    EXPECT_STREQ("/a/light2", payload->resources->uri);
+                    EXPECT_TRUE(EndsWith(payload->resources->uri, "/a/light2"));
                     EXPECT_STREQ("core.light2", payload->resources->types->value);
                     EXPECT_TRUE(payload->resources->types->next == NULL);
                     bool foundInterface = false;
@@ -995,7 +998,7 @@ static OCStackApplicationResult ResourceAndInterfaceQueryMatchVerify(void *ctx,
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, ResourceAndInterfaceQueryMatch)
+TEST_P(RDDiscoverTests, ResourceAndInterfaceQueryMatch)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -1019,8 +1022,7 @@ TEST_F(RDDiscoverTests, ResourceAndInterfaceQueryMatch)
 
     itst::Callback discoverCB(&ResourceAndInterfaceQueryMatchVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=core.light2&if=oic.if.two",
-                                        NULL, 0, CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    NULL, 0, CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -1037,7 +1039,7 @@ static OCStackApplicationResult BaselineVerify(void *ctx, OCDoHandle handle,
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, Baseline)
+TEST_P(RDDiscoverTests, Baseline)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -1052,8 +1054,7 @@ TEST_F(RDDiscoverTests, Baseline)
 
     itst::Callback discoverCB(&BaselineVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?if=oic.if.baseline", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -1076,7 +1077,7 @@ static OCStackApplicationResult DeleteDeviceVerify(void *ctx, OCDoHandle handle,
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, DeleteDevice)
+TEST_P(RDDiscoverTests, DeleteDevice)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -1096,8 +1097,7 @@ TEST_F(RDDiscoverTests, DeleteDevice)
 
     itst::Callback discoverCB(&DeleteDeviceVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -1122,13 +1122,13 @@ static OCStackApplicationResult Delete1Verify(void *ctx, OCDoHandle handle,
                 foundId = true;
                 for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
                 {
-                    if (!strcmp("/a/light", resource->uri))
+                    if (EndsWith(resource->uri, "/a/light2"))
                     {
-                        foundLight = true;
+                        foundLight2 = true;
                     }
-                    if (!strcmp("/a/light2", resource->uri))
+                    else if (EndsWith(resource->uri, "/a/light"))
                     {
-                        foundLight2 = true;
+                        foundLight = true;
                     }
                 }
             }
@@ -1140,7 +1140,7 @@ static OCStackApplicationResult Delete1Verify(void *ctx, OCDoHandle handle,
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, Delete1)
+TEST_P(RDDiscoverTests, Delete1)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -1163,8 +1163,7 @@ TEST_F(RDDiscoverTests, Delete1)
 
     itst::Callback discoverCB(&Delete1Verify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
 
@@ -1190,17 +1189,17 @@ static OCStackApplicationResult DeleteNVerify(void *ctx, OCDoHandle handle,
                 foundId = true;
                 for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
                 {
-                    if (!strcmp("/a/light", resource->uri))
+                    if (EndsWith(resource->uri, "/a/light3"))
                     {
-                        foundLight = true;
+                        foundLight3 = true;
                     }
-                    if (!strcmp("/a/light2", resource->uri))
+                    else if (EndsWith(resource->uri, "/a/light2"))
                     {
                         foundLight2 = true;
                     }
-                    if (!strcmp("/a/light3", resource->uri))
+                    else if (EndsWith(resource->uri, "/a/light"))
                     {
-                        foundLight3 = true;
+                        foundLight = true;
                     }
                 }
             }
@@ -1213,7 +1212,7 @@ static OCStackApplicationResult DeleteNVerify(void *ctx, OCDoHandle handle,
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-TEST_F(RDDiscoverTests, DeleteN)
+TEST_P(RDDiscoverTests, DeleteN)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
 
@@ -1239,9 +1238,11 @@ TEST_F(RDDiscoverTests, DeleteN)
 
     itst::Callback discoverCB(&DeleteNVerify);
     EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res", NULL, 0,
-                                        CT_DEFAULT,
-                                        OC_HIGH_QOS, discoverCB, NULL, 0));
+                    CT_DEFAULT, OC_HIGH_QOS, discoverCB, options, numOptions));
     EXPECT_EQ(OC_STACK_OK, discoverCB.Wait(100));
 }
+
+INSTANTIATE_TEST_CASE_P(ContentFormat, RDDiscoverTests,
+        ::testing::Values(COAP_MEDIATYPE_APPLICATION_VND_OCF_CBOR, COAP_MEDIATYPE_APPLICATION_CBOR));
 #endif
 
index 05f70e1..00f12d5 100644 (file)
  char* OCCreateEndpointString(const OCEndpointPayload* endpoint);
 
 /*
+ * This function returns pointer of endpoint string.
+ *
+ * @param[in]  endpoint Pointer of Endpoint.
+ *
+ * @return     char pointer on success, NULL on failure.
+ */
+ char* OCCreateEndpointStringFromCA(const CAEndpoint_t* endpoint);
+
+/*
  * This function parse endpoint string from payload.
  *
  * @param[in]  endpointStr     Pointer of Endpoint string.
index 09357c1..fa9d0ce 100644 (file)
@@ -173,52 +173,49 @@ OCStackResult OCGetMatchedTpsFlags(const CATransportAdapter_t adapter,
     return OC_STACK_OK;
 }
 
-
-OCStackResult OCConvertTpsToString(const OCTpsSchemeFlags tps, char** out)
+static const char *ConvertTpsToString(const OCTpsSchemeFlags tps)
 {
-    // return given tps as string for payload
-    // OC_COAP_IPV4 -> OC_COAP
-
-    if (!out)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
     switch (tps)
     {
         case OC_COAP:
-            *out = OICStrdup(COAP_STR);
-            break;
+            return COAP_STR;
 
         case OC_COAPS:
-            *out = OICStrdup(COAPS_STR);
-            break;
+            return COAPS_STR;
 #ifdef TCP_ADAPTER
         case OC_COAP_TCP:
-            *out = OICStrdup(COAP_TCP_STR);
-            break;
+            return COAP_TCP_STR;
 
         case OC_COAPS_TCP:
-            *out = OICStrdup(COAPS_TCP_STR);
-            break;
+            return COAPS_TCP_STR;
 #endif
 #ifdef HTTP_ADAPTER
         case OC_HTTP:
-            *out = OICStrdup(HTTP_STR);
-            break;
+            return HTTP_STR;
 
         case OC_HTTPS:
-            *out = OICStrdup(HTTPS_STR);
-            break;
+            return HTTPS_STR;
 #endif
 #ifdef EDR_ADAPTER
         case OC_COAP_RFCOMM:
-            *out = OICStrdup(COAP_RFCOMM_STR);
-            break;
+            return COAP_RFCOMM_STR;
 #endif
         default:
-            return OC_STACK_INVALID_PARAM;
+            return NULL;
     }
+}
+
+OCStackResult OCConvertTpsToString(const OCTpsSchemeFlags tps, char** out)
+{
+    // return given tps as string for payload
+    // OC_COAP_IPV4 -> OC_COAP
+
+    if (!out)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    *out = OICStrdup(ConvertTpsToString(tps));
     VERIFY_NON_NULL(*out);
     return OC_STACK_OK;
 
@@ -275,6 +272,60 @@ exit:
     return NULL;
 }
 
+char* OCCreateEndpointStringFromCA(const CAEndpoint_t* endpoint)
+{
+    if (!endpoint)
+    {
+        return NULL;
+    }
+
+    OCTpsSchemeFlags tps = OC_NO_TPS;
+    OCStackResult result = OCGetMatchedTpsFlags(endpoint->adapter, endpoint->flags, &tps);
+    if (OC_STACK_OK != result)
+    {
+        return NULL;
+    }
+
+    char* buf = (char*)OICCalloc(MAX_ADDR_STR_SIZE, sizeof(char));
+    VERIFY_NON_NULL(buf);
+
+    switch (tps)
+    {
+    case OC_COAP: case OC_COAPS:
+#ifdef TCP_ADAPTER
+    case OC_COAP_TCP: case OC_COAPS_TCP:
+#endif
+#ifdef HTTP_ADAPTER
+    case OC_HTTP: case OC_HTTPS:
+#endif
+        // checking addr is ipv4 or not
+        if (endpoint->flags & CA_IPV4)
+        {
+            // ipv4
+            sprintf(buf, "%s://%s:%d", ConvertTpsToString(tps), endpoint->addr, endpoint->port);
+        }
+        else
+        {
+            // ipv6
+            sprintf(buf, "%s://[%s]:%d", ConvertTpsToString(tps), endpoint->addr, endpoint->port);
+        }
+        break;
+#ifdef EDR_ADAPTER
+    case OC_COAP_RFCOMM:
+        // coap+rfcomm
+        sprintf(buf, "%s://%s", ConvertTpsToString(tps), endpoint->addr);
+        break;
+#endif
+    default:
+        OIC_LOG_V(ERROR, TAG, "Payload has invalid TPS!!! %d", tps);
+        return NULL;
+    }
+    return buf;
+
+exit:
+    return NULL;
+}
+
 OCStackResult OCParseEndpointString(const char* endpointStr, OCEndpointPayload* out)
 {
     if (!endpointStr || !out)
@@ -292,6 +343,7 @@ OCStackResult OCParseEndpointString(const char* endpointStr, OCEndpointPayload*
     size_t addrCharsToWrite = 0;
     OCStackResult isEnabledAdapter = OC_STACK_ADAPTER_NOT_ENABLED;
     OCTransportAdapter parsedAdapter = OC_DEFAULT_ADAPTER;
+    bool isSecure = false;
 
     tps = (char*)OICCalloc(OC_MAX_TPS_STR_SIZE, sizeof(char));
     VERIFY_NON_NULL(tps);
@@ -324,6 +376,7 @@ OCStackResult OCParseEndpointString(const char* endpointStr, OCEndpointPayload*
     {
         isEnabledAdapter = OC_STACK_OK;
         parsedAdapter = OC_ADAPTER_IP;
+        isSecure = true;
     }
 #ifdef TCP_ADAPTER
     else if (strcmp(tps, COAP_TCP_STR) == 0)
@@ -335,6 +388,7 @@ OCStackResult OCParseEndpointString(const char* endpointStr, OCEndpointPayload*
     {
         isEnabledAdapter = OC_STACK_OK;
         parsedAdapter = OC_ADAPTER_TCP;
+        isSecure = true;
     }
 #endif
 #ifdef HTTP_ADAPTER
@@ -387,6 +441,10 @@ OCStackResult OCParseEndpointString(const char* endpointStr, OCEndpointPayload*
             tmp = strrchr(origin, OC_ENDPOINT_ADDR_TOKEN);
         }
         VERIFY_NON_NULL(tmp);
+        if (isSecure)
+        {
+            out->family = (OCTransportFlags)(out->family | OC_FLAG_SECURE);
+        }
 
         // copy addr
         addrCharsToWrite = tmp - tokPos;
index 65f1764..f9f5e3b 100755 (executable)
@@ -208,6 +208,128 @@ static int64_t OCStringLLJoin(CborEncoder *map, char *type, OCStringLL *val)
     return err;
 }
 
+static int64_t OCConvertResourcePayloadCbor(CborEncoder *linkArray, OCResourcePayload *resource,
+                                            OCEndpointPayload *endpoint)
+{
+    int64_t err = CborNoError;
+
+    // resource map inside the links array.
+    size_t linkMapLen = LINKS_MAP_LEN;
+    if (resource->rel)
+    {
+        ++linkMapLen;
+    }
+    CborEncoder linkMap;
+    err |= cbor_encoder_create_map(linkArray, &linkMap, linkMapLen);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed creating links map");
+
+    // Below are insertions of the resource properties into the map.
+
+    // Uri
+    if (endpoint)
+    {
+        char *endpointStr = OCCreateEndpointString(endpoint);
+        if (!endpointStr)
+        {
+            err = CborErrorInternalError;
+        }
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed creating endpoint string");
+        char uri[MAX_URI_LENGTH];
+        snprintf(uri, MAX_URI_LENGTH, "%s%s", endpointStr, resource->uri);
+        OICFree(endpointStr);
+
+        err |= AddTextStringToMap(&linkMap, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
+                                  uri);
+    }
+    else
+    {
+        err |= AddTextStringToMap(&linkMap, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
+                                  resource->uri);
+    }
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding uri to links map");
+
+    // Rel - Not a mandatory field
+    err |= ConditionalAddTextStringToMap(&linkMap, OC_RSRVD_REL, sizeof(OC_RSRVD_REL) - 1,
+                                         resource->rel);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding rel to links map");
+
+    // Resource Type
+    err |= OCStringLLJoin(&linkMap, OC_RSRVD_RESOURCE_TYPE, resource->types);
+    VERIFY_CBOR_SUCCESS(TAG, err,
+                        "Failed adding resourceType tag/value to links map");
+
+    // Interface Types
+    err |= OCStringLLJoin(&linkMap, OC_RSRVD_INTERFACE, resource->interfaces);
+    VERIFY_CBOR_SUCCESS(TAG, err,
+                        "Failed adding interfaces tag/value to links map");
+
+    // Policy
+    CborEncoder policyMap;
+    err |= cbor_encode_text_string(&linkMap, OC_RSRVD_POLICY,
+                                   sizeof(OC_RSRVD_POLICY) - 1);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding policy tag to links map");
+    err |= cbor_encoder_create_map(&linkMap, &policyMap, CborIndefiniteLength);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding policy map to links map");
+
+    // Bitmap
+    err |=  cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP,
+                                    sizeof(OC_RSRVD_BITMAP) - 1);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding bitmap tag to policy map");
+    err |= cbor_encode_uint(&policyMap, resource->bitmap);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding bitmap value to policy map");
+
+    // Secure
+    bool isSecure;
+    isSecure = endpoint ? (endpoint->family & OC_FLAG_SECURE) : resource->secure;
+    err |= cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE,
+                                   sizeof(OC_RSRVD_SECURE) - 1);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding secure tag to policy map");
+    err |= cbor_encode_boolean(&policyMap, isSecure);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding secure value to policy map");
+
+    if (isSecure)
+    {
+        err |= cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT,
+                                       sizeof(OC_RSRVD_HOSTING_PORT) - 1);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding secure port tag");
+        err |= cbor_encode_uint(&policyMap, endpoint ? endpoint->port : resource->port);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding secure port value");
+    }
+
+#ifdef TCP_ADAPTER
+#ifdef __WITH_TLS__
+    // tls
+    if (isSecure)
+    {
+        err |= cbor_encode_text_string(&policyMap, OC_RSRVD_TLS_PORT,
+                                       sizeof(OC_RSRVD_TLS_PORT) - 1);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp secure port tag");
+        err |= cbor_encode_uint(&policyMap, endpoint ? endpoint->port : resource->tcpPort);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp secure port value");
+    }
+
+    // tcp
+    else
+#endif
+    {
+        err |= cbor_encode_text_string(&policyMap, OC_RSRVD_TCP_PORT,
+                                       sizeof(OC_RSRVD_TCP_PORT) - 1);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp port tag");
+        err |= cbor_encode_uint(&policyMap, endpoint ? endpoint->port : resource->tcpPort);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp port value");
+    }
+#endif
+    err |= cbor_encoder_close_container(&linkMap, &policyMap);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing policy map");
+
+    // Finished encoding a resource, close the map.
+    err |= cbor_encoder_close_container(linkArray, &linkMap);
+    VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing link map");
+
+exit:
+    return err;
+}
+
 static int64_t OCConvertDiscoveryPayloadCbor(OCDiscoveryPayload *payload,
                                              uint8_t *outPayload, size_t *size)
 {
@@ -284,107 +406,32 @@ static int64_t OCConvertDiscoveryPayloadCbor(OCDiscoveryPayload *payload,
         err |= cbor_encode_text_string(&rootMap, OC_RSRVD_LINKS, sizeof(OC_RSRVD_LINKS) - 1);
         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting links array tag");
         size_t resourceCount =  OCDiscoveryPayloadGetResourceCount(payload);
-        err |= cbor_encoder_create_array(&rootMap, &linkArray, resourceCount);
+        err |= cbor_encoder_create_array(&rootMap, &linkArray, CborIndefiniteLength);
         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting links array");
 
+        bool isSelf = !strcmp(payload->sid, OCGetServerInstanceIDString());
         for (size_t i = 0; i < resourceCount; ++i)
         {
-            CborEncoder linkMap;
-            size_t linkMapLen;
             OCResourcePayload *resource = OCDiscoveryPayloadGetResource(payload, i);
             VERIFY_PARAM_NON_NULL(TAG, resource, "Failed retrieving resource");
 
-            // resource map inside the links array.
-            linkMapLen = LINKS_MAP_LEN;
-            if (resource->rel)
-            {
-                ++linkMapLen;
-            }
-            err |= cbor_encoder_create_map(&linkArray, &linkMap, linkMapLen);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed creating links map");
-
-            // Below are insertions of the resource properties into the map.
-            // Uri
-            err |= AddTextStringToMap(&linkMap, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
-                    resource->uri);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding uri to links map");
-
-            // Rel - Not a mandatory field
-            err |= ConditionalAddTextStringToMap(&linkMap, OC_RSRVD_REL, sizeof(OC_RSRVD_REL) - 1,
-                    resource->rel);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding rel to links map");
-
-            // Resource Type
-            err |= OCStringLLJoin(&linkMap, OC_RSRVD_RESOURCE_TYPE, resource->types);
-            VERIFY_CBOR_SUCCESS(TAG, err,
-                                "Failed adding resourceType tag/value to links map");
-
-            // Interface Types
-            err |= OCStringLLJoin(&linkMap, OC_RSRVD_INTERFACE, resource->interfaces);
-            VERIFY_CBOR_SUCCESS(TAG, err,
-                                "Failed adding interfaces tag/value to links map");
-
-            // Policy
-            CborEncoder policyMap;
-            err |= cbor_encode_text_string(&linkMap, OC_RSRVD_POLICY,
-                                           sizeof(OC_RSRVD_POLICY) - 1);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding policy tag to links map");
-            err |= cbor_encoder_create_map(&linkMap, &policyMap, CborIndefiniteLength);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding policy map to links map");
-
-            // Bitmap
-            err |=  cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP,
-                                            sizeof(OC_RSRVD_BITMAP) - 1);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding bitmap tag to policy map");
-            err |= cbor_encode_uint(&policyMap, resource->bitmap);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding bitmap value to policy map");
-
-            // Secure
-            err |= cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE,
-                                           sizeof(OC_RSRVD_SECURE) - 1);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding secure tag to policy map");
-            err |= cbor_encode_boolean(&policyMap, resource->secure);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding secure value to policy map");
-
-            if (resource->secure)
+            if (isSelf || !resource->eps)
             {
-                err |= cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT,
-                                               sizeof(OC_RSRVD_HOSTING_PORT) - 1);
-                VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding secure port tag");
-                err |= cbor_encode_uint(&policyMap, resource->port);
-                VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding secure port value");
+                err |= OCConvertResourcePayloadCbor(&linkArray, resource, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting links array");
             }
-
-#ifdef TCP_ADAPTER
-#ifdef __WITH_TLS__
-            // tls
-            if (resource->secure)
-            {
-                err |= cbor_encode_text_string(&policyMap, OC_RSRVD_TLS_PORT,
-                                               sizeof(OC_RSRVD_TLS_PORT) - 1);
-                VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp secure port tag");
-                err |= cbor_encode_uint(&policyMap, resource->tcpPort);
-                VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp secure port value");
-            }
-
-            // tcp
             else
-#endif
             {
-                err |= cbor_encode_text_string(&policyMap, OC_RSRVD_TCP_PORT,
-                                               sizeof(OC_RSRVD_TCP_PORT) - 1);
-                VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp port tag");
-                err |= cbor_encode_uint(&policyMap, resource->tcpPort);
-                VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding tcp port value");
+                size_t epsCount = OCEndpointPayloadGetEndpointCount(resource->eps);
+                for (size_t j = 0; j < epsCount; ++j)
+                {
+                    OCEndpointPayload* ep = OCEndpointPayloadGetEndpoint(resource->eps, j);
+                    err |= OCConvertResourcePayloadCbor(&linkArray, resource, ep);
+                    VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting links array");
+                }
             }
-#endif
-            err |= cbor_encoder_close_container(&linkMap, &policyMap);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing policy map");
-
-            // Finished encoding a resource, close the map.
-            err |= cbor_encoder_close_container(&linkArray, &linkMap);
-            VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing link map");
         }
+
         // Close links array inside the root map.
         err |= cbor_encoder_close_container(&rootMap, &linkArray);
         VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing link array");
@@ -427,15 +474,45 @@ static int64_t OCConvertDiscoveryPayloadVndOcfCbor(OCDiscoveryPayload *payload,
     ]
     */
 
-    // Open the main root array
-    size_t arrayCount = 0;
-    for (OCDiscoveryPayload *temp = payload; temp; temp = temp->next)
+    CborEncoder rootMap;
+    CborEncoder linkArray;
+    bool isBaseline = payload->name || payload->type || payload->iface;
+    if (isBaseline)
     {
-        arrayCount += OCDiscoveryPayloadGetResourceCount(temp);
+        // Open the root map
+        err |= cbor_encoder_create_map(&encoder, &rootMap, CborIndefiniteLength);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed creating discovery map");
+
+        // Insert Name
+        err |= ConditionalAddTextStringToMap(&rootMap, OC_RSRVD_DEVICE_NAME,
+                sizeof(OC_RSRVD_DEVICE_NAME) - 1, payload->name);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting name");
+
+        // Insert Device ID into the root map
+        err |= AddTextStringToMap(&rootMap, OC_RSRVD_DEVICE_ID, sizeof(OC_RSRVD_DEVICE_ID) - 1,
+                payload->sid);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting device id");
+
+        // Insert Resource Type
+        err |= OCStringLLJoin(&rootMap, OC_RSRVD_RESOURCE_TYPE, payload->type);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting RT");
+
+        // Insert interfaces
+        err |= OCStringLLJoin(&rootMap, OC_RSRVD_INTERFACE, payload->iface);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding interface types tag/value");
+
+        // Insert Links into the root map.
+        err |= cbor_encode_text_string(&rootMap, OC_RSRVD_LINKS, sizeof(OC_RSRVD_LINKS) - 1);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting links array tag");
+
+        err |= cbor_encoder_create_array(&rootMap, &linkArray, CborIndefiniteLength);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting links array");
+    }
+    else
+    {
+        err |= cbor_encoder_create_array(&encoder, &linkArray, CborIndefiniteLength);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed creating discovery root array");
     }
-    CborEncoder rootArray;
-    err |= cbor_encoder_create_array(&encoder, &rootArray, arrayCount);
-    VERIFY_CBOR_SUCCESS(TAG, err, "Failed creating discovery root array");
 
     while (payload && payload->resources)
     {
@@ -446,7 +523,7 @@ static int64_t OCConvertDiscoveryPayloadVndOcfCbor(OCDiscoveryPayload *payload,
 
             // Open a link map in the root array
             CborEncoder linkMap;
-            err |= cbor_encoder_create_map(&rootArray, &linkMap, CborIndefiniteLength);
+            err |= cbor_encoder_create_map(&linkArray, &linkMap, CborIndefiniteLength);
             VERIFY_CBOR_SUCCESS(TAG, err, "Failed creating discovery map");
 
             // Uri
@@ -548,16 +625,29 @@ static int64_t OCConvertDiscoveryPayloadVndOcfCbor(OCDiscoveryPayload *payload,
             }
 
             // Finished encoding a resource, close the map.
-            err |= cbor_encoder_close_container(&rootArray, &linkMap);
+            err |= cbor_encoder_close_container(&linkArray, &linkMap);
             VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing link map");
         }
 
         payload = payload->next;
     }
 
-    // Close the final root array.
-    err |= cbor_encoder_close_container(&encoder, &rootArray);
-    VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing root array");
+    if (isBaseline)
+    {
+        // Close the final root array.
+        err |= cbor_encoder_close_container(&rootMap, &linkArray);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing root array");
+
+        // Close root map inside the root array.
+        err |= cbor_encoder_close_container(&encoder, &rootMap);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing root map");
+    }
+    else
+    {
+        // Close the final root array.
+        err |= cbor_encoder_close_container(&encoder, &linkArray);
+        VERIFY_CBOR_SUCCESS(TAG, err, "Failed closing root array");
+    }
 
 exit:
     return checkError(err, &encoder, outPayload, size);
index 0696fc5..2dcd6c6 100755 (executable)
@@ -405,18 +405,77 @@ static OCStackResult OCParseDiscoveryPayloadVndOcfCbor(OCPayload **outPayload, C
     OCEndpointPayload *endpoint = NULL;
     size_t len = 0;
     CborError err = CborNoError;
+    CborValue linkMap;
+    CborValue *linkArray = NULL;
     *outPayload = NULL;
 
     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
     VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
-    if (cbor_value_is_array(rootValue))
+    if (cbor_value_is_map(rootValue))
+    {
+        rootPayload = OCDiscoveryPayloadCreate();
+        VERIFY_PARAM_NON_NULL(TAG, rootPayload, "Failed error initializing discovery payload");
+
+        // Look for DI
+        CborValue curVal;
+        err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &curVal);
+        VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
+        if (cbor_value_is_valid(&curVal))
+        {
+            if (cbor_value_is_byte_string(&curVal))
+            {
+                err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(rootPayload->sid), &len, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
+            }
+            else if (cbor_value_is_text_string(&curVal))
+            {
+                err = cbor_value_dup_text_string(&curVal, &(rootPayload->sid), &len, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
+            }
+        }
+
+        // RT - Not a mandatory field
+        err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
+        if (cbor_value_is_valid(&curVal))
+        {
+            err = OCParseStringLL(rootValue, OC_RSRVD_RESOURCE_TYPE, &rootPayload->type);
+            VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type");
+        }
+
+        // IF - Not a mandatory field
+        err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &curVal);
+        if (cbor_value_is_valid(&curVal))
+        {
+            err =  OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &rootPayload->iface);
+            VERIFY_CBOR_SUCCESS(TAG, err, "to find interface");
+        }
+
+        // Name - Not a mandatory field
+        err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &curVal);
+        if (cbor_value_is_text_string(&curVal))
+        {
+            err = cbor_value_dup_text_string(&curVal, &rootPayload->name, &len, NULL);
+            VERIFY_CBOR_SUCCESS(TAG, err, "to find device name");
+        }
+
+        // Look for Links which will have an array as the value
+        err = cbor_value_map_find_value(rootValue, OC_RSRVD_LINKS, &linkMap);
+        VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
+        linkArray = &linkMap;
+    }
+    else
+    {
+        linkArray = rootValue;
+    }
+
+    if (cbor_value_is_array(linkArray))
     {
         // Root value is already inside the main root array
 
         // Enter the main root array and start iterating through the array processing
         // each resource which shows up as a map.
         CborValue resourceMap;
-        err = cbor_value_enter_container(rootValue, &resourceMap);
+        err = cbor_value_enter_container(linkArray, &resourceMap);
         VERIFY_CBOR_SUCCESS(TAG, err, "to enter root array");
 
         while (cbor_value_is_map(&resourceMap))
@@ -574,7 +633,7 @@ static OCStackResult OCParseDiscoveryPayloadVndOcfCbor(OCPayload **outPayload, C
             }
         }
 
-        err = cbor_value_leave_container(rootValue, &resourceMap);
+        err = cbor_value_leave_container(linkArray, &resourceMap);
         VERIFY_CBOR_SUCCESS(TAG, err, "to leave resource map");
     }
     else
index 3e18cd2..076a44c 100644 (file)
@@ -31,6 +31,7 @@
 #include "ocrandom.h"
 #include "logger.h"
 #include "ocpayload.h"
+#include "ocendpoint.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 
@@ -47,9 +48,11 @@ static sqlite3 *gRDDB = NULL;
 
 /* Column indices of RD_DEVICE_LINK_LIST table */
 static const uint8_t ins_index = 0;
-static const uint8_t uri_index = 1;
-static const uint8_t p_index = 4;
-static const uint8_t d_index = 7;
+static const uint8_t href_index = 1;
+static const uint8_t rel_index = 2;
+static const uint8_t anchor_index = 3;
+static const uint8_t bm_index = 4;
+static const uint8_t d_index = 5;
 
 /* Column indices of RD_LINK_RT table */
 static const uint8_t rt_value_index = 0;
@@ -57,6 +60,10 @@ static const uint8_t rt_value_index = 0;
 /* Column indices of RD_LINK_IF table */
 static const uint8_t if_value_index = 0;
 
+/* Column indices of RD_LINK_EP table */
+static const uint8_t ep_value_index = 0;
+static const uint8_t pri_value_index = 1;
+
 #define VERIFY_SQLITE(arg) \
 if (SQLITE_OK != (arg)) \
 { \
@@ -151,16 +158,36 @@ static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayloa
         }
 
         sqlite3_int64 id = sqlite3_column_int64(stmt, ins_index);
-        const unsigned char *uri = sqlite3_column_text(stmt, uri_index);
-        sqlite3_int64 bitmap = sqlite3_column_int64(stmt, p_index);
+        const unsigned char *uri = sqlite3_column_text(stmt, href_index);
+        const unsigned char *rel = sqlite3_column_text(stmt, rel_index);
+        const unsigned char *anchor = sqlite3_column_text(stmt, anchor_index);
+        sqlite3_int64 bitmap = sqlite3_column_int64(stmt, bm_index);
         sqlite3_int64 deviceId = sqlite3_column_int64(stmt, d_index);
-        OIC_LOG_V(DEBUG, TAG, " %s %" PRId64, uri, deviceId);
+        OIC_LOG_V(DEBUG, TAG, " %s %" PRId64, uri, (int64_t) deviceId);
         resourcePayload->uri = OICStrdup((char *)uri);
         if (!resourcePayload->uri)
         {
             result = OC_STACK_NO_MEMORY;
             goto exit;
         }
+        if (rel)
+        {
+            resourcePayload->rel = OICStrdup((char *)rel);
+            if (!resourcePayload->rel)
+            {
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+        }
+        if (anchor)
+        {
+            resourcePayload->anchor = OICStrdup((char *)anchor);
+            if (!resourcePayload->anchor)
+            {
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+        }
 
         sqlite3_stmt *stmtRT = 0;
         const char rt[] = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=@id";
@@ -170,8 +197,8 @@ static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayloa
         VERIFY_SQLITE(sqlite3_bind_int64(stmtRT, sqlite3_bind_parameter_index(stmtRT, "@id"), id));
         while (SQLITE_ROW == sqlite3_step(stmtRT))
         {
-            const unsigned char *rt1 = sqlite3_column_text(stmtRT, rt_value_index);
-            result = appendStringLL(&resourcePayload->types, rt1);
+            const unsigned char *tempRt = sqlite3_column_text(stmtRT, rt_value_index);
+            result = appendStringLL(&resourcePayload->types, tempRt);
             if (OC_STACK_OK != result)
             {
                 goto exit;
@@ -197,32 +224,62 @@ static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayloa
         VERIFY_SQLITE(sqlite3_finalize(stmtIF));
 
         resourcePayload->bitmap = (uint8_t)(bitmap & (OC_OBSERVABLE | OC_DISCOVERABLE));
-        resourcePayload->secure = ((bitmap & OC_SECURE) != 0);
 
-        const char address[] = "SELECT di FROM RD_DEVICE_LIST "
+        sqlite3_stmt *stmtEp = 0;
+        const char ep[] = "SELECT ep,pri FROM RD_LINK_EP WHERE LINK_ID=@id";
+        int epSize = (int)sizeof(ep);
+
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, ep, epSize, &stmtEp, NULL));
+        VERIFY_SQLITE(sqlite3_bind_int64(stmtEp, sqlite3_bind_parameter_index(stmtEp, "@id"), id));
+        while (SQLITE_ROW == sqlite3_step(stmtEp))
+        {
+            OCEndpointPayload *epPayload = (OCEndpointPayload *)OICCalloc(1, sizeof(OCEndpointPayload));
+            if (!epPayload)
+            {
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+            const unsigned char *tempEp = sqlite3_column_text(stmtEp, ep_value_index);
+            result = OCParseEndpointString((const char *)tempEp, epPayload);
+            if (OC_STACK_OK != result)
+            {
+                goto exit;
+            }
+            sqlite3_int64 pri = sqlite3_column_int64(stmtEp, pri_value_index);
+            epPayload->pri = (uint16_t)pri;
+            OCEndpointPayload **tmp = &resourcePayload->eps;
+            while (*tmp)
+            {
+                tmp = &(*tmp)->next;
+            }
+            *tmp = epPayload;
+        }
+        VERIFY_SQLITE(sqlite3_finalize(stmtEp));
+
+        const char di[] = "SELECT di FROM RD_DEVICE_LIST "
             "INNER JOIN RD_DEVICE_LINK_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID = RD_DEVICE_LIST.ID "
             "WHERE RD_DEVICE_LINK_LIST.DEVICE_ID=@deviceId";
-        int addressSize = (int)sizeof(address);
+        int diSize = (int)sizeof(di);
 
         const uint8_t di_index = 0;
 
-        sqlite3_stmt *stmt1 = 0;
-        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, addressSize, &stmt1, NULL));
-        VERIFY_SQLITE(sqlite3_bind_int64(stmt1, sqlite3_bind_parameter_index(stmt1, "@deviceId"), deviceId));
+        sqlite3_stmt *stmtDI = 0;
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, di, diSize, &stmtDI, NULL));
+        VERIFY_SQLITE(sqlite3_bind_int64(stmtDI, sqlite3_bind_parameter_index(stmtDI, "@deviceId"), deviceId));
 
-        res = sqlite3_step(stmt1);
+        res = sqlite3_step(stmtDI);
         if (SQLITE_ROW == res || SQLITE_DONE == res)
         {
-            const unsigned char *di = sqlite3_column_text(stmt1, di_index);
-            OIC_LOG_V(DEBUG, TAG, " %s", di);
-            discPayload->sid = OICStrdup((char *)di);
+            const unsigned char *tempDi = sqlite3_column_text(stmtDI, di_index);
+            OIC_LOG_V(DEBUG, TAG, " %s", tempDi);
+            discPayload->sid = OICStrdup((char *)tempDi);
             if (!discPayload->sid)
             {
                 result = OC_STACK_NO_MEMORY;
                 goto exit;
             }
         }
-        VERIFY_SQLITE(sqlite3_finalize(stmt1));
+        VERIFY_SQLITE(sqlite3_finalize(stmtDI));
         OCDiscoveryPayloadAddNewResource(discPayload, resourcePayload);
         res = sqlite3_step(stmt);
     }