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