replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / service / notification / src / consumer / NSConsumerCommunication.c
index 32c37db..3039346 100644 (file)
 
 #define NS_SYNC_URI "/notification/sync"
 
-static unsigned long NS_MESSAGE_ACCEPTANCE = 1;
-
-NSMessage * NSCreateMessage_internal(uint64_t msgId, const char * providerId);
 NSSyncInfo * NSCreateSyncInfo_consumer(uint64_t msgId, const char * providerId, NSSyncType state);
 
-NSMessage * 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;
@@ -71,7 +82,7 @@ NSResult NSConsumerSubscribeProvider(NSProvider * provider)
             }
         }
 
-        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;
@@ -82,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);
 
@@ -96,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);
 
@@ -107,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;
 }
 
@@ -164,12 +182,12 @@ OCStackApplicationResult NSConsumerMessageListener(
     NS_VERIFY_STACK_SUCCESS(NSOCResultToSuccess(clientResponse->result), OC_STACK_KEEP_TRANSACTION);
 
     NS_LOG(DEBUG, "build NSMessage");
-    NSMessage * 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 || newNoti->messageId == NS_DENY)
+    if (newNoti->messageId == NS_ALLOW || newNoti->messageId == NS_DENY)
     {
         NS_LOG(DEBUG, "Receive subscribe result");
         type = TASK_CONSUMER_RECV_PROVIDER_CHANGED;
@@ -199,47 +217,6 @@ void NSGetMessagePostClean(char * pId, OCDevAddr * addr)
     NSOICFree(addr);
 }
 
-NSMessage * 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 * 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);
@@ -247,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);
 
@@ -259,37 +236,21 @@ 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 * NSCreateMessage_internal(uint64_t id, const char * providerId)
-{
-    NSMessage * retMsg = (NSMessage *)OICMalloc(sizeof(NSMessage));
-    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);
@@ -329,7 +290,7 @@ OCStackResult NSSendSyncInfo(NSSyncInfo * syncInfo, OCDevAddr * addr)
 
     OCStackResult ret = NSInvokeRequest(NULL, OC_REST_POST, addr,
                             uri, (OCPayload*)payload,
-                            NSConsumerCheckPostResult, NULL, type);
+                            NSConsumerCheckPostResult, NULL, NULL, type);
     NSOICFree(uri);
 
     return ret;
@@ -337,11 +298,11 @@ 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);
     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(retUri, NULL, NSOICFree(uri));
 
-    snprintf(retUri, uriLen, "/%s%s", providerId, uri);
+    snprintf(retUri, uriLen, "/oic/route/%s%s", providerId, uri);
     NSOICFree(uri);
     NS_LOG_V(DEBUG, "Cloud uri : %s", retUri);
 
@@ -358,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;
 
@@ -383,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);
@@ -403,40 +370,32 @@ void NSConsumerCommunicationTaskProcessing(NSTask * task)
             connections->isSubscribing = false;
             connections = connections->next;
         }
+
+        NSRemoveProvider_internal(provider);
     }
-    /* TODO next commit, modify code.
     else if (task->taskType == TASK_CONSUMER_REQ_TOPIC_LIST)
     {
-        NSProvider_internal * provider = (NSProvider_internal *)task->taskData;
-
-        NSProviderConnectionInfo * connections = provider->connection;
-        NS_VERIFY_NOT_NULL_V(connections);
-
-        char * topicUri = OICStrdup(provider->topicUri);
-
-        OCConnectivityType type = CT_DEFAULT;
-        if (connections->addr->adapter == OC_ADAPTER_TCP)
+        NSProvider_internal * provider = NSCopyProvider_internal(task->taskData);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(provider,
         {
-            type = CT_ADAPTER_TCP;
-            if (connections->isCloudConnection == true)
-            {
-                topicUri = NSGetCloudUri(provider->providerId, topicUri);
-            }
-        }
-
-        OCStackResult ret = NSInvokeRequest(NULL, OC_REST_GET, connections->addr,
-                                topicUri, NULL, NSIntrospectTopic, (void *) provider, type);
-        NS_VERIFY_STACK_SUCCESS_V(NSOCResultToSuccess(ret));
-        NSOICFree(topicUri);
-    }
-    else if (task->taskType == TASK_CONSUMER_GET_TOPIC_LIST)
-    {
-        NSProvider_internal * provider = (NSProvider_internal *)task->taskData;
+            NSRemoveProvider_internal((void *) task->taskData);
+            NSOICFree(task);
+        });
+        NSRemoveProvider_internal((NSProvider_internal *)task->taskData);
 
         NSProviderConnectionInfo * connections = provider->connection;
-        NS_VERIFY_NOT_NULL_V(connections);
+        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)
@@ -449,45 +408,107 @@ void NSConsumerCommunicationTaskProcessing(NSTask * task)
         }
 
         NS_LOG(DEBUG, "get topic query");
-        char * query = NULL;
-        query = NSMakeRequestUriWithConsumerId(topicUri);
-        NS_VERIFY_NOT_NULL_V(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, NULL, type);
-        NS_VERIFY_STACK_SUCCESS_V(NSOCResultToSuccess(ret));
+                                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_V(connections);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(connections,
+        {
+            NSRemoveProvider_internal(provider);
+            NSOICFree(task);
+        });
 
         OCRepPayload * payload = OCRepPayloadCreate();
-        NS_VERIFY_NOT_NULL_V(payload);
-        OCRepPayload ** topicPayload = (OCRepPayload **) OICMalloc(
-                                        sizeof(OCRepPayload *)*provider->topicListSize);
-        NS_VERIFY_NOT_NULL_V(topicPayload);
+        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());
 
-        NSTopic ** topic = provider->topicList->topics;
+        iter = topicLL;
+        int iterSize = 0;
+        NS_LOG_V(DEBUG, "DimensionSize: %d", topicLLSize);
 
-        for (int i = 0; i < (int)provider->topicListSize; i++)
+        OCRepPayload ** topicPayload = NULL;
+        if (topicLLSize > 0)
         {
-            topicPayload[i] = OCRepPayloadCreate();
-            OCRepPayloadSetPropString(topicPayload[i], NS_ATTRIBUTE_TOPIC_NAME, topic[i]->topicName);
-            OCRepPayloadSetPropInt(topicPayload[i], NS_ATTRIBUTE_TOPIC_SELECTION, topic[i]->state);
-        }
+            topicPayload = (OCRepPayload **) OICMalloc(sizeof(OCRepPayload *)*topicLLSize);
+            NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(topicPayload,
+            {
+                OCRepPayloadDestroy(payload);
+                NSRemoveProvider_internal(provider);
+                NSOICFree(task);
+            });
 
-        size_t dimensions[3] = {provider->topicListSize, 0, 0};
-        OCRepPayloadSetPropObjectArray(payload, NS_ATTRIBUTE_TOPIC_LIST, (const OCRepPayload **)topicPayload, dimensions);
+            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)
@@ -502,15 +523,31 @@ void NSConsumerCommunicationTaskProcessing(NSTask * task)
         NS_LOG(DEBUG, "get topic query");
         char * query = NULL;
         query = NSMakeRequestUriWithConsumerId(topicUri);
-        NS_VERIFY_NOT_NULL_V(query);
+        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_GET, connections->addr,
-                                query, (OCPayload*)payload, NSConsumerCheckPostResult, NULL, type);
-        NS_VERIFY_STACK_SUCCESS_V(NSOCResultToSuccess(ret));
+        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");
@@ -519,98 +556,94 @@ void NSConsumerCommunicationTaskProcessing(NSTask * task)
     NSOICFree(task);
 }
 
-void NSGetTopicPostClean(
-        char * cId, NSTopicList * tList, size_t dSize)
+NSTopicLL * NSGetTopicLL(OCClientResponse * clientResponse)
 {
-    /* TODO next commit, modify code.
-    NSOICFree(cId);
-    NSRemoveProviderTopicList(tList, dSize);
-    */
-}
-
-NSTopicList * NSGetTopic(OCClientResponse * clientResponse, size_t * topicListSize)
-{
-    /* TODO next commit, modify code.
-    NS_LOG(DEBUG, "create NSTopic");
+    NS_LOG(DEBUG, "create NSTopicLL");
     NS_VERIFY_NOT_NULL(clientResponse->payload, NULL);
 
     OCRepPayload * payload = (OCRepPayload *)clientResponse->payload;
-    while (payload)
+    OCRepPayloadValue * value = payload->values;
+    while (value)
     {
-        NS_LOG_V(DEBUG, "Payload Key : %s", payload->values->name);
-        payload = payload->next;
+        NS_LOG_V(DEBUG, "Payload Key : %s", value->name);
+        value = value->next;
     }
 
-    payload = (OCRepPayload *)clientResponse->payload;
-
     char * consumerId = NULL;
-    OCRepPayload ** topicListPayload = NULL;
-    NSTopicList * topicList = (NSTopicList *) OICMalloc(sizeof(NSTopicList));
-    NS_VERIFY_NOT_NULL(topicList, NULL);
+    OCRepPayload ** topicLLPayload = NULL;
 
     NS_LOG(DEBUG, "get information of consumerId");
-    bool getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_CONSUMER_ID, & consumerId); // is NULL possible? (initial getting)
-    NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
 
-    OICStrcpy(topicList->consumerId, NS_DEVICE_ID_LENGTH, 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_WITH_POST_CLEANING(payloadValue, NULL, NSOICFree(consumerId));
+    NS_VERIFY_NOT_NULL(payloadValue, NULL);
 
     size_t dimensionSize = calcDimTotal(payloadValue->arr.dimensions);
-    size_t dimensions[3] = {dimensionSize, 0, 0};
-    *topicListSize = dimensionSize;
+    NS_LOG_V(DEBUG, "DimensionSize: %d", (int)dimensionSize);
 
-    NS_LOG(DEBUG, "get information of topicList(OCRepPayload)");
-    getResult = OCRepPayloadGetPropObjectArray(payload, NS_ATTRIBUTE_TOPIC_LIST, 
-            & topicListPayload, dimensions);
-    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL, 
-            NULL, NSOICFree(consumerId));
+    if (dimensionSize == 0 || payloadValue->type == OCREP_PROP_NULL ||
+            payloadValue->arr.objArray == NULL)
+    {
+        NS_LOG(DEBUG, "No TopicLL");
+        return NULL;
+    }
 
-    topicList->topics = (NSTopic **) OICMalloc(sizeof(NSTopic *)*dimensionSize);
-    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(topicList->topics,
-            NULL, NSGetTopicPostClean(consumerId, topicList, -1));
+    topicLLPayload = payloadValue->arr.objArray;
 
+    NSTopicLL * topicLL = NULL;
     for (int i = 0; i < (int)dimensionSize; i++)
     {
         char * topicName = NULL;
         int64_t state = 0;
 
-        topicList->topics[i] = (NSTopic *) OICMalloc(sizeof(NSTopic));
-        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(topicList->topics[i],
-                NULL, NSGetTopicPostClean(consumerId, topicList, i));
+        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(topicListPayload[i], NS_ATTRIBUTE_TOPIC_NAME, &topicName);
+        getResult = OCRepPayloadGetPropString(topicLLPayload[i],
+                NS_ATTRIBUTE_TOPIC_NAME, & topicName);
         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL,
-                NULL, NSGetTopicPostClean(consumerId, topicList, i));
+                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;
 
-        NS_LOG(DEBUG, "get topic selection");
-        getResult = OCRepPayloadGetPropInt(topicListPayload[i], NS_ATTRIBUTE_TOPIC_SELECTION, &state);
-        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL,
-                NULL, NSGetTopicPostClean(consumerId, topicList, i));
+        if (i == 0)
+        {
+            topicLL = topicNode;
+            topicNode->next = NULL;
+            continue;
+        }
 
-        topicList->topics[i]->topicName = topicName;
-        topicList->topics[i]->state = state;
+        NSResult ret = NSInsertTopicNode(topicLL, topicNode);
+        NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(ret == NS_OK ? (void *)1 : NULL,
+                                                    NULL, NSRemoveTopicLL(topicLL));
     }
 
-    NSOICFree(consumerId);
-
-    return topicList;*/
+    return topicLL;
 }
 
 OCStackApplicationResult NSIntrospectTopic(
         void * ctx, OCDoHandle handle, OCClientResponse * clientResponse)
 {
-/* TODO next commit, modify code.
     (void) handle;
 
     NS_VERIFY_NOT_NULL(clientResponse, OC_STACK_KEEP_TRANSACTION);
-    NS_VERIFY_STACK_SUCCESS(NSOCResultToSuccess(clientResponse->result), OC_STACK_KEEP_TRANSACTION);
+    NS_VERIFY_STACK_SUCCESS(NSOCResultToSuccess(clientResponse->result),
+                            OC_STACK_KEEP_TRANSACTION)
 
-    NS_LOG_V(DEBUG, "GET response income : %s:%d",
+    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);
@@ -619,24 +652,23 @@ OCStackApplicationResult NSIntrospectTopic(
     NS_LOG_V(DEBUG, "GET response resource uri : %s",
             clientResponse->resourceUri);
     NS_LOG_V(DEBUG, "GET response Transport Type : %d",
-                    clientResponse->devAddr.adapter);
+            clientResponse->devAddr.adapter);
 
-    size_t topicListSize = 0;
-    NSTopicList * newTopicList = NSGetTopic(clientResponse, &topicListSize);
-    NS_VERIFY_NOT_NULL(newTopicList, OC_STACK_KEEP_TRANSACTION);
+    NSTopicLL * newTopicLL = NSGetTopicLL(clientResponse);
 
-    // TODO Call the callback function registered at the start
-    NSProvider_internal * provider = (NSProvider_internal *) ctx;
-    provider->topicList = NSCopyProviderTopicList(newTopicList, topicListSize);
-    provider->topicListSize = topicListSize;
+    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(provider));
+    NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(task, NS_ERROR, NSRemoveProvider_internal(provider));
 
     NSConsumerPushEvent(task);
-    NSRemoveProviderTopicList(newTopicList, topicListSize);
+    NSRemoveTopicLL(newTopicLL);
 
     return OC_STACK_KEEP_TRANSACTION;
-    */
 }