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