Fix memory issue on calling C APIs at Cpp layer.
[platform/upstream/iotivity.git] / service / notification / src / consumer / NSConsumerCommon.c
1
2 //******************************************************************
3 //
4 // Copyright 2016 Samsung Electronics All Rights Reserved.
5 //
6 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 //      http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
19 //
20 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21
22 #include "NSConsumerCommon.h"
23 #include "NSConstants.h"
24 #include "NSThread.h"
25 #include "oic_malloc.h"
26 #include "oic_string.h"
27
28 #include <pthread.h>
29
30 #define NS_QUERY_CONSUMER_ID "consumerid"
31
32 pthread_mutex_t ** NSGetStackMutex()
33 {
34     static pthread_mutex_t * g_stackMutext = NULL;
35     if (g_stackMutext == NULL)
36     {
37         g_stackMutext = (pthread_mutex_t *)OICMalloc(sizeof(pthread_mutex_t));
38         NS_VERIFY_NOT_NULL(g_stackMutext, NULL);
39         pthread_mutex_init(g_stackMutext, NULL);
40     }
41
42     return & g_stackMutext;
43 }
44
45 char ** NSGetConsumerId()
46 {
47     static char * g_consumerId = NULL;
48     return & g_consumerId;
49 }
50
51 void NSSetConsumerId(char * cId)
52 {
53     NS_VERIFY_NOT_NULL_V(cId);
54     char ** consumerId = NSGetConsumerId();
55     NSOICFree(*consumerId);
56     *consumerId = (char *)OICMalloc(sizeof(char) * NS_DEVICE_ID_LENGTH);
57     NS_VERIFY_NOT_NULL_V(*consumerId);
58
59     OICStrcpy(*consumerId, sizeof(char) * NS_DEVICE_ID_LENGTH, cId);
60 }
61
62 char * NSMakeRequestUriWithConsumerId(const char * uri)
63 {
64     NS_VERIFY_NOT_NULL(uri, NULL);
65
66     char * consumerId = OICStrdup(*NSGetConsumerId());
67     NS_VERIFY_NOT_NULL(consumerId, NULL);
68
69     size_t uriLen = strlen(uri) + 1;
70     size_t qKeyLen = sizeof(NS_QUERY_CONSUMER_ID);
71     size_t queryLen = NS_DEVICE_ID_LENGTH + uriLen + qKeyLen + 2;
72
73     char * retQuery = (char *)OICMalloc(sizeof(char) * queryLen);
74     NS_VERIFY_NOT_NULL(retQuery, NULL);
75
76     size_t index = 0;
77     OICStrcpy((retQuery + index), uriLen, uri);
78     index += uriLen - 1;
79     OICStrcpy((retQuery + index), 2, "?");
80     index += 1;
81     OICStrcpy((retQuery + index), qKeyLen, NS_QUERY_CONSUMER_ID);
82     index += qKeyLen - 1;
83     OICStrcpy((retQuery + index), 2, "=");
84     index += 1;
85     OICStrcpy((retQuery + index), NS_DEVICE_ID_LENGTH, consumerId);
86
87     NSOICFree(consumerId);
88
89     return retQuery;
90 }
91
92 bool * NSGetBoneIsStartedConsumer()
93 {
94     static bool g_isStartedConsumer = false;
95
96     return & g_isStartedConsumer;
97 }
98
99 void NSSetIsStartedConsumer(bool setValue)
100 {
101     * NSGetBoneIsStartedConsumer() = setValue;
102 }
103
104 bool NSIsStartedConsumer()
105 {
106     return * NSGetBoneIsStartedConsumer();
107 }
108
109 NSProviderDiscoveredCallback * NSGetBoneDiscoverCb()
110 {
111     static NSProviderDiscoveredCallback g_discoverCb = NULL;
112
113     return & g_discoverCb;
114 }
115
116 void NSSetDiscoverProviderCb(NSProviderDiscoveredCallback cb)
117 {
118     * NSGetBoneDiscoverCb() = cb;
119 }
120
121 NSProviderDiscoveredCallback NSGetDiscoverCb()
122 {
123     return * NSGetBoneDiscoverCb();
124 }
125
126 void * NSDiscoveredProviderFunc(void * provider)
127 {
128     NSGetDiscoverCb()((NSProvider *) provider);
129
130     return NULL;
131 }
132
133 void NSDiscoveredProvider(NSProvider * provider)
134 {
135     NS_VERIFY_NOT_NULL_V(provider);
136
137     NSProvider * retProvider = (NSProvider *)NSCopyProvider_internal((NSProvider_internal *)provider);
138     NS_VERIFY_NOT_NULL_V(retProvider);
139
140     NSConsumerThread * thread = NSThreadInit(NSDiscoveredProviderFunc, (void *) retProvider);
141     NS_VERIFY_NOT_NULL_V(thread);
142 }
143
144 NSProviderChangedCallback * NSGetProviderChangedCb()
145 {
146     static NSProviderChangedCallback g_changedCb = NULL;
147
148     return & g_changedCb;
149 }
150
151 void NSSetProviderChangedCb(NSProviderChangedCallback cb)
152 {
153     *(NSGetProviderChangedCb()) = cb;
154 }
155
156 void NSProviderChanged(NSProvider * provider, NSResponse response)
157 {
158     (*(NSGetProviderChangedCb()))(provider, response);
159 }
160
161 NSSyncInfoReceivedCallback * NSGetBoneNotificationSyncCb()
162 {
163     static NSSyncInfoReceivedCallback g_syncCb = NULL;
164
165     return & g_syncCb;
166 }
167
168 void NSSetNotificationSyncCb(NSSyncInfoReceivedCallback cb)
169 {
170     * NSGetBoneNotificationSyncCb() = cb;
171 }
172
173 void * NSNotificationSyncFunc(void * obj)
174 {
175     (* NSGetBoneNotificationSyncCb())((NSSyncInfo *) obj);
176     return NULL;
177 }
178
179 void NSNotificationSync(NSSyncInfo * sync)
180 {
181     NS_VERIFY_NOT_NULL_V(sync);
182
183     NSSyncInfo * retSync = (NSSyncInfo *)OICMalloc(sizeof(NSSyncInfo));
184     NS_VERIFY_NOT_NULL_V(retSync);
185     memcpy(retSync, sync, sizeof(NSSyncInfo));
186
187     NSConsumerThread * thread = NSThreadInit(NSNotificationSyncFunc, (void *) retSync);
188     NS_VERIFY_NOT_NULL_V(thread);
189 }
190
191 NSMessageReceivedCallback  * NSGetBoneMessagePostedCb()
192 {
193     static NSMessageReceivedCallback  g_postCb = NULL;
194
195     return & g_postCb;
196 }
197
198 void NSSetMessagePostedCb(NSMessageReceivedCallback  cb)
199 {
200     * NSGetBoneMessagePostedCb() = cb;
201 }
202
203 NSMessageReceivedCallback  NSGetMessagePostedCb()
204 {
205     return * NSGetBoneMessagePostedCb();
206 }
207
208 void * NSMessagePostFunc(void * obj)
209 {
210     NSGetMessagePostedCb()((NSMessage *) obj);
211     return NULL;
212 }
213
214 void NSMessagePost(NSMessage * msg)
215 {
216     NS_VERIFY_NOT_NULL_V(msg);
217
218     NSMessage * retMsg = NSCopyMessage(msg);
219     NS_VERIFY_NOT_NULL_V(retMsg);
220
221     NSConsumerThread * thread = NSThreadInit(NSMessagePostFunc, (void *) retMsg);
222     NS_VERIFY_NOT_NULL_V(thread);
223 }
224
225 NSTask * NSMakeTask(NSTaskType type, void * data)
226 {
227     NSTask * retTask = OICMalloc(sizeof(NSTask));
228     NS_VERIFY_NOT_NULL(retTask, NULL);
229
230     retTask->taskType = type;
231     retTask->taskData = data;
232     retTask->nextTask = NULL;
233
234     return retTask;
235 }
236
237 NSMessage * NSCopyMessage(NSMessage * msg)
238 {
239     NS_VERIFY_NOT_NULL(msg, NULL);
240
241     NSMessage * newMsg = (NSMessage *)OICMalloc(sizeof(NSMessage));
242     NS_VERIFY_NOT_NULL(newMsg, NULL);
243
244     OICStrcpy(newMsg->providerId, NS_DEVICE_ID_LENGTH, msg->providerId);
245
246     newMsg->messageId = msg->messageId;
247     newMsg->title = OICStrdup(msg->title);
248     newMsg->contentText = OICStrdup(msg->contentText);
249     newMsg->sourceName = OICStrdup(msg->sourceName);
250     newMsg->dateTime = OICStrdup(msg->dateTime);
251     newMsg->type = msg->type;
252
253     // TODO change to copy function.
254     newMsg->mediaContents = msg->mediaContents;
255
256     return newMsg;
257 }
258 void NSRemoveMessage(NSMessage * msg)
259 {
260     NS_VERIFY_NOT_NULL_V(msg);
261
262     msg->messageId = 0;
263     NSOICFree(msg->title);
264     NSOICFree(msg->contentText);
265     NSOICFree(msg->sourceName);
266     NSOICFree(msg->dateTime);
267
268     // TODO change to remove function.
269     NSOICFree(msg->mediaContents);
270
271     NSOICFree(msg);
272 }
273
274 void NSRemoveConnections(NSProviderConnectionInfo * connections)
275 {
276     NS_VERIFY_NOT_NULL_V(connections);
277
278     NSProviderConnectionInfo * tmp = connections;
279
280     while(tmp)
281     {
282         tmp->messageHandle = NULL;
283         tmp->syncHandle = NULL;
284         NSOICFree(tmp->addr);
285         tmp = tmp->next;
286     }
287
288     NSOICFree(connections);
289 }
290
291 NSProviderConnectionInfo * NSCreateProviderConnections(OCDevAddr * inAddr)
292 {
293     NSProviderConnectionInfo * connections
294         = (NSProviderConnectionInfo *)OICMalloc(sizeof(NSProviderConnectionInfo));
295     NS_VERIFY_NOT_NULL(connections, NULL);
296
297     connections->addr = NULL;
298     connections->messageHandle = NULL;
299     connections->syncHandle = NULL;
300     connections->isCloudConnection = false;
301     connections->isSubscribing = false;
302     connections->next = NULL;
303
304     if (inAddr)
305     {
306         connections->addr = (OCDevAddr *)OICMalloc(sizeof(OCDevAddr));
307         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(connections->addr, NULL, NSRemoveConnections(connections));
308         memcpy(connections->addr, inAddr, sizeof(OCDevAddr));
309     }
310
311     return connections;
312 }
313
314 NSProviderConnectionInfo * NSCopyProviderConnections(NSProviderConnectionInfo * conn)
315 {
316     NS_VERIFY_NOT_NULL(conn, NULL);
317     NSProviderConnectionInfo * tmp = conn;
318
319     NSProviderConnectionInfo * retInfo = NSCreateProviderConnections(tmp->addr);
320     NS_VERIFY_NOT_NULL(retInfo, NULL);
321     tmp = tmp->next;
322     NSProviderConnectionInfo * copyInfo = retInfo;
323
324     while(tmp)
325     {
326         copyInfo = NSCreateProviderConnections(tmp->addr);
327         NS_VERIFY_NOT_NULL(copyInfo, NULL);
328
329         copyInfo->messageHandle = tmp->messageHandle;
330         copyInfo->syncHandle = tmp->syncHandle;
331         copyInfo->isCloudConnection = tmp->isCloudConnection;
332         copyInfo->isSubscribing = tmp->isSubscribing;
333         tmp = tmp->next;
334         copyInfo = copyInfo->next;
335     }
336
337     return retInfo;
338 }
339
340 void NSRemoveTopicNode(NSTopicLL * topicNode)
341 {
342     NS_VERIFY_NOT_NULL_V(topicNode);
343
344     NSOICFree(topicNode->topicName);
345     topicNode->next = NULL;
346
347     NSOICFree(topicNode);
348 }
349
350 NSTopicLL * NSCopyTopicNode(NSTopicLL * topicNode)
351 {
352     NS_VERIFY_NOT_NULL(topicNode, NULL);
353
354     NSTopicLL * newTopicNode = (NSTopicLL *)OICMalloc(sizeof(NSTopicLL));
355     NS_VERIFY_NOT_NULL(newTopicNode, NULL);
356
357     newTopicNode->topicName = OICStrdup(topicNode->topicName);
358     newTopicNode->state = topicNode->state;
359     newTopicNode->next = NULL;
360
361     return newTopicNode;
362 }
363
364 NSResult NSInsertTopicNode(NSTopicLL * topicHead, NSTopicLL * topicNode)
365 {
366     NS_VERIFY_NOT_NULL(topicHead, NS_ERROR);
367     NS_VERIFY_NOT_NULL(topicNode, NS_ERROR);
368
369     NSTopicLL * iter = topicHead;
370
371     while (iter)
372     {
373         iter = (NSTopicLL *) iter->next;
374     }
375
376     iter->next = topicNode;
377     topicNode->next = NULL;
378
379     return NS_OK;
380 }
381
382 void NSRemoveTopicLL(NSTopicLL * topicHead)
383 {
384     NS_VERIFY_NOT_NULL_V(topicHead);
385
386     NSTopicLL * iter = topicHead;
387
388     while (iter)
389     {
390         NSRemoveTopicNode(iter);
391
392         iter = (NSTopicLL *) iter->next;
393     }
394
395     NSOICFree(topicHead);
396 }
397
398 NSTopicLL * NSCopyTopicLL(NSTopicLL * topicHead)
399 {
400     NS_VERIFY_NOT_NULL(topicHead, NULL);
401
402     NSTopicLL * iter = topicHead;
403
404     NSTopicLL * newTopicHead = NSCopyTopicNode(iter);
405     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicHead, NULL, NSRemoveTopicLL(newTopicHead));
406
407     iter = (NSTopicLL *) iter->next;
408
409     while (iter)
410     {
411         NSTopicLL * newTopicNode = NSCopyTopicNode(iter);
412         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicNode, NULL, NSRemoveTopicLL(newTopicHead));
413
414         NSResult ret = NSInsertTopicNode(newTopicHead, newTopicNode);
415         NS_VERIFY_STACK_SUCCESS_WITH_POST_CLEANING(NSOCResultToSuccess(ret),
416                     NULL, NSRemoveTopicLL(newTopicHead));
417
418         iter = (NSTopicLL *) iter->next;
419     }
420
421     return newTopicHead;
422 }
423
424 void NSCopyProviderPostClean(
425         NSProviderConnectionInfo * connections, NSProvider_internal * provider)
426 {
427     NSRemoveConnections(connections);
428     NSOICFree(provider);
429 }
430
431 NSProvider_internal * NSCopyProvider_internal(NSProvider_internal * prov)
432 {
433     NS_VERIFY_NOT_NULL(prov, NULL);
434
435     NSProviderConnectionInfo * connections = NSCopyProviderConnections(prov->connection);
436     NS_VERIFY_NOT_NULL(connections, NULL);
437
438     NSProvider_internal * newProv = (NSProvider_internal *) OICMalloc(sizeof(NSProvider_internal));
439     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newProv, NULL, NSRemoveConnections(connections));
440
441     newProv->topicLL = NULL;
442
443     if (prov->topicLL)
444     {
445         NSTopicLL * newTopicLL = NSCopyTopicLL(prov->topicLL);
446         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicLL, NULL,
447                     NSCopyProviderPostClean(connections, newProv));
448
449         newProv->topicLL = newTopicLL;
450     }
451
452     newProv->connection = connections;
453     OICStrcpy(newProv->providerId, NS_DEVICE_ID_LENGTH, prov->providerId);
454     newProv->messageUri = OICStrdup(prov->messageUri);
455     newProv->syncUri = OICStrdup(prov->syncUri);
456     newProv->topicUri = OICStrdup(prov->topicUri);
457     newProv->accessPolicy = prov->accessPolicy;
458
459     return newProv;
460 }
461
462 NSProvider * NSCopyProvider(NSProvider_internal * prov)
463 {
464     NS_VERIFY_NOT_NULL(prov, NULL);
465
466     NSProvider * newProv = (NSProvider *) OICMalloc(sizeof(NSProvider));
467     NS_VERIFY_NOT_NULL(newProv, NULL);
468
469     newProv->topicLL = NULL;
470
471     if (prov->topicLL)
472     {
473         NSTopicLL * topicList = NSCopyTopicLL(prov->topicLL);
474         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(topicList, NULL, NSRemoveProvider(newProv));
475
476         newProv->topicLL = topicList;
477     }
478
479     OICStrcpy(newProv->providerId, NS_DEVICE_ID_LENGTH, prov->providerId);
480
481     return newProv;
482 }
483
484 void NSRemoveProvider_internal(NSProvider_internal * prov)
485 {
486     NS_VERIFY_NOT_NULL_V(prov);
487
488     NSOICFree(prov->messageUri);
489     NSOICFree(prov->syncUri);
490     NSOICFree(prov->topicUri);
491     NSRemoveConnections(prov->connection);
492     if (prov->topicLL)
493     {
494         NSRemoveTopicLL(prov->topicLL);
495     }
496
497     NSOICFree(prov);
498 }
499
500 void NSRemoveProvider(NSProvider * prov)
501 {
502     NS_VERIFY_NOT_NULL_V(prov);
503
504     if (prov->topicLL)
505     {
506         NSRemoveTopicLL(prov->topicLL);
507     }
508
509     NSOICFree(prov);
510 }
511
512 NSSyncInfo_internal * NSCopySyncInfo(NSSyncInfo_internal * syncInfo)
513 {
514     NS_VERIFY_NOT_NULL(syncInfo, NULL);
515
516     NSProviderConnectionInfo * connections = NSCopyProviderConnections(syncInfo->connection);
517     NS_VERIFY_NOT_NULL(connections, NULL);
518
519     NSSyncInfo_internal * newSyncInfo = (NSSyncInfo_internal *)OICMalloc(sizeof(NSSyncInfo_internal));
520     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newSyncInfo, NULL, NSRemoveConnections(connections));
521
522     OICStrcpy(newSyncInfo->providerId, sizeof(char) * NS_DEVICE_ID_LENGTH, syncInfo->providerId);
523     newSyncInfo->messageId = syncInfo->messageId;
524     newSyncInfo->state = syncInfo->state;
525     newSyncInfo->connection = connections;
526
527     return newSyncInfo;
528 }
529
530 void NSRemoveSyncInfo(NSSyncInfo_internal * syncInfo)
531 {
532     NS_VERIFY_NOT_NULL_V(syncInfo);
533
534     NSRemoveConnections(syncInfo->connection);
535
536     NSOICFree(syncInfo);
537 }
538
539 OCStackResult NSInvokeRequest(OCDoHandle * handle,
540         OCMethod method, const OCDevAddr * addr,
541         const char * queryUrl, OCPayload * payload,
542         void * callbackFunc, void * callbackData, OCConnectivityType type)
543 {
544     int mutexRet = pthread_mutex_lock(*(NSGetStackMutex()));
545     NS_VERIFY_NOT_NULL(mutexRet != 0 ? NULL : (void *)1, OC_STACK_ERROR);
546
547     OCCallbackData cbdata = { 0, };
548
549     cbdata.cb = callbackFunc;
550     cbdata.context = callbackData;
551     cbdata.cd = NULL;
552
553     OCStackResult ret = OCDoResource(handle, method, queryUrl, addr,
554                                      payload, type, NS_QOS, &cbdata, NULL, 0);
555
556     mutexRet = pthread_mutex_unlock(*(NSGetStackMutex()));
557     NS_VERIFY_NOT_NULL(mutexRet != 0 ? NULL : (void *)1, OC_STACK_ERROR);
558
559     return ret;
560 }
561
562 bool NSOCResultToSuccess(OCStackResult ret)
563 {
564     switch (ret)
565     {
566         case OC_STACK_OK:
567         case OC_STACK_RESOURCE_CREATED:
568         case OC_STACK_RESOURCE_DELETED:
569         case OC_STACK_CONTINUE:
570         case OC_STACK_RESOURCE_CHANGED:
571             return true;
572         default:
573             return false;
574     }
575 }