Various patches are applied
[platform/framework/web/data-provider-master.git] / src / notification_service.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <stdio.h>
17
18 #include <Eina.h>
19
20 #include <dlog.h>
21 #include <livebox-errno.h>
22 #include <packet.h>
23
24 #include <notification_ipc.h>
25 #include <notification_noti.h>
26 #include <notification_error.h>
27
28 #include "service_common.h"
29 #include "debug.h"
30 #include "util.h"
31 #include "conf.h"
32
33 #ifndef NOTIFICATION_ADDR
34 #define NOTIFICATION_ADDR "/tmp/.notification.service"
35 #endif
36
37 #ifndef NOTIFICATION_DEL_PACKET_UNIT
38 #define NOTIFICATION_DEL_PACKET_UNIT 10
39 #endif
40
41 static struct info {
42         Eina_List *context_list;
43         struct service_context *svc_ctx;
44 } s_info = {
45         .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
46         .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
47 };
48
49 struct context {
50         struct tcb *tcb;
51         double seq;
52 };
53
54 struct noti_service {
55         const char *cmd;
56         void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
57 };
58
59 /*!
60  * FUNCTIONS to handle notifcation
61  */
62 static inline int get_priv_id(int num_deleted, int *list_deleted, int index) {
63         if (index < num_deleted) {
64                 return *(list_deleted + index);
65         } else {
66                 return -1;
67         }
68 }
69
70 static inline char *get_string(char *string)
71 {
72         if (string == NULL) {
73                 return NULL;
74         }
75         if (string[0] == '\0') {
76                 return NULL;
77         }
78
79         return string;
80 }
81
82 static inline struct packet *create_packet_from_deleted_list(int op_num, int *list, int start_index) {
83         return packet_create(
84                 "del_noti_multiple",
85                 "iiiiiiiiiii",
86                 ((op_num - start_index) > NOTIFICATION_DEL_PACKET_UNIT) ? NOTIFICATION_DEL_PACKET_UNIT : op_num - start_index,
87                 get_priv_id(op_num, list, start_index),
88                 get_priv_id(op_num, list, start_index + 1),
89                 get_priv_id(op_num, list, start_index + 2),
90                 get_priv_id(op_num, list, start_index + 3),
91                 get_priv_id(op_num, list, start_index + 4),
92                 get_priv_id(op_num, list, start_index + 5),
93                 get_priv_id(op_num, list, start_index + 6),
94                 get_priv_id(op_num, list, start_index + 7),
95                 get_priv_id(op_num, list, start_index + 8),
96                 get_priv_id(op_num, list, start_index + 9)
97                 );
98 }
99
100 /*!
101  * SERVICE HANDLER
102  */
103 static void _handler_insert(struct tcb *tcb, struct packet *packet, void *data)
104 {
105         int ret = 0;
106         int priv_id = 0;
107         struct packet *packet_reply = NULL;
108         struct packet *packet_service = NULL;
109         notification_h noti = NULL;
110
111         noti = notification_create(NOTIFICATION_TYPE_NOTI);
112         if (noti != NULL) {
113                 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
114                         ret = notification_noti_insert(noti);
115                         if (ret != NOTIFICATION_ERROR_NONE) {
116                                 ErrPrint("failed to insert a notification\n");
117                                 notification_free(noti);
118                                 return ;
119                         }
120
121                         notification_get_id(noti, NULL, &priv_id);
122                         DbgPrint("priv_id: [%d]\n", priv_id);
123                         packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
124                         if (packet_reply) {
125                                 service_common_unicast_packet(tcb, packet_reply);
126                                 packet_destroy(packet_reply);
127                         }
128
129                         packet_service = notification_ipc_make_packet_from_noti(noti, "add_noti", 2);
130                         if (packet_service != NULL) {
131                                 service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
132                                 packet_destroy(packet_service);
133                         }
134                 } else {
135                         ErrPrint("Failed to create the packet");
136                 }
137                 notification_free(noti);
138         }
139 }
140
141 static void _handler_update(struct tcb *tcb, struct packet *packet, void *data)
142 {
143         int ret = 0;
144         int priv_id = 0;
145         struct packet *packet_reply = NULL;
146         struct packet *packet_service = NULL;
147         notification_h noti = NULL;
148
149         noti = notification_create(NOTIFICATION_TYPE_NOTI);
150         if (noti != NULL) {
151                 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
152                         ret = notification_noti_update(noti);
153                         if (ret != NOTIFICATION_ERROR_NONE) {
154                                 ErrPrint("failed to update a notification\n");
155                                 notification_free(noti);
156                                 return ;
157                         }
158
159                         notification_get_id(noti, NULL, &priv_id);
160                         DbgPrint("priv_id: [%d]\n", priv_id);
161                         packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
162                         if (packet_reply) {
163                                 service_common_unicast_packet(tcb, packet_reply);
164                                 packet_destroy(packet_reply);
165                         }
166
167                         packet_service = notification_ipc_make_packet_from_noti(noti, "update_noti", 2);
168                         if (packet_service != NULL) {
169                                 service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
170                                 packet_destroy(packet_service);
171                         }
172                 } else {
173                         ErrPrint("Failed to create the packet");
174                 }
175                 notification_free(noti);
176         }
177 }
178
179 static void _handler_refresh(struct tcb *tcb, struct packet *packet, void *data)
180 {
181         int ret = NOTIFICATION_ERROR_NONE;
182         struct packet *packet_reply = NULL;
183
184         packet_reply = packet_create_reply(packet, "i", ret);
185         if (packet_reply) {
186                 service_common_unicast_packet(tcb, packet_reply);
187                 packet_destroy(packet_reply);
188         }
189
190         service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE);
191 }
192
193 static void _handler_delete_single(struct tcb *tcb, struct packet *packet, void *data)
194 {
195         int ret = 0;
196         int priv_id = 0;
197         struct packet *packet_reply = NULL;
198         struct packet *packet_service = NULL;
199         char *pkgname = NULL;
200
201         if (packet_get(packet, "si", &pkgname, &priv_id) == 2) {
202                 pkgname = get_string(pkgname);
203
204                 ret = notification_noti_delete_by_priv_id(pkgname, priv_id);
205
206                 DbgPrint("priv_id: [%d]\n", priv_id);
207                 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
208                 if (packet_reply) {
209                         service_common_unicast_packet(tcb, packet_reply);
210                         packet_destroy(packet_reply);
211                 }
212
213                 packet_service = packet_create("del_noti_single", "ii", 1, priv_id);
214                 if (packet_service != NULL) {
215                         service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
216                         packet_destroy(packet_service);
217                 }
218         } else {
219                 ErrPrint("Failed to get data from the packet");
220         }
221 }
222
223 static void _handler_delete_multiple(struct tcb *tcb, struct packet *packet, void *data)
224 {
225         int ret = 0;
226         struct packet *packet_reply = NULL;
227         struct packet *packet_service = NULL;
228         char *pkgname = NULL;
229         notification_type_e type = 0;
230         int num_deleted = 0;
231         int *list_deleted = NULL;
232
233         if (packet_get(packet, "si", &pkgname, &type) == 2) {
234                 pkgname = get_string(pkgname);
235                 DbgPrint("pkgname: [%s] type: [%d]\n", pkgname, type);
236
237                 ret = notification_noti_delete_all(type, pkgname, &num_deleted, &list_deleted);
238                 DbgPrint("ret: [%d] num_deleted: [%d]\n", ret, num_deleted);
239
240                 packet_reply = packet_create_reply(packet, "ii", ret, num_deleted);
241                 if (packet_reply) {
242                         service_common_unicast_packet(tcb, packet_reply);
243                         packet_destroy(packet_reply);
244                 }
245
246                 if (num_deleted > 0) {
247                         if (num_deleted <= NOTIFICATION_DEL_PACKET_UNIT) {
248                                 packet_service = create_packet_from_deleted_list(num_deleted, list_deleted, 0);
249
250                                 if (packet_service) {
251                                         service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
252                                         packet_destroy(packet_service);
253                                 }
254                         } else {
255                                 int set = 0;
256                                 int set_total = num_deleted / NOTIFICATION_DEL_PACKET_UNIT;
257
258                                 for (set = 0; set <= set_total; set++) {
259                                         packet_service = create_packet_from_deleted_list(num_deleted,
260                                                         list_deleted, set * NOTIFICATION_DEL_PACKET_UNIT);
261
262                                         if (packet_service) {
263                                                 service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
264                                                 packet_destroy(packet_service);
265                                         }
266                                 }
267                         }
268                 }
269
270                 if (list_deleted != NULL) {
271                         free(list_deleted);
272                         list_deleted = NULL;
273                 }
274         } else {
275                 ErrPrint("Failed to get data from the packet");
276         }
277 }
278
279 static void _handler_service_register(struct tcb *tcb, struct packet *packet, void *data)
280 {
281         struct packet *packet_reply;
282         int ret;
283
284         ret = tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
285
286         packet_reply = packet_create_reply(packet, "i", ret);
287         if (packet_reply) {
288                 service_common_unicast_packet(tcb, packet_reply);
289                 packet_destroy(packet_reply);
290         }
291 }
292
293 /*!
294  * SERVICE THREAD
295  */
296 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
297 {
298         int i = 0;
299         const char *command;
300         static struct noti_service service_req_table[] = {
301                 {
302                         .cmd = "add_noti",
303                         .handler = _handler_insert,
304                 },
305                 {
306                         .cmd = "update_noti",
307                         .handler = _handler_update,
308                 },
309                 {
310                         .cmd = "refresh_noti",
311                         .handler = _handler_refresh,
312                 },
313                 {
314                         .cmd = "del_noti_single",
315                         .handler = _handler_delete_single,
316                 },
317                 {
318                         .cmd = "del_noti_multiple",
319                         .handler = _handler_delete_multiple,
320                 },
321                 {
322                         .cmd = "service_register",
323                         .handler = _handler_service_register,
324                 },
325                 {
326                         .cmd = NULL,
327                         .handler = NULL,
328                 },
329         };
330
331         DbgPrint("TCB: %p, Packet: %p\n", tcb, packet);
332
333         command = packet_command(packet);
334         if (!command) {
335                 ErrPrint("Invalid command\n");
336                 return -EINVAL;
337         }
338         DbgPrint("Command: %s, Packet type[%d]\n", command, packet_type(packet));
339
340         switch (packet_type(packet)) {
341         case PACKET_REQ:
342                 /* Need to send reply packet */
343                 DbgPrint("REQ: Command: [%s]\n", command);
344
345                 for (i = 0; service_req_table[i].cmd; i++) {
346                         if (strcmp(service_req_table[i].cmd, command))
347                                 continue;
348
349                         service_req_table[i].handler(tcb, packet, data);
350                         break;
351                 }
352
353                 break;
354         case PACKET_REQ_NOACK:
355                 break;
356         case PACKET_ACK:
357                 break;
358         default:
359                 ErrPrint("Packet type is not valid[%s]\n", command);
360                 return -EINVAL;
361         }
362
363         /*!
364          * return value has no meanning,
365          * it will be printed by dlogutil.
366          */
367         return 0;
368 }
369
370
371 /*!
372  * MAIN THREAD
373  * Do not try to do anyother operation in these functions
374  */
375 HAPI int notification_service_init(void)
376 {
377         if (s_info.svc_ctx) {
378                 ErrPrint("Already initialized\n");
379                 return LB_STATUS_ERROR_ALREADY;
380         }
381
382         s_info.svc_ctx = service_common_create(NOTIFICATION_ADDR, service_thread_main, NULL);
383         if (!s_info.svc_ctx) {
384                 ErrPrint("Unable to activate service thread\n");
385                 return LB_STATUS_ERROR_FAULT;
386         }
387
388         DbgPrint("Successfully initiated\n");
389         return LB_STATUS_SUCCESS;
390 }
391
392 HAPI int notification_service_fini(void)
393 {
394         if (!s_info.svc_ctx)
395                 return LB_STATUS_ERROR_INVALID;
396
397         service_common_destroy(s_info.svc_ctx);
398         DbgPrint("Successfully Finalized\n");
399         return LB_STATUS_SUCCESS;
400 }
401
402 /* End of a file */