replace : iotivity -> iotivity-sec
[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 #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.resourceHandle = entityHandlerRequest->resource;\r
105     response.persistentBufferFlag = 0;\r
106     response.ehResult = OC_EH_OK;\r
107     response.payload = (OCPayload *) payload;\r
108 \r
109     // Send Response\r
110     if (OCDoResponse(&response) != OC_STACK_OK)\r
111     {\r
112         NS_LOG(ERROR, "Fail to AccessPolicy send response");\r
113         OCRepPayloadDestroy(payload);\r
114         return NS_ERROR;\r
115     }\r
116     OCRepPayloadDestroy(payload);\r
117     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
118 \r
119     NS_LOG(DEBUG, "NSSendAccessPolicyResponse - OUT");\r
120     return NS_OK;\r
121 }\r
122 \r
123 void NSHandleSubscription(OCEntityHandlerRequest *entityHandlerRequest, NSResourceType resourceType)\r
124 {\r
125     NS_LOG(DEBUG, "NSHandleSubscription - IN");\r
126 \r
127     char * copyReq = OICStrdup(entityHandlerRequest->query);\r
128     char * id = NSGetValueFromQuery(copyReq, NS_QUERY_CONSUMER_ID);\r
129 \r
130     if (!id)\r
131     {\r
132         NSOICFree(copyReq);\r
133         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
134         NS_LOG(ERROR, "Invalid ConsumerID");\r
135         return;\r
136     }\r
137 \r
138     NS_LOG_V(INFO_PRIVATE, "consumerId = %s", id);\r
139     if (resourceType == NS_RESOURCE_MESSAGE)\r
140     {\r
141         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_MESSAGE");\r
142         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
143         NS_VERIFY_NOT_NULL_V(element);\r
144         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
145         NS_VERIFY_NOT_NULL_V(subData);\r
146 \r
147         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
148         NS_LOG_V(INFO_PRIVATE, "SubList ID = [%s]", subData->id);\r
149 \r
150         NS_LOG_V(INFO_PRIVATE, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
151 \r
152         subData->remote_messageObId = subData->messageObId = 0;\r
153 \r
154         bool iSRemoteServer = false;\r
155 \r
156 #if(defined WITH_CLOUD)\r
157         iSRemoteServer = NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr);\r
158         if (iSRemoteServer)\r
159         {\r
160             NS_LOG(DEBUG, "Requested by remote server");\r
161             subData->remote_messageObId = entityHandlerRequest->obsInfo.obsId;\r
162             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->remote_messageObId);\r
163         }\r
164 #endif\r
165 \r
166         if (!iSRemoteServer)\r
167         {\r
168             NS_LOG(DEBUG, "Requested by local consumer");\r
169             subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
170             NS_LOG_V(DEBUG, "SubList message observation ID = [%d]", subData->messageObId);\r
171         }\r
172 \r
173         subData->isWhite = false;\r
174         subData->remote_syncObId = 0;\r
175         subData->syncObId = 0;\r
176 \r
177         element->data = (void*) subData;\r
178         element->next = NULL;\r
179 \r
180         if (NSProviderStorageWrite(consumerSubList, element) != NS_OK)\r
181         {\r
182             NS_LOG(DEBUG, "fail to write cache");\r
183         }\r
184 \r
185         bool currPolicy = NSGetPolicy();\r
186         NSAskAcceptanceToUser(NSCopyOCEntityHandlerRequest(entityHandlerRequest));\r
187 \r
188         if (currPolicy == NS_POLICY_PROVIDER)\r
189         {\r
190             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_PROVIDER");\r
191         }\r
192         else if (currPolicy == NS_POLICY_CONSUMER)\r
193         {\r
194             NS_LOG(DEBUG, "NSGetSubscriptionAccepter == NS_ACCEPTER_CONSUMER");\r
195             NSSendConsumerSubResponse(NSCopyOCEntityHandlerRequest(entityHandlerRequest));\r
196         }\r
197 \r
198         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
199     }\r
200     else if (resourceType == NS_RESOURCE_SYNC)\r
201     {\r
202         NS_LOG(DEBUG, "resourceType == NS_RESOURCE_SYNC");\r
203         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
204         NS_VERIFY_NOT_NULL_V(element);\r
205         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
206         NS_VERIFY_NOT_NULL_V(subData);\r
207 \r
208         OICStrcpy(subData->id, UUID_STRING_SIZE, id);\r
209         NS_LOG_V(INFO_PRIVATE, "SubList ID = [%s]", subData->id);\r
210 \r
211         NS_LOG_V(INFO_PRIVATE, "Consumer Address: %s", entityHandlerRequest->devAddr.addr);\r
212 \r
213         subData->remote_syncObId = subData->syncObId = 0;\r
214         bool isRemoteServer = false;\r
215 \r
216 #if (defined WITH_CLOUD)\r
217         isRemoteServer = NSIsRemoteServerAddress(entityHandlerRequest->devAddr.addr);\r
218         if (isRemoteServer)\r
219         {\r
220             NS_LOG(DEBUG, "Requested by remote server");\r
221             subData->remote_syncObId = entityHandlerRequest->obsInfo.obsId;\r
222             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->remote_syncObId);\r
223         }\r
224 #endif\r
225 \r
226         if (!isRemoteServer)\r
227         {\r
228             NS_LOG(DEBUG, "Requested by local consumer");\r
229             subData->syncObId = entityHandlerRequest->obsInfo.obsId;\r
230             NS_LOG_V(DEBUG, "SubList sync observation ID = [%d]", subData->syncObId);\r
231         }\r
232 \r
233         subData->isWhite = false;\r
234         subData->messageObId = 0;\r
235         subData->remote_messageObId = 0;\r
236 \r
237         element->data = (void*) subData;\r
238         element->next = NULL;\r
239 \r
240         if (NS_OK != NSProviderStorageWrite(consumerSubList, element))\r
241         {\r
242             NS_LOG(ERROR, "Fail to write cache");\r
243         }\r
244 \r
245         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
246     }\r
247     NSOICFree(copyReq);\r
248 \r
249     NS_LOG(DEBUG, "NSHandleSubscription - OUT");\r
250 }\r
251 \r
252 void NSHandleUnsubscription(OCEntityHandlerRequest *entityHandlerRequest)\r
253 {\r
254     NS_LOG(DEBUG, "NSHandleUnsubscription - IN");\r
255 \r
256     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER_OBSERVE_ID;\r
257 \r
258     while (NSProviderStorageDelete(consumerSubList, (char *)\r
259             &(entityHandlerRequest->obsInfo.obsId)) != NS_FAIL);\r
260 \r
261     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER;\r
262     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
263     NS_LOG(DEBUG, "NSHandleUnsubscription - OUT");\r
264 }\r
265 \r
266 void NSAskAcceptanceToUser(OCEntityHandlerRequest *entityHandlerRequest)\r
267 {\r
268     NS_LOG(DEBUG, "NSAskAcceptanceToUser - IN");\r
269 \r
270     NSPushQueue(CALLBACK_RESPONSE_SCHEDULER, TASK_CB_SUBSCRIPTION, entityHandlerRequest);\r
271 \r
272     NS_LOG(DEBUG, "NSAskAcceptanceToUser - OUT");\r
273 }\r
274 \r
275 NSResult NSSendResponse(const char * id, bool accepted)\r
276 {\r
277     NS_LOG(DEBUG, "NSSendResponse - IN");\r
278 \r
279     OCRepPayload* payload = OCRepPayloadCreate();\r
280     if (!payload)\r
281     {\r
282         NS_LOG(ERROR, "fail to create playload");\r
283         return NS_ERROR;\r
284     }\r
285 \r
286     OCResourceHandle rHandle = NULL;\r
287     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
288     {\r
289         NS_LOG(ERROR, "Fail to put notification resource");\r
290         return NS_ERROR;\r
291     }\r
292 \r
293     OCRepPayloadSetUri(payload, NS_COLLECTION_MESSAGE_URI);\r
294     (accepted) ? OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_ALLOW)\r
295         : OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_DENY);\r
296     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
297 \r
298     NSCacheElement * element = NSProviderStorageRead(consumerSubList, id);\r
299 \r
300     if (element == NULL)\r
301     {\r
302         NS_LOG(ERROR, "element is NULL");\r
303         return NS_ERROR;\r
304     }\r
305 \r
306     NSCacheSubData * subData = (NSCacheSubData*) element->data;\r
307 \r
308     if (OCNotifyListOfObservers(rHandle, (OCObservationId*)&subData->messageObId, 1,\r
309             payload, OC_LOW_QOS) != OC_STACK_OK)\r
310     {\r
311         NS_LOG(ERROR, "fail to send Acceptance");\r
312         OCRepPayloadDestroy(payload);\r
313         return NS_ERROR;\r
314 \r
315     }\r
316 \r
317     OCRepPayloadDestroy(payload);\r
318     NS_LOG(DEBUG, "NSSendResponse - OUT");\r
319     return NS_OK;\r
320 }\r
321 \r
322 NSResult NSSendConsumerSubResponse(OCEntityHandlerRequest * entityHandlerRequest)\r
323 {\r
324     NS_LOG(DEBUG, "NSSendSubscriptionResponse - IN");\r
325 \r
326     if (!entityHandlerRequest)\r
327     {\r
328         NS_LOG(ERROR, "Invalid request pointer");\r
329         return NS_ERROR;\r
330     }\r
331 \r
332     char * copyReq = OICStrdup(entityHandlerRequest->query);\r
333     char * id = NSGetValueFromQuery(copyReq, NS_QUERY_CONSUMER_ID);\r
334 \r
335     if (!id)\r
336     {\r
337         NSOICFree(copyReq);\r
338         NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
339         NS_LOG(ERROR, "Invalid ConsumerID");\r
340         return NS_ERROR;\r
341     }\r
342 \r
343     NSCacheUpdateSubScriptionState(consumerSubList, id, true);\r
344     NSSendResponse(id, true);\r
345     NSOICFree(copyReq);\r
346     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
347     NS_LOG(DEBUG, "NSSendSubscriptionResponse - OUT");\r
348     return NS_OK;\r
349 }\r
350 \r
351 #ifdef WITH_MQ\r
352 void NSProviderMQSubscription(NSMQTopicAddress * topicAddr)\r
353 {\r
354     char * serverUri = topicAddr->serverAddr;\r
355     char * topicName = topicAddr->topicName;\r
356 \r
357     NS_LOG_V(DEBUG, "input Topic Name2 : %s", topicAddr->topicName);\r
358 \r
359     OCDevAddr * addr = NSChangeAddress(serverUri);\r
360     OCCallbackData cbdata = { NULL, NULL, NULL };\r
361     cbdata.cb = NSProviderGetMQResponseCB;\r
362     cbdata.context = OICStrdup(topicName);\r
363     cbdata.cd = NSOICFree;\r
364 \r
365     char requestUri[100] = "coap+tcp://";\r
366 \r
367     NS_LOG_V(DEBUG, "requestUri1 = %s", requestUri);\r
368     OICStrcat(requestUri, strlen(requestUri)+strlen(serverUri)+1, serverUri);\r
369     NS_LOG_V(DEBUG, "requestUri2 = %s", requestUri);\r
370     OICStrcat(requestUri, strlen(requestUri)+ strlen("/oic/ps") + 1, "/oic/ps");\r
371     NS_LOG_V(DEBUG, "requestUri3 = %s", requestUri);\r
372     OCStackResult ret = OCDoResource(NULL, OC_REST_GET, requestUri, addr,\r
373                                      NULL, CT_DEFAULT, OC_HIGH_QOS, &cbdata, NULL, 0);\r
374 \r
375     NSOCResultToSuccess(ret);\r
376 \r
377     NSOICFree(topicAddr->serverAddr);\r
378     NSOICFree(topicAddr->topicName);\r
379     NSOICFree(topicAddr);\r
380 }\r
381 #endif\r
382 \r
383 void * NSSubScriptionSchedule(void *ptr)\r
384 {\r
385     if (ptr == NULL)\r
386     {\r
387         NS_LOG(DEBUG, "Create NSSubScriptionSchedule");\r
388     }\r
389 \r
390     while (NSIsRunning[SUBSCRIPTION_SCHEDULER])\r
391     {\r
392         sem_wait(&NSSemaphore[SUBSCRIPTION_SCHEDULER]);\r
393         pthread_mutex_lock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
394 \r
395         if (NSHeadMsg[SUBSCRIPTION_SCHEDULER] != NULL)\r
396         {\r
397             NSTask *node = NSHeadMsg[SUBSCRIPTION_SCHEDULER];\r
398             NSHeadMsg[SUBSCRIPTION_SCHEDULER] = node->nextTask;\r
399 \r
400             switch (node->taskType)\r
401             {\r
402                 case TASK_SEND_POLICY:\r
403                     NS_LOG(DEBUG, "CASE TASK_SEND_POLICY : ");\r
404                     NSSendAccessPolicyResponse((OCEntityHandlerRequest*) node->taskData);\r
405                     break;\r
406 \r
407                 case TASK_RECV_SUBSCRIPTION:\r
408                     NS_LOG(DEBUG, "CASE TASK_RECV_SUBSCRIPTION : ");\r
409                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
410                             NS_RESOURCE_MESSAGE);\r
411                     break;\r
412 \r
413                 case TASK_RECV_UNSUBSCRIPTION:\r
414                     NS_LOG(DEBUG, "CASE TASK_RECV_UNSUBSCRIPTION : ");\r
415                     NSHandleUnsubscription((OCEntityHandlerRequest*) node->taskData);\r
416                     break;\r
417 \r
418                 case TASK_SEND_ALLOW:\r
419                 {\r
420                     NS_LOG(DEBUG, "CASE TASK_SEND_ALLOW : ");\r
421                     char * consumerId = (char *) node->taskData;\r
422 \r
423                     NSCacheUpdateSubScriptionState(consumerSubList, consumerId, true);\r
424                     NSSendResponse(consumerId, true);\r
425                     NSOICFree(consumerId);\r
426                     break;\r
427                 }\r
428                 case TASK_SEND_DENY:\r
429                 {\r
430                     NS_LOG(DEBUG, "CASE TASK_SEND_DENY : ");\r
431                     char * consumerId = (char *) node->taskData;\r
432 \r
433                     NSCacheUpdateSubScriptionState(consumerSubList, consumerId, false);\r
434                     NSSendResponse(consumerId, false);\r
435                     NSOICFree(consumerId);\r
436 \r
437                     break;\r
438                 }\r
439                 case TASK_SYNC_SUBSCRIPTION:\r
440                     NS_LOG(DEBUG, "CASE TASK_SYNC_SUBSCRIPTION : ");\r
441                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
442                             NS_RESOURCE_SYNC);\r
443                     break;\r
444 #ifdef WITH_MQ\r
445                 case TASK_MQ_REQ_SUBSCRIBE:\r
446                     NS_LOG(DEBUG, "CASE TASK_MQ_REQ_SUBSCRIBE : ");\r
447                     NSProviderMQSubscription((NSMQTopicAddress*) node->taskData);\r
448                     break;\r
449 #endif\r
450                 default:\r
451                     break;\r
452 \r
453             }\r
454             NSOICFree(node);\r
455         }\r
456 \r
457         pthread_mutex_unlock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
458 \r
459     }\r
460     NS_LOG(INFO, "Destroy NSSubScriptionSchedule");\r
461     return NULL;\r
462 }\r