add deregister of observe and delete subscription list from observeid
[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     NSProviderDeleteSubDataFromObId(consumerSubList, entityHandlerRequest->obsInfo.obsId);\r
213 \r
214     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
215 \r
216     NS_LOG(DEBUG, "NSHandleUnsubscription - OUT");\r
217 }\r
218 \r
219 void NSAskAcceptanceToUser(OCEntityHandlerRequest *entityHandlerRequest)\r
220 {\r
221     NS_LOG(DEBUG, "NSAskAcceptanceToUser - IN");\r
222 \r
223     NSPushQueue(CALLBACK_RESPONSE_SCHEDULER, TASK_CB_SUBSCRIPTION, entityHandlerRequest);\r
224 \r
225     NS_LOG(DEBUG, "NSAskAcceptanceToUser - OUT");\r
226 }\r
227 \r
228 NSResult NSSendResponse(const char * id, bool accepted)\r
229 {\r
230     NS_LOG(DEBUG, "NSSendResponse - IN");\r
231 \r
232     OCRepPayload* payload = OCRepPayloadCreate();\r
233     if (!payload)\r
234     {\r
235         NS_LOG(ERROR, "fail to create playload");\r
236         return NS_ERROR;\r
237     }\r
238 \r
239     OCResourceHandle rHandle;\r
240     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
241     {\r
242         NS_LOG(ERROR, "Fail to put notification resource");\r
243         return NS_ERROR;\r
244     }\r
245 \r
246     OCRepPayloadSetUri(payload, NS_COLLECTION_MESSAGE_URI);\r
247     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, 1);\r
248     OCRepPayloadSetPropBool(payload, NS_ATTRIBUTE_ACCPETANCE, accepted);\r
249     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
250 \r
251     NSCacheElement * element = NSStorageRead(consumerSubList, id);\r
252 \r
253     if(element == NULL)\r
254     {\r
255         NS_LOG(ERROR, "element is NULL");\r
256         return NS_ERROR;\r
257     }\r
258     NSCacheSubData * subData = (NSCacheSubData*) element->data;\r
259 \r
260     if (OCNotifyListOfObservers(rHandle, (OCObservationId*)&subData->messageObId, 1, payload, OC_HIGH_QOS)\r
261             != OC_STACK_OK)\r
262     {\r
263         NS_LOG(ERROR, "fail to send Acceptance");\r
264         OCRepPayloadDestroy(payload);\r
265         return NS_ERROR;\r
266 \r
267     }\r
268     OCRepPayloadDestroy(payload);\r
269 \r
270     NS_LOG(DEBUG, "NSSendResponse - OUT");\r
271     return NS_OK;\r
272 }\r
273 \r
274 NSResult NSSendSubscriptionResponse(OCEntityHandlerRequest *entityHandlerRequest, bool accepted)\r
275 {\r
276     NS_LOG(DEBUG, "NSSendSubscriptionResponse - IN");\r
277 \r
278     if (!entityHandlerRequest)\r
279     {\r
280         NS_LOG(ERROR, "Invalid request pointer");\r
281         return OC_EH_ERROR;\r
282     }\r
283 \r
284     char * id = NSGetValueFromQuery(OICStrdup(entityHandlerRequest->query), NS_QUERY_CONSUMER_ID);\r
285 \r
286     if(!id)\r
287     {\r
288         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
289         NS_LOG(ERROR, "Invalid ConsumerID");\r
290         return NS_ERROR;\r
291     }\r
292 \r
293     if (accepted)\r
294     {\r
295         NS_LOG(DEBUG, "accepted is true");\r
296         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
297         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
298 \r
299         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
300 \r
301         subData->isWhite = true;\r
302         subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
303 \r
304         element->data = (void*) subData;\r
305         element->next = NULL;\r
306 \r
307         if (NSStorageWrite(consumerSubList, element) != NS_OK)\r
308         {\r
309             NS_LOG(ERROR, "fail to write consumer white list");\r
310         }\r
311     }\r
312 \r
313     NSSendResponse(id, accepted);\r
314 \r
315     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
316 \r
317     NS_LOG(DEBUG, "NSSendSubscriptionResponse - OUT");\r
318     return NS_OK;\r
319 }\r
320 \r
321 void * NSSubScriptionSchedule(void *ptr)\r
322 {\r
323     if (ptr == NULL)\r
324     {\r
325         NS_LOG(DEBUG, "Create NSSubScriptionSchedule");\r
326     }\r
327 \r
328     while (NSIsRunning[SUBSCRIPTION_SCHEDULER])\r
329     {\r
330         sem_wait(&NSSemaphore[SUBSCRIPTION_SCHEDULER]);\r
331         pthread_mutex_lock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
332 \r
333         if (NSHeadMsg[SUBSCRIPTION_SCHEDULER] != NULL)\r
334         {\r
335             NSTask *node = NSHeadMsg[SUBSCRIPTION_SCHEDULER];\r
336             NSHeadMsg[SUBSCRIPTION_SCHEDULER] = node->nextTask;\r
337 \r
338             switch (node->taskType)\r
339             {\r
340                 case TASK_SEND_POLICY:\r
341                     NS_LOG(DEBUG, "CASE TASK_SEND_POLICY : ");\r
342                     NSSendAccessPolicyResponse((OCEntityHandlerRequest*) node->taskData);\r
343                     break;\r
344 \r
345                 case TASK_RECV_SUBSCRIPTION:\r
346                     NS_LOG(DEBUG, "CASE TASK_RECV_SUBSCRIPTION : ");\r
347                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
348                             NS_RESOURCE_MESSAGE);\r
349                     break;\r
350 \r
351                 case TASK_RECV_UNSUBSCRIPTION:\r
352                     NS_LOG(DEBUG, "CASE TASK_RECV_UNSUBSCRIPTION : ");\r
353                     NSHandleUnsubscription((OCEntityHandlerRequest*) node->taskData);\r
354                     break;\r
355 \r
356                 case TASK_SEND_ALLOW:\r
357                 {\r
358                     NS_LOG(DEBUG, "CASE TASK_SEND_ALLOW : ");\r
359                     NSConsumer * consumer = (NSConsumer *) node->taskData;\r
360 \r
361                     NSCacheUpdateSubScriptionState(consumerSubList, consumer->consumerId, true);\r
362                     NSSendResponse(consumer->consumerId, true);\r
363                     NSFreeConsumer(consumer);\r
364                     break;\r
365                 }\r
366                 case TASK_SEND_DENY:\r
367                 {\r
368                     NS_LOG(DEBUG, "CASE TASK_SEND_DENY : ");\r
369                     NSConsumer * consumer = (NSConsumer *) node->taskData;\r
370 \r
371                     NSCacheUpdateSubScriptionState(consumerSubList, consumer->consumerId, false);\r
372                     NSSendResponse(consumer->consumerId, false);\r
373                     NSFreeConsumer(consumer);\r
374 \r
375                     break;\r
376                 }\r
377                 case TASK_SYNC_SUBSCRIPTION:\r
378                     NS_LOG(DEBUG, "CASE TASK_SYNC_SUBSCRIPTION : ");\r
379                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
380                             NS_RESOURCE_SYNC);\r
381                     break;\r
382                 default:\r
383                     break;\r
384 \r
385             }\r
386             OICFree(node);\r
387         }\r
388 \r
389         pthread_mutex_unlock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
390 \r
391     }\r
392     NS_LOG(INFO, "Destroy NSSubScriptionSchedule");\r
393     return NULL;\r
394 }\r