Bug fix about memory leak.
[platform/upstream/iotivity.git] / service / notification / src / provider / NSProviderSubscription.c
1 //******************************************************************\r
2 //\r
3 // Copyright 2016 Samsung Electronics All Rights Reserved.\r
4 //\r
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
6 //\r
7 // Licensed under the Apache License, Version 2.0 (the "License");\r
8 // you may not use this file except in compliance with the License.\r
9 // You may obtain a copy of the License at\r
10 //\r
11 //      http://www.apache.org/licenses/LICENSE-2.0\r
12 //\r
13 // Unless required by applicable law or agreed to in writing, software\r
14 // distributed under the License is distributed on an "AS IS" BASIS,\r
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16 // See the License for the specific language governing permissions and\r
17 // limitations under the License.\r
18 //\r
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
20 \r
21 #include "NSProviderSubscription.h"\r
22 \r
23 NSResult NSInitSubscriptionList()\r
24 {\r
25     NS_LOG(DEBUG, "NSInitSubscriptionList - IN");\r
26 \r
27     consumerSubList = NSProviderStorageCreate();\r
28     NS_VERIFY_NOT_NULL(consumerSubList, NS_FAIL);\r
29     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER;\r
30 \r
31     NS_LOG(DEBUG, "NSInitSubscriptionList - OUT");\r
32     return NS_OK;\r
33 }\r
34 \r
35 NSResult NSSetSubscriptionAccessPolicy(bool policy)\r
36 {\r
37     NS_LOG(DEBUG, "NSSetSubscriptionAcceptPolicy - IN");\r
38 \r
39     if (policy == NS_POLICY_PROVIDER)\r
40     {\r
41         NS_LOG(DEBUG, "Place Provider as a subscription accepter");\r
42     }\r
43     else if (policy == NS_POLICY_CONSUMER)\r
44     {\r
45         NS_LOG(DEBUG, "Place Consumer as a subscription accepter");\r
46     }\r
47 \r
48     NSSetPolicy(policy);\r
49 \r
50     NS_LOG(DEBUG, "NSSetSubscriptionAcceptPolicy - OUT");\r
51     return NS_OK;\r
52 }\r
53 \r
54 NSResult NSSendAccessPolicyResponse(OCEntityHandlerRequest *entityHandlerRequest)\r
55 {\r
56     NS_LOG(DEBUG, "NSSendAccessPolicyResponse - IN");\r
57 \r
58     // put notification resource\r
59     OCResourceHandle notificationResourceHandle = NULL;\r
60     if (NSPutNotificationResource(NSGetPolicy(), &notificationResourceHandle)\r
61             != NS_OK)\r
62     {\r
63         NS_LOG(ERROR, "Fail to put notification resource");\r
64         return NS_ERROR;\r
65     }\r
66 \r
67     // make response for the Get Request\r
68     OCEntityHandlerResponse response;\r
69     response.numSendVendorSpecificHeaderOptions = 0;\r
70     memset(response.sendVendorSpecificHeaderOptions, 0,\r
71             sizeof response.sendVendorSpecificHeaderOptions);\r
72     memset(response.resourceUri, 0, sizeof response.resourceUri);\r
73 \r
74     OCRepPayload* payload = OCRepPayloadCreate();\r
75     if (!payload)\r
76     {\r
77         NS_LOG(ERROR, "payload is NULL");\r
78         return NS_ERROR;\r
79     }\r
80 \r
81     NS_LOG_V(DEBUG, "NS Provider ID: %s", NSGetProviderInfo()->providerId);\r
82 \r
83     char * copyReq = OICStrdup(entityHandlerRequest->query);\r
84     char * reqInterface = NSGetValueFromQuery(copyReq, NS_QUERY_INTERFACE);\r
85 \r
86     if (reqInterface && strcmp(reqInterface, NS_INTERFACE_BASELINE) == 0)\r
87     {\r
88         OCResourcePayloadAddStringLL(&payload->interfaces, NS_INTERFACE_BASELINE);\r
89         OCResourcePayloadAddStringLL(&payload->interfaces, NS_INTERFACE_READ);\r
90         OCResourcePayloadAddStringLL(&payload->types, NS_ROOT_TYPE);\r
91     }\r
92     OICFree(copyReq);\r
93     OCRepPayloadSetUri(payload, NS_ROOT_URI);\r
94     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
95     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_VERSION, VERSION);\r
96     OCRepPayloadSetPropBool(payload, NS_ATTRIBUTE_POLICY, NSGetPolicy());\r
97     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_MESSAGE, NS_COLLECTION_MESSAGE_URI);\r
98     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_SYNC, NS_COLLECTION_SYNC_URI);\r
99     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_TOPIC, NS_COLLECTION_TOPIC_URI);\r
100 \r
101     response.requestHandle = entityHandlerRequest->requestHandle;\r
102     response.resourceHandle = entityHandlerRequest->resource;\r
103     response.persistentBufferFlag = 0;\r
104     response.ehResult = OC_EH_OK;\r
105     response.payload = (OCPayload *) payload;\r
106 \r
107     // Send Response\r
108     if (OCDoResponse(&response) != OC_STACK_OK)\r
109     {\r
110         NS_LOG(ERROR, "Fail to AccessPolicy send response");\r
111         OCRepPayloadDestroy(payload);\r
112         return NS_ERROR;\r
113     }\r
114     OCRepPayloadDestroy(payload);\r
115     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
116 \r
117     NS_LOG(DEBUG, "NSSendAccessPolicyResponse - OUT");\r
118     return NS_OK;\r
119 }\r
120 \r
121 void NSHandleSubscription(OCEntityHandlerRequest *entityHandlerRequest, NSResourceType resourceType)\r
122 {\r
123     NS_LOG(DEBUG, "NSHandleSubscription - IN");\r
124 \r
125     char * copyReq = OICStrdup(entityHandlerRequest->query);\r
126     char * id = NSGetValueFromQuery(copyReq, NS_QUERY_CONSUMER_ID);\r
127 \r
128     if(!id)\r
129     {\r
130         OICFree(copyReq);\r
131         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
132         NS_LOG(ERROR, "Invalid ConsumerID");\r
133         return;\r
134     }\r
135 \r
136     NS_LOG_V(DEBUG, "consumerId = %s", id);\r
137     if (resourceType == NS_RESOURCE_MESSAGE)\r
138     {\r
139         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_MESSAGE");\r
140         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
141         NS_VERIFY_NOT_NULL_V(element);\r
142         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
143         NS_VERIFY_NOT_NULL_V(subData);\r
144 \r
145         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
146         NS_LOG_V(DEBUG, "SubList ID = [%s]", subData->id);\r
147 \r
148         NS_LOG_V(DEBUG, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
149 \r
150         subData->remote_messageObId = subData->messageObId = 0;\r
151 \r
152         bool iSRemoteServer = false;\r
153 \r
154 #if(defined WITH_CLOUD && defined RD_CLIENT)\r
155         iSRemoteServer = NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr);\r
156         if(iSRemoteServer)\r
157         {\r
158             NS_LOG(DEBUG, "Requested by remote server");\r
159             subData->remote_messageObId = entityHandlerRequest->obsInfo.obsId;\r
160             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->remote_messageObId);\r
161         }\r
162 #endif\r
163 \r
164         if(!iSRemoteServer)\r
165         {\r
166             NS_LOG(DEBUG, "Requested by local consumer");\r
167             subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
168             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->messageObId);\r
169         }\r
170 \r
171         subData->isWhite = false;\r
172         subData->remote_syncObId = 0;\r
173         subData->syncObId = 0;\r
174 \r
175         element->data = (void*) subData;\r
176         element->next = NULL;\r
177 \r
178         if (NSProviderStorageWrite(consumerSubList, element) != NS_OK)\r
179         {\r
180             NS_LOG(DEBUG, "fail to write cache");\r
181         }\r
182 \r
183         bool currPolicy = NSGetPolicy();\r
184         NSAskAcceptanceToUser(entityHandlerRequest);\r
185 \r
186         if (currPolicy == NS_POLICY_PROVIDER)\r
187         {\r
188             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_PROVIDER");\r
189         }\r
190         else if (currPolicy == NS_POLICY_CONSUMER)\r
191         {\r
192             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_CONSUMER");\r
193             NSSendConsumerSubResponse(NSCopyOCEntityHandlerRequest(entityHandlerRequest));\r
194         }\r
195     }\r
196     else if (resourceType == NS_RESOURCE_SYNC)\r
197     {\r
198         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_SYNC");\r
199         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
200         NS_VERIFY_NOT_NULL_V(element);\r
201         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
202         NS_VERIFY_NOT_NULL_V(subData);\r
203 \r
204         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
205         NS_LOG_V(DEBUG, "SubList ID = [%s]", subData->id);\r
206 \r
207         NS_LOG_V(DEBUG, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
208 \r
209         subData->remote_syncObId = subData->syncObId = 0;\r
210         bool isRemoteServer = false;\r
211 \r
212 #if(defined WITH_CLOUD && defined RD_CLIENT)\r
213         isRemoteServer = NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr);\r
214         if(isRemoteServer)\r
215         {\r
216             NS_LOG(DEBUG, "Requested by remote server");\r
217             subData->remote_syncObId = entityHandlerRequest->obsInfo.obsId;\r
218             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->remote_syncObId);\r
219         }\r
220 #endif\r
221 \r
222         if(!isRemoteServer)\r
223         {\r
224             NS_LOG(DEBUG, "Requested by local consumer");\r
225             subData->syncObId = entityHandlerRequest->obsInfo.obsId;\r
226             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->syncObId);\r
227         }\r
228 \r
229         subData->isWhite = false;\r
230         subData->messageObId = 0;\r
231         subData->remote_messageObId = 0;\r
232 \r
233         element->data = (void*) subData;\r
234         element->next = NULL;\r
235 \r
236         if (NSProviderStorageWrite(consumerSubList, element) != NS_OK)\r
237         {\r
238             NS_LOG(ERROR, "Fail to write cache");\r
239         }\r
240 \r
241         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
242     }\r
243     OICFree(copyReq);\r
244 \r
245     NS_LOG(DEBUG, "NSHandleSubscription - OUT");\r
246 }\r
247 \r
248 void NSHandleUnsubscription(OCEntityHandlerRequest *entityHandlerRequest)\r
249 {\r
250     NS_LOG(DEBUG, "NSHandleUnsubscription - IN");\r
251 \r
252     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER_OBSERVE_ID;\r
253 \r
254     while(NSProviderStorageDelete(consumerSubList, (char *)\r
255             &(entityHandlerRequest->obsInfo.obsId)) != NS_FAIL);\r
256     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER;\r
257 \r
258     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
259 \r
260     NS_LOG(DEBUG, "NSHandleUnsubscription - OUT");\r
261 }\r
262 \r
263 void NSAskAcceptanceToUser(OCEntityHandlerRequest *entityHandlerRequest)\r
264 {\r
265     NS_LOG(DEBUG, "NSAskAcceptanceToUser - IN");\r
266 \r
267     NSPushQueue(CALLBACK_RESPONSE_SCHEDULER, TASK_CB_SUBSCRIPTION, entityHandlerRequest);\r
268 \r
269     NS_LOG(DEBUG, "NSAskAcceptanceToUser - OUT");\r
270 }\r
271 \r
272 NSResult NSSendResponse(const char * id, bool accepted)\r
273 {\r
274     NS_LOG(DEBUG, "NSSendResponse - IN");\r
275 \r
276     OCRepPayload* payload = OCRepPayloadCreate();\r
277     if (!payload)\r
278     {\r
279         NS_LOG(ERROR, "fail to create playload");\r
280         return NS_ERROR;\r
281     }\r
282 \r
283     OCResourceHandle rHandle = NULL;\r
284     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
285     {\r
286         NS_LOG(ERROR, "Fail to put notification resource");\r
287         return NS_ERROR;\r
288     }\r
289 \r
290     OCRepPayloadSetUri(payload, NS_COLLECTION_MESSAGE_URI);\r
291     (accepted) ? OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_ALLOW)\r
292         : OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_DENY);\r
293     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
294 \r
295     NSCacheElement * element = NSProviderStorageRead(consumerSubList, id);\r
296 \r
297     if(element == NULL)\r
298     {\r
299         NS_LOG(ERROR, "element is NULL");\r
300         return NS_ERROR;\r
301     }\r
302     NSCacheSubData * subData = (NSCacheSubData*) element->data;\r
303 \r
304     if (OCNotifyListOfObservers(rHandle, (OCObservationId*)&subData->messageObId, 1,\r
305             payload, OC_LOW_QOS) != OC_STACK_OK)\r
306     {\r
307         NS_LOG(ERROR, "fail to send Acceptance");\r
308         OCRepPayloadDestroy(payload);\r
309         return NS_ERROR;\r
310 \r
311     }\r
312     OCRepPayloadDestroy(payload);\r
313 \r
314     NS_LOG(DEBUG, "NSSendResponse - OUT");\r
315     return NS_OK;\r
316 }\r
317 \r
318 NSResult NSSendConsumerSubResponse(OCEntityHandlerRequest * entityHandlerRequest)\r
319 {\r
320     NS_LOG(DEBUG, "NSSendSubscriptionResponse - IN");\r
321 \r
322     if (!entityHandlerRequest)\r
323     {\r
324         NS_LOG(ERROR, "Invalid request pointer");\r
325         return NS_ERROR;\r
326     }\r
327 \r
328     char * copyReq = OICStrdup(entityHandlerRequest->query);\r
329     char * id = NSGetValueFromQuery(copyReq, NS_QUERY_CONSUMER_ID);\r
330 \r
331     if(!id)\r
332     {\r
333         OICFree(copyReq);\r
334         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
335         NS_LOG(ERROR, "Invalid ConsumerID");\r
336         return NS_ERROR;\r
337     }\r
338 \r
339     NSCacheUpdateSubScriptionState(consumerSubList, id, true);\r
340     NSSendResponse(id, true);\r
341     OICFree(copyReq);\r
342     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
343     NS_LOG(DEBUG, "NSSendSubscriptionResponse - OUT");\r
344     return NS_OK;\r
345 }\r
346 \r
347 void * NSSubScriptionSchedule(void *ptr)\r
348 {\r
349     if (ptr == NULL)\r
350     {\r
351         NS_LOG(DEBUG, "Create NSSubScriptionSchedule");\r
352     }\r
353 \r
354     while (NSIsRunning[SUBSCRIPTION_SCHEDULER])\r
355     {\r
356         sem_wait(&NSSemaphore[SUBSCRIPTION_SCHEDULER]);\r
357         pthread_mutex_lock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
358 \r
359         if (NSHeadMsg[SUBSCRIPTION_SCHEDULER] != NULL)\r
360         {\r
361             NSTask *node = NSHeadMsg[SUBSCRIPTION_SCHEDULER];\r
362             NSHeadMsg[SUBSCRIPTION_SCHEDULER] = node->nextTask;\r
363 \r
364             switch (node->taskType)\r
365             {\r
366                 case TASK_SEND_POLICY:\r
367                     NS_LOG(DEBUG, "CASE TASK_SEND_POLICY : ");\r
368                     NSSendAccessPolicyResponse((OCEntityHandlerRequest*) node->taskData);\r
369                     break;\r
370 \r
371                 case TASK_RECV_SUBSCRIPTION:\r
372                     NS_LOG(DEBUG, "CASE TASK_RECV_SUBSCRIPTION : ");\r
373                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
374                             NS_RESOURCE_MESSAGE);\r
375                     break;\r
376 \r
377                 case TASK_RECV_UNSUBSCRIPTION:\r
378                     NS_LOG(DEBUG, "CASE TASK_RECV_UNSUBSCRIPTION : ");\r
379                     NSHandleUnsubscription((OCEntityHandlerRequest*) node->taskData);\r
380                     break;\r
381 \r
382                 case TASK_SEND_ALLOW:\r
383                 {\r
384                     NS_LOG(DEBUG, "CASE TASK_SEND_ALLOW : ");\r
385                     char * consumerId = (char *) node->taskData;\r
386 \r
387                     NSCacheUpdateSubScriptionState(consumerSubList, consumerId, true);\r
388                     NSSendResponse(consumerId, true);\r
389                     OICFree(consumerId);\r
390                     break;\r
391                 }\r
392                 case TASK_SEND_DENY:\r
393                 {\r
394                     NS_LOG(DEBUG, "CASE TASK_SEND_DENY : ");\r
395                     char * consumerId = (char *) node->taskData;\r
396 \r
397                     NSCacheUpdateSubScriptionState(consumerSubList, consumerId, false);\r
398                     NSSendResponse(consumerId, false);\r
399                     OICFree(consumerId);\r
400 \r
401                     break;\r
402                 }\r
403                 case TASK_SYNC_SUBSCRIPTION:\r
404                     NS_LOG(DEBUG, "CASE TASK_SYNC_SUBSCRIPTION : ");\r
405                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
406                             NS_RESOURCE_SYNC);\r
407                     break;\r
408                 default:\r
409                     break;\r
410 \r
411             }\r
412             OICFree(node);\r
413         }\r
414 \r
415         pthread_mutex_unlock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
416 \r
417     }\r
418     NS_LOG(INFO, "Destroy NSSubScriptionSchedule");\r
419     return NULL;\r
420 }\r