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