Modify for Related Topic.
[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     if(!currList)\r
215     {\r
216         NS_LOG(DEBUG, "currList is NULL");\r
217         return NS_ERROR;\r
218     }\r
219 \r
220     // make response for the Get Request\r
221     OCEntityHandlerResponse response;\r
222     response.numSendVendorSpecificHeaderOptions = 0;\r
223     memset(response.sendVendorSpecificHeaderOptions, 0,\r
224             sizeof response.sendVendorSpecificHeaderOptions);\r
225     memset(response.resourceUri, 0, sizeof response.resourceUri);\r
226 \r
227     OCRepPayload* payload = OCRepPayloadCreate();\r
228     if (!payload)\r
229     {\r
230         NS_LOG(ERROR, "payload is NULL");\r
231         return NS_ERROR;\r
232     }\r
233 \r
234     // set topics to the array of resource property\r
235 \r
236     NSCacheElement * iter = currList;\r
237     size_t dimensionSize = (size_t)NSProviderGetListSize(iter);\r
238 \r
239     NS_LOG_V(DEBUG, "dimensionSize = %d", dimensionSize);\r
240 \r
241     if(!dimensionSize)\r
242     {\r
243         return NS_ERROR;\r
244     }\r
245 \r
246     OCRepPayload** payloadTopicArray = (OCRepPayload **) OICMalloc(\r
247             sizeof(OCRepPayload *) * dimensionSize);\r
248 \r
249     size_t dimensions[3] = {dimensionSize, 0, 0};\r
250     for (int i = 0; i < (int)dimensionSize; i++)\r
251     {\r
252         NSTopicLL * topic = (NSTopicLL *) iter->data;\r
253 \r
254         NS_LOG_V(DEBUG, "topicName = %s", topic->topicName);\r
255         NS_LOG_V(DEBUG, "topicState = %d",(int) topic->state);\r
256 \r
257         payloadTopicArray[i] = OCRepPayloadCreate();\r
258         OCRepPayloadSetPropString(payloadTopicArray[i], NS_ATTRIBUTE_TOPIC_NAME, topic->topicName);\r
259         OCRepPayloadSetPropInt(payloadTopicArray[i], NS_ATTRIBUTE_TOPIC_SELECTION,\r
260                 (int)topic->state);\r
261 \r
262         iter = iter->next;\r
263     }\r
264 \r
265     OCRepPayloadSetUri(payload, NS_COLLECTION_TOPIC_URI);\r
266     if(id)\r
267     {\r
268         OCRepPayloadSetPropString(payload, NS_ATTRIBUTE_CONSUMER_ID, id);\r
269     }\r
270     OCRepPayloadSetPropObjectArray(payload, NS_ATTRIBUTE_TOPIC_LIST,\r
271             (const OCRepPayload**)(payloadTopicArray), dimensions);\r
272 \r
273     response.requestHandle = entityHandlerRequest->requestHandle;\r
274     response.resourceHandle = entityHandlerRequest->resource;\r
275     response.persistentBufferFlag = 0;\r
276     response.ehResult = OC_EH_OK;\r
277     response.payload = (OCPayload *) payload;\r
278 \r
279     if (OCDoResponse(&response) != OC_STACK_OK)\r
280     {\r
281         NS_LOG(ERROR, "Fail to response topic list");\r
282         return NS_ERROR;\r
283     }\r
284     OCRepPayloadDestroy(payload);\r
285     NSFreeOCEntityHandlerRequest(entityHandlerRequest);\r
286 \r
287     NS_LOG(DEBUG, "NSSendTopicList - OUT");\r
288     return NS_OK;\r
289 }\r
290 \r
291 NSResult NSPostConsumerTopics(OCEntityHandlerRequest * entityHandlerRequest)\r
292 {\r
293     NS_LOG(DEBUG, "NSPostConsumerTopics() - IN");\r
294 \r
295     char * consumerId = NULL;\r
296     OCRepPayload * payload = entityHandlerRequest->payload;\r
297     OCRepPayloadGetPropString(payload, NS_ATTRIBUTE_CONSUMER_ID, &consumerId);\r
298 \r
299     if(!consumerId)\r
300     {\r
301         NS_LOG(DEBUG, "Invalid consumer ID");\r
302         return NS_ERROR;\r
303     }\r
304 \r
305     OCRepPayload ** topicListPayload = NULL;\r
306     OCRepPayloadValue * payloadValue = NULL;\r
307     payloadValue = NSPayloadFindValue(payload, NS_ATTRIBUTE_TOPIC_LIST);\r
308     size_t dimensionSize = calcDimTotal(payloadValue->arr.dimensions);\r
309     size_t dimensions[3] = {dimensionSize, 0, 0};\r
310     OCRepPayloadGetPropObjectArray(payload, NS_ATTRIBUTE_TOPIC_LIST, & topicListPayload, dimensions);\r
311 \r
312     for(int i = 0; i <(int)dimensionSize; i++)\r
313     {\r
314         char * topicName = NULL;\r
315         int topicState = 0;\r
316 \r
317         OCRepPayloadGetPropString(topicListPayload[i], NS_ATTRIBUTE_TOPIC_NAME, &topicName);\r
318         OCRepPayloadGetPropInt(topicListPayload[i], NS_ATTRIBUTE_TOPIC_SELECTION, &topicState);\r
319         NS_LOG_V(DEBUG, "Topic Name(state):  %s(%d)", topicName, topicState);\r
320 \r
321         if(NS_TOPIC_SUBSCRIBED == (NSTopicState)topicState)\r
322         {\r
323             NSCacheTopicSubData * topicSubData =\r
324             (NSCacheTopicSubData *) OICMalloc(sizeof(NSCacheTopicSubData));\r
325 \r
326             OICStrcpy(topicSubData->id, NS_UUID_STRING_SIZE, consumerId);\r
327             topicSubData->topicName = OICStrdup(topicName);\r
328 \r
329             NSCacheElement * newObj = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
330             newObj->data = (NSCacheData *) topicSubData;\r
331             newObj->next = NULL;\r
332             NSStorageWrite(consumerTopicList, newObj);\r
333         }\r
334     }\r
335 \r
336     NS_LOG(DEBUG, "NSPostConsumerTopics() - OUT");\r
337     return NS_OK;\r
338 }\r
339 \r
340 void * NSTopicSchedule(void * ptr)\r
341 {\r
342     if (ptr == NULL)\r
343     {\r
344         NS_LOG(DEBUG, "Create NSTopicSchedule");\r
345     }\r
346 \r
347     while (NSIsRunning[TOPIC_SCHEDULER])\r
348     {\r
349         sem_wait(&NSSemaphore[TOPIC_SCHEDULER]);\r
350         pthread_mutex_lock(&NSMutex[TOPIC_SCHEDULER]);\r
351 \r
352         if (NSHeadMsg[TOPIC_SCHEDULER] != NULL)\r
353         {\r
354             NSTask *node = NSHeadMsg[TOPIC_SCHEDULER];\r
355             NSHeadMsg[TOPIC_SCHEDULER] = node->nextTask;\r
356 \r
357             switch (node->taskType)\r
358             {\r
359                 case TASK_SEND_TOPICS:\r
360                     NS_LOG(DEBUG, "CASE TASK_SEND_TOPICS : ");\r
361                     NSSendTopicList((OCEntityHandlerRequest*) node->taskData);\r
362                     break;\r
363                 case TASK_SUBSCRIBE_TOPIC:\r
364                     NS_LOG(DEBUG, "CASE TASK_SUBSCRIBE_TOPIC : ");\r
365                     NSCacheElement * newObj = (NSCacheElement *) OICMalloc(sizeof(NSCacheElement));\r
366                     newObj->data = node->taskData;\r
367                     newObj->next = NULL;\r
368                     NSStorageWrite(consumerTopicList, newObj);\r
369                     break;\r
370                 case TASK_UNSUBSCRIBE_TOPIC:\r
371                     NS_LOG(DEBUG, "CASE TASK_SUBSCRIBE_TOPIC : ");\r
372                     NSProviderDeleteConsumerTopic(consumerTopicList,\r
373                             (NSCacheTopicSubData *) node->taskData);\r
374                     NS_LOG(DEBUG, "CASE TASK_SUBSCRIBE_TOPIC AFter: ");\r
375                     break;\r
376                 case TASK_ADD_TOPIC:\r
377                 {\r
378                     NS_LOG(DEBUG, "CASE TASK_ADD_TOPIC : ");\r
379                     NSAddTopics((const char *) node->taskData);\r
380                 }\r
381                     break;\r
382                 case TASK_DELETE_TOPIC:\r
383                 {\r
384                     NS_LOG(DEBUG, "CASE_TASK_DELETE_TOPIC : ");\r
385                     NSDeleteTopics((const char *) node->taskData);\r
386                 }\r
387                     break;\r
388                 case TASK_POST_TOPIC:\r
389                 {\r
390                     NS_LOG(DEBUG, "TASK_POST_TOPIC : ");\r
391                     NSPostConsumerTopics((OCEntityHandlerRequest*) node->taskData);\r
392                 }\r
393                     break;\r
394                 default:\r
395                     break;\r
396             }\r
397 \r
398             OICFree(node);\r
399         }\r
400 \r
401         pthread_mutex_unlock(&NSMutex[TOPIC_SCHEDULER]);\r
402     }\r
403 \r
404     NS_LOG(DEBUG, "Destroy NSTopicSchedule");\r
405     return NULL;\r
406 }\r