{
#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"
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));
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
#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)) \
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