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