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