Add Consumer Logic to update observe result for each connections
[platform/upstream/iotivity.git] / service / notification / src / consumer / NSConsumerCommunication.c
1 //******************************************************************
2 //
3 // Copyright 2016 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "NSConsumerCommunication.h"
22
23 #include "NSConstants.h"
24 #include "NSUtil.h"
25 #include "NSConsumerCommon.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "ocpayload.h"
29
30 #define NS_SYNC_URI "/notification/sync"
31
32 static unsigned long NS_MESSAGE_ACCEPTANCE = 1;
33
34 NSMessage * NSCreateMessage_internal(uint64_t msgId, const char * providerId);
35 NSSyncInfo * NSCreateSyncInfo_consumer(uint64_t msgId, const char * providerId, NSSyncType state);
36
37 NSMessage * NSGetMessage(OCClientResponse * clientResponse);
38 NSSyncInfo * NSGetSyncInfoc(OCClientResponse * clientResponse);
39 NSTopicLL * NSGetTopicLL(OCClientResponse * clientResponse);
40
41 char * NSGetCloudUri(const char * providerId, char * uri);
42
43 NSResult NSUpdateObserveResult(NSProvider_internal * prov, char * query)
44 {
45     NSOICFree(query);
46
47     NSProvider_internal * taskProvider = NSCopyProvider_internal(prov);
48     NSTask * task = NSMakeTask(TASK_CONSUMER_SENT_REQ_OBSERVE, (void *) taskProvider);
49     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(task,
50                     NS_ERROR, NSRemoveProvider_internal(taskProvider));
51
52     NSConsumerPushEvent(task);
53
54     return NS_OK;
55 }
56
57 NSResult NSConsumerSubscribeProvider(NSProvider * provider)
58 {
59     NSProvider_internal * provider_internal = (NSProvider_internal *) provider;
60     NS_VERIFY_NOT_NULL(provider_internal, NS_ERROR);
61
62     NSProviderConnectionInfo * connections = provider_internal->connection;
63     while(connections)
64     {
65         if (connections->isSubscribing == true)
66         {
67             connections = connections->next;
68             continue;
69         }
70
71         char * msgUri = OICStrdup(provider_internal->messageUri);
72         NS_VERIFY_NOT_NULL(msgUri, NS_ERROR);
73         char * syncUri = OICStrdup(provider_internal->syncUri);
74         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(syncUri, NS_ERROR, NSOICFree(msgUri));
75
76         OCConnectivityType type = CT_DEFAULT;
77         if (connections->addr->adapter == OC_ADAPTER_TCP)
78         {
79             type = CT_ADAPTER_TCP;
80             if (connections->isCloudConnection == true)
81             {
82                 msgUri = NSGetCloudUri(provider_internal->providerId, msgUri);
83                 NS_VERIFY_NOT_NULL(msgUri, NS_ERROR);
84                 syncUri = NSGetCloudUri(provider_internal->providerId, syncUri);
85                 NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(syncUri, NS_ERROR, NSOICFree(msgUri));
86             }
87         }
88
89         NS_LOG_V(DEBUG, "subscribe to %s:%d", connections->addr->addr, connections->addr->port);
90
91         NS_LOG(DEBUG, "get subscribe message query");
92         char * query = NULL;
93         query = NSMakeRequestUriWithConsumerId(msgUri);
94         NS_VERIFY_NOT_NULL(query, NS_ERROR);
95
96         NS_LOG(DEBUG, "subscribe message");
97         NS_LOG_V(DEBUG, "subscribe query : %s", query);
98         OCStackResult ret = NSInvokeRequest(&(connections->messageHandle),
99                               OC_REST_OBSERVE, connections->addr, query, NULL,
100                               NSConsumerMessageListener, NULL, type);
101         NS_VERIFY_STACK_SUCCESS_WITH_POST_CLEANING(NSOCResultToSuccess(ret),
102                             NS_ERROR, NSUpdateObserveResult(provider_internal, query));
103         NSOICFree(query);
104         NSOICFree(msgUri);
105
106         NS_LOG(DEBUG, "get subscribe sync query");
107         query = NSMakeRequestUriWithConsumerId(syncUri);
108         NS_VERIFY_NOT_NULL(query, NS_ERROR);
109
110         NS_LOG(DEBUG, "subscribe sync");
111         NS_LOG_V(DEBUG, "subscribe query : %s", query);
112         ret = NSInvokeRequest(&(connections->syncHandle),
113                               OC_REST_OBSERVE, connections->addr, query, NULL,
114                               NSConsumerSyncInfoListener, NULL, type);
115         NS_VERIFY_STACK_SUCCESS_WITH_POST_CLEANING(NSOCResultToSuccess(ret),
116                             NS_ERROR, NSUpdateObserveResult(provider_internal, query));
117         NSOICFree(query);
118         NSOICFree(syncUri);
119
120         connections->isSubscribing = true;
121
122         connections = connections->next;
123     }
124
125     NSProvider_internal * taskProvider = NSCopyProvider_internal(provider_internal);
126     NSTask * task = NSMakeTask(TASK_CONSUMER_SENT_REQ_OBSERVE, (void *) taskProvider);
127     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(task,
128                     NS_ERROR, NSRemoveProvider_internal(taskProvider));
129
130     NSConsumerPushEvent(task);
131
132     return NS_OK;
133 }
134
135 OCStackApplicationResult NSConsumerCheckPostResult(
136         void * ctx, OCDoHandle handle, OCClientResponse * clientResponse)
137 {
138     (void) ctx;
139     (void) handle;
140
141     NS_VERIFY_NOT_NULL(clientResponse, OC_STACK_KEEP_TRANSACTION);
142     NS_VERIFY_STACK_SUCCESS(
143             NSOCResultToSuccess(clientResponse->result), OC_STACK_KEEP_TRANSACTION);
144
145     return OC_STACK_KEEP_TRANSACTION;
146 }
147
148 void NSRemoveSyncInfoObj(NSSyncInfo * sync)
149 {
150     NSOICFree(sync);
151 }
152
153 OCStackApplicationResult NSConsumerSyncInfoListener(
154         void * ctx, OCDoHandle handle, OCClientResponse * clientResponse)
155 {
156     (void) ctx;
157     (void) handle;
158
159     NS_VERIFY_NOT_NULL(clientResponse, OC_STACK_KEEP_TRANSACTION);
160     NS_VERIFY_STACK_SUCCESS(
161             NSOCResultToSuccess(clientResponse->result), OC_STACK_KEEP_TRANSACTION);
162
163     NS_LOG(DEBUG, "get NSSyncInfo");
164     NSSyncInfo * newSync = NSGetSyncInfoc(clientResponse);
165     NS_VERIFY_NOT_NULL(newSync, OC_STACK_KEEP_TRANSACTION);
166
167     NSTaskType taskType = TASK_RECV_SYNCINFO;
168
169     NS_LOG(DEBUG, "build NSTask");
170     NSTask * task = NSMakeTask(taskType, (void *) newSync);
171     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(task,
172                OC_STACK_KEEP_TRANSACTION, NSRemoveSyncInfoObj(newSync));
173
174     NSConsumerPushEvent(task);
175
176     return OC_STACK_KEEP_TRANSACTION;
177 }
178
179 OCStackApplicationResult NSConsumerMessageListener(
180         void * ctx, OCDoHandle handle, OCClientResponse * clientResponse)
181 {
182     (void) ctx;
183     (void) handle;
184
185     NS_VERIFY_NOT_NULL(clientResponse, OC_STACK_KEEP_TRANSACTION);
186     NS_VERIFY_STACK_SUCCESS(NSOCResultToSuccess(clientResponse->result), OC_STACK_KEEP_TRANSACTION);
187
188     NS_LOG(DEBUG, "build NSMessage");
189     NSMessage * newNoti = NSGetMessage(clientResponse);
190     NS_VERIFY_NOT_NULL(newNoti, OC_STACK_KEEP_TRANSACTION);
191
192     NSTaskType type = TASK_CONSUMER_RECV_MESSAGE;
193
194     if (newNoti->messageId == NS_MESSAGE_ACCEPTANCE || newNoti->messageId == NS_DENY)
195     {
196         NS_LOG(DEBUG, "Receive subscribe result");
197         type = TASK_CONSUMER_RECV_PROVIDER_CHANGED;
198     }
199     else if (newNoti->messageId == NS_TOPIC)
200     {
201         NS_LOG(DEBUG, "Receive Topic change");
202         type = TASK_CONSUMER_REQ_TOPIC_URI;
203     }
204     else
205     {
206         NS_LOG(DEBUG, "Receive new message");
207     }
208
209     NS_LOG(DEBUG, "build NSTask");
210     NSTask * task = NSMakeTask(type, (void *) newNoti);
211     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(task, NS_ERROR, NSRemoveMessage(newNoti));
212
213     NSConsumerPushEvent(task);
214
215     return OC_STACK_KEEP_TRANSACTION;
216 }
217
218 void NSGetMessagePostClean(char * pId, OCDevAddr * addr)
219 {
220     NSOICFree(pId);
221     NSOICFree(addr);
222 }
223
224 NSMessage * NSGetMessage(OCClientResponse * clientResponse)
225 {
226     NS_VERIFY_NOT_NULL(clientResponse->payload, NULL);
227     OCRepPayload * payload = (OCRepPayload *)clientResponse->payload;
228
229     NS_LOG(DEBUG, "get msg id");
230     uint64_t id = NULL;
231     bool getResult = OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, (int64_t *)&id);
232     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
233
234     NS_LOG(DEBUG, "get provider id");
235     char * pId = NULL;
236     getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, &pId);
237     NS_LOG_V (DEBUG, "provider id: %s", pId);
238     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
239
240     NS_LOG(DEBUG, "create NSMessage");
241     NSMessage * retMsg = NSCreateMessage_internal(id, pId);
242     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(retMsg, NULL, NSOICFree(pId));
243     NSOICFree(pId);
244
245     NS_LOG(DEBUG, "get msg optional field");
246     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_TITLE, &retMsg->title);
247     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_TEXT, &retMsg->contentText);
248     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_SOURCE, &retMsg->sourceName);
249     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_TOPIC_NAME, &retMsg->topic);
250
251     OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_TYPE, (int64_t *)&retMsg->type);
252     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_DATETIME, &retMsg->dateTime);
253     OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_TTL, (int64_t *)&retMsg->ttl);
254
255     NS_LOG_V(DEBUG, "Msg ID      : %lld", (long long int)retMsg->messageId);
256     NS_LOG_V(DEBUG, "Msg Title   : %s", retMsg->title);
257     NS_LOG_V(DEBUG, "Msg Content : %s", retMsg->contentText);
258     NS_LOG_V(DEBUG, "Msg Source  : %s", retMsg->sourceName);
259     NS_LOG_V(DEBUG, "Msg Topic   : %s", retMsg->topic);
260     NS_LOG_V(DEBUG, "Msg Type    : %d", retMsg->type);
261     NS_LOG_V(DEBUG, "Msg Date    : %s", retMsg->dateTime);
262     NS_LOG_V(DEBUG, "Msg ttl     : %lld", (long long int)retMsg->ttl);
263
264     return retMsg;
265 }
266
267 NSSyncInfo * NSGetSyncInfoc(OCClientResponse * clientResponse)
268 {
269     NS_VERIFY_NOT_NULL(clientResponse->payload, NULL);
270
271     OCRepPayload * payload = (OCRepPayload *)clientResponse->payload;
272
273     NS_LOG(DEBUG, "get msg id");
274     uint64_t id = NULL;
275     bool getResult = OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, (int64_t *)&id);
276     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
277
278     NS_LOG(DEBUG, "get provider id");
279     char * pId = NULL;
280     getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, &pId);
281     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
282
283     NS_LOG(DEBUG, "get state");
284     int64_t state = 0;
285     getResult = OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_STATE, & state);
286     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
287
288     NS_LOG(DEBUG, "create NSSyncInfo");
289     NSSyncInfo * retSync = NSCreateSyncInfo_consumer(id, pId, (NSSyncType)state);
290     NS_VERIFY_NOT_NULL(retSync, NULL);
291
292     NS_LOG_V(DEBUG, "Sync ID : %lld", (long long int)retSync->messageId);
293     NS_LOG_V(DEBUG, "Sync State : %d", (int) retSync->state);
294     NS_LOG_V(DEBUG, "Sync Provider ID : %s", retSync->providerId);
295
296     return retSync;
297 }
298
299 NSMessage * NSCreateMessage_internal(uint64_t id, const char * providerId)
300 {
301     NSMessage * retMsg = (NSMessage *)OICMalloc(sizeof(NSMessage));
302     NS_VERIFY_NOT_NULL(retMsg, NULL);
303
304     retMsg->messageId = id;
305     OICStrcpy(retMsg->providerId, sizeof(char) * NS_DEVICE_ID_LENGTH, providerId);
306     retMsg->title = NULL;
307     retMsg->contentText = NULL;
308     retMsg->sourceName = NULL;
309     retMsg->topic = NULL;
310     retMsg->type = NS_MESSAGE_INFO;
311     retMsg->dateTime = NULL;
312     retMsg->ttl = 0;
313     retMsg->mediaContents = NULL;
314
315     return retMsg;
316 }
317
318 NSSyncInfo * NSCreateSyncInfo_consumer(uint64_t msgId, const char * providerId, NSSyncType state)
319 {
320     NS_VERIFY_NOT_NULL(providerId, NULL);
321
322     NSSyncInfo * retSync = (NSSyncInfo *)OICMalloc(sizeof(NSSyncInfo));
323     NS_VERIFY_NOT_NULL(retSync, NULL);
324
325     retSync->messageId = msgId;
326     retSync->state = state;
327     OICStrcpy(retSync->providerId, sizeof(char) * NS_DEVICE_ID_LENGTH, providerId);
328
329     return retSync;
330 }
331
332 OCStackResult NSSendSyncInfo(NSSyncInfo * syncInfo, OCDevAddr * addr)
333 {
334     NS_VERIFY_NOT_NULL(syncInfo, OC_STACK_ERROR);
335     NS_VERIFY_NOT_NULL(addr, OC_STACK_ERROR);
336
337     OCRepPayload * payload = OCRepPayloadCreate();
338     NS_VERIFY_NOT_NULL(payload, OC_STACK_ERROR);
339
340     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, (int64_t)syncInfo->messageId);
341     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_STATE, syncInfo->state);
342     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, syncInfo->providerId);
343
344     char * uri = (char*)OICStrdup(NS_SYNC_URI);
345     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(uri, OC_STACK_ERROR, OCRepPayloadDestroy(payload));
346
347     OCConnectivityType type = CT_DEFAULT;
348     if(addr->adapter == OC_ADAPTER_TCP)
349     {
350         type = CT_ADAPTER_TCP;
351         uri = NSGetCloudUri(syncInfo->providerId, uri);
352         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(uri, OC_STACK_ERROR, OCRepPayloadDestroy(payload));
353     }
354
355     OCStackResult ret = NSInvokeRequest(NULL, OC_REST_POST, addr,
356                             uri, (OCPayload*)payload,
357                             NSConsumerCheckPostResult, NULL, type);
358     NSOICFree(uri);
359
360     return ret;
361 }
362
363 char * NSGetCloudUri(const char * providerId, char * uri)
364 {
365     size_t uriLen = NS_DEVICE_ID_LENGTH + 1 + strlen(uri) + 1;
366     char * retUri = (char *)OICMalloc(uriLen);
367     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(retUri, NULL, NSOICFree(uri));
368
369     snprintf(retUri, uriLen, "/%s%s", providerId, uri);
370     NSOICFree(uri);
371     NS_LOG_V(DEBUG, "Cloud uri : %s", retUri);
372
373     return retUri;
374 }
375
376 void NSConsumerCommunicationTaskProcessing(NSTask * task)
377 {
378     NS_VERIFY_NOT_NULL_V(task);
379
380     NS_LOG_V(DEBUG, "Receive Event : %d", (int)task->taskType);
381     if (task->taskType == TASK_CONSUMER_REQ_SUBSCRIBE)
382     {
383         NS_VERIFY_NOT_NULL_V(task->taskData);
384         NS_LOG(DEBUG, "Request Subscribe");
385         NSResult ret = NSConsumerSubscribeProvider((NSProvider *)task->taskData);
386         NS_VERIFY_NOT_NULL_V(ret == NS_OK ? (void *)1 : NULL);
387     }
388     else if (task->taskType == TASK_SEND_SYNCINFO)
389     {
390         NS_VERIFY_NOT_NULL_V(task->taskData);
391         NSSyncInfo_internal * syncInfo = (NSSyncInfo_internal *)task->taskData;
392         NSProviderConnectionInfo * info = syncInfo->connection;
393
394         while(info)
395         {
396             OCStackResult ret = NSSendSyncInfo((NSSyncInfo *)(task->taskData), info->addr);
397             if (ret != OC_STACK_OK)
398             {
399                 NS_LOG_V(ERROR, "send sync info fail : %d", info->addr->adapter);
400             }
401
402             info = info->next;
403         }
404
405         NSRemoveConnections(syncInfo->connection);
406         NSOICFree(syncInfo);
407     }
408     else if (task->taskType == TASK_CONSUMER_REQ_SUBSCRIBE_CANCEL)
409     {
410         NSProvider_internal * provider = (NSProvider_internal *)task->taskData;
411
412         NSProviderConnectionInfo * connections = provider->connection;
413         while(connections)
414         {
415             if (connections->isSubscribing == false)
416             {
417                 NS_LOG_V(DEBUG, "unsubscribed to %s:%d",
418                      connections->addr->addr, connections->addr->port);
419                 connections = connections->next;
420                 continue;
421             }
422             NS_LOG_V(DEBUG, "cancel subscribe to %s:%d",
423                      connections->addr->addr, connections->addr->port);
424             OCCancel(connections->messageHandle, NS_QOS, NULL, 0);
425             OCCancel(connections->syncHandle, NS_QOS, NULL, 0);
426             connections->messageHandle = NULL;
427             connections->syncHandle = NULL;
428             connections->isSubscribing = false;
429             connections = connections->next;
430         }
431     }
432     else if (task->taskType == TASK_CONSUMER_REQ_TOPIC_LIST
433                 || task->taskType == TASK_CONSUMER_GET_TOPIC_LIST)
434     {
435         NSProvider_internal * provider = (NSProvider_internal *)task->taskData;
436
437         NSProviderConnectionInfo * connections = provider->connection;
438         NS_VERIFY_NOT_NULL_V(connections);
439
440         char * topicUri = OICStrdup(provider->topicUri);
441
442         OCConnectivityType type = CT_DEFAULT;
443         if (connections->addr->adapter == OC_ADAPTER_TCP)
444         {
445             type = CT_ADAPTER_TCP;
446             if (connections->isCloudConnection == true)
447             {
448                 topicUri = NSGetCloudUri(provider->providerId, topicUri);
449             }
450         }
451
452         NS_LOG(DEBUG, "get topic query");
453         char * query = NULL;
454         if (task->taskType == TASK_CONSUMER_REQ_TOPIC_LIST)
455         {
456             query = OICStrdup(topicUri);
457         }
458         else if (task->taskType == TASK_CONSUMER_GET_TOPIC_LIST)
459         {
460             query = NSMakeRequestUriWithConsumerId(topicUri);
461         }
462         NS_VERIFY_NOT_NULL_V(query);
463         NS_LOG_V(DEBUG, "topic query : %s", query);
464
465         OCStackResult ret = NSInvokeRequest(NULL, OC_REST_GET, connections->addr,
466                                 query, NULL, NSIntrospectTopic, (void *) provider, type);
467         NS_VERIFY_STACK_SUCCESS_V(NSOCResultToSuccess(ret));
468
469         NSOICFree(query);
470         NSOICFree(topicUri);
471     }
472     else if (task->taskType == TASK_CONSUMER_SELECT_TOPIC_LIST)
473     {
474         NSProvider_internal * provider = (NSProvider_internal *)task->taskData;
475
476         NSProviderConnectionInfo * connections = provider->connection;
477         NS_VERIFY_NOT_NULL_V(connections);
478
479         OCRepPayload * payload = OCRepPayloadCreate();
480         NS_VERIFY_NOT_NULL_V(payload);
481
482         NSTopicLL * topicLL = provider->topicLL;
483         NSTopicLL * iter = topicLL;
484         int topicLLSize = 0;
485         while (iter)
486         {
487             topicLLSize ++;
488             NS_LOG_V(DEBUG, "[%d] Topic Name:%s\tTopic State:%d",
489                                         topicLLSize, iter->topicName, iter->state);
490             iter = (NSTopicLL *) iter->next;
491         }
492
493         OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_CONSUMER_ID, *NSGetConsumerId());
494         NS_LOG_V(DEBUG, "NS_ATTRIBUTE_CONSUMER_ID: %s", *NSGetConsumerId());
495
496         iter = topicLL;
497         int iterSize = 0;
498         NS_LOG_V(DEBUG, "DimensionSize: %d", topicLLSize);
499
500         OCRepPayload ** topicPayload = NULL;
501         if (topicLLSize > 0)
502         {
503             topicPayload = (OCRepPayload **) OICMalloc(sizeof(OCRepPayload *)*topicLLSize);
504             NS_VERIFY_NOT_NULL_V(topicPayload);
505
506             while (iter || iterSize < topicLLSize)
507             {
508                 topicPayload[iterSize] = OCRepPayloadCreate();
509                 OCRepPayloadSetPropString(topicPayload[iterSize], NS_ATTRIBUTE_TOPIC_NAME,
510                                             iter->topicName);
511                 OCRepPayloadSetPropInt(topicPayload[iterSize], NS_ATTRIBUTE_TOPIC_SELECTION,
512                                             iter->state);
513                 NS_LOG_V(DEBUG, "NS_ATTRIBUTE_TOPIC_NAME: %s", iter->topicName);
514                 NS_LOG_V(DEBUG, "NS_ATTRIBUTE_TOPIC_SELECTION: %d", iter->state);
515                 iterSize++;
516                 iter = iter->next;
517             }
518             size_t dimensions[3] = {topicLLSize, 0, 0};
519
520             OCRepPayloadSetPropObjectArrayAsOwner(payload, NS_ATTRIBUTE_TOPIC_LIST,
521                                                     topicPayload, dimensions);
522         }
523         else
524         {
525             OCRepPayloadSetNull(payload, NS_ATTRIBUTE_TOPIC_LIST);
526         }
527
528         char * topicUri = OICStrdup(provider->topicUri);
529
530         OCConnectivityType type = CT_DEFAULT;
531         if (connections->addr->adapter == OC_ADAPTER_TCP)
532         {
533             type = CT_ADAPTER_TCP;
534             if (connections->isCloudConnection == true)
535             {
536                 topicUri = NSGetCloudUri(provider->providerId, topicUri);
537             }
538         }
539
540         NS_LOG(DEBUG, "get topic query");
541         char * query = NULL;
542         query = NSMakeRequestUriWithConsumerId(topicUri);
543         NS_VERIFY_NOT_NULL_V(query);
544         NS_LOG_V(DEBUG, "topic query : %s", query);
545
546         OCStackResult ret = NSInvokeRequest(NULL, OC_REST_POST, connections->addr,
547                                 query, (OCPayload*)payload, NSConsumerCheckPostResult, NULL, type);
548         NS_VERIFY_STACK_SUCCESS_V(NSOCResultToSuccess(ret));
549
550         NSOICFree(query);
551         NSOICFree(topicUri);
552     }
553     else
554     {
555         NS_LOG(ERROR, "Unknown type message");
556     }
557
558     NSOICFree(task);
559 }
560
561 NSTopicLL * NSGetTopicLL(OCClientResponse * clientResponse)
562 {
563     NS_LOG(DEBUG, "create NSTopicLL");
564     NS_VERIFY_NOT_NULL(clientResponse->payload, NULL);
565
566     OCRepPayload * payload = (OCRepPayload *)clientResponse->payload;
567     while (payload)
568     {
569         NS_LOG_V(DEBUG, "Payload Key : %s", payload->values->name);
570         payload = payload->next;
571     }
572
573     payload = (OCRepPayload *)clientResponse->payload;
574
575     char * consumerId = NULL;
576     OCRepPayload ** topicLLPayload = NULL;
577
578     NS_LOG(DEBUG, "get information of consumerId");
579
580     bool getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_CONSUMER_ID, & consumerId);
581     NSOICFree(consumerId);
582
583     OCRepPayloadValue * payloadValue = NULL;
584     payloadValue = NSPayloadFindValue(payload, NS_ATTRIBUTE_TOPIC_LIST);
585     NS_VERIFY_NOT_NULL(payloadValue, NULL);
586
587     size_t dimensionSize = calcDimTotal(payloadValue->arr.dimensions);
588     NS_LOG_V(DEBUG, "DimensionSize: %d", (int)dimensionSize);
589
590     if (dimensionSize == 0 || payloadValue->type == OCREP_PROP_NULL ||
591             payloadValue->arr.objArray == NULL)
592     {
593         NS_LOG(DEBUG, "No TopicLL");
594         return NULL;
595     }
596
597     topicLLPayload = payloadValue->arr.objArray;
598
599     NSTopicLL * topicLL = NULL;
600     for (int i = 0; i < (int)dimensionSize; i++)
601     {
602         char * topicName = NULL;
603         int64_t state = 0;
604
605         NSTopicLL * topicNode = (NSTopicLL *) OICMalloc(sizeof(NSTopicLL));
606         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(topicNode, NULL, NSRemoveTopicLL(topicLL));
607
608         NS_LOG(DEBUG, "get topic selection");
609         getResult = OCRepPayloadGetPropInt(topicLLPayload[i],
610                 NS_ATTRIBUTE_TOPIC_SELECTION, & state);
611         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL,
612                 NULL, NSRemoveTopicLL(topicLL));
613
614         NS_LOG(DEBUG, "get topic name");
615         getResult = OCRepPayloadGetPropString(topicLLPayload[i],
616                 NS_ATTRIBUTE_TOPIC_NAME, & topicName);
617         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL,
618                 NULL, NSRemoveTopicLL(topicLL));
619         NS_LOG_V(DEBUG, "topic name: %s", topicName);
620         NS_LOG_V(DEBUG, "topic selection: %d", (int)state);
621
622         topicNode->topicName = topicName;
623         topicNode->state = state;
624
625         if (i == 0)
626         {
627             topicLL = topicNode;
628             topicNode->next = NULL;
629             continue;
630         }
631
632         NSResult ret = NSInsertTopicNode(topicLL, topicNode);
633         NS_VERIFY_STACK_SUCCESS_WITH_POST_CLEANING(ret, NULL, NSRemoveTopicLL(topicLL));
634     }
635
636     return topicLL;
637 }
638
639 OCStackApplicationResult NSIntrospectTopic(
640         void * ctx, OCDoHandle handle, OCClientResponse * clientResponse)
641 {
642     (void) handle;
643
644     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(clientResponse, OC_STACK_KEEP_TRANSACTION,
645             NSRemoveProvider_internal((NSProvider_internal *) ctx));
646     NS_VERIFY_STACK_SUCCESS_WITH_POST_CLEANING(NSOCResultToSuccess(clientResponse->result),
647             OC_STACK_KEEP_TRANSACTION, NSRemoveProvider_internal((NSProvider_internal *) ctx));
648
649     NS_LOG_V(DEBUG, "GET response income : %s:%d",
650             clientResponse->devAddr.addr, clientResponse->devAddr.port);
651     NS_LOG_V(DEBUG, "GET response result : %d",
652             clientResponse->result);
653     NS_LOG_V(DEBUG, "GET response sequenceNum : %d",
654             clientResponse->sequenceNumber);
655     NS_LOG_V(DEBUG, "GET response resource uri : %s",
656             clientResponse->resourceUri);
657     NS_LOG_V(DEBUG, "GET response Transport Type : %d",
658             clientResponse->devAddr.adapter);
659
660     NSTopicLL * newTopicLL = NSGetTopicLL(clientResponse);
661     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicLL, OC_STACK_KEEP_TRANSACTION,
662           NSRemoveProvider_internal((NSProvider_internal *) ctx));
663
664     NSProvider_internal * provider = (NSProvider_internal *) ctx;
665     provider->topicLL = NSCopyTopicLL(newTopicLL);
666
667     NS_LOG(DEBUG, "build NSTask");
668     NSTask * task = NSMakeTask(TASK_CONSUMER_RECV_TOPIC_LIST, (void *) provider);
669     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(task, NS_ERROR, NSRemoveProvider_internal(provider));
670
671     NSConsumerPushEvent(task);
672     NSRemoveTopicLL(newTopicLL);
673
674     return OC_STACK_KEEP_TRANSACTION;
675 }