Fix bug for invalid remove a context at request.
[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 #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     if (setValue == false)
104     {
105         pthread_mutex_destroy(*NSGetStackMutex());
106         *NSGetStackMutex() = NULL;
107
108         NSOICFree(*NSGetConsumerId());
109         *NSGetConsumerId() = NULL;
110     }
111 }
112
113 bool NSIsStartedConsumer()
114 {
115     return * NSGetBoneIsStartedConsumer();
116 }
117
118 NSProviderStateCallback * NSGetProviderChangedCb()
119 {
120     static NSProviderStateCallback g_changedCb = NULL;
121
122     return & g_changedCb;
123 }
124
125 void NSSetProviderChangedCb(NSProviderStateCallback cb)
126 {
127     *(NSGetProviderChangedCb()) = cb;
128 }
129
130 typedef struct
131 {
132     NSProvider * provider;
133     NSProviderState state;
134 } NSProviderChangedData;
135
136 void * NSProviderChangedFunc(void * obj)
137 {
138     NSProviderChangedData * data = (NSProviderChangedData *) obj;
139     (*(NSGetProviderChangedCb()))(data->provider, data->state);
140     NSOICFree(data);
141     return NULL;
142 }
143
144 void NSProviderChanged(NSProvider * provider, NSProviderState response)
145 {
146     NS_VERIFY_NOT_NULL_V(provider);
147
148     NSProvider * retProvider = NSCopyProvider((NSProvider_internal *) provider);
149     NS_VERIFY_NOT_NULL_V(retProvider);
150
151     NSProviderChangedData * data =
152             (NSProviderChangedData *)OICMalloc(sizeof(NSProviderChangedData));
153     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING_V(data, NSRemoveProvider(retProvider));
154
155     data->provider = retProvider;
156     data->state = response;
157
158     NSConsumerThread * thread = NSThreadInit(NSProviderChangedFunc, (void *) data);
159     NS_VERIFY_NOT_NULL_V(thread);
160
161     NSDestroyThreadHandle(thread);
162 }
163
164 NSSyncInfoReceivedCallback * NSGetBoneNotificationSyncCb()
165 {
166     static NSSyncInfoReceivedCallback g_syncCb = NULL;
167
168     return & g_syncCb;
169 }
170
171 void NSSetNotificationSyncCb(NSSyncInfoReceivedCallback cb)
172 {
173     * NSGetBoneNotificationSyncCb() = cb;
174 }
175
176 void * NSNotificationSyncFunc(void * obj)
177 {
178     (* NSGetBoneNotificationSyncCb())((NSSyncInfo *) obj);
179     return NULL;
180 }
181
182 void NSNotificationSync(NSSyncInfo * sync)
183 {
184     NS_VERIFY_NOT_NULL_V(sync);
185
186     NSSyncInfo * retSync = (NSSyncInfo *)OICMalloc(sizeof(NSSyncInfo));
187     NS_VERIFY_NOT_NULL_V(retSync);
188     memcpy(retSync, sync, sizeof(NSSyncInfo));
189
190     NSConsumerThread * thread = NSThreadInit(NSNotificationSyncFunc, (void *) retSync);
191     NS_VERIFY_NOT_NULL_V(thread);
192
193     NSDestroyThreadHandle(thread);
194 }
195
196 NSMessageReceivedCallback  * NSGetBoneMessagePostedCb()
197 {
198     static NSMessageReceivedCallback  g_postCb = NULL;
199
200     return & g_postCb;
201 }
202
203 void NSSetMessagePostedCb(NSMessageReceivedCallback  cb)
204 {
205     * NSGetBoneMessagePostedCb() = cb;
206 }
207
208 NSMessageReceivedCallback  NSGetMessagePostedCb()
209 {
210     return * NSGetBoneMessagePostedCb();
211 }
212
213 void * NSMessagePostFunc(void * obj)
214 {
215     NSGetMessagePostedCb()((NSMessage *) obj);
216     return NULL;
217 }
218
219 void NSMessagePost(NSMessage * msg)
220 {
221     NS_VERIFY_NOT_NULL_V(msg);
222
223     NSMessage * retMsg = NSCopyMessage(msg);
224     NS_VERIFY_NOT_NULL_V(retMsg);
225
226     NSConsumerThread * thread = NSThreadInit(NSMessagePostFunc, (void *) retMsg);
227     NS_VERIFY_NOT_NULL_V(thread);
228
229     NSDestroyThreadHandle(thread);
230 }
231
232 NSTask * NSMakeTask(NSTaskType type, void * data)
233 {
234     NSTask * retTask = OICMalloc(sizeof(NSTask));
235     NS_VERIFY_NOT_NULL(retTask, NULL);
236
237     retTask->taskType = type;
238     retTask->taskData = data;
239     retTask->nextTask = NULL;
240
241     return retTask;
242 }
243
244 NSMessage * NSCopyMessage(NSMessage * msg)
245 {
246     NS_VERIFY_NOT_NULL(msg, NULL);
247
248     NSMessage * newMsg = (NSMessage *)OICMalloc(sizeof(NSMessage));
249     NS_VERIFY_NOT_NULL(newMsg, NULL);
250
251     OICStrcpy(newMsg->providerId, NS_DEVICE_ID_LENGTH, msg->providerId);
252
253     newMsg->messageId = msg->messageId;
254     newMsg->title = OICStrdup(msg->title);
255     newMsg->contentText = OICStrdup(msg->contentText);
256     newMsg->sourceName = OICStrdup(msg->sourceName);
257     newMsg->dateTime = OICStrdup(msg->dateTime);
258     newMsg->type = msg->type;
259
260     newMsg->topic = NULL;
261     if (msg->topic && strlen(msg->topic) > 0)
262     {
263         newMsg->topic = OICStrdup(msg->topic);
264     }
265
266     newMsg->mediaContents = NULL;
267     if (msg->mediaContents)
268     {
269         newMsg->mediaContents = (NSMediaContents *)OICMalloc(sizeof(NSMediaContents));
270         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(
271                 newMsg->mediaContents, NULL, NSRemoveMessage(newMsg));
272         newMsg->mediaContents->iconImage =
273                 (char *)OICMalloc(sizeof(char)*strlen(msg->mediaContents->iconImage));
274         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(
275                 newMsg->mediaContents->iconImage, NULL, NSRemoveMessage(newMsg));
276         memcpy(newMsg->mediaContents->iconImage, msg->mediaContents->iconImage,
277                strlen(msg->mediaContents->iconImage));
278     }
279
280     newMsg->extraInfo = NULL;
281     if (msg->extraInfo)
282     {
283         newMsg->extraInfo = OCRepPayloadClone(msg->extraInfo);
284     }
285
286     return newMsg;
287 }
288 void NSRemoveMessage(NSMessage * msg)
289 {
290     NS_VERIFY_NOT_NULL_V(msg);
291
292     msg->messageId = 0;
293     NSOICFree(msg->title);
294     NSOICFree(msg->contentText);
295     NSOICFree(msg->sourceName);
296     NSOICFree(msg->dateTime);
297     NSOICFree(msg->topic);
298
299     if (msg->mediaContents)
300     {
301         NSOICFree(msg->mediaContents->iconImage);
302     }
303     NSOICFree(msg->mediaContents);
304
305     if (msg->extraInfo)
306     {
307         OCRepPayloadDestroy(msg->extraInfo);
308         msg->extraInfo = NULL;
309     }
310
311     NSOICFree(msg);
312 }
313
314 void NSRemoveConnections(NSProviderConnectionInfo * connections)
315 {
316     NS_VERIFY_NOT_NULL_V(connections);
317
318     NSProviderConnectionInfo * tmp = connections;
319
320     while(tmp)
321     {
322         tmp->messageHandle = NULL;
323         tmp->syncHandle = NULL;
324         NSOICFree(tmp->addr);
325         tmp = tmp->next;
326     }
327
328     NSOICFree(connections);
329 }
330
331 NSProviderConnectionInfo * NSCreateProviderConnections(OCDevAddr * inAddr)
332 {
333     NSProviderConnectionInfo * connections
334         = (NSProviderConnectionInfo *)OICMalloc(sizeof(NSProviderConnectionInfo));
335     NS_VERIFY_NOT_NULL(connections, NULL);
336
337     connections->addr = NULL;
338     connections->messageHandle = NULL;
339     connections->syncHandle = NULL;
340     connections->isCloudConnection = false;
341     connections->isSubscribing = false;
342     connections->next = NULL;
343
344     if (inAddr)
345     {
346         connections->addr = (OCDevAddr *)OICMalloc(sizeof(OCDevAddr));
347         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(connections->addr, NULL, NSRemoveConnections(connections));
348         memcpy(connections->addr, inAddr, sizeof(OCDevAddr));
349     }
350
351     return connections;
352 }
353
354 NSProviderConnectionInfo * NSCopyProviderConnections(NSProviderConnectionInfo * conn)
355 {
356     NS_VERIFY_NOT_NULL(conn, NULL);
357     NSProviderConnectionInfo * tmp = conn;
358
359     NSProviderConnectionInfo * retInfo = NSCreateProviderConnections(tmp->addr);
360     NS_VERIFY_NOT_NULL(retInfo, NULL);
361     retInfo->messageHandle = tmp->messageHandle;
362     retInfo->syncHandle = tmp->syncHandle;
363     retInfo->isCloudConnection = tmp->isCloudConnection;
364     retInfo->isSubscribing = tmp->isSubscribing;
365
366     tmp = tmp->next;
367     NSProviderConnectionInfo * copyInfo = retInfo;
368
369     while(tmp)
370     {
371         NSProviderConnectionInfo * tmpInfo = NSCreateProviderConnections(tmp->addr);
372         NS_VERIFY_NOT_NULL(tmpInfo, NULL);
373
374         tmpInfo->messageHandle = tmp->messageHandle;
375         tmpInfo->syncHandle = tmp->syncHandle;
376         tmpInfo->isCloudConnection = tmp->isCloudConnection;
377         tmpInfo->isSubscribing = tmp->isSubscribing;
378         tmp = tmp->next;
379         copyInfo->next = tmpInfo;
380         copyInfo = tmpInfo;
381     }
382
383     return retInfo;
384 }
385
386 void NSRemoveTopicNode(NSTopicLL * topicNode)
387 {
388     NS_VERIFY_NOT_NULL_V(topicNode);
389
390     NSOICFree(topicNode->topicName);
391     topicNode->next = NULL;
392
393     NSOICFree(topicNode);
394 }
395
396 NSTopicLL * NSCopyTopicNode(NSTopicLL * topicNode)
397 {
398     NS_VERIFY_NOT_NULL(topicNode, NULL);
399
400     NSTopicLL * newTopicNode = (NSTopicLL *)OICMalloc(sizeof(NSTopicLL));
401     NS_VERIFY_NOT_NULL(newTopicNode, NULL);
402
403     newTopicNode->topicName = OICStrdup(topicNode->topicName);
404     newTopicNode->state = topicNode->state;
405     newTopicNode->next = NULL;
406
407     return newTopicNode;
408 }
409
410 NSResult NSInsertTopicNode(NSTopicLL * topicHead, NSTopicLL * topicNode)
411 {
412     NS_VERIFY_NOT_NULL(topicHead, NS_ERROR);
413     NS_VERIFY_NOT_NULL(topicNode, NS_ERROR);
414
415     NSTopicLL * iter = topicHead;
416     NSTopicLL * prev = NULL;
417
418     while (iter)
419     {
420         prev = iter;
421         iter = (NSTopicLL *) iter->next;
422     }
423
424     prev->next = topicNode;
425     topicNode->next = NULL;
426
427     return NS_OK;
428 }
429
430 void NSRemoveTopicLL(NSTopicLL * topicHead)
431 {
432     NS_VERIFY_NOT_NULL_V(topicHead);
433
434     NSTopicLL * iter = topicHead;
435     NSTopicLL * following = NULL;
436
437     while (iter)
438     {
439         following = iter->next;
440
441         NSRemoveTopicNode(iter);
442
443         iter = following;
444     }
445 }
446
447 NSTopicLL * NSCopyTopicLL(NSTopicLL * topicHead)
448 {
449     NS_VERIFY_NOT_NULL(topicHead, NULL);
450
451     NSTopicLL * iter = topicHead;
452
453     NS_LOG_V(DEBUG, "[NSCopyTopicLL] Name:%s\t State:%d", iter->topicName, iter->state);
454     NSTopicLL * newTopicHead = NSCopyTopicNode(iter);
455     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicHead, NULL, NSRemoveTopicLL(newTopicHead));
456
457     iter = (NSTopicLL *) iter->next;
458
459     while (iter)
460     {
461         NS_LOG_V(DEBUG, "[NSCopyTopicLL] Name:%s\t State:%d", iter->topicName, iter->state);
462         NSTopicLL * newTopicNode = NSCopyTopicNode(iter);
463         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicNode, NULL, NSRemoveTopicLL(newTopicHead));
464
465         NSResult ret = NSInsertTopicNode(newTopicHead, newTopicNode);
466         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(ret == NS_OK ? (void *)1 : NULL,
467                                                     NULL, NSRemoveTopicLL(newTopicHead));
468
469         iter = (NSTopicLL *) iter->next;
470     }
471
472     return newTopicHead;
473 }
474
475 void NSCopyProviderPostClean(
476         NSProviderConnectionInfo * connections, NSProvider_internal * provider)
477 {
478     NSRemoveConnections(connections);
479     NSOICFree(provider);
480 }
481
482 NSProvider_internal * NSCopyProvider_internal(NSProvider_internal * prov)
483 {
484     NS_VERIFY_NOT_NULL(prov, NULL);
485
486     NSProviderConnectionInfo * connections = NSCopyProviderConnections(prov->connection);
487     NS_VERIFY_NOT_NULL(connections, NULL);
488
489     NSProvider_internal * newProv = (NSProvider_internal *) OICMalloc(sizeof(NSProvider_internal));
490     NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newProv, NULL, NSRemoveConnections(connections));
491
492     newProv->topicLL = NULL;
493
494     if (prov->topicLL)
495     {
496         NSTopicLL * newTopicLL = NSCopyTopicLL(prov->topicLL);
497         NS_VERIFY_NOT_NULL_WITH_POST_CLEANING(newTopicLL, NULL,
498                     NSCopyProviderPostClean(connections, newProv));
499
500         newProv->topicLL = newTopicLL;
501     }
502
503     newProv->connection = connections;
504     OICStrcpy(newProv->providerId, NS_DEVICE_ID_LENGTH, prov->providerId);
505     newProv->messageUri = OICStrdup(prov->messageUri);
506     newProv->syncUri = OICStrdup(prov->syncUri);
507     newProv->topicUri = OICStrdup(prov->topicUri);
508     newProv->accessPolicy = prov->accessPolicy;
509     newProv->state = prov->state;
510
511     return newProv;
512 }
513
514 NSProvider * NSCopyProvider(NSProvider_internal * prov)
515 {
516     NS_VERIFY_NOT_NULL(prov, NULL);
517
518     NSProvider * newProv = (NSProvider *) OICMalloc(sizeof(NSProvider));
519     NS_VERIFY_NOT_NULL(newProv, NULL);
520
521     OICStrcpy(newProv->providerId, NS_DEVICE_ID_LENGTH, prov->providerId);
522
523     return newProv;
524 }
525
526 void NSRemoveProvider_internal(void * data)
527 {
528     NS_VERIFY_NOT_NULL_V(data);
529
530     NSProvider_internal * prov = data;
531
532     NSOICFree(prov->messageUri);
533     NSOICFree(prov->syncUri);
534     NSOICFree(prov->topicUri);
535     NSRemoveConnections(prov->connection);
536     if (prov->topicLL)
537     {
538         NSRemoveTopicLL(prov->topicLL);
539     }
540
541     NSOICFree(prov);
542 }
543
544 void NSRemoveProvider(NSProvider * prov)
545 {
546     NS_VERIFY_NOT_NULL_V(prov);
547     NSOICFree(prov);
548 }
549
550 OCStackResult NSInvokeRequest(OCDoHandle * handle,
551         OCMethod method, const OCDevAddr * addr,
552         const char * queryUrl, OCPayload * payload,
553         void * callbackFunc, void * callbackData,
554         OCClientContextDeleter cd, OCConnectivityType type)
555 {
556     int mutexRet = pthread_mutex_lock(*(NSGetStackMutex()));
557     NS_VERIFY_NOT_NULL(mutexRet != 0 ? NULL : (void *)1, OC_STACK_ERROR);
558
559     OCCallbackData cbdata = { 0, };
560
561     cbdata.cb = callbackFunc;
562     cbdata.context = callbackData;
563     cbdata.cd = cd;
564
565     OCStackResult ret = OCDoResource(handle, method, queryUrl, addr,
566                                      payload, type, NS_QOS, &cbdata, NULL, 0);
567
568     mutexRet = pthread_mutex_unlock(*(NSGetStackMutex()));
569     NS_VERIFY_NOT_NULL(mutexRet != 0 ? NULL : (void *)1, OC_STACK_ERROR);
570
571     return ret;
572 }
573
574 bool NSOCResultToSuccess(OCStackResult ret)
575 {
576     switch (ret)
577     {
578         case OC_STACK_OK:
579         case OC_STACK_RESOURCE_CREATED:
580         case OC_STACK_RESOURCE_DELETED:
581         case OC_STACK_PRESENCE_STOPPED:
582         case OC_STACK_CONTINUE:
583         case OC_STACK_RESOURCE_CHANGED:
584             return true;
585         default:
586             NS_LOG_V(DEBUG, "OCStackResult : %d", (int)ret);
587             return false;
588     }
589 }