added cacheadapter interface and memorycache of notification.
[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     consumerSubList = NSCacheCreate();\r
26     consumerSubList->cacheType = NS_PROVIDER_CACHE_SUBSCRIBER;\r
27     return NS_OK;\r
28 }\r
29 \r
30 NSResult NSSetSubscriptionAcceptPolicy(NSAccessPolicy policy)\r
31 {\r
32     if (policy == NS_ACCEPTER_PROVIDER)\r
33     {\r
34         OIC_LOG(INFO, SUBSCRIPTION_TAG, "Place Provider as a subscription accepter");\r
35     }\r
36     else if (policy == NS_ACCEPTER_CONSUMER)\r
37     {\r
38         OIC_LOG(INFO, SUBSCRIPTION_TAG, "Place Consumer as a subscription accepter");\r
39     }\r
40 \r
41     NSSubscriptionAccepter = policy;\r
42 \r
43     return NS_OK;\r
44 }\r
45 \r
46 int NSGetSubscriptionAccepter()\r
47 {\r
48     return NSSubscriptionAccepter;\r
49 }\r
50 \r
51 NSResult NSSendAccessPolicyResponse(OCEntityHandlerRequest *entityHandlerRequest)\r
52 {\r
53     OIC_LOG(DEBUG, NOTIFICATION_TAG, "Send Notification Policy to consumer");\r
54 \r
55     // put notification resource\r
56     OCResourceHandle notificationResourceHandle;\r
57     if (NSPutNotificationResource(NSGetSubscriptionAccepter(), &notificationResourceHandle)\r
58             != NS_OK)\r
59     {\r
60         OIC_LOG(ERROR, SUBSCRIPTION_TAG, PCF("Failed to put notification resource"));\r
61         return NS_ERROR;\r
62     }\r
63 \r
64     // make response for the Get Request\r
65     OCEntityHandlerResponse response;\r
66     response.numSendVendorSpecificHeaderOptions = 0;\r
67     memset(response.sendVendorSpecificHeaderOptions, 0,\r
68             sizeof response.sendVendorSpecificHeaderOptions);\r
69     memset(response.resourceUri, 0, sizeof response.resourceUri);\r
70 \r
71     OCRepPayload* payload = OCRepPayloadCreate();\r
72     //response.payload = OCRepPayloadCreate();\r
73     if (!payload)\r
74     {\r
75         OIC_LOG(ERROR, SUBSCRIPTION_TAG, PCF("Failed to allocate Payload"));\r
76         return NS_ERROR;\r
77     }\r
78 \r
79     OCRepPayloadSetUri(payload, NSGetNotificationUri());\r
80     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_POLICY, NSGetSubscriptionAccepter());\r
81     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_MESSAGE, NSGetNotificationMessageUri());\r
82     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_SYNC, NSGetNotificationSyncUri());\r
83 \r
84     response.requestHandle = entityHandlerRequest->requestHandle;\r
85     response.resourceHandle = entityHandlerRequest->resource;\r
86     response.persistentBufferFlag = 0;\r
87     response.ehResult = OC_EH_OK;\r
88     response.payload = (OCPayload *) payload;\r
89 \r
90     // Send Response\r
91     if (OCDoResponse(&response) != OC_STACK_OK)\r
92     {\r
93         OIC_LOG(ERROR, SUBSCRIPTION_TAG, PCF("Fail to send response"));\r
94         return NS_ERROR;\r
95     }\r
96     OCRepPayloadDestroy(payload);\r
97 \r
98     return NS_OK;\r
99 }\r
100 \r
101 void NSHandleSubscription(OCEntityHandlerRequest *entityHandlerRequest, NSResourceType resourceType)\r
102 {\r
103 \r
104     OIC_LOG(INFO, SUBSCRIPTION_TAG, "Start to subscription process");\r
105 \r
106     printf("state = 0 \n");\r
107 \r
108     // write consumer info to cache\r
109 \r
110     if (resourceType == NS_RESOURCE_MESSAGE)\r
111     {\r
112         int obId = entityHandlerRequest->obsInfo.obsId;\r
113 \r
114         NSCacheElement * element = (NSCacheElement *) malloc(sizeof(NSCacheElement));\r
115 \r
116         NSCacheSubData * subData = (NSCacheSubData *) malloc(sizeof(NSCacheSubData));\r
117         subData->id = OICStrdup(entityHandlerRequest->devAddr.addr);\r
118         subData->isWhite = false;\r
119         subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
120         subData->syncObId = 0;\r
121 \r
122         element->data = (void*) subData;\r
123         element->next = NULL;\r
124 \r
125         printf("NS_ message ob Id = %d\n", subData->messageObId);\r
126 \r
127         if (NSCacheWrite(consumerSubList, element) != NS_OK)\r
128         {\r
129             printf("Cache Write Error\n");\r
130         }\r
131 \r
132         if (NSGetSubscriptionAccepter() == NS_ACCEPTER_PROVIDER)\r
133         {\r
134             // OCDevAddr --> NSConsumer\r
135             printf("before NSGetSubscriptionAccepter() == NS_ACCEPTER_PROVIDER)\n");\r
136             NSAskAcceptanceToUser(entityHandlerRequest);\r
137             printf("After NSGetSubscriptionAccepter() == NS_ACCEPTER_PROVIDER)\n");\r
138         }\r
139         else if (NSGetSubscriptionAccepter() == NS_ACCEPTER_CONSUMER)\r
140         {\r
141             printf("state = 0 - 3\n");\r
142             NSSendSubscriptionResponse(entityHandlerRequest, NS_ACCEPTER_CONSUMER, true);\r
143         }\r
144     }\r
145     else if (resourceType == NS_RESOURCE_SYNC)\r
146     {\r
147         int obId = entityHandlerRequest->obsInfo.obsId;\r
148 \r
149         NSCacheElement * element = (NSCacheElement *) malloc(sizeof(NSCacheElement));\r
150 \r
151         NSCacheSubData * subData = (NSCacheSubData *) malloc(sizeof(NSCacheSubData));\r
152         printf("NS_ entityHandlerRequest->devAddr.addr = %s\n", entityHandlerRequest->devAddr.addr);\r
153         subData->id = OICStrdup(entityHandlerRequest->devAddr.addr);\r
154         subData->isWhite = false;\r
155         subData->syncObId = entityHandlerRequest->obsInfo.obsId;\r
156         subData->messageObId = 0;\r
157 \r
158         element->data = (void*) subData;\r
159         element->next = NULL;\r
160 \r
161         printf("NS_ sync ob Id = %d\n", subData->syncObId);\r
162 \r
163         if (NSCacheWrite(consumerSubList, element) != NS_OK)\r
164         {\r
165             printf("Cache Write Error\n");\r
166         }\r
167     }\r
168 }\r
169 \r
170 void NSHandleUnsubscription(OCEntityHandlerRequest *entityHandlerRequest)\r
171 {\r
172     OIC_LOG(INFO, SUBSCRIPTION_TAG, "Start to unsubscription process");\r
173 \r
174     // ProcessObserveUnregister (entityHandlerRequest);\r
175 \r
176     // write consumer info to cache\r
177     int obId = entityHandlerRequest->obsInfo.obsId;\r
178 \r
179     NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
180     NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
181     subData->id = OICStrdup(entityHandlerRequest->devAddr.addr);\r
182     subData->isWhite = false;\r
183     subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
184 \r
185     element->data = (void*) subData;\r
186     element->next = NULL;\r
187 \r
188     if (NSCacheWrite(consumerSubList, element) != NS_OK)\r
189     {\r
190         OIC_LOG(ERROR, SUBSCRIPTION_TAG, "fail to write consumer white list");\r
191     }\r
192 }\r
193 \r
194 void NSAskAcceptanceToUser(OCEntityHandlerRequest *entityHandlerRequest)\r
195 {\r
196     OIC_LOG(DEBUG, SUBSCRIPTION_TAG, "Ask for user to Allow or Deny");\r
197 \r
198     NSPushQueue(RESPONSE_SCHEDULER, TASK_CB_SUBSCRIPTION, entityHandlerRequest);\r
199     // one queue is required for response callback to ask subscription allowance\r
200 }\r
201 \r
202 NSResult NSSendResponse(const char * id, bool accepted)\r
203 {\r
204 \r
205     OCRepPayload* payload = OCRepPayloadCreate();\r
206     if (!payload)\r
207     {\r
208         OIC_LOG(ERROR, SUBSCRIPTION_TAG, PCF("Failed to allocate Payload"));\r
209         return NS_ERROR;\r
210     }\r
211 \r
212     OCResourceHandle rHandle;\r
213     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
214     {\r
215         OIC_LOG(ERROR, NOTIFICATION_TAG, PCF("Fail to put notification resource"));\r
216         return NS_ERROR;\r
217     }\r
218 \r
219     OCRepPayloadSetUri(payload, NSGetNotificationMessageUri());\r
220     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_ID, "0000-0000-0000-0000");\r
221     OCRepPayloadSetPropBool(payload, NS_ATTRIBUTE_ACCPETANCE, accepted);\r
222 \r
223     NSCacheElement * element = NSCacheRead(consumerSubList, id);\r
224     NSCacheSubData * subData = element->data;\r
225 \r
226     if (OCNotifyListOfObservers(rHandle, &subData->messageObId, 1, payload, OC_HIGH_QOS)\r
227             != OC_STACK_OK)\r
228     {\r
229         OIC_LOG(ERROR, SUBSCRIPTION_TAG, "fail to send Acceptance");\r
230         OCRepPayloadDestroy(payload);\r
231         return NS_ERROR;\r
232 \r
233     }\r
234     OCRepPayloadDestroy(payload);\r
235 \r
236     return NS_OK;\r
237 }\r
238 \r
239 NSResult NSSendSubscriptionResponse(OCEntityHandlerRequest *entityHandlerRequest,\r
240         NSAccessPolicy accepter, bool accepted)\r
241 {\r
242     OIC_LOG(INFO, SUBSCRIPTION_TAG, "Send ACCEPT message to consumer");\r
243 \r
244     if (!entityHandlerRequest)\r
245     {\r
246         OIC_LOG (ERROR, LISTENER_TAG, "Invalid request pointer");\r
247         return OC_EH_ERROR;\r
248     }\r
249 \r
250     // write consumer info to cache\r
251 \r
252     printf("accepted 1 \n");\r
253     if (accepted)\r
254     {\r
255         int obId = entityHandlerRequest->obsInfo.obsId;\r
256 \r
257         NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
258 \r
259         NSCacheSubData * subData = (NSCacheSubData *) OICMalloc(sizeof(NSCacheSubData));\r
260         subData->id = OICStrdup(entityHandlerRequest->devAddr.addr);\r
261         subData->isWhite = true;\r
262         subData->messageObId = entityHandlerRequest->obsInfo.obsId;\r
263 \r
264         element->data = (void*) subData;\r
265         element->next = NULL;\r
266 \r
267         if (NSCacheWrite(consumerSubList, element) != NS_OK)\r
268         {\r
269             OIC_LOG(ERROR, SUBSCRIPTION_TAG, "fail to write consumer white list");\r
270         }\r
271     }\r
272 \r
273     NSSendResponse(&entityHandlerRequest->obsInfo.obsId, accepted);\r
274 \r
275     return NS_OK;\r
276 \r
277 }\r
278 \r
279 void * NSSubScriptionSchedule(void *ptr)\r
280 {\r
281 \r
282     if (ptr == NULL)\r
283     {\r
284         OIC_LOG(INFO, SUBSCRIPTION_TAG, "Create NSSubscriptionSchedule");\r
285     }\r
286 \r
287     while (NSIsRunning[SUBSCRIPTION_SCHEDULER])\r
288     {\r
289         sem_wait(&NSSemaphore[SUBSCRIPTION_SCHEDULER]);\r
290         pthread_mutex_lock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
291 \r
292         if (NSHeadMsg[SUBSCRIPTION_SCHEDULER] != NULL)\r
293         {\r
294             NSTask *node = NSHeadMsg[SUBSCRIPTION_SCHEDULER];\r
295             NSHeadMsg[SUBSCRIPTION_SCHEDULER] = node->nextTask;\r
296 \r
297             switch (node->taskType)\r
298             {\r
299 \r
300                 case TASK_SEND_POLICY:\r
301 \r
302                     NSSendAccessPolicyResponse((OCEntityHandlerRequest*) node->taskData);\r
303                     break;\r
304 \r
305                 case TASK_RECV_SUBSCRIPTION:\r
306                     printf("before TASK_RECV_SUBSCRIPTION:\n");\r
307                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
308                             NS_RESOURCE_MESSAGE);\r
309                     printf("after TASK_RECV_SUBSCRIPTION:\n");\r
310                     break;\r
311 \r
312                 case TASK_RECV_UNSUBSCRIPTION:\r
313 \r
314                     NSHandleUnsubscription((OCEntityHandlerRequest*) node->taskData);\r
315                     break;\r
316 \r
317                 case TASK_SEND_ALLOW:\r
318                 {\r
319                     NSConsumer * consumer = (NSConsumer *) node->taskData;\r
320                     int * pObId = (int *) consumer->mUserData;\r
321 \r
322                     NSCacheSubData * subData = (NSCacheMsgData *) OICMalloc(sizeof(NSCacheSubData));\r
323                     subData->id = OICStrdup(consumer->mId);\r
324                     subData->isWhite = true;\r
325                     subData->messageObId = 0;\r
326                     subData->syncObId = 0;\r
327 \r
328                     NSCacheUpdateSubScriptionState(consumerSubList, subData);\r
329 \r
330                     printf("observer ID = %d\n", *pObId);\r
331 \r
332                     NSSendResponse(consumer->mId, true);\r
333 \r
334                     break;\r
335                 }\r
336                 case TASK_SEND_DENY:\r
337                 {\r
338                     NSConsumer * consumer = (NSConsumer *) node->taskData;\r
339                     int * pObId = (int *) consumer->mUserData;\r
340 \r
341                     NSCacheSubData * subData = (NSCacheMsgData *) OICMalloc(sizeof(NSCacheSubData));\r
342                     subData->id = OICStrdup(consumer->mId);\r
343                     subData->isWhite = false;\r
344                     subData->messageObId = 0;\r
345                     subData->syncObId = 0;\r
346 \r
347                     NSCacheUpdateSubScriptionState(consumerSubList, subData);\r
348                     printf("observer ID = %d\n", *pObId);\r
349                     NSSendResponse(consumer->mId, false);\r
350                     break;\r
351                 }\r
352                 case TASK_SYNC_SUBSCRIPTION:\r
353                     NSHandleSubscription((OCEntityHandlerRequest*) node->taskData,\r
354                             NS_RESOURCE_SYNC);\r
355                     break;\r
356 \r
357             }\r
358             OICFree(node);\r
359         }\r
360 \r
361         pthread_mutex_unlock(&NSMutex[SUBSCRIPTION_SCHEDULER]);\r
362 \r
363     }\r
364     return NULL;\r
365 }\r