replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / service / notification / src / consumer / NSConsumerCommon.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 "NSConsumerCommon.h"
22 #include "NSConstants.h"
23 #include "NSThread.h"
24 #include "oic_malloc.h"
25 #include "oic_string.h"
26 #include "ocpayload.h"
27
28 #include <pthread.h>
29
30 static bool NSIsExtraValue(const char * name);
31 static void NSCopyPayloadValueArray(OCRepPayloadValue* dest, OCRepPayloadValue* source);
32 static OCRepPayloadValue * NSCopyPayloadValue(OCRepPayloadValue * value);
33
34 pthread_mutex_t ** NSGetStackMutex()
35 {
36     static pthread_mutex_t * g_stackMutext = NULL;
37     if (g_stackMutext == NULL)
38     {
39         g_stackMutext = (pthread_mutex_t *)OICMalloc(sizeof(pthread_mutex_t));
40         NS_VERIFY_NOT_NULL(g_stackMutext, NULL);
41         pthread_mutex_init(g_stackMutext, NULL);
42     }
43
44     return & g_stackMutext;
45 }
46
47 char ** NSGetConsumerId()
48 {
49     static char * g_consumerId = NULL;
50     return & g_consumerId;
51 }
52
53 void NSSetConsumerId(char * cId)
54 {
55     NS_VERIFY_NOT_NULL_V(cId);
56     char ** consumerId = NSGetConsumerId();
57     NSOICFree(*consumerId);
58     *consumerId = (char *)OICMalloc(sizeof(char) * NS_DEVICE_ID_LENGTH);
59     NS_VERIFY_NOT_NULL_V(*consumerId);
60
61     OICStrcpy(*consumerId, sizeof(char) * NS_DEVICE_ID_LENGTH, cId);
62 }
63
64 char * NSMakeRequestUriWithConsumerId(const char * uri)
65 {
66     NS_VERIFY_NOT_NULL(uri, NULL);
67
68     char * consumerId = OICStrdup(*NSGetConsumerId());
69     NS_VERIFY_NOT_NULL(consumerId, NULL);
70
71     size_t uriLen = strlen(uri) + 1;
72     size_t qKeyLen = sizeof(NS_QUERY_CONSUMER_ID);
73     size_t queryLen = NS_DEVICE_ID_LENGTH + uriLen + qKeyLen + 2;
74
75     char * retQuery = (char *)OICMalloc(sizeof(char) * queryLen);
76     NS_VERIFY_NOT_NULL(retQuery, NULL);
77
78     size_t index = 0;
79     OICStrcpy((retQuery + index), uriLen, uri);
80     index += uriLen - 1;
81     OICStrcpy((retQuery + index), 2, "?");
82     index += 1;
83     OICStrcpy((retQuery + index), qKeyLen, NS_QUERY_CONSUMER_ID);
84     index += qKeyLen - 1;
85     OICStrcpy((retQuery + index), 2, "=");
86     index += 1;
87     OICStrcpy((retQuery + index), NS_DEVICE_ID_LENGTH, consumerId);
88
89     NSOICFree(consumerId);
90
91     return retQuery;
92 }
93
94 bool * NSGetBoneIsStartedConsumer()
95 {
96     static bool g_isStartedConsumer = false;
97
98     return & g_isStartedConsumer;
99 }
100
101 void NSSetIsStartedConsumer(bool setValue)
102 {
103     * NSGetBoneIsStartedConsumer() = setValue;
104
105     if (setValue == false)
106     {
107         pthread_mutex_destroy(*NSGetStackMutex());
108         NSOICFree(*NSGetStackMutex());
109         *NSGetStackMutex() = NULL;
110
111         NSOICFree(*NSGetConsumerId());
112         *NSGetConsumerId() = NULL;
113     }
114 }
115
116 bool NSIsStartedConsumer()
117 {
118     return * NSGetBoneIsStartedConsumer();
119 }
120
121 NSProviderStateCallback * NSGetProviderChangedCb()
122 {
123     static NSProviderStateCallback g_changedCb = NULL;
124
125     return & g_changedCb;
126 }
127
128 void NSSetProviderChangedCb(NSProviderStateCallback cb)
129 {
130     *(NSGetProviderChangedCb()) = cb;
131 }
132
133 typedef struct
134 {
135     NSProvider * provider;
136     NSProviderState state;
137 } NSProviderChangedData;
138
139 void * NSProviderChangedFunc(void * obj)
140 {
141     NS_LOG_V(DEBUG, "%s IN", __func__);
142     NSProviderChangedData * data = (NSProviderChangedData *) obj;
143     NSProviderStateCallback cb = *(NSGetProviderChangedCb());
144     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(cb, NULL,
145     {
146         NSRemoveProvider(data->provider);
147         NSOICFree(data);
148     });
149     NS_LOG(DEBUG, "Callback to user");
150     cb(data->provider, data->state);
151     NS_LOG(DEBUG, "Callback is Returned");
152
153     NSOICFree(data);
154     NS_LOG_V(DEBUG, "%s OUT", __func__);
155     return NULL;
156 }
157
158 void NSProviderChanged(NSProvider * provider, NSProviderState response)
159 {
160     NS_VERIFY_NOT_NULL_V(provider);
161
162     NSProvider * retProvider = NSCopyProvider((NSProvider_internal *) provider);
163     NS_VERIFY_NOT_NULL_V(retProvider);
164
165     NSProviderChangedData * data =
166             (NSProviderChangedData *)OICMalloc(sizeof(NSProviderChangedData));
167     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(data, NSRemoveProvider(retProvider));
168
169     data->provider = retProvider;
170     data->state = response;
171
172     NSConsumerThread * thread = NSThreadInit(NSProviderChangedFunc, (void *) data);
173     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(thread,
174     {
175         NSRemoveProvider(retProvider);
176         NSOICFree(data);
177     });
178
179     NSDestroyThreadHandle(thread);
180     NSOICFree(thread);
181 }
182
183 NSSyncInfoReceivedCallback * NSGetBoneNotificationSyncCb()
184 {
185     static NSSyncInfoReceivedCallback g_syncCb = NULL;
186
187     return & g_syncCb;
188 }
189
190 void NSSetNotificationSyncCb(NSSyncInfoReceivedCallback cb)
191 {
192     * NSGetBoneNotificationSyncCb() = cb;
193 }
194
195 void * NSNotificationSyncFunc(void * obj)
196 {
197     (* NSGetBoneNotificationSyncCb())((NSSyncInfo *) obj);
198     return NULL;
199 }
200
201 void NSNotificationSync(NSSyncInfo * sync)
202 {
203     NS_VERIFY_NOT_NULL_V(sync);
204
205     NSSyncInfo * retSync = (NSSyncInfo *)OICMalloc(sizeof(NSSyncInfo));
206     NS_VERIFY_NOT_NULL_V(retSync);
207     memcpy(retSync, sync, sizeof(NSSyncInfo));
208
209     NSConsumerThread * thread = NSThreadInit(NSNotificationSyncFunc, (void *) retSync);
210     NS_VERIFY_NOT_NULL_V(thread);
211
212     NSDestroyThreadHandle(thread);
213     NSOICFree(thread);
214 }
215
216 NSMessageReceivedCallback  * NSGetBoneMessagePostedCb()
217 {
218     static NSMessageReceivedCallback  g_postCb = NULL;
219
220     return & g_postCb;
221 }
222
223 void NSSetMessagePostedCb(NSMessageReceivedCallback  cb)
224 {
225     * NSGetBoneMessagePostedCb() = cb;
226 }
227
228 NSMessageReceivedCallback  NSGetMessagePostedCb()
229 {
230     return * NSGetBoneMessagePostedCb();
231 }
232
233 void * NSMessagePostFunc(void * obj)
234 {
235     NSGetMessagePostedCb()((NSMessage *) obj);
236     return NULL;
237 }
238
239 void NSMessagePost(NSMessage * msg)
240 {
241     NS_VERIFY_NOT_NULL_V(msg);
242
243     NSMessage * retMsg = NSCopyMessage(msg);
244     NS_VERIFY_NOT_NULL_V(retMsg);
245
246     NSConsumerThread * thread = NSThreadInit(NSMessagePostFunc, (void *) retMsg);
247     NS_VERIFY_NOT_NULL_V(thread);
248
249     NSDestroyThreadHandle(thread);
250     NSOICFree(thread);
251 }
252
253 NSTask * NSMakeTask(NSTaskType type, void * data)
254 {
255     NSTask * retTask = OICMalloc(sizeof(NSTask));
256     NS_VERIFY_NOT_NULL(retTask, NULL);
257
258     retTask->taskType = type;
259     retTask->taskData = data;
260     retTask->nextTask = NULL;
261
262     return retTask;
263 }
264
265 static NSMessage * NSCreateMessage_internal(uint64_t id, const char * providerId)
266 {
267     NSMessage * retMsg = (NSMessage *)OICMalloc(sizeof(NSMessage));
268     NS_VERIFY_NOT_NULL(retMsg, NULL);
269
270     retMsg->messageId = id;
271     OICStrcpy(retMsg->providerId, sizeof(char) * NS_DEVICE_ID_LENGTH, providerId);
272     retMsg->title = NULL;
273     retMsg->contentText = NULL;
274     retMsg->sourceName = NULL;
275     retMsg->topic = NULL;
276     retMsg->type = NS_MESSAGE_INFO;
277     retMsg->dateTime = NULL;
278     retMsg->ttl = 0;
279     retMsg->mediaContents = NULL;
280     retMsg->extraInfo = NULL;
281
282     return retMsg;
283 }
284
285 static OCRepPayload * NSGetExtraInfo(OCRepPayload * payload)
286 {
287     NS_LOG(DEBUG, "get extra info");
288     OCRepPayload * extraInfo = OCRepPayloadCreate();
289     NS_VERIFY_NOT_NULL(extraInfo, NULL);
290     OCRepPayload * origin = OCRepPayloadClone(payload);
291
292     bool isFirstExtra = true;
293     OCRepPayloadValue * headValue = NULL;
294     OCRepPayloadValue * curValue = NULL;
295     OCRepPayloadValue * value = origin->values;
296     while(value)
297     {
298         if (NSIsExtraValue(value->name))
299         {
300             curValue = NSCopyPayloadValue(value);
301             NS_LOG_V(DEBUG, " key : %s", curValue->name);
302             if (isFirstExtra)
303             {
304                 headValue = curValue;
305                 extraInfo->values = headValue;
306                 isFirstExtra = false;
307             }
308             else
309             {
310                 headValue->next = curValue;
311                 headValue = curValue;
312             }
313             curValue = NULL;
314         }
315         value = value->next;
316     }
317     OCRepPayloadDestroy(origin);
318
319
320     if (!isFirstExtra && extraInfo->values)
321     {
322         return extraInfo;
323     }
324     else
325     {
326         OCRepPayloadDestroy(extraInfo);
327         return NULL;
328     }
329 }
330
331 NSMessage * NSGetMessage(OCRepPayload * payload)
332 {
333     NS_LOG(DEBUG, "get msg id");
334     uint64_t id = 0;
335     bool getResult = OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, (int64_t *)&id);
336     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
337
338     NS_LOG(DEBUG, "get provider id");
339     char * pId = NULL;
340     getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, &pId);
341     NS_LOG_V (INFO_PRIVATE, "provider id: %s", pId);
342     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
343
344     NS_LOG(DEBUG, "create NSMessage");
345     NSMessage * retMsg = NSCreateMessage_internal(id, pId);
346     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(retMsg, NULL, NSOICFree(pId));
347     NSOICFree(pId);
348
349     NS_LOG(DEBUG, "get msg optional field");
350     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_TITLE, &retMsg->title);
351     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_TEXT, &retMsg->contentText);
352     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_SOURCE, &retMsg->sourceName);
353     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_TOPIC_NAME, &retMsg->topic);
354
355     OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_TYPE, (int64_t *)&retMsg->type);
356     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_DATETIME, &retMsg->dateTime);
357     OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_TTL, (int64_t *)&retMsg->ttl);
358
359     char * icon = NULL;
360     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_ICON_IMAGE, &icon);
361
362     if (icon && strlen(icon))
363     {
364         NSMediaContents * contents = (NSMediaContents *)OICMalloc(sizeof(NSMediaContents));
365         if (contents)
366         {
367             contents->iconImage = icon;
368             retMsg->mediaContents = contents;
369         }
370         else
371         {
372             NSOICFree(icon);
373         }
374     }
375
376     retMsg->extraInfo = NSGetExtraInfo(payload);
377
378     NS_LOG_V(DEBUG, "Msg ID      : %lld", (long long int)retMsg->messageId);
379     NS_LOG_V(DEBUG, "Msg Title   : %s", retMsg->title);
380     NS_LOG_V(DEBUG, "Msg Content : %s", retMsg->contentText);
381     NS_LOG_V(DEBUG, "Msg Source  : %s", retMsg->sourceName);
382     NS_LOG_V(DEBUG, "Msg Topic   : %s", retMsg->topic);
383     NS_LOG_V(DEBUG, "Msg Type    : %d", retMsg->type);
384     NS_LOG_V(DEBUG, "Msg Date    : %s", retMsg->dateTime);
385     NS_LOG_V(DEBUG, "Msg ttl     : %lld", (long long int)retMsg->ttl);
386
387     return retMsg;
388 }
389
390 NSMessage * NSCopyMessage(NSMessage * msg)
391 {
392     NS_VERIFY_NOT_NULL(msg, NULL);
393
394     NSMessage * newMsg = (NSMessage *)OICMalloc(sizeof(NSMessage));
395     NS_VERIFY_NOT_NULL(newMsg, NULL);
396
397     OICStrcpy(newMsg->providerId, NS_DEVICE_ID_LENGTH, msg->providerId);
398
399     newMsg->messageId = msg->messageId;
400     newMsg->title = OICStrdup(msg->title);
401     newMsg->contentText = OICStrdup(msg->contentText);
402     newMsg->sourceName = OICStrdup(msg->sourceName);
403     newMsg->dateTime = OICStrdup(msg->dateTime);
404     newMsg->type = msg->type;
405     newMsg->ttl= msg->ttl;
406
407     newMsg->topic = NULL;
408     if (msg->topic && strlen(msg->topic) > 0)
409     {
410         newMsg->topic = OICStrdup(msg->topic);
411     }
412
413     newMsg->mediaContents = NULL;
414     if (msg->mediaContents)
415     {
416         newMsg->mediaContents = (NSMediaContents *)OICMalloc(sizeof(NSMediaContents));
417         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(
418                 newMsg->mediaContents, NULL, NSRemoveMessage(newMsg));
419         newMsg->mediaContents->iconImage =
420                 (char *)OICMalloc(sizeof(char)*strlen(msg->mediaContents->iconImage) + 1);
421         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(
422                 newMsg->mediaContents->iconImage, NULL, NSRemoveMessage(newMsg));
423         memcpy(newMsg->mediaContents->iconImage, msg->mediaContents->iconImage,
424                strlen(msg->mediaContents->iconImage) + 1);
425     }
426
427     newMsg->extraInfo = NULL;
428     if (msg->extraInfo)
429     {
430         newMsg->extraInfo = OCRepPayloadClone(msg->extraInfo);
431     }
432
433     return newMsg;
434 }
435 void NSRemoveMessage(NSMessage * msg)
436 {
437     NS_VERIFY_NOT_NULL_V(msg);
438
439     msg->messageId = 0;
440     NSOICFree(msg->title);
441     NSOICFree(msg->contentText);
442     NSOICFree(msg->sourceName);
443     NSOICFree(msg->dateTime);
444     NSOICFree(msg->topic);
445
446     if (msg->mediaContents)
447     {
448         NSOICFree(msg->mediaContents->iconImage);
449     }
450     NSOICFree(msg->mediaContents);
451
452     if (msg->extraInfo)
453     {
454         OCRepPayloadDestroy(msg->extraInfo);
455         msg->extraInfo = NULL;
456     }
457
458     NSOICFree(msg);
459 }
460
461 void NSGetProviderPostClean(
462         char * pId, char * mUri, char * sUri, char * tUri, NSProviderConnectionInfo * connection)
463 {
464     NSOICFree(pId);
465     NSOICFree(mUri);
466     NSOICFree(sUri);
467     NSOICFree(tUri);
468     NSRemoveConnections(connection);
469 }
470
471 NSProvider_internal * NSGetProvider(OCClientResponse * clientResponse)
472 {
473     NS_LOG(DEBUG, "create NSProvider");
474     NS_VERIFY_NOT_NULL(clientResponse->payload, NULL);
475
476     OCRepPayloadPropType accepterType = OCREP_PROP_BOOL;
477
478     OCRepPayload * payload = (OCRepPayload *)clientResponse->payload;
479     OCRepPayloadValue * value = payload->values;
480     while (value)
481     {
482         NS_LOG_V(DEBUG, "Payload Key : %s", value->name);
483         NS_LOG_V(DEBUG, "Payload Type : %d", (int) value->type);
484         if (!strcmp(value->name, NS_ATTRIBUTE_POLICY))
485         {
486             accepterType = value->type;
487         }
488         value = value->next;
489     }
490
491     char * providerId = NULL;
492     char * messageUri = NULL;
493     char * syncUri = NULL;
494     char * topicUri = NULL;
495     bool bAccepter = 0;
496     int64_t iAccepter = 0;
497     NSProviderConnectionInfo * connection = NULL;
498
499     NS_LOG(DEBUG, "get information of accepter");
500     bool getResult = false;
501     if (accepterType == OCREP_PROP_BOOL)
502     {
503         getResult = OCRepPayloadGetPropBool(payload, NS_ATTRIBUTE_POLICY, & bAccepter);
504     }
505     else if (accepterType == OCREP_PROP_INT)
506     {
507         getResult = OCRepPayloadGetPropInt(payload, NS_ATTRIBUTE_POLICY, & iAccepter);
508     }
509     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
510
511     NS_LOG(DEBUG, "get provider ID");
512     getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, & providerId);
513     NS_VERIFY_NOT_NULL(getResult == true ? (void *) 1 : NULL, NULL);
514
515     NS_LOG(DEBUG, "get message URI");
516     getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_MESSAGE, & messageUri);
517     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL, NULL,
518             NSGetProviderPostClean(providerId, messageUri, syncUri, topicUri, connection));
519
520     NS_LOG(DEBUG, "get sync URI");
521     getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_SYNC, & syncUri);
522     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(getResult == true ? (void *) 1 : NULL, NULL,
523             NSGetProviderPostClean(providerId, messageUri, syncUri, topicUri, connection));
524
525     NS_LOG(DEBUG, "get topic URI");
526     getResult = OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_TOPIC, & topicUri);
527
528     NS_LOG(DEBUG, "get provider connection information");
529     NS_VERIFY_NOT_NULL(clientResponse->addr, NULL);
530     connection = NSCreateProviderConnections(clientResponse->addr);
531     NS_VERIFY_NOT_NULL(connection, NULL);
532
533     NSProvider_internal * newProvider
534         = (NSProvider_internal *)OICMalloc(sizeof(NSProvider_internal));
535     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newProvider, NULL,
536           NSGetProviderPostClean(providerId, messageUri, syncUri, topicUri, connection));
537
538     OICStrcpy(newProvider->providerId, sizeof(char) * NS_DEVICE_ID_LENGTH, providerId);
539     NSOICFree(providerId);
540     newProvider->messageUri = messageUri;
541     newProvider->syncUri = syncUri;
542     newProvider->topicUri = NULL;
543     if (topicUri && strlen(topicUri) > 0)
544     {
545         newProvider->topicUri = topicUri;
546     }
547     if (accepterType == OCREP_PROP_BOOL)
548     {
549         newProvider->accessPolicy = (NSSelector)bAccepter;
550     }
551     else if (accepterType == OCREP_PROP_INT)
552     {
553         newProvider->accessPolicy = (NSSelector)iAccepter;
554     }
555
556     newProvider->connection = connection;
557     newProvider->topicLL = NULL;
558     newProvider->state = NS_DISCOVERED;
559
560     return newProvider;
561 }
562
563 void NSRemoveConnections(NSProviderConnectionInfo * connections)
564 {
565     NS_VERIFY_NOT_NULL_V(connections);
566
567     NSProviderConnectionInfo * tmp = connections;
568
569     while(tmp)
570     {
571         tmp->messageHandle = NULL;
572         tmp->syncHandle = NULL;
573         NSOICFree(tmp->addr);
574         NSProviderConnectionInfo * next = tmp->next;
575         NSOICFree(tmp);
576         tmp = next;
577     }
578 }
579
580 NSProviderConnectionInfo * NSCreateProviderConnections(OCDevAddr * inAddr)
581 {
582     NSProviderConnectionInfo * connections
583         = (NSProviderConnectionInfo *)OICMalloc(sizeof(NSProviderConnectionInfo));
584     NS_VERIFY_NOT_NULL(connections, NULL);
585
586     connections->addr = NULL;
587     connections->messageHandle = NULL;
588     connections->syncHandle = NULL;
589     connections->isCloudConnection = false;
590     connections->isSubscribing = false;
591     connections->next = NULL;
592
593     if (inAddr)
594     {
595         connections->addr = (OCDevAddr *)OICMalloc(sizeof(OCDevAddr));
596         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(connections->addr, NULL, NSRemoveConnections(connections));
597         memcpy(connections->addr, inAddr, sizeof(OCDevAddr));
598     }
599
600     return connections;
601 }
602
603 NSProviderConnectionInfo * NSCopyProviderConnections(NSProviderConnectionInfo * conn)
604 {
605     NS_VERIFY_NOT_NULL(conn, NULL);
606     NSProviderConnectionInfo * tmp = conn;
607
608     NSProviderConnectionInfo * retInfo = NSCreateProviderConnections(tmp->addr);
609     NS_VERIFY_NOT_NULL(retInfo, NULL);
610     retInfo->messageHandle = tmp->messageHandle;
611     retInfo->syncHandle = tmp->syncHandle;
612     retInfo->isCloudConnection = tmp->isCloudConnection;
613     retInfo->isSubscribing = tmp->isSubscribing;
614
615     tmp = tmp->next;
616     NSProviderConnectionInfo * copyInfo = retInfo;
617
618     while(tmp)
619     {
620         NSProviderConnectionInfo * tmpInfo = NSCreateProviderConnections(tmp->addr);
621         NS_VERIFY_NOT_NULL(tmpInfo, NULL);
622
623         tmpInfo->messageHandle = tmp->messageHandle;
624         tmpInfo->syncHandle = tmp->syncHandle;
625         tmpInfo->isCloudConnection = tmp->isCloudConnection;
626         tmpInfo->isSubscribing = tmp->isSubscribing;
627         tmp = tmp->next;
628         copyInfo->next = tmpInfo;
629         copyInfo = tmpInfo;
630     }
631
632     return retInfo;
633 }
634
635 void NSRemoveTopicNode(NSTopicLL * topicNode)
636 {
637     NS_VERIFY_NOT_NULL_V(topicNode);
638
639     NSOICFree(topicNode->topicName);
640     topicNode->next = NULL;
641
642     NSOICFree(topicNode);
643 }
644
645 NSTopicLL * NSCopyTopicNode(NSTopicLL * topicNode)
646 {
647     NS_VERIFY_NOT_NULL(topicNode, NULL);
648
649     NSTopicLL * newTopicNode = (NSTopicLL *)OICMalloc(sizeof(NSTopicLL));
650     NS_VERIFY_NOT_NULL(newTopicNode, NULL);
651
652     newTopicNode->topicName = OICStrdup(topicNode->topicName);
653     newTopicNode->state = topicNode->state;
654     newTopicNode->next = NULL;
655
656     return newTopicNode;
657 }
658
659 NSResult NSInsertTopicNode(NSTopicLL * topicHead, NSTopicLL * topicNode)
660 {
661     NS_VERIFY_NOT_NULL(topicHead, NS_ERROR);
662     NS_VERIFY_NOT_NULL(topicNode, NS_ERROR);
663
664     NSTopicLL * iter = topicHead;
665     NSTopicLL * prev = NULL;
666
667     while (iter)
668     {
669         prev = iter;
670         iter = (NSTopicLL *) iter->next;
671     }
672
673     prev->next = topicNode;
674     topicNode->next = NULL;
675
676     return NS_OK;
677 }
678
679 void NSRemoveTopicLL(NSTopicLL * topicHead)
680 {
681     NS_VERIFY_NOT_NULL_V(topicHead);
682
683     NSTopicLL * iter = topicHead;
684     NSTopicLL * following = NULL;
685
686     while (iter)
687     {
688         following = iter->next;
689
690         NSRemoveTopicNode(iter);
691
692         iter = following;
693     }
694 }
695
696 NSTopicLL * NSCopyTopicLL(NSTopicLL * topicHead)
697 {
698     NS_VERIFY_NOT_NULL(topicHead, NULL);
699
700     NSTopicLL * iter = topicHead;
701
702     NS_LOG_V(DEBUG, "[NSCopyTopicLL] Name:%s\t State:%d", iter->topicName, iter->state);
703     NSTopicLL * newTopicHead = NSCopyTopicNode(iter);
704     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicHead, NULL, NSRemoveTopicLL(newTopicHead));
705
706     iter = (NSTopicLL *) iter->next;
707
708     while (iter)
709     {
710         NS_LOG_V(DEBUG, "[NSCopyTopicLL] Name:%s\t State:%d", iter->topicName, iter->state);
711         NSTopicLL * newTopicNode = NSCopyTopicNode(iter);
712         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicNode, NULL, NSRemoveTopicLL(newTopicHead));
713
714         NSResult ret = NSInsertTopicNode(newTopicHead, newTopicNode);
715         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(ret == NS_OK ? (void *)1 : NULL,
716                                                     NULL, NSRemoveTopicLL(newTopicHead));
717
718         iter = (NSTopicLL *) iter->next;
719     }
720
721     return newTopicHead;
722 }
723
724 void NSCopyProviderPostClean(
725         NSProviderConnectionInfo * connections, NSProvider_internal * provider)
726 {
727     NSRemoveConnections(connections);
728     NSOICFree(provider);
729 }
730
731 NSProvider_internal * NSCopyProvider_internal(NSProvider_internal * prov)
732 {
733     NS_VERIFY_NOT_NULL(prov, NULL);
734
735     NSProviderConnectionInfo * connections = NSCopyProviderConnections(prov->connection);
736     NS_VERIFY_NOT_NULL(connections, NULL);
737
738     NSProvider_internal * newProv = (NSProvider_internal *) OICMalloc(sizeof(NSProvider_internal));
739     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newProv, NULL, NSRemoveConnections(connections));
740
741     newProv->topicLL = NULL;
742
743     if (prov->topicLL)
744     {
745         NSTopicLL * newTopicLL = NSCopyTopicLL(prov->topicLL);
746         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicLL, NULL,
747                     NSCopyProviderPostClean(connections, newProv));
748
749         newProv->topicLL = newTopicLL;
750     }
751
752     newProv->connection = connections;
753     OICStrcpy(newProv->providerId, NS_DEVICE_ID_LENGTH, prov->providerId);
754     newProv->messageUri = OICStrdup(prov->messageUri);
755     newProv->syncUri = OICStrdup(prov->syncUri);
756     newProv->topicUri = OICStrdup(prov->topicUri);
757     newProv->accessPolicy = prov->accessPolicy;
758     newProv->state = prov->state;
759
760     return newProv;
761 }
762
763 NSProvider * NSCopyProvider(NSProvider_internal * prov)
764 {
765     NS_VERIFY_NOT_NULL(prov, NULL);
766
767     NSProvider * newProv = (NSProvider *) OICMalloc(sizeof(NSProvider));
768     NS_VERIFY_NOT_NULL(newProv, NULL);
769
770     OICStrcpy(newProv->providerId, NS_DEVICE_ID_LENGTH, prov->providerId);
771
772     return newProv;
773 }
774
775 void NSRemoveProvider_internal(void * data)
776 {
777     NS_VERIFY_NOT_NULL_V(data);
778
779     NSProvider_internal * prov = (NSProvider_internal *) data;
780
781     NSOICFree(prov->messageUri);
782     NSOICFree(prov->syncUri);
783     NSOICFree(prov->topicUri);
784     NSRemoveConnections(prov->connection);
785     if (prov->topicLL)
786     {
787         NSRemoveTopicLL(prov->topicLL);
788     }
789
790     NSOICFree(prov);
791 }
792
793 void NSRemoveProvider(NSProvider * prov)
794 {
795     NS_VERIFY_NOT_NULL_V(prov);
796     NSOICFree(prov);
797 }
798
799 OCStackResult NSInvokeRequest(OCDoHandle * handle,
800         OCMethod method, const OCDevAddr * addr,
801         const char * queryUrl, OCPayload * payload,
802         void * callbackFunc, void * callbackData,
803         OCClientContextDeleter cd, OCConnectivityType type)
804 {
805     int mutexRet = pthread_mutex_lock(*(NSGetStackMutex()));
806     NS_VERIFY_NOT_NULL(mutexRet != 0 ? NULL : (void *)1, OC_STACK_ERROR);
807
808     OCCallbackData cbdata = { NULL, NULL, NULL };
809
810     cbdata.cb = callbackFunc;
811     cbdata.context = callbackData;
812     cbdata.cd = cd;
813
814     OCStackResult ret = OCDoResource(handle, method, queryUrl, addr,
815                                      payload, type, NS_QOS, &cbdata, NULL, 0);
816
817     mutexRet = pthread_mutex_unlock(*(NSGetStackMutex()));
818     NS_VERIFY_NOT_NULL(mutexRet != 0 ? NULL : (void *)1, OC_STACK_ERROR);
819
820     return ret;
821 }
822
823 bool NSIsExtraValue(const char * name)
824 {
825     if (!strcmp(name, NS_ATTRIBUTE_MESSAGE_ID) ||
826         !strcmp(name, NS_ATTRIBUTE_PROVIDER_ID) ||
827         !strcmp(name, NS_ATTRIBUTE_TITLE) ||
828         !strcmp(name, NS_ATTRIBUTE_TEXT) ||
829         !strcmp(name, NS_ATTRIBUTE_SOURCE) ||
830         !strcmp(name, NS_ATTRIBUTE_TOPIC_NAME) ||
831         !strcmp(name, NS_ATTRIBUTE_TYPE) ||
832         !strcmp(name, NS_ATTRIBUTE_DATETIME) ||
833         !strcmp(name, NS_ATTRIBUTE_TTL) ||
834         !strcmp(name, NS_ATTRIBUTE_ICON_IMAGE))
835     {
836         return false;
837     }
838
839     return true;
840 }
841
842
843 void NSCopyPayloadValueArray(OCRepPayloadValue* dest, OCRepPayloadValue* source)
844 {
845     NS_VERIFY_NOT_NULL_V(source);
846
847     size_t dimTotal = calcDimTotal(source->arr.dimensions);
848     switch(source->arr.type)
849     {
850         case OCREP_PROP_INT:
851             dest->arr.iArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
852             NS_VERIFY_NOT_NULL_V(dest->arr.iArray);
853             memcpy(dest->arr.iArray, source->arr.iArray, dimTotal * sizeof(int64_t));
854             break;
855         case OCREP_PROP_DOUBLE:
856             dest->arr.dArray = (double*)OICMalloc(dimTotal * sizeof(double));
857             NS_VERIFY_NOT_NULL_V(dest->arr.dArray);
858             memcpy(dest->arr.dArray, source->arr.dArray, dimTotal * sizeof(double));
859             break;
860         case OCREP_PROP_BOOL:
861             dest->arr.bArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
862             NS_VERIFY_NOT_NULL_V(dest->arr.bArray);
863             memcpy(dest->arr.bArray, source->arr.bArray, dimTotal * sizeof(bool));
864             break;
865         case OCREP_PROP_STRING:
866             dest->arr.strArray = (char**)OICMalloc(dimTotal * sizeof(char*));
867             NS_VERIFY_NOT_NULL_V(dest->arr.strArray);
868             for(size_t i = 0; i < dimTotal; ++i)
869             {
870                 dest->arr.strArray[i] = OICStrdup(source->arr.strArray[i]);
871             }
872             break;
873         case OCREP_PROP_OBJECT:
874             dest->arr.objArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
875             NS_VERIFY_NOT_NULL_V(dest->arr.objArray);
876             for(size_t i = 0; i < dimTotal; ++i)
877             {
878                 dest->arr.objArray[i] = OCRepPayloadClone(source->arr.objArray[i]);
879             }
880             break;
881         case OCREP_PROP_ARRAY:
882             dest->arr.objArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
883             NS_VERIFY_NOT_NULL_V(dest->arr.objArray);
884             for(size_t i = 0; i < dimTotal; ++i)
885             {
886                 dest->arr.objArray[i] = OCRepPayloadClone(source->arr.objArray[i]);
887             }
888             break;
889         case OCREP_PROP_BYTE_STRING:
890             dest->arr.ocByteStrArray = (OCByteString*)OICMalloc(dimTotal * sizeof(OCByteString));
891             NS_VERIFY_NOT_NULL_V(dest->arr.ocByteStrArray);
892             for (size_t i = 0; i < dimTotal; ++i)
893             {
894                 OCByteStringCopy(&dest->arr.ocByteStrArray[i], &source->arr.ocByteStrArray[i]);
895                 NS_VERIFY_NOT_NULL_V(dest->arr.ocByteStrArray[i].bytes);
896             }
897             break;
898         default:
899             break;
900     }
901 }
902
903 OCRepPayloadValue * NSCopyPayloadValue(OCRepPayloadValue * value)
904 {
905     OCRepPayloadValue * retValue = (OCRepPayloadValue *)OICMalloc(sizeof(OCRepPayloadValue));
906     NS_VERIFY_NOT_NULL(retValue, NULL);
907
908     * retValue = * value;
909     retValue->next = NULL;
910     retValue->name = OICStrdup(value->name);
911
912     switch(value->type)
913     {
914         case OCREP_PROP_STRING:
915             retValue->str = OICStrdup(value->str);
916             break;
917         case OCREP_PROP_BYTE_STRING:
918             retValue->ocByteStr.bytes = (uint8_t * )OICMalloc(value->ocByteStr.len * sizeof(uint8_t));
919             NS_VERIFY_NOT_NULL(retValue->ocByteStr.bytes, NULL);
920             retValue->ocByteStr.len = value->ocByteStr.len;
921             memcpy(retValue->ocByteStr.bytes, value->ocByteStr.bytes, retValue->ocByteStr.len);
922             break;
923         case OCREP_PROP_OBJECT:
924             retValue->obj = OCRepPayloadClone(value->obj);
925             break;
926         case OCREP_PROP_ARRAY:
927             NSCopyPayloadValueArray(retValue, value);
928             break;
929         default:
930             break;
931     }
932
933     return retValue;
934 }