Merge "Merge branch 'master' into notification-service" into notification-service
[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 = NSStorageCreate();\r
28     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER;\r
29 \r
30     NS_LOG(DEBUG, "NSInitSubscriptionList - OUT");\r
31     return NS_OK;\r
32 }\r
33 \r
34 NSResult NSSetSubscriptionAccessPolicy(NSAccessPolicy access)\r
35 {\r
36     NS_LOG(DEBUG, "NSSetSubscriptionAcceptPolicy - IN");\r
37 \r
38     if (access == NS_ACCESS_ALLOW)\r
39     {\r
40         NS_LOG(DEBUG, "Place Provider as a subscription accepter");\r
41     }\r
42     else if (access == NS_ACCESS_DENY)\r
43     {\r
44         NS_LOG(DEBUG, "Place Consumer as a subscription accepter");\r
45     }\r
46 \r
47     NSSubscriptionAccess = access;\r
48 \r
49     NS_LOG(DEBUG, "NSSetSubscriptionAcceptPolicy - OUT");\r
50     return NS_OK;\r
51 }\r
52 \r
53 int NSGetSubscriptionAccepter()\r
54 {\r
55     return NSSubscriptionAccess;\r
56 }\r
57 \r
58 NSResult NSSendAccessPolicyResponse(OCEntityHandlerRequest *entityHandlerRequest)\r
59 {\r
60     NS_LOG(DEBUG, "NSSendAccessPolicyResponse - IN");\r
61 \r
62     // put notification resource\r
63     OCResourceHandle notificationResourceHandle;\r
64     if (NSPutNotificationResource(NSGetSubscriptionAccepter(), &notificationResourceHandle)\r
65             != NS_OK)\r
66     {\r
67         NS_LOG(ERROR, "Fail to put notification resource");\r
68         return NS_ERROR;\r
69     }\r
70 \r
71     // make response for the Get Request\r
72     OCEntityHandlerResponse response;\r
73     response.numSendVendorSpecificHeaderOptions = 0;\r
74     memset(response.sendVendorSpecificHeaderOptions, 0,\r
75             sizeof response.sendVendorSpecificHeaderOptions);\r
76     memset(response.resourceUri, 0, sizeof response.resourceUri);\r
77 \r
78     OCRepPayload* payload = OCRepPayloadCreate();\r
79     if (!payload)\r
80     {\r
81         NS_LOG(ERROR, "payload is NULL");\r
82         return NS_ERROR;\r
83     }\r
84 \r
85     NS_LOG_V(DEBUG, "NS Provider ID: %s", NSGetProviderInfo()->providerId);\r
86 \r
87     OCRepPayloadSetUri(payload, NS_ROOT_URI);\r
88     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
89     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_POLICY, NSGetSubscriptionAccepter());\r
90     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_MESSAGE, NS_COLLECTION_MESSAGE_URI);\r
91     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_SYNC, NS_COLLECTION_SYNC_URI);\r
92 \r
93     response.requestHandle = entityHandlerRequest->requestHandle;\r
94     response.resourceHandle = entityHandlerRequest->resource;\r
95     response.persistentBufferFlag = 0;\r
96     response.ehResult = OC_EH_OK;\r
97     response.payload = (OCPayload *) payload;\r
98 \r
99     // Send Response\r
100     if (OCDoResponse(&response) != OC_STACK_OK)\r
101     {\r
102         NS_LOG(ERROR, "Fail to AccessPolicy send response");\r
103         return NS_ERROR;\r
104     }\r
105     OCRepPayloadDestroy(payload);\r
106     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
107 \r
108     NS_LOG(DEBUG, "NSSendAccessPolicyResponse - OUT");\r
109     return NS_OK;\r
110 }\r
111 \r
112 void NSHandleSubscription(OCEntityHandlerRequest *entityHandlerRequest, NSResourceType resourceType)\r
113 {\r
114     NS_LOG(DEBUG, "NSHandleSubscription - IN");\r
115 \r
116     char * id = NSGetValueFromQuery(OICStrdup(entityHandlerRequest->query), NS_QUERY_CONSUMER_ID);\r
117 \r
118     if(!id)\r
119     {\r
120         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
121         NS_LOG(ERROR, "Invalid ConsumerID");\r
122         return;\r
123     }\r
124 \r
125     NS_LOG_V(DEBUG, "consumerId = %s", id);\r
126     if (resourceType == NS_RESOURCE_MESSAGE)\r
127     {\r
128         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_MESSAGE");\r
129         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
130         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
131 \r
132         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
133         NS_LOG_V(DEBUG, "SubList ID = [%s]", subData->id);\r
134 \r
135         NS_LOG_V(DEBUG, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
136         if(NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr))\r
137         {\r
138             NS_LOG(DEBUG, "Requested by remote server");\r
139             subData->remote_messageObId = entityHandlerRequest->obsInfo.obsId;\r
140             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->remote_messageObId);\r
141         }\r
142         else\r
143         {\r
144             NS_LOG(DEBUG, "Requested by local consumer");\r
145             subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
146             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->messageObId);\r
147         }\r
148         subData->isWhite = false;\r
149 \r
150         element->data = (void*) subData;\r
151         element->next = NULL;\r
152 \r
153         if (NSStorageWrite(consumerSubList, element) != NS_OK)\r
154         {\r
155             NS_LOG(DEBUG, "fail to write cache");\r
156         }\r
157 \r
158         if (NSGetSubscriptionAccepter() == NS_ACCESS_ALLOW)\r
159         {\r
160             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_PROVIDER");\r
161             NSAskAcceptanceToUser(entityHandlerRequest);\r
162         }\r
163         else if (NSGetSubscriptionAccepter() == NS_ACCESS_DENY)\r
164         {\r
165             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_CONSUMER");\r
166             NSSendSubscriptionResponse(entityHandlerRequest, true);\r
167         }\r
168     }\r
169     else if (resourceType == NS_RESOURCE_SYNC)\r
170     {\r
171         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_SYNC");\r
172         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
173         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
174 \r
175         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
176         NS_LOG_V(DEBUG, "SubList ID = [%s]", subData->id);\r
177 \r
178         NS_LOG_V(DEBUG, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
179         if(NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr))\r
180         {\r
181             NS_LOG(DEBUG, "Requested by remote server");\r
182             subData->remote_syncObId = entityHandlerRequest->obsInfo.obsId;\r
183             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->remote_syncObId);\r
184         }\r
185         else\r
186         {\r
187             NS_LOG(DEBUG, "Requested by local consumer");\r
188             subData->syncObId = entityHandlerRequest->obsInfo.obsId;\r
189             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->syncObId);\r
190         }\r
191 \r
192         subData->isWhite = false;\r
193 \r
194         element->data = (void*) subData;\r
195         element->next = NULL;\r
196 \r
197         if (NSStorageWrite(consumerSubList, element) != NS_OK)\r
198         {\r
199             NS_LOG(ERROR, "Fail to write cache");\r
200         }\r
201 \r
202         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
203     }\r
204 \r
205     NS_LOG(DEBUG, "NSHandleSubscription - OUT");\r
206 }\r
207 \r
208 void NSHandleUnsubscription(OCEntityHandlerRequest *entityHandlerRequest)\r
209 {\r
210     NS_LOG(DEBUG, "NSHandleUnsubscription - IN");\r
211 \r
212     char * id = NSGetValueFromQuery(OICStrdup(entityHandlerRequest->query), NS_QUERY_CONSUMER_ID);\r
213 \r
214     if(!id)\r
215     {\r
216         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
217         NS_LOG(ERROR, "Invalid ConsumerID");\r
218         return;\r
219     }\r
220 \r
221     NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
222     NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
223 \r
224     OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
225     subData->isWhite = false;\r
226     subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
227 \r
228     element->data = (void*) subData;\r
229     element->next = NULL;\r
230 \r
231     NS_LOG_V(DEBUG, "SubList IP[ID] = [%s]", subData->id);\r
232     NS_LOG_V(DEBUG, "SubList observation ID = [%d]", subData->syncObId);\r
233 \r
234     if (NSStorageWrite(consumerSubList, element) != NS_OK)\r
235     {\r
236         NS_LOG(ERROR, "fail to write consumer white list");\r
237     }\r
238 \r
239     NS_LOG(DEBUG, "NSHandleUnsubscription - IN");\r
240 \r
241     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
242 }\r
243 \r
244 void NSAskAcceptanceToUser(OCEntityHandlerRequest *entityHandlerRequest)\r
245 {\r
246     NS_LOG(DEBUG, "NSAskAcceptanceToUser - IN");\r
247 \r
248     NSPushQueue(CALLBACK_RESPONSE_SCHEDULER, TASK_CB_SUBSCRIPTION, entityHandlerRequest);\r
249 \r
250     NS_LOG(DEBUG, "NSAskAcceptanceToUser - OUT");\r
251 }\r
252 \r
253 NSResult NSSendResponse(const char * id, bool accepted)\r
254 {\r
255     NS_LOG(DEBUG, "NSSendResponse - IN");\r
256 \r
257     OCRepPayload* payload = OCRepPayloadCreate();\r
258     if (!payload)\r
259     {\r
260         NS_LOG(ERROR, "fail to create playload");\r
261         return NS_ERROR;\r
262     }\r
263 \r
264     OCResourceHandle rHandle;\r
265     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
266     {\r
267         NS_LOG(ERROR, "Fail to put notification resource");\r
268         return NS_ERROR;\r
269     }\r
270 \r
271     OCRepPayloadSetUri(payload, NS_COLLECTION_MESSAGE_URI);\r
272     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, 1);\r
273     OCRepPayloadSetPropBool(payload, NS_ATTRIBUTE_ACCPETANCE, accepted);\r
274     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
275 \r
276     NSCacheElement * element = NSStorageRead(consumerSubList, id);\r
277 \r
278     if(element == NULL)\r
279     {\r
280         NS_LOG(ERROR, "element is NULL");\r
281         return NS_ERROR;\r
282     }\r
283     NSCacheSubData * subData = (NSCacheSubData*) element->data;\r
284 \r
285     if (OCNotifyListOfObservers(rHandle, (OCObservationId*)&subData->messageObId, 1, payload, OC_HIGH_QOS)\r
286             != OC_STACK_OK)\r
287     {\r
288         NS_LOG(ERROR, "fail to send Acceptance");\r
289         OCRepPayloadDestroy(payload);\r
290         return NS_ERROR;\r
291 \r
292     }\r
293     OCRepPayloadDestroy(payload);\r
294 \r
295     NS_LOG(DEBUG, "NSSendResponse - OUT");\r
296     return NS_OK;\r
297 }\r
298 \r
299 NSResult NSSendSubscriptionResponse(OCEntityHandlerRequest *entityHandlerRequest, bool accepted)\r
300 {\r
301     NS_LOG(DEBUG, "NSSendSubscriptionResponse - IN");\r
302 \r
303     if (!entityHandlerRequest)\r
304     {\r
305         NS_LOG(ERROR, "Invalid request pointer");\r
306         return OC_EH_ERROR;\r
307     }\r
308 \r
309     char * id = NSGetValueFromQuery(OICStrdup(entityHandlerRequest->query), NS_QUERY_CONSUMER_ID);\r
310 \r
311     if(!id)\r
312     {\r
313         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
314         NS_LOG(ERROR, "Invalid ConsumerID");\r
315         return NS_ERROR;\r
316     }\r
317 \r
318     if (accepted)\r
319     {\r
320         NS_LOG(DEBUG, "accepted is true");\r
321         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
322         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
323 \r
324         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
325 \r
326         subData->isWhite = true;\r
327         subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
328 \r
329         element->data = (void*) subData;\r
330         element->next = NULL;\r
331 \r
332         if (NSStorageWrite(consumerSubList, element) != NS_OK)\r
333         {\r
334             NS_LOG(ERROR, "fail to write consumer white list");\r
335         }\r
336     }\r
337 \r
338     NSSendResponse(id, accepted);\r
339 \r
340     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
341 \r
342     NS_LOG(DEBUG, "NSSendSubscriptionResponse - OUT");\r
343     return NS_OK;\r
344 }\r
345 \r
346 void * NSSubScriptionSchedule(void *ptr)\r
347 {\r
348     if (ptr == NULL)\r
349     {\r
350         NS_LOG(DEBUG, "Create NSSubScriptionSchedule");\r
351     }\r
352 \r
353     while (NSIsRunning[SUBSCRIPTION_SCHEDULER])\r
354     {\r
355         sem_wait(&NSSemaphore[SUBSCRIPTION_SCHEDULER]);\r
356         pthread_mutex_lock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
357 \r
358         if (NSHeadMsg[SUBSCRIPTION_SCHEDULER] != NULL)\r
359         {\r
360             NSTask *node = NSHeadMsg[SUBSCRIPTION_SCHEDULER];\r
361             NSHeadMsg[SUBSCRIPTION_SCHEDULER] = node->nextTask;\r
362 \r
363             switch (node->taskType)\r
364             {\r
365                 case TASK_SEND_POLICY:\r
366                     NS_LOG(DEBUG, "CASE TASK_SEND_POLICY : ");\r
367                     NSSendAccessPolicyResponse((OCEntityHandlerRequest*) node->taskData);\r
368                     break;\r
369 \r
370                 case TASK_RECV_SUBSCRIPTION:\r
371                     NS_LOG(DEBUG, "CASE TASK_RECV_SUBSCRIPTION : ");\r
372                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
373                             NS_RESOURCE_MESSAGE);\r
374                     break;\r
375 \r
376                 case TASK_RECV_UNSUBSCRIPTION:\r
377                     NS_LOG(DEBUG, "CASE TASK_RECV_UNSUBSCRIPTION : ");\r
378                     NSHandleUnsubscription((OCEntityHandlerRequest*) node->taskData);\r
379                     break;\r
380 \r
381                 case TASK_SEND_ALLOW:\r
382                 {\r
383                     NS_LOG(DEBUG, "CASE TASK_SEND_ALLOW : ");\r
384                     NSConsumer * consumer = (NSConsumer *) node->taskData;\r
385 \r
386                     NSCacheUpdateSubScriptionState(consumerSubList, consumer->consumerId, true);\r
387                     NSSendResponse(consumer->consumerId, true);\r
388                     NSFreeConsumer(consumer);\r
389                     break;\r
390                 }\r
391                 case TASK_SEND_DENY:\r
392                 {\r
393                     NS_LOG(DEBUG, "CASE TASK_SEND_DENY : ");\r
394                     NSConsumer * consumer = (NSConsumer *) node->taskData;\r
395 \r
396                     NSCacheUpdateSubScriptionState(consumerSubList, consumer->consumerId, false);\r
397                     NSSendResponse(consumer->consumerId, false);\r
398                     NSFreeConsumer(consumer);\r
399 \r
400                     break;\r
401                 }\r
402                 case TASK_SYNC_SUBSCRIPTION:\r
403                     NS_LOG(DEBUG, "CASE TASK_SYNC_SUBSCRIPTION : ");\r
404                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
405                             NS_RESOURCE_SYNC);\r
406                     break;\r
407                 default:\r
408                     break;\r
409 \r
410             }\r
411             OICFree(node);\r
412         }\r
413 \r
414         pthread_mutex_unlock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
415 \r
416     }\r
417     NS_LOG(INFO, "Destroy NSSubScriptionSchedule");\r
418     return NULL;\r
419 }\r