replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / service / notification / src / consumer / NSConsumerCommunication.c
index 249828a..3039346 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+#include "NSConsumerCommunication.h"
+
 #include "NSConstants.h"
+#include "NSUtil.h"
 #include "NSConsumerCommon.h"
-#include "NSConsumerCommunication.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 #include "ocpayload.h"
 
 #define NS_SYNC_URI "/notification/sync"
 
-unsigned long NS_MESSAGE_ACCEPTANCE = 1;
-
-NSMessage_consumer * NSCreateMessage_internal(uint64_t msgId, const char * providerId);
 NSSyncInfo * NSCreateSyncInfo_consumer(uint64_t msgId, const char * providerId, NSSyncType state);
 
-NSMessage_consumer * NSGetMessage(OCClientResponse * clientResponse);
 NSSyncInfo * NSGetSyncInfoc(OCClientResponse * clientResponse);
+NSTopicLL * NSGetTopicLL(OCClientResponse * clientResponse);
 
 char * NSGetCloudUri(const char * providerId, char * uri);
 
+NSResult NSUpdateObserveResult(NSProvider_internal * prov, char * query)
+{
+    NSOICFree(query);
+
+    NSProvider_internal * taskProvider = NSCopyProvider_internal(prov);
+    NSTask * task = NSMakeTask(TASK_CONSUMER_SENT_REQ_OBSERVE, (void *) taskProvider);
+    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(task,
+                    NS_ERROR, NSRemoveProvider_internal(taskProvider));
+
+    NSConsumerPushEvent(task);
+
+    return NS_OK;
+}
+
 NSResult NSConsumerSubscribeProvider(NSProvider * provider)
 {
     NSProvider_internal * provider_internal = (NSProvider_internal *) provider;
@@ -52,7 +65,9 @@ NSResult NSConsumerSubscribeProvider(NSProvider * provider)
         }
 
         char * msgUri = OICStrdup(provider_internal->messageUri);
+        NS_VERIFY_NOT_NULL(msgUri, NS_ERROR);
         char * syncUri = OICStrdup(provider_internal->syncUri);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(syncUri, NS_ERROR, NSOICFree(msgUri));
 
         OCConnectivityType type = CT_DEFAULT;
         if (connections->addr->adapter == OC_ADAPTER_TCP)
@@ -61,11 +76,13 @@ NSResult NSConsumerSubscribeProvider(NSProvider * provider)
             if (connections->isCloudConnection == true)
             {
                 msgUri = NSGetCloudUri(provider_internal->providerId, msgUri);
+                NS_VERIFY_NOT_NULL(msgUri, NS_ERROR);
                 syncUri = NSGetCloudUri(provider_internal->providerId, syncUri);
+                NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(syncUri, NS_ERROR, NSOICFree(msgUri));
             }
         }
 
-        NS_LOG_V(DEBUG, "subscribe to %s:%d", connections->addr->addr, connections->addr->port);
+        NS_LOG_V(INFO_PRIVATE, "subscribe to %s:%d", connections->addr->addr, connections->addr->port);
 
         NS_LOG(DEBUG, "get subscribe message query");
         char * query = NULL;
@@ -76,9 +93,9 @@ NSResult NSConsumerSubscribeProvider(NSProvider * provider)
         NS_LOG_V(DEBUG, "subscribe query : %s", query);
         OCStackResult ret = NSInvokeRequest(&(connections->messageHandle),
                               OC_REST_OBSERVE, connections->addr, query, NULL,
-                              NSConsumerMessageListener, NULL, type);
-        NS_VERIFY_STACK_SUCCESS_WITH_POST_CLEANING(
-                NSOCResultToSuccess(ret), NS_ERROR, NSOICFree(query));
+                              NSConsumerMessageListener, NULL, NULL, type);
+        NS_VERIFY_STACK_SUCCESS_WITH_POST_CLEANING(NSOCResultToSuccess(ret),
+                            NS_ERROR, NSUpdateObserveResult(provider_internal, query));
         NSOICFree(query);
         NSOICFree(msgUri);
 
@@ -90,9 +107,9 @@ NSResult NSConsumerSubscribeProvider(NSProvider * provider)
         NS_LOG_V(DEBUG, "subscribe query : %s", query);
         ret = NSInvokeRequest(&(connections->syncHandle),
                               OC_REST_OBSERVE, connections->addr, query, NULL,
-                              NSConsumerSyncInfoListener, NULL, type);
-        NS_VERIFY_STACK_SUCCESS_WITH_POST_CLEANING(
-                NSOCResultToSuccess(ret), NS_ERROR, NSOICFree(query));
+                              NSConsumerSyncInfoListener, NULL, NULL, type);
+        NS_VERIFY_STACK_SUCCESS_WITH_POST_CLEANING(NSOCResultToSuccess(ret),
+                            NS_ERROR, NSUpdateObserveResult(provider_internal, query));
         NSOICFree(query);
         NSOICFree(syncUri);
 
@@ -101,6 +118,13 @@ NSResult NSConsumerSubscribeProvider(NSProvider * provider)
         connections = connections->next;
     }
 
+    NSProvider_internal * taskProvider = NSCopyProvider_internal(provider_internal);
+    NSTask * task = NSMakeTask(TASK_CONSUMER_SENT_REQ_OBSERVE, (void *) taskProvider);
+    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(task,
+                    NS_ERROR, NSRemoveProvider_internal(taskProvider));
+
+    NSConsumerPushEvent(task);
+
     return NS_OK;
 }
 
@@ -158,15 +182,20 @@ OCStackApplicationResult NSConsumerMessageListener(
     NS_VERIFY_STACK_SUCCESS(NSOCResultToSuccess(clientResponse->result), OC_STACK_KEEP_TRANSACTION);
 
     NS_LOG(DEBUG, "build NSMessage");
-    NSMessage_consumer * newNoti = NSGetMessage(clientResponse);
+    NSMessage * newNoti = NSGetMessage((OCRepPayload *) clientResponse->payload);
     NS_VERIFY_NOT_NULL(newNoti, OC_STACK_KEEP_TRANSACTION);
 
     NSTaskType type = TASK_CONSUMER_RECV_MESSAGE;
 
-    if (newNoti->messageId == NS_MESSAGE_ACCEPTANCE)
+    if (newNoti->messageId == NS_ALLOW || newNoti->messageId == NS_DENY)
+    {
+        NS_LOG(DEBUG, "Receive subscribe result");
+        type = TASK_CONSUMER_RECV_PROVIDER_CHANGED;
+    }
+    else if (newNoti->messageId == NS_TOPIC)
     {
-        NS_LOG(DEBUG, "Receive Subscribe confirm");
-        type = TASK_CONSUMER_RECV_SUBSCRIBE_CONFIRMED;
+        NS_LOG(DEBUG, "Receive Topic change");
+        type = TASK_CONSUMER_REQ_TOPIC_URI;
     }
     else
     {
@@ -188,47 +217,6 @@ void NSGetMessagePostClean(char * pId, OCDevAddr * addr)
     NSOICFree(addr);
 }
 
-NSMessage_consumer * NSGetMessage(OCClientResponse * clientResponse)
-{
-    NS_VERIFY_NOT_NULL(clientResponse->payload, NULL);
-    OCRepPayload * payload = (OCRepPayload *)clientResponse->payload;
-
-    NS_LOG(DEBUG, "get msg id");
-    uint64_t id = NULL;
-    bool getResult = OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, (int64_t *)&id);
-    NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
-
-    NS_LOG(DEBUG, "get provider id");
-    char * pId = NULL;
-    getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, &pId);
-    NS_LOG_V (DEBUG, "provider id: %s", pId);
-    NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
-
-    NS_LOG(DEBUG, "create NSMessage");
-    NSMessage_consumer * retMsg = NSCreateMessage_internal(id, pId);
-    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(retMsg, NULL, NSOICFree(pId));
-    NSOICFree(pId);
-
-    NS_LOG(DEBUG, "get msg optional field");
-    OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_TITLE, &retMsg->title);
-    OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_TEXT, &retMsg->contentText);
-    OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_SOURCE, &retMsg->sourceName);
-
-    OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_TYPE, (int64_t *)&retMsg->type);
-    OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_DATETIME, &retMsg->dateTime);
-    OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_TTL, (int64_t *)&retMsg->ttl);
-
-    NS_LOG_V(DEBUG, "Msg ID      : %lld", (long long int)retMsg->messageId);
-    NS_LOG_V(DEBUG, "Msg Title   : %s", retMsg->title);
-    NS_LOG_V(DEBUG, "Msg Content : %s", retMsg->contentText);
-    NS_LOG_V(DEBUG, "Msg Source  : %s", retMsg->sourceName);
-    NS_LOG_V(DEBUG, "Msg Type    : %d", retMsg->type);
-    NS_LOG_V(DEBUG, "Msg Date    : %s", retMsg->dateTime);
-    NS_LOG_V(DEBUG, "Msg ttl     : %lld", (long long int)retMsg->ttl);
-
-    return retMsg;
-}
-
 NSSyncInfo * NSGetSyncInfoc(OCClientResponse * clientResponse)
 {
     NS_VERIFY_NOT_NULL(clientResponse->payload, NULL);
@@ -236,7 +224,7 @@ NSSyncInfo * NSGetSyncInfoc(OCClientResponse * clientResponse)
     OCRepPayload * payload = (OCRepPayload *)clientResponse->payload;
 
     NS_LOG(DEBUG, "get msg id");
-    uint64_t id = NULL;
+    uint64_t id = 0;
     bool getResult = OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, (int64_t *)&id);
     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
 
@@ -248,39 +236,25 @@ NSSyncInfo * NSGetSyncInfoc(OCClientResponse * clientResponse)
     NS_LOG(DEBUG, "get state");
     int64_t state = 0;
     getResult = OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_STATE, & state);
-    NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
+    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL,
+            NULL, NSOICFree(pId));
 
     NS_LOG(DEBUG, "create NSSyncInfo");
     NSSyncInfo * retSync = NSCreateSyncInfo_consumer(id, pId, (NSSyncType)state);
+    NSOICFree(pId);
     NS_VERIFY_NOT_NULL(retSync, NULL);
 
     NS_LOG_V(DEBUG, "Sync ID : %lld", (long long int)retSync->messageId);
     NS_LOG_V(DEBUG, "Sync State : %d", (int) retSync->state);
-    NS_LOG_V(DEBUG, "Sync Provider ID : %s", retSync->providerId);
+    NS_LOG_V(INFO_PRIVATE, "Sync Provider ID : %s", retSync->providerId);
 
     return retSync;
 }
 
-NSMessage_consumer * NSCreateMessage_internal(uint64_t id, const char * providerId)
-{
-    NSMessage_consumer * retMsg = (NSMessage_consumer *)OICMalloc(sizeof(NSMessage_consumer));
-    NS_VERIFY_NOT_NULL(retMsg, NULL);
-
-    retMsg->messageId = id;
-    OICStrcpy(retMsg->providerId, sizeof(char) * NS_DEVICE_ID_LENGTH, providerId);
-    retMsg->title = NULL;
-    retMsg->contentText = NULL;
-    retMsg->sourceName = NULL;
-    retMsg->type = NS_MESSAGE_INFO;
-    retMsg->dateTime = NULL;
-    retMsg->ttl = 0;
-    retMsg->mediaContents = NULL;
-
-    return retMsg;
-}
-
 NSSyncInfo * NSCreateSyncInfo_consumer(uint64_t msgId, const char * providerId, NSSyncType state)
 {
+    NS_VERIFY_NOT_NULL(providerId, NULL);
+
     NSSyncInfo * retSync = (NSSyncInfo *)OICMalloc(sizeof(NSSyncInfo));
     NS_VERIFY_NOT_NULL(retSync, NULL);
 
@@ -293,6 +267,9 @@ NSSyncInfo * NSCreateSyncInfo_consumer(uint64_t msgId, const char * providerId,
 
 OCStackResult NSSendSyncInfo(NSSyncInfo * syncInfo, OCDevAddr * addr)
 {
+    NS_VERIFY_NOT_NULL(syncInfo, OC_STACK_ERROR);
+    NS_VERIFY_NOT_NULL(addr, OC_STACK_ERROR);
+
     OCRepPayload * payload = OCRepPayloadCreate();
     NS_VERIFY_NOT_NULL(payload, OC_STACK_ERROR);
 
@@ -301,16 +278,19 @@ OCStackResult NSSendSyncInfo(NSSyncInfo * syncInfo, OCDevAddr * addr)
     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, syncInfo->providerId);
 
     char * uri = (char*)OICStrdup(NS_SYNC_URI);
+    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(uri, OC_STACK_ERROR, OCRepPayloadDestroy(payload));
+
     OCConnectivityType type = CT_DEFAULT;
     if(addr->adapter == OC_ADAPTER_TCP)
     {
         type = CT_ADAPTER_TCP;
         uri = NSGetCloudUri(syncInfo->providerId, uri);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(uri, OC_STACK_ERROR, OCRepPayloadDestroy(payload));
     }
 
     OCStackResult ret = NSInvokeRequest(NULL, OC_REST_POST, addr,
                             uri, (OCPayload*)payload,
-                            NSConsumerCheckPostResult, NULL, type);
+                            NSConsumerCheckPostResult, NULL, NULL, type);
     NSOICFree(uri);
 
     return ret;
@@ -318,11 +298,13 @@ OCStackResult NSSendSyncInfo(NSSyncInfo * syncInfo, OCDevAddr * addr)
 
 char * NSGetCloudUri(const char * providerId, char * uri)
 {
-    size_t uriLen = NS_DEVICE_ID_LENGTH + 1 + strlen(uri) + 1;
+    size_t uriLen = NS_DEVICE_ID_LENGTH + 1 + strlen(uri) + 1 + 10;
     char * retUri = (char *)OICMalloc(uriLen);
-    snprintf(retUri, uriLen, "/%s%s", providerId, uri);
+    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(retUri, NULL, NSOICFree(uri));
+
+    snprintf(retUri, uriLen, "/oic/route/%s%s", providerId, uri);
     NSOICFree(uri);
-    NS_LOG_V(DEBUG, "TCP uri : %s", retUri);
+    NS_LOG_V(DEBUG, "Cloud uri : %s", retUri);
 
     return retUri;
 }
@@ -337,11 +319,12 @@ void NSConsumerCommunicationTaskProcessing(NSTask * task)
         NS_VERIFY_NOT_NULL_V(task->taskData);
         NS_LOG(DEBUG, "Request Subscribe");
         NSResult ret = NSConsumerSubscribeProvider((NSProvider *)task->taskData);
+        NSRemoveProvider_internal((void *) task->taskData);
         NS_VERIFY_NOT_NULL_V(ret == NS_OK ? (void *)1 : NULL);
     }
     else if (task->taskType == TASK_SEND_SYNCINFO)
     {
-        NS_VERIFY_NOT_NULL_V(task->taskData);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(task->taskData, NSOICFree(task));
         NSSyncInfo_internal * syncInfo = (NSSyncInfo_internal *)task->taskData;
         NSProviderConnectionInfo * info = syncInfo->connection;
 
@@ -362,18 +345,23 @@ void NSConsumerCommunicationTaskProcessing(NSTask * task)
     else if (task->taskType == TASK_CONSUMER_REQ_SUBSCRIBE_CANCEL)
     {
         NSProvider_internal * provider = (NSProvider_internal *)task->taskData;
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(provider,
+        {
+            NSRemoveProvider_internal(provider);
+            NSOICFree(task);
+        });
 
         NSProviderConnectionInfo * connections = provider->connection;
         while(connections)
         {
             if (connections->isSubscribing == false)
             {
-                NS_LOG_V(DEBUG, "unsubscribed to %s:%d",
+                NS_LOG_V(INFO_PRIVATE, "unsubscribed to %s:%d",
                      connections->addr->addr, connections->addr->port);
                 connections = connections->next;
                 continue;
             }
-            NS_LOG_V(DEBUG, "cancel subscribe to %s:%d",
+            NS_LOG_V(INFO_PRIVATE, "cancel subscribe to %s:%d",
                      connections->addr->addr, connections->addr->port);
             OCCancel(connections->messageHandle, NS_QOS, NULL, 0);
             OCCancel(connections->syncHandle, NS_QOS, NULL, 0);
@@ -382,10 +370,305 @@ void NSConsumerCommunicationTaskProcessing(NSTask * task)
             connections->isSubscribing = false;
             connections = connections->next;
         }
+
+        NSRemoveProvider_internal(provider);
+    }
+    else if (task->taskType == TASK_CONSUMER_REQ_TOPIC_LIST)
+    {
+        NSProvider_internal * provider = NSCopyProvider_internal(task->taskData);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(provider,
+        {
+            NSRemoveProvider_internal((void *) task->taskData);
+            NSOICFree(task);
+        });
+        NSRemoveProvider_internal((NSProvider_internal *)task->taskData);
+
+        NSProviderConnectionInfo * connections = provider->connection;
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(connections,
+        {
+            NSRemoveProvider_internal((void *) provider);
+            NSOICFree(task);
+        });
+
+        char * topicUri = OICStrdup(provider->topicUri);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(topicUri,
+        {
+            NSRemoveProvider_internal((void *) provider);
+            NSOICFree(task);
+        });
+
+        OCConnectivityType type = CT_DEFAULT;
+        if (connections->addr->adapter == OC_ADAPTER_TCP)
+        {
+            type = CT_ADAPTER_TCP;
+            if (connections->isCloudConnection == true)
+            {
+                topicUri = NSGetCloudUri(provider->providerId, topicUri);
+            }
+        }
+
+        NS_LOG(DEBUG, "get topic query");
+        char * query = NSMakeRequestUriWithConsumerId(topicUri);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(query,
+        {
+            NSRemoveProvider_internal((void *) provider);
+            NSOICFree(task);
+        });
+        NS_LOG_V(DEBUG, "topic query : %s", query);
+
+        OCStackResult ret = NSInvokeRequest(NULL, OC_REST_GET, connections->addr,
+                                query, NULL, NSIntrospectTopic, (void *) provider,
+                                NSRemoveProvider_internal, type);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(NSOCResultToSuccess(ret) == true ? (void *) 1 : NULL,
+        {
+            NSRemoveProvider_internal((void *) provider);
+            NSOICFree(task);
+        });
+
+        NSOICFree(query);
+        NSOICFree(topicUri);
+    }
+    else if (task->taskType == TASK_CONSUMER_SELECT_TOPIC_LIST)
+    {
+        NSProvider_internal * provider = (NSProvider_internal *)task->taskData;
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(provider,
+        {
+            NSRemoveProvider_internal(provider);
+            NSOICFree(task);
+        });
+
+        NSProviderConnectionInfo * connections = provider->connection;
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(connections,
+        {
+            NSRemoveProvider_internal(provider);
+            NSOICFree(task);
+        });
+
+        OCRepPayload * payload = OCRepPayloadCreate();
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(payload,
+        {
+            NSRemoveProvider_internal(provider);
+            NSOICFree(task);
+        });
+
+        NSTopicLL * topicLL = provider->topicLL;
+        NSTopicLL * iter = topicLL;
+        int topicLLSize = 0;
+        while (iter)
+        {
+            topicLLSize ++;
+            NS_LOG_V(DEBUG, "[%d] Topic Name:%s\tTopic State:%d",
+                                        topicLLSize, iter->topicName, iter->state);
+            iter = (NSTopicLL *) iter->next;
+        }
+
+        OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_CONSUMER_ID, *NSGetConsumerId());
+        NS_LOG_V(INFO_PRIVATE, "NS_ATTRIBUTE_CONSUMER_ID: %s", *NSGetConsumerId());
+
+        iter = topicLL;
+        int iterSize = 0;
+        NS_LOG_V(DEBUG, "DimensionSize: %d", topicLLSize);
+
+        OCRepPayload ** topicPayload = NULL;
+        if (topicLLSize > 0)
+        {
+            topicPayload = (OCRepPayload **) OICMalloc(sizeof(OCRepPayload *)*topicLLSize);
+            NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(topicPayload,
+            {
+                OCRepPayloadDestroy(payload);
+                NSRemoveProvider_internal(provider);
+                NSOICFree(task);
+            });
+
+            while (iter || iterSize < topicLLSize)
+            {
+                topicPayload[iterSize] = OCRepPayloadCreate();
+                OCRepPayloadSetPropString(topicPayload[iterSize], NS_ATTRIBUTE_TOPIC_NAME,
+                                            iter->topicName);
+                OCRepPayloadSetPropInt(topicPayload[iterSize], NS_ATTRIBUTE_TOPIC_SELECTION,
+                                            iter->state);
+                NS_LOG_V(DEBUG, "NS_ATTRIBUTE_TOPIC_NAME: %s", iter->topicName);
+                NS_LOG_V(DEBUG, "NS_ATTRIBUTE_TOPIC_SELECTION: %d", iter->state);
+                iterSize++;
+                iter = iter->next;
+            }
+            size_t dimensions[3] = {topicLLSize, 0, 0};
+
+            OCRepPayloadSetPropObjectArrayAsOwner(payload, NS_ATTRIBUTE_TOPIC_LIST,
+                                                    topicPayload, dimensions);
+        }
+        else
+        {
+            OCRepPayloadSetNull(payload, NS_ATTRIBUTE_TOPIC_LIST);
+        }
+
+        char * topicUri = OICStrdup(provider->topicUri);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(topicUri,
+        {
+            OCRepPayloadDestroy(payload);
+            NSRemoveProvider_internal(provider);
+            NSOICFree(task);
+        });
+
+        OCConnectivityType type = CT_DEFAULT;
+        if (connections->addr->adapter == OC_ADAPTER_TCP)
+        {
+            type = CT_ADAPTER_TCP;
+            if (connections->isCloudConnection == true)
+            {
+                topicUri = NSGetCloudUri(provider->providerId, topicUri);
+            }
+        }
+
+        NS_LOG(DEBUG, "get topic query");
+        char * query = NULL;
+        query = NSMakeRequestUriWithConsumerId(topicUri);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(query,
+        {
+            NSOICFree(topicUri);
+            OCRepPayloadDestroy(payload);
+            NSRemoveProvider_internal(provider);
+            NSOICFree(task);
+        });
+        NS_LOG_V(DEBUG, "topic query : %s", query);
+
+        OCStackResult ret = NSInvokeRequest(NULL, OC_REST_POST, connections->addr,
+                                query, (OCPayload*)payload, NSConsumerCheckPostResult,
+                                NULL, NULL, type);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(
+                NSOCResultToSuccess(ret) == true ? (void *) 1 : NULL,
+        {
+            NSOICFree(query);
+            NSOICFree(topicUri);
+            NSRemoveProvider_internal(provider);
+            NSOICFree(task);
+        });
+
+        NSRemoveProvider_internal(provider);
+        NSOICFree(query);
+        NSOICFree(topicUri);
     }
     else
     {
         NS_LOG(ERROR, "Unknown type message");
     }
+
     NSOICFree(task);
 }
+
+NSTopicLL * NSGetTopicLL(OCClientResponse * clientResponse)
+{
+    NS_LOG(DEBUG, "create NSTopicLL");
+    NS_VERIFY_NOT_NULL(clientResponse->payload, NULL);
+
+    OCRepPayload * payload = (OCRepPayload *)clientResponse->payload;
+    OCRepPayloadValue * value = payload->values;
+    while (value)
+    {
+        NS_LOG_V(DEBUG, "Payload Key : %s", value->name);
+        value = value->next;
+    }
+
+    char * consumerId = NULL;
+    OCRepPayload ** topicLLPayload = NULL;
+
+    NS_LOG(DEBUG, "get information of consumerId");
+
+    bool getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_CONSUMER_ID, & consumerId);
+    NSOICFree(consumerId);
+
+    OCRepPayloadValue * payloadValue = NULL;
+    payloadValue = NSPayloadFindValue(payload, NS_ATTRIBUTE_TOPIC_LIST);
+    NS_VERIFY_NOT_NULL(payloadValue, NULL);
+
+    size_t dimensionSize = calcDimTotal(payloadValue->arr.dimensions);
+    NS_LOG_V(DEBUG, "DimensionSize: %d", (int)dimensionSize);
+
+    if (dimensionSize == 0 || payloadValue->type == OCREP_PROP_NULL ||
+            payloadValue->arr.objArray == NULL)
+    {
+        NS_LOG(DEBUG, "No TopicLL");
+        return NULL;
+    }
+
+    topicLLPayload = payloadValue->arr.objArray;
+
+    NSTopicLL * topicLL = NULL;
+    for (int i = 0; i < (int)dimensionSize; i++)
+    {
+        char * topicName = NULL;
+        int64_t state = 0;
+
+        NSTopicLL * topicNode = (NSTopicLL *) OICMalloc(sizeof(NSTopicLL));
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(topicNode, NULL, NSRemoveTopicLL(topicLL));
+
+        NS_LOG(DEBUG, "get topic selection");
+        getResult = OCRepPayloadGetPropInt(topicLLPayload[i],
+                NS_ATTRIBUTE_TOPIC_SELECTION, & state);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL,
+                NULL, NSRemoveTopicLL(topicLL));
+
+        NS_LOG(DEBUG, "get topic name");
+        getResult = OCRepPayloadGetPropString(topicLLPayload[i],
+                NS_ATTRIBUTE_TOPIC_NAME, & topicName);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL,
+                NULL, NSRemoveTopicLL(topicLL));
+        NS_LOG_V(DEBUG, "topic name: %s", topicName);
+        NS_LOG_V(DEBUG, "topic selection: %d", (int)state);
+
+        topicNode->topicName = topicName;
+        topicNode->state = state;
+
+        if (i == 0)
+        {
+            topicLL = topicNode;
+            topicNode->next = NULL;
+            continue;
+        }
+
+        NSResult ret = NSInsertTopicNode(topicLL, topicNode);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(ret == NS_OK ? (void *)1 : NULL,
+                                                    NULL, NSRemoveTopicLL(topicLL));
+    }
+
+    return topicLL;
+}
+
+OCStackApplicationResult NSIntrospectTopic(
+        void * ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+{
+    (void) handle;
+
+    NS_VERIFY_NOT_NULL(clientResponse, OC_STACK_KEEP_TRANSACTION);
+    NS_VERIFY_STACK_SUCCESS(NSOCResultToSuccess(clientResponse->result),
+                            OC_STACK_KEEP_TRANSACTION)
+
+    NS_LOG_V(INFO_PRIVATE, "GET response income : %s:%d",
+            clientResponse->devAddr.addr, clientResponse->devAddr.port);
+    NS_LOG_V(DEBUG, "GET response result : %d",
+            clientResponse->result);
+    NS_LOG_V(DEBUG, "GET response sequenceNum : %d",
+            clientResponse->sequenceNumber);
+    NS_LOG_V(DEBUG, "GET response resource uri : %s",
+            clientResponse->resourceUri);
+    NS_LOG_V(DEBUG, "GET response Transport Type : %d",
+            clientResponse->devAddr.adapter);
+
+    NSTopicLL * newTopicLL = NSGetTopicLL(clientResponse);
+
+    NSProvider_internal * provider = NSCopyProvider_internal((NSProvider_internal *) ctx);
+    NS_VERIFY_NOT_NULL(provider, OC_STACK_KEEP_TRANSACTION);
+    NSRemoveTopicLL(provider->topicLL);
+    provider->topicLL = NSCopyTopicLL(newTopicLL);
+    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(provider->topicLL, OC_STACK_KEEP_TRANSACTION,
+                          NSRemoveProvider_internal((void *) provider));
+
+    NS_LOG(DEBUG, "build NSTask");
+    NSTask * task = NSMakeTask(TASK_CONSUMER_RECV_TOPIC_LIST, (void *) provider);
+    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(task, NS_ERROR, NSRemoveProvider_internal(provider));
+
+    NSConsumerPushEvent(task);
+    NSRemoveTopicLL(newTopicLL);
+
+    return OC_STACK_KEEP_TRANSACTION;
+}