Merge branch 'master' 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     OCRepPayloadSetUri(payload, NS_ROOT_URI);\r
86     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_POLICY, NSGetSubscriptionAccepter());\r
87     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_MESSAGE, NS_COLLECTION_MESSAGE_URI);\r
88     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_SYNC, NS_COLLECTION_SYNC_URI);\r
89 \r
90     response.requestHandle = entityHandlerRequest->requestHandle;\r
91     response.resourceHandle = entityHandlerRequest->resource;\r
92     response.persistentBufferFlag = 0;\r
93     response.ehResult = OC_EH_OK;\r
94     response.payload = (OCPayload *) payload;\r
95 \r
96     // Send Response\r
97     if (OCDoResponse(&response) != OC_STACK_OK)\r
98     {\r
99         NS_LOG(ERROR, "Fail to AccessPolicy send response");\r
100         return NS_ERROR;\r
101     }\r
102     OCRepPayloadDestroy(payload);\r
103     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
104 \r
105     NS_LOG(DEBUG, "NSSendAccessPolicyResponse - OUT");\r
106     return NS_OK;\r
107 }\r
108 \r
109 void NSHandleSubscription(OCEntityHandlerRequest *entityHandlerRequest, NSResourceType resourceType)\r
110 {\r
111     NS_LOG(DEBUG, "NSHandleSubscription - IN");\r
112 \r
113     if (resourceType == NS_RESOURCE_MESSAGE)\r
114     {\r
115         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_MESSAGE");\r
116         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
117         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
118 \r
119         char * id = NSGetValueFromQuery(entityHandlerRequest->query, NS_QUERY_CONSUMER_ID);\r
120         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
121         OICFree(id);\r
122         subData->isWhite = false;\r
123         subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
124         subData->syncObId = 0;\r
125 \r
126         element->data = (void*) subData;\r
127         element->next = NULL;\r
128 \r
129         NS_LOG_V(DEBUG, "SubList IP[ID] = [%s]", subData->id);\r
130         NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->messageObId);\r
131 \r
132         if (NSStorageWrite(consumerSubList, element) != NS_OK)\r
133         {\r
134             NS_LOG(DEBUG, "fail to write cache");\r
135         }\r
136 \r
137         if (NSGetSubscriptionAccepter() == NS_ACCESS_ALLOW)\r
138         {\r
139             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_PROVIDER");\r
140             NSAskAcceptanceToUser(entityHandlerRequest);\r
141         }\r
142         else if (NSGetSubscriptionAccepter() == NS_ACCESS_DENY)\r
143         {\r
144             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_CONSUMER");\r
145             NSSendSubscriptionResponse(entityHandlerRequest, true);\r
146         }\r
147     }\r
148     else if (resourceType == NS_RESOURCE_SYNC)\r
149     {\r
150         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_SYNC");\r
151         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
152 \r
153         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
154 \r
155         char * id = NSGetValueFromQuery(entityHandlerRequest->query, NS_QUERY_CONSUMER_ID);\r
156         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
157         OICFree(id);\r
158 \r
159         subData->isWhite = false;\r
160         subData->syncObId = entityHandlerRequest->obsInfo.obsId;\r
161         subData->messageObId = 0;\r
162 \r
163         element->data = (void*) subData;\r
164         element->next = NULL;\r
165 \r
166         NS_LOG_V(DEBUG, "SubList IP[ID] = [%s]", subData->id);\r
167         NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->syncObId);\r
168 \r
169         if (NSStorageWrite(consumerSubList, element) != NS_OK)\r
170         {\r
171             NS_LOG(ERROR, "Fail to write cache");\r
172         }\r
173     }\r
174 \r
175     NS_LOG(DEBUG, "NSHandleSubscription - OUT");\r
176 }\r
177 \r
178 void NSHandleUnsubscription(OCEntityHandlerRequest *entityHandlerRequest)\r
179 {\r
180     NS_LOG(DEBUG, "NSHandleUnsubscription - IN");\r
181 \r
182     NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
183     NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
184 \r
185     char * id = NSGetValueFromQuery(entityHandlerRequest->query, NS_QUERY_CONSUMER_ID);\r
186     OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
187     OICFree(id);\r
188 \r
189     subData->isWhite = false;\r
190     subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
191 \r
192     element->data = (void*) subData;\r
193     element->next = NULL;\r
194 \r
195     NS_LOG_V(DEBUG, "SubList IP[ID] = [%s]", subData->id);\r
196     NS_LOG_V(DEBUG, "SubList observation ID = [%d]", subData->syncObId);\r
197 \r
198     if (NSStorageWrite(consumerSubList, element) != NS_OK)\r
199     {\r
200         NS_LOG(ERROR, "fail to write consumer white list");\r
201     }\r
202 \r
203     NS_LOG(DEBUG, "NSHandleUnsubscription - IN");\r
204     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
205 }\r
206 \r
207 void NSAskAcceptanceToUser(OCEntityHandlerRequest *entityHandlerRequest)\r
208 {\r
209     NS_LOG(DEBUG, "NSAskAcceptanceToUser - IN");\r
210 \r
211     NSPushQueue(INTERFACE_SCHEDULER, TASK_CB_SUBSCRIPTION, entityHandlerRequest);\r
212 \r
213     NS_LOG(DEBUG, "NSAskAcceptanceToUser - OUT");\r
214 }\r
215 \r
216 NSResult NSSendResponse(const char * id, bool accepted)\r
217 {\r
218     NS_LOG(DEBUG, "NSSendResponse - IN");\r
219 \r
220     OCRepPayload* payload = OCRepPayloadCreate();\r
221     if (!payload)\r
222     {\r
223         NS_LOG(ERROR, "fail to create playload");\r
224         return NS_ERROR;\r
225     }\r
226 \r
227     OCResourceHandle rHandle;\r
228     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
229     {\r
230         NS_LOG(ERROR, "Fail to put notification resource");\r
231         return NS_ERROR;\r
232     }\r
233 \r
234     OCRepPayloadSetUri(payload, NS_COLLECTION_MESSAGE_URI);\r
235     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, 1);\r
236     OCRepPayloadSetPropBool(payload, NS_ATTRIBUTE_ACCPETANCE, accepted);\r
237 \r
238     NSCacheElement * element = NSStorageRead(consumerSubList, id);\r
239 \r
240     if(element == NULL)\r
241     {\r
242         NS_LOG(ERROR, "element is NULL");\r
243         return NS_ERROR;\r
244     }\r
245     NSCacheSubData * subData = (NSCacheSubData*) element->data;\r
246 \r
247     if (OCNotifyListOfObservers(rHandle, (OCObservationId*)&subData->messageObId, 1, payload, OC_HIGH_QOS)\r
248             != OC_STACK_OK)\r
249     {\r
250         NS_LOG(ERROR, "fail to send Acceptance");\r
251         OCRepPayloadDestroy(payload);\r
252         return NS_ERROR;\r
253 \r
254     }\r
255     OCRepPayloadDestroy(payload);\r
256 \r
257     NS_LOG(DEBUG, "NSSendResponse - OUT");\r
258     return NS_OK;\r
259 }\r
260 \r
261 NSResult NSSendSubscriptionResponse(OCEntityHandlerRequest *entityHandlerRequest, bool accepted)\r
262 {\r
263     NS_LOG(DEBUG, "NSSendSubscriptionResponse - IN");\r
264 \r
265     if (!entityHandlerRequest)\r
266     {\r
267         NS_LOG(ERROR, "Invalid request pointer");\r
268         return OC_EH_ERROR;\r
269     }\r
270 \r
271     if (accepted)\r
272     {\r
273         NS_LOG(DEBUG, "accepted is true");\r
274         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
275 \r
276         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
277         char * id = NSGetValueFromQuery(entityHandlerRequest->query, NS_QUERY_CONSUMER_ID);\r
278         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
279         OICFree(id);\r
280         subData->isWhite = true;\r
281         subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
282 \r
283         element->data = (void*) subData;\r
284         element->next = NULL;\r
285 \r
286         if (NSStorageWrite(consumerSubList, element) != NS_OK)\r
287         {\r
288             NS_LOG(ERROR, "fail to write consumer white list");\r
289         }\r
290     }\r
291 \r
292     char * id = NSGetValueFromQuery(entityHandlerRequest->query, NS_QUERY_CONSUMER_ID);\r
293     NSSendResponse(id, accepted);\r
294 \r
295     OICFree(id);\r
296     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
297 \r
298     NS_LOG(DEBUG, "NSSendSubscriptionResponse - OUT");\r
299     return NS_OK;\r
300 }\r
301 \r
302 void * NSSubScriptionSchedule(void *ptr)\r
303 {\r
304     if (ptr == NULL)\r
305     {\r
306         NS_LOG(DEBUG, "Create NSSubScriptionSchedule");\r
307     }\r
308 \r
309     while (NSIsRunning[SUBSCRIPTION_SCHEDULER])\r
310     {\r
311         sem_wait(&NSSemaphore[SUBSCRIPTION_SCHEDULER]);\r
312         pthread_mutex_lock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
313 \r
314         if (NSHeadMsg[SUBSCRIPTION_SCHEDULER] != NULL)\r
315         {\r
316             NSTask *node = NSHeadMsg[SUBSCRIPTION_SCHEDULER];\r
317             NSHeadMsg[SUBSCRIPTION_SCHEDULER] = node->nextTask;\r
318 \r
319             switch (node->taskType)\r
320             {\r
321                 case TASK_SEND_POLICY:\r
322                     NS_LOG(DEBUG, "CASE TASK_SEND_POLICY : ");\r
323                     NSSendAccessPolicyResponse((OCEntityHandlerRequest*) node->taskData);\r
324                     break;\r
325 \r
326                 case TASK_RECV_SUBSCRIPTION:\r
327                     NS_LOG(DEBUG, "CASE TASK_RECV_SUBSCRIPTION : ");\r
328                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
329                             NS_RESOURCE_MESSAGE);\r
330                     break;\r
331 \r
332                 case TASK_RECV_UNSUBSCRIPTION:\r
333                     NS_LOG(DEBUG, "CASE TASK_RECV_UNSUBSCRIPTION : ");\r
334                     NSHandleUnsubscription((OCEntityHandlerRequest*) node->taskData);\r
335                     break;\r
336 \r
337                 case TASK_SEND_ALLOW:\r
338                 {\r
339                     NS_LOG(DEBUG, "CASE TASK_SEND_ALLOW : ");\r
340                     NSConsumer * consumer = (NSConsumer *) node->taskData;\r
341 \r
342                     NSCacheUpdateSubScriptionState(consumerSubList, consumer->consumerId, true);\r
343                     NSSendResponse(consumer->consumerId, true);\r
344                     NSFreeConsumer(consumer);\r
345                     break;\r
346                 }\r
347                 case TASK_SEND_DENY:\r
348                 {\r
349                     NS_LOG(DEBUG, "CASE TASK_SEND_DENY : ");\r
350                     NSConsumer * consumer = (NSConsumer *) node->taskData;\r
351 \r
352                     NSCacheUpdateSubScriptionState(consumerSubList, consumer->consumerId, false);\r
353                     NSSendResponse(consumer->consumerId, false);\r
354                     NSFreeConsumer(consumer);\r
355 \r
356                     break;\r
357                 }\r
358                 case TASK_SYNC_SUBSCRIPTION:\r
359                     NS_LOG(DEBUG, "CASE TASK_SYNC_SUBSCRIPTION : ");\r
360                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
361                             NS_RESOURCE_SYNC);\r
362                     break;\r
363                 default:\r
364                     break;\r
365 \r
366             }\r
367             OICFree(node);\r
368         }\r
369 \r
370         pthread_mutex_unlock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
371 \r
372     }\r
373     NS_LOG(INFO, "Destroy NSSubScriptionSchedule");\r
374     return NULL;\r
375 }\r