Update SMACK, Fix a crash of terminating sequence, etc, ...
[apps/livebox/data-provider-master.git] / src / badge_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
17 #include <stdio.h>
18
19 #include <Eina.h>
20
21 #include <dlog.h>
22 #include <livebox-errno.h>
23 #include <packet.h>
24
25 #include <sys/smack.h>
26
27 #include <badge.h>
28 #include <badge_db.h>
29
30 #include "service_common.h"
31 #include "debug.h"
32 #include "util.h"
33 #include "conf.h"
34
35 static struct info {
36         Eina_List *context_list;
37         struct service_context *svc_ctx;
38 } s_info = {
39         .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
40         .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
41 };
42
43 struct context {
44         struct tcb *tcb;
45         double seq;
46 };
47
48 struct noti_service {
49         const char *cmd;
50         void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
51 };
52
53 /*!
54  * FUNCTIONS to handle badge
55  */
56 static inline char *get_string(char *string)
57 {
58         if (string == NULL) {
59                 return NULL;
60         }
61         if (string[0] == '\0') {
62                 return NULL;
63         }
64
65         return string;
66 }
67
68 /*!
69  * SERVICE HANDLER
70  */
71 static void _handler_insert_badge(struct tcb *tcb, struct packet *packet, void *data)
72 {
73         int ret = 0, ret_p = 0;
74         struct packet *packet_reply = NULL;
75         struct packet *packet_service = NULL;
76         char *pkgname = NULL;
77         char *writable_pkg = NULL;
78         char *caller = NULL;
79
80         if (packet_get(packet, "sss", &pkgname, &writable_pkg, &caller) == 3) {
81                 pkgname = get_string(pkgname);
82                 writable_pkg = get_string(writable_pkg);
83                 caller = get_string(caller);
84
85                 if (pkgname != NULL && writable_pkg != NULL && caller != NULL) {
86                         ret = badge_db_insert(pkgname, writable_pkg, caller);
87
88                 } else {
89                         ret = BADGE_ERROR_INVALID_DATA;
90                 }
91
92                 packet_reply = packet_create_reply(packet, "i", ret);
93                 if (packet_reply) {
94                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
95                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
96                         }
97                         packet_destroy(packet_reply);
98                 } else {
99                         ErrPrint("Failed to create a reply packet");
100                 }
101
102                 if (ret == BADGE_ERROR_NONE) {
103                         packet_service = packet_create("insert_badge", "is", ret, pkgname);
104                         if (packet_service != NULL) {
105                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
106                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
107                                 }
108                                 packet_destroy(packet_service);
109                         } else {
110                                 ErrPrint("Failed to create a multicast packet");
111                         }
112                 } else {
113                         ErrPrint("Failed to insert a badge:%d", ret);
114                 }
115         } else {
116                 ErrPrint("Failed to get data from the packet");
117         }
118 }
119
120 static void _handler_delete_badge(struct tcb *tcb, struct packet *packet, void *data)
121 {
122         int ret = 0, ret_p = 0;
123         struct packet *packet_reply = NULL;
124         struct packet *packet_service = NULL;
125         char *pkgname = NULL;
126         char *caller = NULL;
127
128         if (packet_get(packet, "ss", &pkgname, &caller) == 2) {
129                 pkgname = get_string(pkgname);
130                 caller = get_string(caller);
131
132                 if (pkgname != NULL && caller != NULL) {
133                         ret = badge_db_delete(pkgname, caller);
134
135                 } else {
136                         ret = BADGE_ERROR_INVALID_DATA;
137                 }
138
139                 packet_reply = packet_create_reply(packet, "i", ret);
140                 if (packet_reply) {
141                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
142                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
143                         }
144                         packet_destroy(packet_reply);
145                 } else {
146                         ErrPrint("Failed to create a reply packet");
147                 }
148
149                 if (ret == BADGE_ERROR_NONE) {
150                         packet_service = packet_create("delete_badge", "is", ret, pkgname);
151                         if (packet_service != NULL) {
152                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
153                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
154                                 }
155                                 packet_destroy(packet_service);
156                         } else {
157                                 ErrPrint("Failed to create a multicast packet");
158                         }
159                 } else {
160                         ErrPrint("Failed to delete a badge:%d", ret);
161                 }
162         } else {
163                 ErrPrint("Failed to get data from the packet");
164         }
165 }
166
167 static void _handler_set_badge_count(struct tcb *tcb, struct packet *packet, void *data)
168 {
169         int ret = 0, ret_p = 0;
170         struct packet *packet_reply = NULL;
171         struct packet *packet_service = NULL;
172         char *pkgname = NULL;
173         char *caller = NULL;
174         int count = 0;
175
176         if (packet_get(packet, "ssi", &pkgname, &caller, &count) == 3) {
177                 pkgname = get_string(pkgname);
178                 caller = get_string(caller);
179
180                 if (pkgname != NULL && caller != NULL) {
181                         ret = badge_db_set_count(pkgname, caller, count);
182
183                 } else {
184                         ret = BADGE_ERROR_INVALID_DATA;
185                 }
186
187                 packet_reply = packet_create_reply(packet, "i", ret);
188                 if (packet_reply) {
189                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
190                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
191                         }
192                         packet_destroy(packet_reply);
193                 } else {
194                         ErrPrint("Failed to create a reply packet");
195                 }
196
197                 if (ret == BADGE_ERROR_NONE) {
198                         packet_service = packet_create("set_badge_count", "isi", ret, pkgname, count);
199                         if (packet_service != NULL) {
200                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
201                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
202                                 }
203                                 packet_destroy(packet_service);
204                         } else {
205                                 ErrPrint("Failed to create a multicast packet");
206                         }
207                 } else {
208                         ErrPrint("Failed to set count of badge:%d", ret);
209                 }
210         } else {
211                 ErrPrint("Failed to get data from the packet");
212         }
213 }
214
215 static void _handler_set_display_option(struct tcb *tcb, struct packet *packet, void *data)
216 {
217         int ret = 0, ret_p = 0;
218         struct packet *packet_reply = NULL;
219         struct packet *packet_service = NULL;
220         char *pkgname = NULL;
221         char *caller = NULL;
222         int is_display = 0;
223
224         if (packet_get(packet, "ssi", &pkgname, &caller, &is_display) == 3) {
225                 pkgname = get_string(pkgname);
226                 caller = get_string(caller);
227
228                 if (pkgname != NULL && caller != NULL) {
229                         ret = badge_db_set_display_option(pkgname, caller, is_display);
230
231                 } else {
232                         ret = BADGE_ERROR_INVALID_DATA;
233                 }
234
235                 packet_reply = packet_create_reply(packet, "i", ret);
236                 if (packet_reply) {
237                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
238                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
239                         }
240                         packet_destroy(packet_reply);
241                 } else {
242                         ErrPrint("Failed to create a reply packet");
243                 }
244
245                 if (ret == BADGE_ERROR_NONE) {
246                         packet_service = packet_create("set_disp_option", "isi", ret, pkgname, is_display);
247                         if (packet_service != NULL) {
248                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
249                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
250                                 }
251                                 packet_destroy(packet_service);
252                         } else {
253                                 ErrPrint("Failed to create a multicast packet");
254                         }
255                 } else {
256                         ErrPrint("Failed to set display option of badge:%d", ret);
257                 }
258         } else {
259                 ErrPrint("Failed to get data from the packet");
260         }
261 }
262
263 static void _handler_service_register(struct tcb *tcb, struct packet *packet, void *data)
264 {
265         int ret = 0;
266         struct packet *packet_reply;
267
268         ret = tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
269         if (ret < 0) {
270                 ErrPrint("Failed to set the type of client:%d", ret);
271         }
272
273         packet_reply = packet_create_reply(packet, "i", ret);
274         if (packet_reply) {
275                 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
276                         ErrPrint("Failed to send a reply packet:%d", ret);
277                 }
278                 packet_destroy(packet_reply);
279         } else {
280                 ErrPrint("Failed to create a reply packet");
281         }
282 }
283
284 /*!
285  * SERVICE THREAD
286  */
287 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
288 {
289         int i = 0;
290         const char *command;
291         static struct noti_service service_req_table[] = {
292                 {
293                         .cmd = "insert_badge",
294                         .handler = _handler_insert_badge,
295                 },
296                 {
297                         .cmd = "delete_badge",
298                         .handler = _handler_delete_badge,
299                 },
300                 {
301                         .cmd = "set_badge_count",
302                         .handler = _handler_set_badge_count,
303                 },
304                 {
305                         .cmd = "set_disp_option",
306                         .handler = _handler_set_display_option,
307                 },
308                 {
309                         .cmd = "service_register",
310                         .handler = _handler_service_register,
311                 },
312                 {
313                         .cmd = NULL,
314                         .handler = NULL,
315                 },
316         };
317
318         if (!packet) {
319                 DbgPrint("TCB: %p is terminated (NIL packet)\n", tcb);
320                 return 0;
321         }
322
323         command = packet_command(packet);
324         if (!command) {
325                 ErrPrint("Invalid command\n");
326                 return -EINVAL;
327         }
328         DbgPrint("Command: [%s], Packet type[%d]\n", command, packet_type(packet));
329
330         switch (packet_type(packet)) {
331         case PACKET_REQ:
332                 /* Need to send reply packet */
333                 for (i = 0; service_req_table[i].cmd; i++) {
334                         if (strcmp(service_req_table[i].cmd, command))
335                                 continue;
336
337                         service_req_table[i].handler(tcb, packet, data);
338                         break;
339                 }
340
341                 break;
342         case PACKET_REQ_NOACK:
343                 break;
344         case PACKET_ACK:
345                 break;
346         default:
347                 ErrPrint("Packet type is not valid[%s]\n", command);
348                 return -EINVAL;
349         }
350
351         /*!
352          * return value has no meanning,
353          * it will be printed by dlogutil.
354          */
355         return 0;
356 }
357
358
359 /*!
360  * MAIN THREAD
361  * Do not try to do anyother operation in these functions
362  */
363 HAPI int badge_service_init(void)
364 {
365         if (s_info.svc_ctx) {
366                 ErrPrint("Already initialized\n");
367                 return LB_STATUS_ERROR_ALREADY;
368         }
369
370         s_info.svc_ctx = service_common_create(BADGE_SOCKET, service_thread_main, NULL);
371         if (!s_info.svc_ctx) {
372                 ErrPrint("Unable to activate service thread\n");
373                 return LB_STATUS_ERROR_FAULT;
374         }
375
376         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), BADGE_SMACK_LABEL, SMACK_LABEL_IPOUT) != 0) {
377                 if (errno != EOPNOTSUPP) {
378                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
379                         service_common_destroy(s_info.svc_ctx);
380                         s_info.svc_ctx = NULL;
381                         return LB_STATUS_ERROR_FAULT;
382                 }
383         }
384
385         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), BADGE_SMACK_LABEL, SMACK_LABEL_IPIN) != 0) {
386                 if (errno != EOPNOTSUPP) {
387                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
388                         service_common_destroy(s_info.svc_ctx);
389                         s_info.svc_ctx = NULL;
390                         return LB_STATUS_ERROR_FAULT;
391                 }
392         }
393
394         DbgPrint("Successfully initiated\n");
395         return LB_STATUS_SUCCESS;
396 }
397
398 HAPI int badge_service_fini(void)
399 {
400         if (!s_info.svc_ctx)
401                 return LB_STATUS_ERROR_INVALID;
402
403         service_common_destroy(s_info.svc_ctx);
404         s_info.svc_ctx = NULL;
405         DbgPrint("Successfully finalized\n");
406         return LB_STATUS_SUCCESS;
407 }
408
409 /* End of a file */