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