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