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