Fix for SVACE defects
[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 #include "NSProviderListener.h"\r
23 \r
24 NSCacheList * consumerSubList;\r
25 \r
26 NSResult NSInitSubscriptionList()\r
27 {\r
28     NS_LOG(DEBUG, "NSInitSubscriptionList - IN");\r
29 \r
30     consumerSubList = NSProviderStorageCreate();\r
31     NS_VERIFY_NOT_NULL(consumerSubList, NS_FAIL);\r
32     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER;\r
33 \r
34     NS_LOG(DEBUG, "NSInitSubscriptionList - OUT");\r
35     return NS_OK;\r
36 }\r
37 \r
38 NSResult NSSetSubscriptionAccessPolicy(bool policy)\r
39 {\r
40     NS_LOG(DEBUG, "NSSetSubscriptionAcceptPolicy - IN");\r
41 \r
42     if (policy == NS_POLICY_PROVIDER)\r
43     {\r
44         NS_LOG(DEBUG, "Place Provider as a subscription accepter");\r
45     }\r
46     else if (policy == NS_POLICY_CONSUMER)\r
47     {\r
48         NS_LOG(DEBUG, "Place Consumer as a subscription accepter");\r
49     }\r
50 \r
51     NSSetPolicy(policy);\r
52 \r
53     NS_LOG(DEBUG, "NSSetSubscriptionAcceptPolicy - OUT");\r
54     return NS_OK;\r
55 }\r
56 \r
57 NSResult NSSendAccessPolicyResponse(OCEntityHandlerRequest *entityHandlerRequest)\r
58 {\r
59     NS_LOG(DEBUG, "NSSendAccessPolicyResponse - IN");\r
60 \r
61     // put notification resource\r
62     OCResourceHandle notificationResourceHandle = NULL;\r
63     if (NSPutNotificationResource(NSGetPolicy(), &notificationResourceHandle)\r
64             != NS_OK)\r
65     {\r
66         NS_LOG(ERROR, "Fail to put notification resource");\r
67         return NS_ERROR;\r
68     }\r
69 \r
70     // make response for the Get Request\r
71     OCEntityHandlerResponse response;\r
72     response.numSendVendorSpecificHeaderOptions = 0;\r
73     memset(response.sendVendorSpecificHeaderOptions, 0,\r
74             sizeof response.sendVendorSpecificHeaderOptions);\r
75     memset(response.resourceUri, 0, sizeof response.resourceUri);\r
76 \r
77     OCRepPayload* payload = OCRepPayloadCreate();\r
78     if (!payload)\r
79     {\r
80         NS_LOG(ERROR, "payload is NULL");\r
81         return NS_ERROR;\r
82     }\r
83 \r
84     NS_LOG_V(INFO_PRIVATE, "NS Provider ID: %s", NSGetProviderInfo()->providerId);\r
85 \r
86     char * copyReq = OICStrdup(entityHandlerRequest->query);\r
87     char * reqInterface = NSGetValueFromQuery(copyReq, NS_QUERY_INTERFACE);\r
88 \r
89     if (reqInterface && strcmp(reqInterface, NS_INTERFACE_BASELINE) == 0)\r
90     {\r
91         OCResourcePayloadAddStringLL(&payload->interfaces, NS_INTERFACE_BASELINE);\r
92         OCResourcePayloadAddStringLL(&payload->interfaces, NS_INTERFACE_READ);\r
93         OCResourcePayloadAddStringLL(&payload->types, NS_ROOT_TYPE);\r
94     }\r
95 \r
96     NSOICFree(copyReq);\r
97     OCRepPayloadSetUri(payload, NS_ROOT_URI);\r
98     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
99     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_VERSION, VERSION);\r
100     OCRepPayloadSetPropBool(payload, NS_ATTRIBUTE_POLICY, NSGetPolicy());\r
101     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_MESSAGE, NS_COLLECTION_MESSAGE_URI);\r
102     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_SYNC, NS_COLLECTION_SYNC_URI);\r
103     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_TOPIC, NS_COLLECTION_TOPIC_URI);\r
104 \r
105     response.requestHandle = entityHandlerRequest->requestHandle;\r
106     response.resourceHandle = entityHandlerRequest->resource;\r
107     response.persistentBufferFlag = 0;\r
108     response.ehResult = OC_EH_OK;\r
109     response.payload = (OCPayload *) payload;\r
110 \r
111     // Send Response\r
112     if (OCDoResponse(&response) != OC_STACK_OK)\r
113     {\r
114         NS_LOG(ERROR, "Fail to AccessPolicy send response");\r
115         OCRepPayloadDestroy(payload);\r
116         return NS_ERROR;\r
117     }\r
118     OCRepPayloadDestroy(payload);\r
119     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
120 \r
121     NS_LOG(DEBUG, "NSSendAccessPolicyResponse - OUT");\r
122     return NS_OK;\r
123 }\r
124 \r
125 void NSHandleSubscription(OCEntityHandlerRequest *entityHandlerRequest, NSResourceType resourceType)\r
126 {\r
127     NS_LOG(DEBUG, "NSHandleSubscription - IN");\r
128 \r
129     char * copyReq = OICStrdup(entityHandlerRequest->query);\r
130     char * id = NSGetValueFromQuery(copyReq, NS_QUERY_CONSUMER_ID);\r
131 \r
132     if (!id)\r
133     {\r
134         NSOICFree(copyReq);\r
135         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
136         NS_LOG(ERROR, "Invalid ConsumerID");\r
137         return;\r
138     }\r
139 \r
140     NS_LOG_V(INFO_PRIVATE, "consumerId = %s", id);\r
141     if (resourceType == NS_RESOURCE_MESSAGE)\r
142     {\r
143         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_MESSAGE");\r
144         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
145         NS_VERIFY_NOT_NULL_V(element);\r
146         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
147         if (!subData)\r
148         {\r
149             NS_LOG(ERROR, "Memory assignment to subData failed");\r
150             NSOICFree(element);\r
151             return;\r
152         }\r
153         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
154         NS_LOG_V(INFO_PRIVATE, "SubList ID = [%s]", subData->id);\r
155 \r
156         NS_LOG_V(INFO_PRIVATE, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
157 \r
158         subData->remote_messageObId = subData->messageObId = 0;\r
159 \r
160         bool iSRemoteServer = false;\r
161 \r
162 #if(defined WITH_CLOUD)\r
163         iSRemoteServer = NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr);\r
164         if (iSRemoteServer)\r
165         {\r
166             NS_LOG(DEBUG, "Requested by remote server");\r
167             subData->remote_messageObId = entityHandlerRequest->obsInfo.obsId;\r
168             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->remote_messageObId);\r
169         }\r
170 #endif\r
171 \r
172         if (!iSRemoteServer)\r
173         {\r
174             NS_LOG(DEBUG, "Requested by local consumer");\r
175             subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
176             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->messageObId);\r
177         }\r
178 \r
179         subData->isWhite = false;\r
180         subData->remote_syncObId = 0;\r
181         subData->syncObId = 0;\r
182 \r
183         element->data = (void*) subData;\r
184         element->next = NULL;\r
185 \r
186         if (NSProviderStorageWrite(consumerSubList, element) != NS_OK)\r
187         {\r
188             NS_LOG(DEBUG, "fail to write cache");\r
189         }\r
190 \r
191         bool currPolicy = NSGetPolicy();\r
192         NSAskAcceptanceToUser(NSCopyOCEntityHandlerRequest(entityHandlerRequest));\r
193 \r
194         if (currPolicy == NS_POLICY_PROVIDER)\r
195         {\r
196             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_PROVIDER");\r
197         }\r
198         else if (currPolicy == NS_POLICY_CONSUMER)\r
199         {\r
200             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_CONSUMER");\r
201             NSSendConsumerSubResponse(NSCopyOCEntityHandlerRequest(entityHandlerRequest));\r
202         }\r
203 \r
204         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
205     }\r
206     else if (resourceType == NS_RESOURCE_SYNC)\r
207     {\r
208         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_SYNC");\r
209         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
210         NS_VERIFY_NOT_NULL_V(element);\r
211         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
212         if (!subData)\r
213         {\r
214             NS_LOG(ERROR, "Memory assignment to subData failed");\r
215             NSOICFree(element);\r
216             return;\r
217         }\r
218 \r
219         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
220         NS_LOG_V(INFO_PRIVATE, "SubList ID = [%s]", subData->id);\r
221 \r
222         NS_LOG_V(INFO_PRIVATE, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
223 \r
224         subData->remote_syncObId = subData->syncObId = 0;\r
225         bool isRemoteServer = false;\r
226 \r
227 #if (defined WITH_CLOUD)\r
228         isRemoteServer = NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr);\r
229         if (isRemoteServer)\r
230         {\r
231             NS_LOG(DEBUG, "Requested by remote server");\r
232             subData->remote_syncObId = entityHandlerRequest->obsInfo.obsId;\r
233             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->remote_syncObId);\r
234         }\r
235 #endif\r
236 \r
237         if (!isRemoteServer)\r
238         {\r
239             NS_LOG(DEBUG, "Requested by local consumer");\r
240             subData->syncObId = entityHandlerRequest->obsInfo.obsId;\r
241             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->syncObId);\r
242         }\r
243 \r
244         subData->isWhite = false;\r
245         subData->messageObId = 0;\r
246         subData->remote_messageObId = 0;\r
247 \r
248         element->data = (void*) subData;\r
249         element->next = NULL;\r
250 \r
251         if (NS_OK != NSProviderStorageWrite(consumerSubList, element))\r
252         {\r
253             NS_LOG(ERROR, "Fail to write cache");\r
254         }\r
255 \r
256         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
257     }\r
258     NSOICFree(copyReq);\r
259 \r
260     NS_LOG(DEBUG, "NSHandleSubscription - OUT");\r
261 }\r
262 \r
263 void NSHandleUnsubscription(OCEntityHandlerRequest *entityHandlerRequest)\r
264 {\r
265     NS_LOG(DEBUG, "NSHandleUnsubscription - IN");\r
266 \r
267     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER_OBSERVE_ID;\r
268 \r
269     while (NSProviderStorageDelete(consumerSubList, (char *)\r
270             &(entityHandlerRequest->obsInfo.obsId)) != NS_FAIL);\r
271 \r
272     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER;\r
273     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
274     NS_LOG(DEBUG, "NSHandleUnsubscription - OUT");\r
275 }\r
276 \r
277 void NSAskAcceptanceToUser(OCEntityHandlerRequest *entityHandlerRequest)\r
278 {\r
279     NS_LOG(DEBUG, "NSAskAcceptanceToUser - IN");\r
280 \r
281     NSPushQueue(CALLBACK_RESPONSE_SCHEDULER, TASK_CB_SUBSCRIPTION, entityHandlerRequest);\r
282 \r
283     NS_LOG(DEBUG, "NSAskAcceptanceToUser - OUT");\r
284 }\r
285 \r
286 NSResult NSSendResponse(const char * id, bool accepted)\r
287 {\r
288     NS_LOG(DEBUG, "NSSendResponse - IN");\r
289 \r
290     OCRepPayload* payload = OCRepPayloadCreate();\r
291     if (!payload)\r
292     {\r
293         NS_LOG(ERROR, "fail to create playload");\r
294         return NS_ERROR;\r
295     }\r
296 \r
297     OCResourceHandle rHandle = NULL;\r
298     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
299     {\r
300         NS_LOG(ERROR, "Fail to put notification resource");\r
301         return NS_ERROR;\r
302     }\r
303 \r
304     OCRepPayloadSetUri(payload, NS_COLLECTION_MESSAGE_URI);\r
305     (accepted) ? OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_ALLOW)\r
306         : OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_DENY);\r
307     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
308 \r
309     NSCacheElement * element = NSProviderStorageRead(consumerSubList, id);\r
310 \r
311     if (element == NULL)\r
312     {\r
313         NS_LOG(ERROR, "element is NULL");\r
314         return NS_ERROR;\r
315     }\r
316 \r
317     NSCacheSubData * subData = (NSCacheSubData*) element->data;\r
318 \r
319     if (OCNotifyListOfObservers(rHandle, (OCObservationId*)&subData->messageObId, 1,\r
320             payload, OC_LOW_QOS) != OC_STACK_OK)\r
321     {\r
322         NS_LOG(ERROR, "fail to send Acceptance");\r
323         OCRepPayloadDestroy(payload);\r
324         return NS_ERROR;\r
325 \r
326     }\r
327 \r
328     OCRepPayloadDestroy(payload);\r
329     NS_LOG(DEBUG, "NSSendResponse - OUT");\r
330     return NS_OK;\r
331 }\r
332 \r
333 NSResult NSSendConsumerSubResponse(OCEntityHandlerRequest * entityHandlerRequest)\r
334 {\r
335     NS_LOG(DEBUG, "NSSendSubscriptionResponse - IN");\r
336 \r
337     if (!entityHandlerRequest)\r
338     {\r
339         NS_LOG(ERROR, "Invalid request pointer");\r
340         return NS_ERROR;\r
341     }\r
342 \r
343     char * copyReq = OICStrdup(entityHandlerRequest->query);\r
344     char * id = NSGetValueFromQuery(copyReq, NS_QUERY_CONSUMER_ID);\r
345 \r
346     if (!id)\r
347     {\r
348         NSOICFree(copyReq);\r
349         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
350         NS_LOG(ERROR, "Invalid ConsumerID");\r
351         return NS_ERROR;\r
352     }\r
353 \r
354     NSCacheUpdateSubScriptionState(consumerSubList, id, true);\r
355     NSSendResponse(id, true);\r
356     NSOICFree(copyReq);\r
357     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
358     NS_LOG(DEBUG, "NSSendSubscriptionResponse - OUT");\r
359     return NS_OK;\r
360 }\r
361 \r
362 #ifdef WITH_MQ\r
363 void NSProviderMQSubscription(NSMQTopicAddress * topicAddr)\r
364 {\r
365     char * serverUri = topicAddr->serverAddr;\r
366     char * topicName = topicAddr->topicName;\r
367 \r
368     NS_LOG_V(DEBUG, "input Topic Name2 : %s", topicAddr->topicName);\r
369 \r
370     OCDevAddr * addr = NSChangeAddress(serverUri);\r
371     OCCallbackData cbdata = { NULL, NULL, NULL };\r
372     cbdata.cb = NSProviderGetMQResponseCB;\r
373     cbdata.context = OICStrdup(topicName);\r
374     cbdata.cd = NSOICFree;\r
375 \r
376     char requestUri[100] = "coap+tcp://";\r
377 \r
378     NS_LOG_V(DEBUG, "requestUri1 = %s", requestUri);\r
379     OICStrcat(requestUri, strlen(requestUri)+strlen(serverUri)+1, serverUri);\r
380     NS_LOG_V(DEBUG, "requestUri2 = %s", requestUri);\r
381     OICStrcat(requestUri, strlen(requestUri)+ strlen("/oic/ps") + 1, "/oic/ps");\r
382     NS_LOG_V(DEBUG, "requestUri3 = %s", requestUri);\r
383     OCStackResult ret = OCDoResource(NULL, OC_REST_GET, requestUri, addr,\r
384                                      NULL, CT_DEFAULT, OC_HIGH_QOS, &cbdata, NULL, 0);\r
385 \r
386     NSOCResultToSuccess(ret);\r
387 \r
388     NSOICFree(topicAddr->serverAddr);\r
389     NSOICFree(topicAddr->topicName);\r
390     NSOICFree(topicAddr);\r
391 }\r
392 #endif\r
393 \r
394 void * NSSubScriptionSchedule(void *ptr)\r
395 {\r
396     if (ptr == NULL)\r
397     {\r
398         NS_LOG(DEBUG, "Create NSSubScriptionSchedule");\r
399     }\r
400 \r
401     while (NSIsRunning[SUBSCRIPTION_SCHEDULER])\r
402     {\r
403         sem_wait(&NSSemaphore[SUBSCRIPTION_SCHEDULER]);\r
404         pthread_mutex_lock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
405 \r
406         if (NSHeadMsg[SUBSCRIPTION_SCHEDULER] != NULL)\r
407         {\r
408             NSTask *node = NSHeadMsg[SUBSCRIPTION_SCHEDULER];\r
409             NSHeadMsg[SUBSCRIPTION_SCHEDULER] = node->nextTask;\r
410 \r
411             switch (node->taskType)\r
412             {\r
413                 case TASK_SEND_POLICY:\r
414                     NS_LOG(DEBUG, "CASE TASK_SEND_POLICY : ");\r
415                     NSSendAccessPolicyResponse((OCEntityHandlerRequest*) node->taskData);\r
416                     break;\r
417 \r
418                 case TASK_RECV_SUBSCRIPTION:\r
419                     NS_LOG(DEBUG, "CASE TASK_RECV_SUBSCRIPTION : ");\r
420                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
421                             NS_RESOURCE_MESSAGE);\r
422                     break;\r
423 \r
424                 case TASK_RECV_UNSUBSCRIPTION:\r
425                     NS_LOG(DEBUG, "CASE TASK_RECV_UNSUBSCRIPTION : ");\r
426                     NSHandleUnsubscription((OCEntityHandlerRequest*) node->taskData);\r
427                     break;\r
428 \r
429                 case TASK_SEND_ALLOW:\r
430                 {\r
431                     NS_LOG(DEBUG, "CASE TASK_SEND_ALLOW : ");\r
432                     char * consumerId = (char *) node->taskData;\r
433 \r
434                     NSCacheUpdateSubScriptionState(consumerSubList, consumerId, true);\r
435                     NSSendResponse(consumerId, true);\r
436                     NSOICFree(consumerId);\r
437                     break;\r
438                 }\r
439                 case TASK_SEND_DENY:\r
440                 {\r
441                     NS_LOG(DEBUG, "CASE TASK_SEND_DENY : ");\r
442                     char * consumerId = (char *) node->taskData;\r
443 \r
444                     NSCacheUpdateSubScriptionState(consumerSubList, consumerId, false);\r
445                     NSSendResponse(consumerId, false);\r
446                     NSOICFree(consumerId);\r
447 \r
448                     break;\r
449                 }\r
450                 case TASK_SYNC_SUBSCRIPTION:\r
451                     NS_LOG(DEBUG, "CASE TASK_SYNC_SUBSCRIPTION : ");\r
452                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
453                             NS_RESOURCE_SYNC);\r
454                     break;\r
455 #ifdef WITH_MQ\r
456                 case TASK_MQ_REQ_SUBSCRIBE:\r
457                     NS_LOG(DEBUG, "CASE TASK_MQ_REQ_SUBSCRIBE : ");\r
458                     NSProviderMQSubscription((NSMQTopicAddress*) node->taskData);\r
459                     break;\r
460 #endif\r
461                 default:\r
462                     break;\r
463 \r
464             }\r
465             NSOICFree(node);\r
466         }\r
467 \r
468         pthread_mutex_unlock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
469 \r
470     }\r
471     NS_LOG(INFO, "Destroy NSSubScriptionSchedule");\r
472     return NULL;\r
473 }\r