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