Add logic for NSIsTopicSubscribed.
[platform/upstream/iotivity.git] / service / notification / src / provider / NSProviderTopic.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 "NSProviderTopic.h"\r
22 \r
23 NSResult NSSendTopicUpdation();\r
24 \r
25 NSResult NSInitTopicList()\r
26 {\r
27     NS_LOG(DEBUG, "NSInitTopicList - IN");\r
28     consumerTopicList = NSStorageCreate();\r
29     consumerTopicList->cacheType = NS_PROVIDER_CACHE_CONSUMER_TOPIC_NAME;\r
30 \r
31     registeredTopicList = NSStorageCreate();\r
32     registeredTopicList->cacheType = NS_PROVIDER_CACHE_REGISTER_TOPIC;\r
33 \r
34     NS_LOG(DEBUG, "NSInitTopicList - OUT");\r
35     return NS_OK;\r
36 }\r
37 \r
38 NSResult NSAddTopics(const char * topicName)\r
39 {\r
40     NS_LOG(DEBUG, "NSWriteTopicsToStorage()");\r
41 \r
42     NSCacheTopicData * data = (NSCacheTopicData *)OICMalloc(sizeof(NSCacheTopicData));\r
43     data->topicName = topicName;\r
44     data->state = NS_TOPIC_UNSUBSCRIBED;\r
45 \r
46     NSCacheElement * element = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
47     element->data = (void *) data;\r
48     element->next = NULL;\r
49 \r
50     if(NSStorageWrite(registeredTopicList, element) != NS_OK)\r
51     {\r
52         NS_LOG(DEBUG, "fail to write cache");\r
53     }\r
54     NSSendTopicUpdation();\r
55 \r
56     NS_LOG(DEBUG, "NSWriteTopicsToStorage() NS_OK");\r
57     return NS_OK;\r
58 }\r
59 \r
60 NSResult NSDeleteTopics(const char * topicName)\r
61 {\r
62     NS_LOG(DEBUG, "NSDeleteTopics()");\r
63 \r
64     if(!topicName)\r
65     {\r
66         NS_LOG(ERROR, "topicName is NULL");\r
67         return NS_ERROR;\r
68     }\r
69 \r
70     NSStorageDelete(registeredTopicList, topicName);\r
71     while(NSStorageDelete(consumerTopicList, topicName) != NS_FAIL);\r
72     return NS_OK;\r
73 }\r
74 \r
75 NSResult NSSendTopicUpdation()\r
76 {\r
77     NS_LOG(DEBUG, "NSSendTopicUpdation - IN");\r
78 \r
79     OCRepPayload* payload = OCRepPayloadCreate();\r
80 \r
81     if (!payload)\r
82     {\r
83         NS_LOG(ERROR, "fail to create playload");\r
84         return NS_ERROR;\r
85     }\r
86 \r
87     OCResourceHandle rHandle = NULL;\r
88     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
89     {\r
90         NS_LOG(ERROR, "Fail to put message resource");\r
91         return NS_ERROR;\r
92     }\r
93 \r
94     OCRepPayloadSetUri(payload, NS_COLLECTION_MESSAGE_URI);\r
95     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_TOPIC);\r
96     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
97 \r
98     OCObservationId obArray[255] = { 0, };\r
99     int obCount = 0;\r
100 \r
101     NSCacheElement * it = consumerSubList->head;\r
102 \r
103     while (it)\r
104     {\r
105         NSCacheSubData * subData = (NSCacheSubData *) it->data;\r
106 \r
107         if (subData->isWhite)\r
108         {\r
109             if(subData->messageObId != 0)\r
110             {\r
111                 obArray[obCount++] = subData->messageObId;\r
112             }\r
113 \r
114 #ifdef WITH_CLOUD\r
115             if(subData->remote_messageObId != 0)\r
116             {\r
117                 obArray[obCount++] = subData->remote_messageObId;\r
118             }\r
119 #endif\r
120 \r
121         }\r
122         it = it->next;\r
123     }\r
124 \r
125     if(!obCount)\r
126     {\r
127         NS_LOG(ERROR, "observer count is zero");\r
128         return NS_ERROR;\r
129     }\r
130 \r
131     if (OCNotifyListOfObservers(rHandle, obArray, obCount, payload, OC_HIGH_QOS)\r
132             != OC_STACK_OK)\r
133     {\r
134         NS_LOG(ERROR, "fail to send topic updation");\r
135         OCRepPayloadDestroy(payload);\r
136         return NS_ERROR;\r
137 \r
138     }\r
139     OCRepPayloadDestroy(payload);\r
140 \r
141     NS_LOG(DEBUG, "NSSendTopicUpdation - OUT");\r
142     return NS_OK;\r
143 }\r
144 \r
145 NSResult NSSendTopicUpdationToConsumer(char *consumerId)\r
146 {\r
147     NS_LOG(DEBUG, "NSSendTopicUpdationToConsumer - IN");\r
148 \r
149     OCRepPayload* payload = OCRepPayloadCreate();\r
150 \r
151     if (!payload)\r
152     {\r
153         NS_LOG(ERROR, "fail to create playload");\r
154         return NS_ERROR;\r
155     }\r
156 \r
157     OCResourceHandle rHandle = NULL;\r
158     if (NSPutMessageResource(NULL, &rHandle) != NS_OK)\r
159     {\r
160         NS_LOG(ERROR, "Fail to put message resource");\r
161         return NS_ERROR;\r
162     }\r
163 \r
164     OCRepPayloadSetUri(payload, NS_COLLECTION_MESSAGE_URI);\r
165     OCRepPayloadSetPropInt(payload, NS_ATTRIBUTE_MESSAGE_ID, NS_TOPIC);\r
166     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_PROVIDER_ID, NSGetProviderInfo()->providerId);\r
167 \r
168     NSCacheElement * element = NSStorageRead(consumerSubList, consumerId);\r
169 \r
170     if(element == NULL)\r
171     {\r
172         NS_LOG(ERROR, "element is NULL");\r
173         return NS_ERROR;\r
174     }\r
175 \r
176     NSCacheSubData * subData = (NSCacheSubData*) element->data;\r
177 \r
178     if (OCNotifyListOfObservers(rHandle, (OCObservationId*)&subData->messageObId, 1, payload, OC_HIGH_QOS)\r
179             != OC_STACK_OK)\r
180     {\r
181         NS_LOG(ERROR, "fail to send topic updation");\r
182         OCRepPayloadDestroy(payload);\r
183         return NS_ERROR;\r
184 \r
185     }\r
186 \r
187     OCRepPayloadDestroy(payload);\r
188 \r
189     NS_LOG(DEBUG, "NSSendTopicUpdationToConsumer - OUT");\r
190     return NS_OK;\r
191 }\r
192 \r
193 NSResult NSSendTopicList(OCEntityHandlerRequest * entityHandlerRequest)\r
194 {\r
195     NS_LOG(DEBUG, "NSSendTopicList - IN");\r
196 \r
197     char * id = NSGetValueFromQuery(OICStrdup(entityHandlerRequest->query), NS_QUERY_CONSUMER_ID);\r
198     NSTopicLL * topics = NULL;\r
199     NSCacheElement * currList = NULL;\r
200 \r
201     if(!id)\r
202     {\r
203         NS_LOG(DEBUG, "Send registered topic list");\r
204         topics = NSProviderGetTopicsCacheData(registeredTopicList);\r
205         currList = registeredTopicList->head;\r
206     }\r
207     else\r
208     {\r
209         NS_LOG(DEBUG, "Send subscribed topic list to consumer");\r
210         topics = NSProviderGetConsumerTopicsCacheData(consumerTopicList, id);\r
211         currList = consumerTopicList->head;\r
212     }\r
213 \r
214     // make response for the Get Request\r
215     OCEntityHandlerResponse response;\r
216     response.numSendVendorSpecificHeaderOptions = 0;\r
217     memset(response.sendVendorSpecificHeaderOptions, 0,\r
218             sizeof response.sendVendorSpecificHeaderOptions);\r
219     memset(response.resourceUri, 0, sizeof response.resourceUri);\r
220 \r
221     OCRepPayload* payload = OCRepPayloadCreate();\r
222     if (!payload)\r
223     {\r
224         NS_LOG(ERROR, "payload is NULL");\r
225         return NS_ERROR;\r
226     }\r
227 \r
228     // set topics to the array of resource property\r
229 \r
230     NSCacheElement * iter = currList;\r
231     size_t dimensionSize = (size_t)NSProviderGetListSize(iter);\r
232 \r
233     if(!dimensionSize)\r
234     {\r
235         return NS_ERROR;\r
236     }\r
237 \r
238     OCRepPayload** payloadTopicArray = (OCRepPayload **) OICMalloc(\r
239             sizeof(OCRepPayload *) * dimensionSize);\r
240 \r
241     size_t dimensions[3] = {dimensionSize, 0, 0};\r
242     for (int i = 0; i < (int)dimensionSize; i++)\r
243     {\r
244         NSTopicLL * topic = (NSTopicLL *) iter->data;\r
245 \r
246         payloadTopicArray[i] = OCRepPayloadCreate();\r
247         OCRepPayloadSetPropString(payloadTopicArray[i], NS_ATTRIBUTE_TOPIC_NAME, topic->topicName);\r
248         OCRepPayloadSetPropInt(payloadTopicArray[i], NS_ATTRIBUTE_TOPIC_SELECTION,\r
249                 (int)topic->state);\r
250 \r
251         iter = iter->next;\r
252     }\r
253 \r
254     OCRepPayloadSetUri(payload, NS_COLLECTION_TOPIC_URI);\r
255     OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_CONSUMER_ID, id);\r
256     OCRepPayloadSetPropObjectArray(payload, NS_ATTRIBUTE_TOPIC_LIST,\r
257             (const OCRepPayload**)(payloadTopicArray), dimensions);\r
258 \r
259     response.requestHandle = entityHandlerRequest->requestHandle;\r
260     response.resourceHandle = entityHandlerRequest->resource;\r
261     response.persistentBufferFlag = 0;\r
262     response.ehResult = OC_EH_OK;\r
263     response.payload = (OCPayload *) payload;\r
264 \r
265     if (OCDoResponse(&response) != OC_STACK_OK)\r
266     {\r
267         NS_LOG(ERROR, "Fail to response topic list");\r
268         return NS_ERROR;\r
269     }\r
270     OCRepPayloadDestroy(payload);\r
271     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
272 \r
273     NS_LOG(DEBUG, "NSSendTopicList - OUT");\r
274     return NS_OK;\r
275 }\r
276 \r
277 bool NSIsTopicSubscribed(char * consumerId, char * topic)\r
278 {\r
279     return NSProviderIsTopicSubScribed(consumerTopicList->head, consumerId, topic);\r
280 }\r
281 \r
282 NSResult NSPostConsumerTopics(OCEntityHandlerRequest * entityHandlerRequest)\r
283 {\r
284     NS_LOG(DEBUG, "NSPostConsumerTopics() - IN");\r
285 \r
286     char * consumerId = NULL;\r
287     OCRepPayload * payload = entityHandlerRequest->payload;\r
288     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_CONSUMER_ID, &consumerId);\r
289 \r
290     if(!consumerId)\r
291     {\r
292         NS_LOG(DEBUG, "Invalid consumer ID");\r
293         return NS_ERROR;\r
294     }\r
295 \r
296     OCRepPayload ** topicListPayload = NULL;\r
297     OCRepPayloadValue * payloadValue = NULL;\r
298     payloadValue = NSPayloadFindValue(payload, NS_ATTRIBUTE_TOPIC_LIST);\r
299     size_t dimensionSize = calcDimTotal(payloadValue->arr.dimensions);\r
300     size_t dimensions[3] = {dimensionSize, 0, 0};\r
301     OCRepPayloadGetPropObjectArray(payload, NS_ATTRIBUTE_TOPIC_LIST, & topicListPayload, dimensions);\r
302 \r
303     for(int i = 0; i <(int)dimensionSize; i++)\r
304     {\r
305         char * topicName = NULL;\r
306         int topicState = 0;\r
307 \r
308         OCRepPayloadGetPropString(topicListPayload[i], NS_ATTRIBUTE_TOPIC_NAME, &topicName);\r
309         OCRepPayloadGetPropInt(topicListPayload[i], NS_ATTRIBUTE_TOPIC_SELECTION, &topicState);\r
310         NS_LOG_V(DEBUG, "Topic Name(state):  %s(%d)", topicName, topicState);\r
311 \r
312         if(NS_TOPIC_SUBSCRIBED == (NSTopicState)topicState)\r
313         {\r
314             NSCacheTopicSubData * topicSubData =\r
315             (NSCacheTopicSubData *) OICMalloc(sizeof(NSCacheTopicSubData));\r
316 \r
317             OICStrcpy(topicSubData->id, NS_UUID_STRING_SIZE, consumerId);\r
318             topicSubData->topicName = OICStrdup(topicName);\r
319 \r
320             NSCacheElement * newObj = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
321             newObj->data = (NSCacheData *) topicSubData;\r
322             newObj->next = NULL;\r
323             NSStorageWrite(consumerTopicList, newObj);\r
324         }\r
325     }\r
326 \r
327     NS_LOG(DEBUG, "NSPostConsumerTopics() - OUT");\r
328     return NS_OK;\r
329 }\r
330 \r
331 void * NSTopicSchedule(void * ptr)\r
332 {\r
333     if (ptr == NULL)\r
334     {\r
335         NS_LOG(DEBUG, "Create NSTopicSchedule");\r
336     }\r
337 \r
338     while (NSIsRunning[TOPIC_SCHEDULER])\r
339     {\r
340         sem_wait(&NSSemaphore[TOPIC_SCHEDULER]);\r
341         pthread_mutex_lock(&NSMutex[TOPIC_SCHEDULER]);\r
342 \r
343         if (NSHeadMsg[TOPIC_SCHEDULER] != NULL)\r
344         {\r
345             NSTask *node = NSHeadMsg[TOPIC_SCHEDULER];\r
346             NSHeadMsg[TOPIC_SCHEDULER] = node->nextTask;\r
347 \r
348             switch (node->taskType)\r
349             {\r
350                 case TASK_SEND_TOPICS:\r
351                     NS_LOG(DEBUG, "CASE TASK_SEND_TOPICS : ");\r
352                     NSSendTopicList((OCEntityHandlerRequest*) node->taskData);\r
353                     break;\r
354                 case TASK_SUBSCRIBE_TOPIC:\r
355                     NS_LOG(DEBUG, "CASE TASK_SUBSCRIBE_TOPIC : ");\r
356                     NSCacheElement * newObj = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
357                     newObj->data = node->taskData;\r
358                     newObj->next = NULL;\r
359                     NSStorageWrite(consumerTopicList, newObj);\r
360                     break;\r
361                 case TASK_UNSUBSCRIBE_TOPIC:\r
362                     consumerTopicList->cacheType = NS_PROVIDER_CACHE_CONSUMER_TOPIC_CID;\r
363                     NSStorageDelete(consumerTopicList, (const char *) node->taskData);\r
364                     consumerTopicList->cacheType = NS_PROVIDER_CACHE_CONSUMER_TOPIC_NAME;\r
365                     OICFree((char *)node->taskData);\r
366                     break;\r
367                 case TASK_ADD_TOPIC:\r
368                 {\r
369                     NS_LOG(DEBUG, "CASE TASK_ADD_TOPIC : ");\r
370                     NSAddTopics((const char *) node->taskData);\r
371                 }\r
372                     break;\r
373                 case TASK_DELETE_TOPIC:\r
374                 {\r
375                     NS_LOG(DEBUG, "CASE_TASK_DELETE_TOPIC : ");\r
376                     NSDeleteTopics((const char *) node->taskData);\r
377                 }\r
378                     break;\r
379                 case TASK_POST_TOPIC:\r
380                 {\r
381                     NS_LOG(DEBUG, "TASK_POST_TOPIC : ");\r
382                     NSPostConsumerTopics((OCEntityHandlerRequest*) node->taskData);\r
383                 }\r
384                     break;\r
385                 default:\r
386                     break;\r
387             }\r
388 \r
389             OICFree(node);\r
390         }\r
391 \r
392         pthread_mutex_unlock(&NSMutex[TOPIC_SCHEDULER]);\r
393     }\r
394 \r
395     NS_LOG(DEBUG, "Destroy NSTopicSchedule");\r
396     return NULL;\r
397 }\r