Resource directory related fixes.
authorTodd Malsbary <todd.malsbary@intel.com>
Mon, 21 Nov 2016 20:01:33 +0000 (12:01 -0800)
committerHabib Virji <habib.virji@samsung.com>
Tue, 7 Feb 2017 14:22:00 +0000 (14:22 +0000)
- Use the passed in ID in OCRDPublishWithDeviceId(),
- Set the size of the CBOR array to the length of the discovery
  payload list in OCConvertDiscoveryPayload(),
- Return all local and published resources in response to GET
  /oic/res,
- Set the di and baseURI correctly in discovery payloads,
- Only return resources that match the intersection of 'rt' and 'if'
  queries.
- Add missing calls to ROLLBACK in error paths.

Change-Id: Ib1ad770fec8ec6f9eafff0e5f864ee115f1ba5b5
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/14581
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Habib Virji <habib.virji@samsung.com>
resource/csdk/resource-directory/src/internal/rd_database.c
resource/csdk/resource-directory/unittests/rddatabase.cpp
resource/csdk/resource-directory/unittests/rdtests.cpp
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/src/ocpayloadconvert.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/oicresourcedirectory.c

index 024ffe054a92ad2f0be7c05ad69dfaf24ec141af..abcb3672f8c6d8f3f5ce2d90d5713e1ea99a5eb5 100644 (file)
@@ -181,6 +181,7 @@ static int storeResourceType(char **link, size_t size, uint8_t rowid)
         }
         if (sqlite3_step(stmtRT) != SQLITE_DONE)
         {
+            sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
             sqlite3_finalize(stmtRT);
             return res;
         }
@@ -215,6 +216,7 @@ static int storeInterfaceType(char **link, size_t size, uint8_t rowid)
         }
         if (sqlite3_step(stmtIF) != SQLITE_DONE)
         {
+            sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
             res = sqlite3_finalize(stmtIF);
             return res;
         }
@@ -280,6 +282,7 @@ static int storeLinkPayload(OCRepPayload *rdPayload, int64_t rowid)
 
             if (sqlite3_step(stmt) != SQLITE_DONE)
             {
+                sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
                 sqlite3_finalize(stmt);
                 return res;
             }
@@ -344,6 +347,7 @@ OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr
 
     if (sqlite3_step(stmt) != SQLITE_DONE)
     {
+        sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
         sqlite3_finalize(stmt);
         return OC_STACK_ERROR;
     }
index a4dfcc81311088f338f83cdeed0f1265c800f770..97207e9e60083d67cd14218164a13be95ed3941e 100644 (file)
@@ -96,9 +96,9 @@ TEST_F(RDDatabaseTests, PublishDatabase)
     // itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
     EXPECT_EQ(OC_STACK_OK, OCRDDatabaseInit(NULL));
     OCRepPayload *repPayload = OCRepPayloadCreate();
-    EXPECT_TRUE(repPayload != NULL);
-    const char *deviceId = OCGetServerInstanceIDString();
-    EXPECT_TRUE(deviceId != NULL);
+    ASSERT_TRUE(repPayload != NULL);
+    const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
+    ASSERT_TRUE(deviceId != NULL);
     EXPECT_TRUE(OCRepPayloadSetPropString(repPayload, OC_RSRVD_DEVICE_ID, deviceId));
     EXPECT_TRUE(OCRepPayloadSetPropInt(repPayload, OC_RSRVD_DEVICE_TTL, 86400));
     OCDevAddr address;
@@ -155,19 +155,21 @@ TEST_F(RDDatabaseTests, PublishDatabase)
     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)repPayload);
 
     EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
-    OCDiscoveryPayload *discPayload = OCDiscoveryPayloadCreate();
-    EXPECT_TRUE(discPayload != NULL);
-    EXPECT_EQ(discPayload->base.type, PAYLOAD_TYPE_DISCOVERY);
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseCheckResources(NULL, "core.light", discPayload));
+
+    OCDiscoveryPayload *discPayload = NULL;
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDiscoveryPayloadCreate(NULL, "core.light", &discPayload));
+    OCDiscoveryPayloadDestroy(discPayload);
+    discPayload = NULL;
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDiscoveryPayloadCreate(OC_RSRVD_INTERFACE_DEFAULT, NULL, &discPayload));
+    OCDiscoveryPayloadDestroy(discPayload);
+    discPayload = NULL;
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDiscoveryPayloadCreate(NULL, "core.light", &discPayload));
     OCDiscoveryPayloadDestroy(discPayload);
-    OCDiscoveryPayload *discPayload1 = OCDiscoveryPayloadCreate();
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseCheckResources(OC_RSRVD_INTERFACE_DEFAULT, NULL, discPayload1));
-    OCDiscoveryPayloadDestroy(discPayload1);
-    OCDiscoveryPayload *discPayload2 = OCDiscoveryPayloadCreate();
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseCheckResources(NULL, "core.light", discPayload2));
-    OCDiscoveryPayloadDestroy(discPayload2);
-    OCDiscoveryPayload *discPayload3 = OCDiscoveryPayloadCreate();
-    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseCheckResources(OC_RSRVD_INTERFACE_DEFAULT, "core.light", discPayload3));
+    discPayload = NULL;
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDiscoveryPayloadCreate(OC_RSRVD_INTERFACE_DEFAULT, "core.light", &discPayload));
+    OCDiscoveryPayloadDestroy(discPayload);
+    discPayload = NULL;
+
     EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDeleteDevice(deviceId));
     EXPECT_EQ(OC_STACK_OK, OCRDDatabaseClose());
 }
index 50909ade45c4d0d028150d28edcef4f862ea950d..3973c81dc93306a9b08795d311f055e242a724ec 100644 (file)
@@ -22,9 +22,12 @@ extern "C"
 {
     #include "rd_client.h"
     #include "rd_server.h"
+    #include "ocpayload.h"
     #include "ocstack.h"
     #include "logger.h"
     #include "oic_malloc.h"
+    #include "oic_string.h"
+    #include "payload_logging.h"
 }
 
 #include "gtest/gtest.h"
@@ -131,7 +134,7 @@ TEST_F(RDTests, CreateRDResource)
     EXPECT_EQ(OC_STACK_OK, OCRDStart());
 
     OCCallbackData cbData;
-    cbData.cb = &handleDiscoveryCB;;
+    cbData.cb = &handleDiscoveryCB;
     cbData.cd = NULL;
     cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
     EXPECT_EQ(OC_STACK_OK, OCRDDiscover(CT_ADAPTER_IP, &cbData, OC_LOW_QOS));
@@ -291,3 +294,799 @@ TEST_F(RDTests, RDDeleteSpecificResource)
                                       1, &cbData, OC_LOW_QOS));
 }
 #endif
+
+#if (defined(RD_SERVER) && defined(RD_CLIENT))
+class Callback
+{
+    public:
+        Callback(OCClientResponseHandler cb)
+            : m_cb(cb), m_called(false)
+        {
+            m_cbData.cb = &Callback::handler;
+            m_cbData.cd = NULL;
+            m_cbData.context = this;
+        }
+        void Wait()
+        {
+            while (!m_called)
+            {
+                OCProcess();
+            }
+        }
+        operator OCCallbackData *()
+        {
+            return &m_cbData;
+        }
+    private:
+        OCCallbackData m_cbData;
+        OCClientResponseHandler m_cb;
+        bool m_called;
+        static OCStackApplicationResult handler(void *ctx, OCDoHandle handle,
+                                                OCClientResponse *clientResponse)
+        {
+            Callback *callback = (Callback *) ctx;
+            OCStackApplicationResult result = callback->m_cb(NULL, handle, clientResponse);
+            callback->m_called = true;
+            return result;
+        }
+};
+
+class RDDiscoverTests : public testing::Test
+{
+    protected:
+        virtual void SetUp()
+        {
+            remove("RD.db");
+            EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER));
+            EXPECT_EQ(OC_STACK_OK, OCRDStart());
+        }
+
+        virtual void TearDown()
+        {
+            OCStop();
+            remove("RD.db");
+        }
+    public:
+        static const unsigned char *di[3];
+};
+const unsigned char *RDDiscoverTests::di[3] =
+{
+    (const unsigned char *) "7a960f46-a52e-4837-bd83-460b1a6dd56b",
+    (const unsigned char *) "983656a7-c7e5-49c2-a201-edbeb7606fb5",
+    (const unsigned char *) "9338c0b2-2373-4324-ba78-17c0ef79506d"
+};
+
+static OCStackApplicationResult DiscoverAllResourcesVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        bool foundId = false;
+        bool foundLight = false;
+        bool foundLight2 = false;
+        for (OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload; payload;
+             payload = payload->next)
+        {
+            if (!strcmp((const char *) RDDiscoverTests::di[0], payload->sid))
+            {
+                foundId = true;
+                for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
+                {
+                    if (!strcmp("/a/light", resource->uri))
+                    {
+                        foundLight = true;
+                    }
+                    if (!strcmp("/a/light2", resource->uri))
+                    {
+                        foundLight2 = true;
+                    }
+                }
+            }
+        }
+        EXPECT_TRUE(foundId);
+        EXPECT_TRUE(foundLight);
+        EXPECT_TRUE(foundLight2);
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, DiscoverAllResources)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[2];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.baseline", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light",
+                                            "oic.if.baseline", "/a/light2", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publishCB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, handles,
+              2, publishCB, OC_LOW_QOS));
+    publishCB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult ResourceQueryMatchesLocalAndRemoteVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        // Verify that only resources with the queried type are present in the response
+        for (OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload; payload;
+             payload = payload->next)
+        {
+            EXPECT_TRUE(payload->resources != NULL);
+            if (payload->resources)
+            {
+                EXPECT_TRUE(payload->resources->next == NULL);
+                EXPECT_STREQ("/a/light", payload->resources->uri);
+                EXPECT_STREQ("core.light", payload->resources->types->value);
+                EXPECT_TRUE(payload->resources->types->next == NULL);
+            }
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, ResourceQueryMatchesLocalAndRemote)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[1];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.baseline", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publishCB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, handles,
+              1, publishCB, OC_LOW_QOS));
+    publishCB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult ResourceQueryMatchesLocalOnlyVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+        EXPECT_STREQ(OCGetServerInstanceIDString(), payload->sid);
+        EXPECT_TRUE(payload->next == NULL);
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, ResourceQueryMatchesLocalOnly)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[2];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.baseline", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light2",
+                                            "oic.if.baseline", "/a/light2", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publishCB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, &handles[1],
+              1, publishCB, OC_LOW_QOS));
+    publishCB.Wait();
+
+    OIC_LOG(INFO, TAG, "Published");
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult ResourceQueryMatchesRemoteOnlyVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+        EXPECT_STREQ((const char *)RDDiscoverTests::di[0], payload->sid);
+        EXPECT_TRUE(payload->next == NULL);
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+static void SetStringArray(OCRepPayload *payload, const char *name, const char *value)
+{
+    size_t dim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
+    char **ss = (char **)OICMalloc(sizeof(char *) * 1);
+    ss[0] = OICStrdup(value);
+    OCRepPayloadSetStringArray(payload, name, (const char **)ss, dim);
+}
+
+TEST_F(RDDiscoverTests, ResourceQueryMatchesRemoteOnly)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[1];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.baseline", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    OCRepPayload *repPayload = OCRepPayloadCreate();
+    ASSERT_TRUE(repPayload != NULL);
+    EXPECT_TRUE(OCRepPayloadSetPropString(repPayload, OC_RSRVD_DEVICE_ID, (const char *)di[0]));
+    EXPECT_TRUE(OCRepPayloadSetPropInt(repPayload, OC_RSRVD_DEVICE_TTL, 86400));
+    OCDevAddr address;
+    address.port = 54321;
+    OICStrcpy(address.addr,MAX_ADDR_STR_SIZE, "192.168.1.1");
+
+    std::string resourceURI_light = "/a/light";
+    std::string resourceTypeName_light = "core.light2";
+
+    const OCRepPayload *linkArr[1];
+    size_t dimensions[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
+
+    OCRepPayload *link = OCRepPayloadCreate();
+    OCRepPayloadSetPropString(link, OC_RSRVD_HREF, resourceURI_light.c_str());
+    SetStringArray(link, OC_RSRVD_RESOURCE_TYPE, resourceTypeName_light.c_str());
+    SetStringArray(link, OC_RSRVD_INTERFACE, OC_RSRVD_INTERFACE_DEFAULT);
+    OCRepPayloadSetPropInt(link, OC_RSRVD_INS, 0);
+    SetStringArray(link, OC_RSRVD_MEDIA_TYPE, DEFAULT_MESSAGE_TYPE);
+    OCRepPayload *policy = OCRepPayloadCreate();
+    OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, OC_DISCOVERABLE);
+    OCRepPayloadSetPropObjectAsOwner(link, OC_RSRVD_POLICY, policy);
+    linkArr[0] = link;
+
+    OCRepPayloadSetPropObjectArray(repPayload, OC_RSRVD_LINKS, linkArr, dimensions);
+
+    OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)repPayload);
+
+    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));
+    publishCB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult DatabaseHas0ResourceQueryMatchesVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+        EXPECT_TRUE(payload->next == NULL);
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, DatabaseHas0ResourceQueryMatches)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[4];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.baseline", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light2",
+                                            "oic.if.baseline", "/a/light2", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[2], "core.light3",
+                                            "oic.if.baseline", "/a/light3", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[3], "core.light4",
+                                            "oic.if.baseline", "/a/light4", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publish0CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, &handles[1],
+              1, publish0CB, OC_LOW_QOS));
+    publish0CB.Wait();
+    Callback publish1CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[1], CT_ADAPTER_IP, &handles[2],
+              1, publish1CB, OC_LOW_QOS));
+    publish1CB.Wait();
+    Callback publish2CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[2], CT_ADAPTER_IP, &handles[3],
+              1, publish2CB, OC_LOW_QOS));
+    publish2CB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult DatabaseHas1ResourceQueryMatchVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+        EXPECT_TRUE(payload->next != NULL);
+        if (payload->next)
+        {
+            payload = payload->next;
+            EXPECT_TRUE(payload->resources != NULL);
+            if (payload->resources)
+            {
+                EXPECT_TRUE(payload->resources->next == NULL);
+                EXPECT_STREQ("/a/light2", payload->resources->uri);
+                EXPECT_STREQ("core.light2", payload->resources->types->value);
+                EXPECT_TRUE(payload->resources->types->next == NULL);
+            }
+            payload = payload->next;
+            EXPECT_TRUE(payload == NULL);
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, DatabaseHas1ResourceQueryMatch)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[4];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.baseline", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light2",
+                                            "oic.if.baseline", "/a/light2", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[2], "core.light3",
+                                            "oic.if.baseline", "/a/light3", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[3], "core.light4",
+                                            "oic.if.baseline", "/a/light4", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publish0CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, &handles[1],
+              1, publish0CB, OC_LOW_QOS));
+    publish0CB.Wait();
+    Callback publish1CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[1], CT_ADAPTER_IP, &handles[2],
+              1, publish1CB, OC_LOW_QOS));
+    publish1CB.Wait();
+    Callback publish2CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[2], CT_ADAPTER_IP, &handles[3],
+              1, publish2CB, OC_LOW_QOS));
+    publish2CB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult DatabaseHasNResourceQueryMatchesVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+        EXPECT_TRUE(payload->next != NULL);
+        if (payload->next)
+        {
+            payload = payload->next;
+            for (int i = 0; i < 3; ++i)
+            {
+                EXPECT_TRUE(payload->resources != NULL);
+                if (payload->resources)
+                {
+                    EXPECT_TRUE(payload->resources->next == NULL);
+                    EXPECT_STREQ("core.light", payload->resources->types->value);
+                    EXPECT_TRUE(payload->resources->types->next == NULL);
+                }
+                payload = payload->next;
+            }
+            EXPECT_TRUE(payload == NULL);
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, DatabaseHasNResourceQueryMatches)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[4];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.baseline", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light",
+                                            "oic.if.baseline", "/a/light2", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[2], "core.light",
+                                            "oic.if.baseline", "/a/light3", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[3], "core.light",
+                                            "oic.if.baseline", "/a/light4", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publish0CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, &handles[1],
+              1, publish0CB, OC_LOW_QOS));
+    publish0CB.Wait();
+    Callback publish1CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[1], CT_ADAPTER_IP, &handles[2],
+              1, publish1CB, OC_LOW_QOS));
+    publish1CB.Wait();
+    Callback publish2CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[2], CT_ADAPTER_IP, &handles[3],
+              1, publish2CB, OC_LOW_QOS));
+    publish2CB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult DatabaseHas0InterfaceQueryMatchesVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+        EXPECT_TRUE(payload->next == NULL);
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, DatabaseHas0InterfaceQueryMatches)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[4];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.one", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light2",
+                                            "oic.if.two", "/a/light2", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[2], "core.light3",
+                                            "oic.if.three", "/a/light3", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[3], "core.light4",
+                                            "oic.if.four", "/a/light4", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publish0CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, &handles[1],
+              1, publish0CB, OC_LOW_QOS));
+    publish0CB.Wait();
+    Callback publish1CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[1], CT_ADAPTER_IP, &handles[2],
+              1, publish1CB, OC_LOW_QOS));
+    publish1CB.Wait();
+    Callback publish2CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[2], CT_ADAPTER_IP, &handles[3],
+              1, publish2CB, OC_LOW_QOS));
+    publish2CB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult DatabaseHas1InterfaceQueryMatchVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+        EXPECT_TRUE(payload->next != NULL);
+        if (payload->next)
+        {
+            payload = payload->next;
+            for (int i = 0; i < 1; ++i)
+            {
+                EXPECT_TRUE(payload->resources != NULL);
+                if (payload->resources)
+                {
+                    EXPECT_TRUE(payload->resources->next == NULL);
+                    EXPECT_STREQ("/a/light2", payload->resources->uri);
+                    bool foundInterface = false;
+                    for (OCStringLL *iface = payload->resources->interfaces; iface; iface = iface->next)
+                    {
+                        if (!strcmp("oic.if.two", iface->value))
+                        {
+                            foundInterface = true;
+                        }
+                    }
+                    EXPECT_TRUE(foundInterface);
+                }
+                payload = payload->next;
+            }
+            EXPECT_TRUE(payload == NULL);
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, DatabaseHas1InterfaceQueryMatch)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[4];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.one", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light2",
+                                            "oic.if.two", "/a/light2", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[2], "core.light3",
+                                            "oic.if.three", "/a/light3", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[3], "core.light4",
+                                            "oic.if.four", "/a/light4", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publish0CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, &handles[1],
+              1, publish0CB, OC_LOW_QOS));
+    publish0CB.Wait();
+    Callback publish1CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[1], CT_ADAPTER_IP, &handles[2],
+              1, publish1CB, OC_LOW_QOS));
+    publish1CB.Wait();
+    Callback publish2CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[2], CT_ADAPTER_IP, &handles[3],
+              1, publish2CB, OC_LOW_QOS));
+    publish2CB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult DatabaseHasNInterfaceQueryMatchesVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+        EXPECT_TRUE(payload->next != NULL);
+        if (payload->next)
+        {
+            payload = payload->next;
+            for (int i = 0; i < 3; ++i)
+            {
+                EXPECT_TRUE(payload->resources != NULL);
+                if (payload->resources)
+                {
+                    EXPECT_TRUE(payload->resources->next == NULL);
+                    bool foundInterface = false;
+                    for (OCStringLL *iface = payload->resources->interfaces; iface; iface = iface->next)
+                    {
+                        if (!strcmp("oic.if.a", iface->value))
+                        {
+                            foundInterface = true;
+                        }
+                    }
+                    EXPECT_TRUE(foundInterface);
+                }
+                payload = payload->next;
+            }
+            EXPECT_TRUE(payload == NULL);
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, DatabaseHasNInterfaceQueryMatches)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[4];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.a", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light",
+                                            "oic.if.a", "/a/light2", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[2], "core.light",
+                                            "oic.if.a", "/a/light3", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[3], "core.light",
+                                            "oic.if.a", "/a/light4", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publish0CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, &handles[1],
+              1, publish0CB, OC_LOW_QOS));
+    publish0CB.Wait();
+    Callback publish1CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[1], CT_ADAPTER_IP, &handles[2],
+              1, publish1CB, OC_LOW_QOS));
+    publish1CB.Wait();
+    Callback publish2CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[2], CT_ADAPTER_IP, &handles[3],
+              1, publish2CB, OC_LOW_QOS));
+    publish2CB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult ResourceAndInterfaceQueryMatchVerify(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(response->payload != NULL);
+    if (response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+        EXPECT_TRUE(payload->next != NULL);
+        if (payload->next)
+        {
+            payload = payload->next;
+            for (int i = 0; i < 1; ++i)
+            {
+                EXPECT_TRUE(payload->resources != NULL);
+                if (payload->resources)
+                {
+                    EXPECT_TRUE(payload->resources->next == NULL);
+                    EXPECT_STREQ("/a/light2", payload->resources->uri);
+                    EXPECT_STREQ("core.light2", payload->resources->types->value);
+                    EXPECT_TRUE(payload->resources->types->next == NULL);
+                    bool foundInterface = false;
+                    for (OCStringLL *iface = payload->resources->interfaces; iface; iface = iface->next)
+                    {
+                        if (!strcmp("oic.if.two", iface->value))
+                        {
+                            foundInterface = true;
+                        }
+                    }
+                    EXPECT_TRUE(foundInterface);
+                }
+                payload = payload->next;
+            }
+            EXPECT_TRUE(payload == NULL);
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, ResourceAndInterfaceQueryMatch)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[4];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.a", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light2",
+                                            "oic.if.two", "/a/light2", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[2], "core.light3",
+                                            "oic.if.two", "/a/light3", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[3], "core.light2",
+                                            "oic.if.a", "/a/light4", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publish0CB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, &handles[1],
+              3, publish0CB, OC_LOW_QOS));
+    publish0CB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+
+static OCStackApplicationResult BaselineVerify(void *ctx, OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+    OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload;
+    EXPECT_TRUE(payload->type != NULL);
+    EXPECT_TRUE(payload->iface != NULL);
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, Baseline)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+    OCResourceHandle handles[1];
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+                                            "oic.if.baseline", "/a/light", rdEntityHandler,
+                                            NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+    Callback publishCB(&handlePublishCB);
+    EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, handles,
+              1, publishCB, OC_LOW_QOS));
+    publishCB.Wait();
+
+    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));
+    discoverCB.Wait();
+}
+#endif
index 565fe19d84b32b15ba33f53dd4f23f7cfcf62205..05914835cda1b434e561c083aa2d2e5be5499f14 100644 (file)
@@ -708,13 +708,13 @@ OCResourceHandle OCGetResourceHandleAtUri(const char *uri);
 *
 * @param interfaceType is the interface type that is queried.
 * @param resourceType is the resource type that is queried.
-* @param discPayload is NULL if no resource found or else OCDiscoveryPayload with the details
-* about the resource.
+* @param discPayload NULL if no resource found or else OCDiscoveryPayload with the details
+* about the resources.
 *
 * @return ::OC_STACK_OK in case of success or else other value.
 */
-OCStackResult OCRDDatabaseCheckResources(const char *interfaceType, const char *resourceType,
-    OCDiscoveryPayload *discPayload);
+OCStackResult OCRDDatabaseDiscoveryPayloadCreate(const char *interfaceType, const char *resourceType,
+    OCDiscoveryPayload **discPayload);
 #endif
 //#endif // DIRECT_PAIRING
 
index 5c2d083318d63cd0cfa473f57234321b30c34e78..26be51b7cd654fcc7fe64acb849f3bd8f82b5229 100755 (executable)
@@ -244,8 +244,13 @@ static int64_t OCConvertDiscoveryPayload(OCDiscoveryPayload *payload, uint8_t *o
     */
 
     // Open the main root array
+    size_t arrayCount = 0;
+    for (OCDiscoveryPayload *temp = payload; temp; temp = temp->next)
+    {
+        arrayCount++;
+    }
     CborEncoder rootArray;
-    err |= cbor_encoder_create_array(&encoder, &rootArray, 1);
+    err |= cbor_encoder_create_array(&encoder, &rootArray, arrayCount);
     VERIFY_CBOR_SUCCESS(TAG, err, "Failed creating discovery root array");
 
     while (payload && payload->resources)
index 76320644ee8d9d68aded156af9ae5edc52468a90..ac3810516c9925127ac6c727585f6ba07ac87ef1 100755 (executable)
@@ -1260,29 +1260,30 @@ static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType
 
 #ifdef RD_SERVER
 /**
- * Find resource at the resource directory server. This resource is not local resource but a
- * remote resource.
+ * Find resources at the resource directory server. These resources are not local resources but
+ * remote resources.
  *
- * @param resource The resource to check the matching resource URI.
  * @param interfaceQuery The interface query parameter.
  * @param resourceTypeQuery The resourceType query parameter.
  * @param discPayload The payload that will be added with the resource information if found at RD.
  *
- * @return ::OC_STACK_OK if the resource is found else ::OC_STACK_NO_RESOURCE.
- * In case if build is not with flag RD_SERVER, it returns ::OC_STACK_NO_RESOURCE.
+ * @return ::OC_STACK_OK if any resources are found else ::OC_STACK_NO_RESOURCE.
+ * In case if RD server is not started, it returns ::OC_STACK_NO_RESOURCE.
  */
-static OCStackResult findResourceAtRD(const OCResource* resource, const char *interfaceQuery,
-    const char *resourceTypeQuery, OCDiscoveryPayload *discPayload)
+static OCStackResult findResourcesAtRD(const char *interfaceQuery,
+                                       const char *resourceTypeQuery, OCDiscoveryPayload **discPayload)
 {
-    if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
+    OCStackResult result = OC_STACK_NO_RESOURCE;
+    if (OCGetResourceHandleAtUri(OC_RSRVD_RD_URI) != NULL)
     {
-        if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
-        {
-            return OC_STACK_OK;
-        }
+        result = OCRDDatabaseDiscoveryPayloadCreate(interfaceQuery, resourceTypeQuery,
+            (*discPayload) ? &(*discPayload)->next : discPayload);
     }
-
-    return OC_STACK_NO_RESOURCE;
+    if ((*discPayload) && (*discPayload)->resources)
+    {
+        result = OC_STACK_OK;
+    }
+    return result;
 }
 #endif
 
@@ -1476,12 +1477,17 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
         if (discPayload->resources == NULL)
         {
             discoveryResult = OC_STACK_NO_RESOURCE;
+            OCPayloadDestroy(payload);
+            payload = NULL;
         }
 
         if (networkInfo)
         {
             OICFree(networkInfo);
         }
+#ifdef RD_SERVER
+        discoveryResult = findResourcesAtRD(interfaceQuery, resourceTypeQuery, (OCDiscoveryPayload **)&payload);
+#endif
     }
     else if (virtualUriInRequest == OC_DEVICE_URI)
     {
index 7e8e6b9ca892b99fdd69d21cee67ae1d50b4a211..e8e1eac60f42b76d3df05acdd21ecdf6ad181b1b 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "octypes.h"
 #include "ocstack.h"
+#include "ocrandom.h"
 #include "logger.h"
 #include "ocpayload.h"
 #include "oic_malloc.h"
 
 static sqlite3 *gRDDB = NULL;
 
-static const uint8_t uri_index = 2;
-static const uint8_t p_index = 5;
-static const uint8_t mt_index = 7;
-static const uint8_t d_index = 8;
+/* 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 rt_value_index = 1;
-static const uint8_t rt_link_id_index = 2;
+/* Column indices of RD_LINK_RT table */
+static const uint8_t rt_value_index = 0;
 
-static const uint8_t if_value_index = 1;
-static const uint8_t if_link_id_index = 2;
+/* Column indices of RD_LINK_IF table */
+static const uint8_t if_value_index = 0;
 
 #define VERIFY_SQLITE(arg) \
 if (SQLITE_OK != (arg)) \
@@ -112,158 +114,244 @@ static OCStackResult appendStringLL(OCStringLL **type, const unsigned char *valu
     return OC_STACK_OK;
 }
 
-OCStackResult OCRDDatabaseCheckResources(const char *interfaceType, const char *resourceType,
-    OCDiscoveryPayload *discPayload)
+/* stmt is of form "SELECT * FROM RD_DEVICE_LINK_LIST ..." */
+static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayload *discPayload)
 {
-    if (initializeDatabase(NULL) != OC_STACK_OK)
-    {
-        return OC_STACK_INTERNAL_SERVER_ERROR;
-    }
-    if (!interfaceType && !resourceType)
+    int res = sqlite3_step(stmt);
+    if (SQLITE_ROW != res)
     {
-        return OC_STACK_INVALID_QUERY;
+        return OC_STACK_NO_RESOURCE;
     }
-    OCResourcePayload *resourcePayload = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
-    if (!resourcePayload)
-    {
-        return OC_STACK_NO_MEMORY;
-    }
-
-    if (resourceType)
+    OCStackResult result = OC_STACK_OK;
+    OCResourcePayload *resourcePayload = NULL;
+    while (SQLITE_ROW == res)
     {
-        sqlite3_stmt *stmt = 0;
-        const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST INNER JOIN RD_LINK_RT ON " \
-        "RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID WHERE RD_LINK_RT.rt LIKE ? ";
+        resourcePayload = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
+        if (!resourcePayload)
+        {
+            result = OC_STACK_NO_MEMORY;
+            goto exit;
+        }
 
-        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
-        VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, resourceType, strlen(resourceType) + 1, SQLITE_STATIC));
+        int id = sqlite3_column_int(stmt, ins_index);
+        const unsigned char *uri = sqlite3_column_text(stmt, uri_index);
+        int bitmap = sqlite3_column_int(stmt, p_index);
+        int deviceId = sqlite3_column_int(stmt, d_index);
+        OIC_LOG_V(DEBUG, TAG, " %s %d", uri, deviceId);
+        resourcePayload->uri = OICStrdup((char *)uri);
+        if (!resourcePayload->uri)
+        {
+            result = OC_STACK_NO_MEMORY;
+            goto exit;
+        }
 
-        int res = sqlite3_step (stmt);
-        if (res == SQLITE_ROW || res == SQLITE_DONE)
+        sqlite3_stmt *stmtRT = 0;
+        const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=?";
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, -1, &stmtRT, NULL));
+        VERIFY_SQLITE(sqlite3_bind_int(stmtRT, 1, id));
+        while (SQLITE_ROW == sqlite3_step(stmtRT))
         {
-            int id = sqlite3_column_int(stmt, 0);
-            const unsigned char *uri = sqlite3_column_text(stmt, uri_index - 1);
-            int bitmap = sqlite3_column_int(stmt, p_index - 1);
-            int deviceId = sqlite3_column_int(stmt, d_index - 1);
-            OIC_LOG_V(DEBUG, TAG, " %s %d", uri, deviceId);
-            resourcePayload->uri = OICStrdup((char *)uri);
-            if (!resourcePayload->uri)
+            const unsigned char *rt1 = sqlite3_column_text(stmtRT, rt_value_index);
+            result = appendStringLL(&resourcePayload->types, rt1);
+            if (OC_STACK_OK != result)
             {
-                OCDiscoveryResourceDestroy(resourcePayload);
-                return OC_STACK_NO_MEMORY;
+                goto exit;
             }
-            res = sqlite3_reset(stmt);
-            VERIFY_SQLITE(res);
+        }
+        VERIFY_SQLITE(sqlite3_finalize(stmtRT));
 
-            sqlite3_stmt *stmtRT = 0;
-            const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=?";
-            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, -1, &stmtRT, NULL));
-            VERIFY_SQLITE(sqlite3_bind_int(stmtRT, 1, id));
-            while (SQLITE_ROW == sqlite3_step(stmtRT))
+        sqlite3_stmt *stmtIF = 0;
+        const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=?";
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, -1, &stmtIF, NULL));
+        VERIFY_SQLITE(sqlite3_bind_int(stmtIF, 1, id));
+        while (SQLITE_ROW == sqlite3_step(stmtIF))
+        {
+            const unsigned char *itf = sqlite3_column_text(stmtIF, if_value_index);
+            result = appendStringLL(&resourcePayload->interfaces, itf);
+            if (OC_STACK_OK != result)
             {
-                const unsigned char *rt1 = sqlite3_column_text(stmtRT, (rt_value_index - 1));
-                appendStringLL(&resourcePayload->types, rt1);
+                goto exit;
             }
+        }
+        VERIFY_SQLITE(sqlite3_finalize(stmtIF));
 
-            sqlite3_stmt *stmtIF = 0;
-            const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=?";
-            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, -1, &stmtIF, NULL));
-            VERIFY_SQLITE(sqlite3_bind_int(stmtIF, 1, id));
-            while (SQLITE_ROW == sqlite3_step(stmtIF))
-            {
-                const unsigned char *itf = sqlite3_column_text(stmtIF, (if_value_index - 1));
-                appendStringLL(&resourcePayload->interfaces, itf);
-            }
+        resourcePayload->bitmap = bitmap & (OC_OBSERVABLE | OC_DISCOVERABLE);
+        resourcePayload->secure = (bitmap & OC_SECURE) != 0;
 
-            resourcePayload->bitmap = bitmap & (OC_OBSERVABLE | OC_DISCOVERABLE);
-            resourcePayload->secure = (bitmap & OC_SECURE) != 0;
+        const char *address = "SELECT di, address 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=?";
+        const uint8_t di_index = 0;
+        const uint8_t address_index = 1;
 
-            const char *address = "SELECT di, address 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=?";
+        sqlite3_stmt *stmt1 = 0;
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, -1, &stmt1, NULL));
+        VERIFY_SQLITE(sqlite3_bind_int(stmt1, 1, deviceId));
 
-            sqlite3_stmt *stmt1 = 0;
-            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, -1, &stmt1, NULL));
-            VERIFY_SQLITE(sqlite3_bind_int(stmt1, 1, deviceId));
-            // TODO: Right now, we have a bug where discovery payload can only send one device information.
-            res = sqlite3_step(stmt1);
-            if (res == SQLITE_ROW || res == SQLITE_DONE)
+        res = sqlite3_step(stmt1);
+        if (SQLITE_ROW == res || SQLITE_DONE == res)
+        {
+            const unsigned char *di = sqlite3_column_text(stmt1, di_index);
+            const unsigned char *address = sqlite3_column_text(stmt1, address_index);
+            OIC_LOG_V(DEBUG, TAG, " %s %s", di, address);
+            discPayload->baseURI = OICStrdup((char *)address);
+            if (!discPayload->baseURI)
+            {
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+            discPayload->sid = OICStrdup((char *)di);
+            if (!discPayload->sid)
             {
-                const unsigned char *di = sqlite3_column_text(stmt1, 0);
-                const unsigned char *address = sqlite3_column_text(stmt1, 1);
-                OIC_LOG_V(DEBUG, TAG, " %s %s", di, address);
-                (discPayload)->baseURI = OICStrdup((char *)address);
-                (discPayload)->sid = OICStrdup((char *)di);
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
             }
-            OCDiscoveryPayloadAddNewResource(discPayload, resourcePayload);
         }
+        VERIFY_SQLITE(sqlite3_finalize(stmt1));
+        OCDiscoveryPayloadAddNewResource(discPayload, resourcePayload);
+        res = sqlite3_step(stmt);
     }
-    if (interfaceType)
+exit:
+    if (OC_STACK_OK != result)
     {
-        sqlite3_stmt *stmt = 0;
-        const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST INNER JOIN RD_LINK_IF ON " \
-        "RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID WHERE RD_LINK_IF.if LIKE ? ";
+        OCDiscoveryResourceDestroy(resourcePayload);
+    }
+    return result;
+}
 
-        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
-        VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, interfaceType, strlen(interfaceType) + 1, SQLITE_STATIC));
+static OCStackResult CheckResources(const char *interfaceType, const char *resourceType,
+        OCDiscoveryPayload *discPayload)
+{
+    if (initializeDatabase(NULL) != OC_STACK_OK)
+    {
+        return OC_STACK_INTERNAL_SERVER_ERROR;
+    }
+    if (!interfaceType && !resourceType)
+    {
+        return OC_STACK_INVALID_QUERY;
+    }
+    if (!discPayload || !discPayload->sid)
+    {
+        return OC_STACK_INTERNAL_SERVER_ERROR;
+    }
 
-        int res = sqlite3_step (stmt);
-        if (res == SQLITE_ROW || res == SQLITE_DONE)
+    OCStackResult result = OC_STACK_OK;
+    sqlite3_stmt *stmt = 0;
+    if (resourceType)
+    {
+        if (!interfaceType || 0 == strcmp(interfaceType, OC_RSRVD_INTERFACE_LL))
         {
-            int id = sqlite3_column_int(stmt, 0);
-            const unsigned char *uri = sqlite3_column_text(stmt, uri_index - 1);
-            int bitmap = sqlite3_column_int(stmt, p_index - 1);
-            int deviceId = sqlite3_column_int(stmt, d_index - 1);
-            OIC_LOG_V(DEBUG, TAG, " %s %d", uri, deviceId);
-            resourcePayload->uri = OICStrdup((char *)uri);
-            if (!resourcePayload->uri)
-            {
-                OCDiscoveryResourceDestroy(resourcePayload);
-                return OC_STACK_NO_MEMORY;
-            }
-            VERIFY_SQLITE(sqlite3_reset(stmt));
-
-            sqlite3_stmt *stmtRT = 0;
-            const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=?";
-            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, -1, &stmtRT, NULL));
-            VERIFY_SQLITE(sqlite3_bind_int(stmtRT, 1, id));
-            while (SQLITE_ROW == sqlite3_step(stmtRT))
-            {
-                const unsigned char *rt1 = sqlite3_column_text(stmtRT, (rt_value_index - 1));
-                appendStringLL(&resourcePayload->types, rt1);
-            }
-
-            sqlite3_stmt *stmtIF = 0;
-            const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=?";
-            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, -1, &stmtIF, NULL));
-            VERIFY_SQLITE(sqlite3_bind_int(stmtIF, 1, id));
-            while (SQLITE_ROW == sqlite3_step (stmtIF))
-            {
-                const unsigned char *itf = sqlite3_column_text(stmtIF, (if_value_index - 1));
-                appendStringLL(&resourcePayload->interfaces, itf);
-            }
-
-            resourcePayload->bitmap = bitmap & (OC_OBSERVABLE | OC_DISCOVERABLE);
-            resourcePayload->secure = ((bitmap & OC_SECURE) != 0);
+            const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
+                                "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
+                                "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
+                                "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2";
+            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid) + 1,
+                                            SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType) + 1, SQLITE_STATIC));
+        }
+        else
+        {
+            const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
+                                "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
+                                "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
+                                "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
+                                "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2 AND RD_LINK_IF.if LIKE ?3";
+            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid) + 1,
+                                            SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType) + 1, SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, 3, interfaceType, strlen(interfaceType) + 1, SQLITE_STATIC));
+        }
+        result = ResourcePayloadCreate(stmt, discPayload);
+    }
+    else if (interfaceType)
+    {
+        if (0 == strcmp(interfaceType, OC_RSRVD_INTERFACE_LL))
+        {
+            const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
+                                "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
+                                "WHERE RD_DEVICE_LIST.di LIKE ?1";
+            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid) + 1,
+                                            SQLITE_STATIC));
+        }
+        else
+        {
+            const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
+                                "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
+                                "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
+                                "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_IF.if LIKE ?2";
+            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid) + 1,
+                                            SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, interfaceType, strlen(interfaceType) + 1, SQLITE_STATIC));
+        }
+        result = ResourcePayloadCreate(stmt, discPayload);
+    }
+    if (stmt)
+    {
+        VERIFY_SQLITE(sqlite3_finalize(stmt));
+    }
+    return result;
+}
 
-            const char *address = "SELECT di, address 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=?";
+OCStackResult OCRDDatabaseDiscoveryPayloadCreate(const char *interfaceType,
+        const char *resourceType,
+        OCDiscoveryPayload **payload)
+{
+    OCStackResult result = OC_STACK_NO_RESOURCE;
+    OCDiscoveryPayload *head = NULL;
+    OCDiscoveryPayload **tail = &head;
 
-            sqlite3_stmt *stmt1 = 0;
-            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, -1, &stmt1, NULL));
-            VERIFY_SQLITE(sqlite3_bind_int(stmt1, 1, deviceId));
+    if (*payload)
+    {
+        /*
+         * This is an error of the caller, return here instead of touching the
+         * caller provided payload.
+         */
+        OIC_LOG_V(ERROR, TAG, "Payload is already allocated");
+        return OC_STACK_INTERNAL_SERVER_ERROR;
+    }
+    if (initializeDatabase(NULL) != OC_STACK_OK)
+    {
+        goto exit;
+    }
 
-            res = sqlite3_step(stmt1);
-            if (res == SQLITE_ROW || res == SQLITE_DONE)
-            {
-                const unsigned char *di = sqlite3_column_text(stmt1, 0);
-                const unsigned char *address = sqlite3_column_text(stmt1, 1);
-                OIC_LOG_V(DEBUG, TAG, " %s %s", di, address);
-                (discPayload)->baseURI = OICStrdup((char *)address);
-                (discPayload)->sid = OICStrdup((char *)di);
-            }
-            OCDiscoveryPayloadAddNewResource(discPayload, resourcePayload);
+    const char *serverID = OCGetServerInstanceIDString();
+    sqlite3_stmt *stmt = 0;
+    const char *input = "SELECT di FROM RD_DEVICE_LIST";
+    const uint8_t di_index = 0;
+    VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
+    while (SQLITE_ROW == sqlite3_step(stmt))
+    {
+        const unsigned char *di = sqlite3_column_text(stmt, di_index);
+        if (0 == strcmp((const char *)di, serverID))
+        {
+            continue;
+        }
+        *tail = OCDiscoveryPayloadCreate();
+        VERIFY_PARAM_NON_NULL(TAG, *tail, "Failed creating discovery payload.");
+        (*tail)->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
+        VERIFY_PARAM_NON_NULL(TAG, (*tail)->sid, "Failed adding device id to discovery payload.");
+        memcpy((*tail)->sid, di, UUID_STRING_SIZE);
+        result = CheckResources(interfaceType, resourceType, *tail);
+        if (OC_STACK_OK == result)
+        {
+            tail = &(*tail)->next;
+        }
+        else
+        {
+            OCPayloadDestroy((OCPayload *) *tail);
+            *tail = NULL;
         }
     }
-    return OC_STACK_OK;
+    VERIFY_SQLITE(sqlite3_finalize(stmt));
+    *payload = head;
+    return result;
+exit:
+    OCPayloadDestroy((OCPayload *) *tail);
+    *payload = NULL;
+    return OC_STACK_INTERNAL_SERVER_ERROR;
 }
 #endif