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