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