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