Add logic about checking the NULL and modify warning code.
[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 * reqInterface =\r
84             NSGetValueFromQuery(OICStrdup(entityHandlerRequest->query), 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     OCRepPayloadSetUri(payload, NS_ROOT_URI);\r
93     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
94     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_VERSION, VERSION);\r
95     OCRepPayloadSetPropBool(payload, NS_ATTRIBUTE_POLICY, NSGetPolicy());\r
96     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_MESSAGE, NS_COLLECTION_MESSAGE_URI);\r
97     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_SYNC, NS_COLLECTION_SYNC_URI);\r
98     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_TOPIC, NS_COLLECTION_TOPIC_URI);\r
99 \r
100     response.requestHandle = entityHandlerRequest->requestHandle;\r
101     response.resourceHandle = entityHandlerRequest->resource;\r
102     response.persistentBufferFlag = 0;\r
103     response.ehResult = OC_EH_OK;\r
104     response.payload = (OCPayload *) payload;\r
105 \r
106     // Send Response\r
107     if (OCDoResponse(&response) != OC_STACK_OK)\r
108     {\r
109         NS_LOG(ERROR, "Fail to AccessPolicy send response");\r
110         OCRepPayloadDestroy(payload);\r
111         return NS_ERROR;\r
112     }\r
113     OCRepPayloadDestroy(payload);\r
114     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
115 \r
116     NS_LOG(DEBUG, "NSSendAccessPolicyResponse - OUT");\r
117     return NS_OK;\r
118 }\r
119 \r
120 void NSHandleSubscription(OCEntityHandlerRequest *entityHandlerRequest, NSResourceType resourceType)\r
121 {\r
122     NS_LOG(DEBUG, "NSHandleSubscription - IN");\r
123 \r
124     char * id = NSGetValueFromQuery(OICStrdup(entityHandlerRequest->query), NS_QUERY_CONSUMER_ID);\r
125 \r
126     if(!id)\r
127     {\r
128         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
129         NS_LOG(ERROR, "Invalid ConsumerID");\r
130         return;\r
131     }\r
132 \r
133     NS_LOG_V(DEBUG, "consumerId = %s", id);\r
134     if (resourceType == NS_RESOURCE_MESSAGE)\r
135     {\r
136         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_MESSAGE");\r
137         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
138         NS_VERIFY_NOT_NULL_V(element);\r
139         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
140         NS_VERIFY_NOT_NULL_V(subData);\r
141 \r
142         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
143         NS_LOG_V(DEBUG, "SubList ID = [%s]", subData->id);\r
144 \r
145         NS_LOG_V(DEBUG, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
146 \r
147         subData->remote_messageObId = subData->messageObId = 0;\r
148 \r
149         bool iSRemoteServer = false;\r
150 \r
151 #if(defined WITH_CLOUD && defined RD_CLIENT)\r
152         iSRemoteServer = NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr);\r
153         if(iSRemoteServer)\r
154         {\r
155             NS_LOG(DEBUG, "Requested by remote server");\r
156             subData->remote_messageObId = entityHandlerRequest->obsInfo.obsId;\r
157             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->remote_messageObId);\r
158         }\r
159 #endif\r
160 \r
161         if(!iSRemoteServer)\r
162         {\r
163             NS_LOG(DEBUG, "Requested by local consumer");\r
164             subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
165             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->messageObId);\r
166         }\r
167 \r
168         subData->isWhite = false;\r
169         subData->remote_syncObId = 0;\r
170         subData->syncObId = 0;\r
171 \r
172         element->data = (void*) subData;\r
173         element->next = NULL;\r
174 \r
175         if (NSProviderStorageWrite(consumerSubList, element) != NS_OK)\r
176         {\r
177             NS_LOG(DEBUG, "fail to write cache");\r
178         }\r
179 \r
180         bool currPolicy = NSGetPolicy();\r
181         NSAskAcceptanceToUser(entityHandlerRequest);\r
182 \r
183         if (currPolicy == NS_POLICY_PROVIDER)\r
184         {\r
185             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_PROVIDER");\r
186         }\r
187         else if (currPolicy == NS_POLICY_CONSUMER)\r
188         {\r
189             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_CONSUMER");\r
190             NSSendConsumerSubResponse(NSCopyOCEntityHandlerRequest(entityHandlerRequest));\r
191         }\r
192     }\r
193     else if (resourceType == NS_RESOURCE_SYNC)\r
194     {\r
195         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_SYNC");\r
196         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
197         NS_VERIFY_NOT_NULL_V(element);\r
198         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
199         NS_VERIFY_NOT_NULL_V(subData);\r
200 \r
201         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
202         NS_LOG_V(DEBUG, "SubList ID = [%s]", subData->id);\r
203 \r
204         NS_LOG_V(DEBUG, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
205 \r
206         subData->remote_syncObId = subData->syncObId = 0;\r
207         bool isRemoteServer = false;\r
208 \r
209 #if(defined WITH_CLOUD && defined RD_CLIENT)\r
210         isRemoteServer = NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr);\r
211         if(isRemoteServer)\r
212         {\r
213             NS_LOG(DEBUG, "Requested by remote server");\r
214             subData->remote_syncObId = entityHandlerRequest->obsInfo.obsId;\r
215             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->remote_syncObId);\r
216         }\r
217 #endif\r
218 \r
219         if(!isRemoteServer)\r
220         {\r
221             NS_LOG(DEBUG, "Requested by local consumer");\r
222             subData->syncObId = entityHandlerRequest->obsInfo.obsId;\r
223             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->syncObId);\r
224         }\r
225 \r
226         subData->isWhite = false;\r
227         subData->messageObId = 0;\r
228         subData->remote_messageObId = 0;\r
229 \r
230         element->data = (void*) subData;\r
231         element->next = NULL;\r
232 \r
233         if (NSProviderStorageWrite(consumerSubList, element) != NS_OK)\r
234         {\r
235             NS_LOG(ERROR, "Fail to write cache");\r
236         }\r
237 \r
238         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
239     }\r
240 \r
241     NS_LOG(DEBUG, "NSHandleSubscription - OUT");\r
242 }\r
243 \r
244 void NSHandleUnsubscription(OCEntityHandlerRequest *entityHandlerRequest)\r
245 {\r
246     NS_LOG(DEBUG, "NSHandleUnsubscription - IN");\r
247 \r
248     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER_OBSERVE_ID;\r
249 \r
250     while(NSProviderStorageDelete(consumerSubList, (char *)\r
251             &(entityHandlerRequest->obsInfo.obsId)) != NS_FAIL);\r
252     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER;\r
253 \r
254     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
255 \r
256     NS_LOG(DEBUG, "NSHandleUnsubscription - OUT");\r
257 }\r
258 \r
259 void NSAskAcceptanceToUser(OCEntityHandlerRequest *entityHandlerRequest)\r
260 {\r
261     NS_LOG(DEBUG, "NSAskAcceptanceToUser - IN");\r
262 \r
263     NSPushQueue(CALLBACK_RESPONSE_SCHEDULER, TASK_CB_SUBSCRIPTION, entityHandlerRequest);\r
264 \r
265     NS_LOG(DEBUG, "NSAskAcceptanceToUser - OUT");\r
266 }\r
267 \r
268 NSResult NSSendResponse(const char * id, bool accepted)\r
269 {\r
270     NS_LOG(DEBUG, "NSSendResponse - IN");\r
271 \r
272     OCRepPayload* payload = OCRepPayloadCreate();\r
273     if (!payload)\r
274     {\r
275         NS_LOG(ERROR, "fail to create playload");\r
276         return NS_ERROR;\r
277     }\r
278 \r
279     OCResourceHandle rHandle = NULL;\r
280     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
281     {\r
282         NS_LOG(ERROR, "Fail to put notification resource");\r
283         return NS_ERROR;\r
284     }\r
285 \r
286     OCRepPayloadSetUri(payload, NS_COLLECTION_MESSAGE_URI);\r
287     (accepted) ? OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_ALLOW)\r
288         : OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_DENY);\r
289     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
290 \r
291     NSCacheElement * element = NSProviderStorageRead(consumerSubList, id);\r
292 \r
293     if(element == NULL)\r
294     {\r
295         NS_LOG(ERROR, "element is NULL");\r
296         return NS_ERROR;\r
297     }\r
298     NSCacheSubData * subData = (NSCacheSubData*) element->data;\r
299 \r
300     if (OCNotifyListOfObservers(rHandle, (OCObservationId*)&subData->messageObId, 1,\r
301             payload, OC_LOW_QOS) != OC_STACK_OK)\r
302     {\r
303         NS_LOG(ERROR, "fail to send Acceptance");\r
304         OCRepPayloadDestroy(payload);\r
305         return NS_ERROR;\r
306 \r
307     }\r
308     OCRepPayloadDestroy(payload);\r
309 \r
310     NS_LOG(DEBUG, "NSSendResponse - OUT");\r
311     return NS_OK;\r
312 }\r
313 \r
314 NSResult NSSendConsumerSubResponse(OCEntityHandlerRequest * entityHandlerRequest)\r
315 {\r
316     NS_LOG(DEBUG, "NSSendSubscriptionResponse - IN");\r
317 \r
318     if (!entityHandlerRequest)\r
319     {\r
320         NS_LOG(ERROR, "Invalid request pointer");\r
321         return NS_ERROR;\r
322     }\r
323 \r
324     char * id = NSGetValueFromQuery(OICStrdup(entityHandlerRequest->query), NS_QUERY_CONSUMER_ID);\r
325 \r
326     if(!id)\r
327     {\r
328         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
329         NS_LOG(ERROR, "Invalid ConsumerID");\r
330         return NS_ERROR;\r
331     }\r
332 \r
333     NSCacheUpdateSubScriptionState(consumerSubList, id, true);\r
334     NSSendResponse(id, true);\r
335     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
336     NS_LOG(DEBUG, "NSSendSubscriptionResponse - OUT");\r
337     return NS_OK;\r
338 }\r
339 \r
340 void * NSSubScriptionSchedule(void *ptr)\r
341 {\r
342     if (ptr == NULL)\r
343     {\r
344         NS_LOG(DEBUG, "Create NSSubScriptionSchedule");\r
345     }\r
346 \r
347     while (NSIsRunning[SUBSCRIPTION_SCHEDULER])\r
348     {\r
349         sem_wait(&NSSemaphore[SUBSCRIPTION_SCHEDULER]);\r
350         pthread_mutex_lock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
351 \r
352         if (NSHeadMsg[SUBSCRIPTION_SCHEDULER] != NULL)\r
353         {\r
354             NSTask *node = NSHeadMsg[SUBSCRIPTION_SCHEDULER];\r
355             NSHeadMsg[SUBSCRIPTION_SCHEDULER] = node->nextTask;\r
356 \r
357             switch (node->taskType)\r
358             {\r
359                 case TASK_SEND_POLICY:\r
360                     NS_LOG(DEBUG, "CASE TASK_SEND_POLICY : ");\r
361                     NSSendAccessPolicyResponse((OCEntityHandlerRequest*) node->taskData);\r
362                     break;\r
363 \r
364                 case TASK_RECV_SUBSCRIPTION:\r
365                     NS_LOG(DEBUG, "CASE TASK_RECV_SUBSCRIPTION : ");\r
366                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
367                             NS_RESOURCE_MESSAGE);\r
368                     break;\r
369 \r
370                 case TASK_RECV_UNSUBSCRIPTION:\r
371                     NS_LOG(DEBUG, "CASE TASK_RECV_UNSUBSCRIPTION : ");\r
372                     NSHandleUnsubscription((OCEntityHandlerRequest*) node->taskData);\r
373                     break;\r
374 \r
375                 case TASK_SEND_ALLOW:\r
376                 {\r
377                     NS_LOG(DEBUG, "CASE TASK_SEND_ALLOW : ");\r
378                     char * consumerId = (char *) node->taskData;\r
379 \r
380                     NSCacheUpdateSubScriptionState(consumerSubList, consumerId, true);\r
381                     NSSendResponse(consumerId, true);\r
382                     OICFree(consumerId);\r
383                     break;\r
384                 }\r
385                 case TASK_SEND_DENY:\r
386                 {\r
387                     NS_LOG(DEBUG, "CASE TASK_SEND_DENY : ");\r
388                     char * consumerId = (char *) node->taskData;\r
389 \r
390                     NSCacheUpdateSubScriptionState(consumerSubList, consumerId, false);\r
391                     NSSendResponse(consumerId, false);\r
392                     OICFree(consumerId);\r
393 \r
394                     break;\r
395                 }\r
396                 case TASK_SYNC_SUBSCRIPTION:\r
397                     NS_LOG(DEBUG, "CASE TASK_SYNC_SUBSCRIPTION : ");\r
398                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
399                             NS_RESOURCE_SYNC);\r
400                     break;\r
401                 default:\r
402                     break;\r
403 \r
404             }\r
405             OICFree(node);\r
406         }\r
407 \r
408         pthread_mutex_unlock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
409 \r
410     }\r
411     NS_LOG(INFO, "Destroy NSSubScriptionSchedule");\r
412     return NULL;\r
413 }\r