2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
21 #include <livebox-errno.h>
24 #include <sys/smack.h>
26 #include <notification_ipc.h>
27 #include <notification_noti.h>
28 #include <notification_error.h>
30 #include "service_common.h"
35 #ifndef NOTIFICATION_DEL_PACKET_UNIT
36 #define NOTIFICATION_DEL_PACKET_UNIT 10
40 Eina_List *context_list;
41 struct service_context *svc_ctx;
43 .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
44 .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
54 void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
58 * FUNCTIONS to handle notifcation
60 static inline int get_priv_id(int num_deleted, int *list_deleted, int index) {
61 if (index < num_deleted) {
62 return *(list_deleted + index);
68 static inline char *get_string(char *string)
73 if (string[0] == '\0') {
80 static inline struct packet *create_packet_from_deleted_list(int op_num, int *list, int start_index) {
84 ((op_num - start_index) > NOTIFICATION_DEL_PACKET_UNIT) ? NOTIFICATION_DEL_PACKET_UNIT : op_num - start_index,
85 get_priv_id(op_num, list, start_index),
86 get_priv_id(op_num, list, start_index + 1),
87 get_priv_id(op_num, list, start_index + 2),
88 get_priv_id(op_num, list, start_index + 3),
89 get_priv_id(op_num, list, start_index + 4),
90 get_priv_id(op_num, list, start_index + 5),
91 get_priv_id(op_num, list, start_index + 6),
92 get_priv_id(op_num, list, start_index + 7),
93 get_priv_id(op_num, list, start_index + 8),
94 get_priv_id(op_num, list, start_index + 9)
101 static void _handler_insert(struct tcb *tcb, struct packet *packet, void *data)
103 int ret = 0, ret_p = 0;
105 struct packet *packet_reply = NULL;
106 struct packet *packet_service = NULL;
107 notification_h noti = NULL;
109 noti = notification_create(NOTIFICATION_TYPE_NOTI);
111 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
112 ret = notification_noti_insert(noti);
113 notification_get_id(noti, NULL, &priv_id);
114 DbgPrint("priv_id: [%d]\n", priv_id);
115 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
117 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
118 ErrPrint("failed to send reply packet: %d\n", ret_p);
120 packet_destroy(packet_reply);
122 ErrPrint("failed to create a reply packet\n");
125 if (ret != NOTIFICATION_ERROR_NONE) {
126 ErrPrint("failed to insert a notification: %d\n", ret);
127 notification_free(noti);
131 packet_service = notification_ipc_make_packet_from_noti(noti, "add_noti", 2);
132 if (packet_service != NULL) {
133 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
134 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
136 packet_destroy(packet_service);
138 ErrPrint("failed to create a multicats packet\n");
141 ErrPrint("Failed to create the packet");
143 notification_free(noti);
147 static void _handler_update(struct tcb *tcb, struct packet *packet, void *data)
149 int ret = 0, ret_p = 0;
151 struct packet *packet_reply = NULL;
152 struct packet *packet_service = NULL;
153 notification_h noti = NULL;
155 noti = notification_create(NOTIFICATION_TYPE_NOTI);
157 if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
158 ret = notification_noti_update(noti);
160 notification_get_id(noti, NULL, &priv_id);
161 DbgPrint("priv_id: [%d]\n", priv_id);
162 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
164 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
165 ErrPrint("failed to send reply packet:%d\n", ret_p);
167 packet_destroy(packet_reply);
169 ErrPrint("failed to create a reply packet\n");
172 if (ret != NOTIFICATION_ERROR_NONE) {
173 ErrPrint("failed to update a notification:%d\n", ret);
174 notification_free(noti);
178 packet_service = notification_ipc_make_packet_from_noti(noti, "update_noti", 2);
179 if (packet_service != NULL) {
180 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
181 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
183 packet_destroy(packet_service);
186 ErrPrint("Failed to create the packet");
188 notification_free(noti);
192 static void _handler_refresh(struct tcb *tcb, struct packet *packet, void *data)
195 struct packet *packet_reply = NULL;
197 packet_reply = packet_create_reply(packet, "i", ret);
199 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
200 ErrPrint("failed to send reply packet:%d\n", ret);
202 packet_destroy(packet_reply);
204 ErrPrint("failed to create a reply packet\n");
207 if ((ret = service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE)) < 0) {
208 ErrPrint("failed to send a multicast packet:%d\n", ret);
212 static void _handler_delete_single(struct tcb *tcb, struct packet *packet, void *data)
215 int ret = 0, ret_p = 0;
217 struct packet *packet_reply = NULL;
218 struct packet *packet_service = NULL;
219 char *pkgname = NULL;
221 if (packet_get(packet, "si", &pkgname, &priv_id) == 2) {
222 pkgname = get_string(pkgname);
224 ret = notification_noti_delete_by_priv_id_get_changes(pkgname, priv_id, &num_changes);
226 DbgPrint("priv_id: [%d] num_delete:%d\n", priv_id, num_changes);
227 packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
229 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
230 ErrPrint("failed to send reply packet:%d\n", ret_p);
232 packet_destroy(packet_reply);
234 ErrPrint("failed to create a reply packet\n");
237 if (ret != NOTIFICATION_ERROR_NONE && num_changes <= 0) {
238 ErrPrint("failed to delete a notification:%d %d\n", ret, num_changes);
242 packet_service = packet_create("del_noti_single", "ii", 1, priv_id);
243 if (packet_service != NULL) {
244 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
245 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
247 packet_destroy(packet_service);
250 ErrPrint("Failed to get data from the packet");
254 static void _handler_delete_multiple(struct tcb *tcb, struct packet *packet, void *data)
256 int ret = 0, ret_p = 0;
257 struct packet *packet_reply = NULL;
258 struct packet *packet_service = NULL;
259 char *pkgname = NULL;
260 notification_type_e type = 0;
262 int *list_deleted = NULL;
264 if (packet_get(packet, "si", &pkgname, &type) == 2) {
265 pkgname = get_string(pkgname);
266 DbgPrint("pkgname: [%s] type: [%d]\n", pkgname, type);
268 ret = notification_noti_delete_all(type, pkgname, &num_deleted, &list_deleted);
269 DbgPrint("ret: [%d] num_deleted: [%d]\n", ret, num_deleted);
271 packet_reply = packet_create_reply(packet, "ii", ret, num_deleted);
273 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
274 ErrPrint("failed to send reply packet:%d\n", ret_p);
276 packet_destroy(packet_reply);
278 ErrPrint("failed to create a reply packet\n");
281 if (ret != NOTIFICATION_ERROR_NONE) {
282 ErrPrint("failed to delete notifications:%d\n", ret);
283 if (list_deleted != NULL) {
289 if (num_deleted > 0) {
290 if (num_deleted <= NOTIFICATION_DEL_PACKET_UNIT) {
291 packet_service = create_packet_from_deleted_list(num_deleted, list_deleted, 0);
293 if (packet_service) {
294 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
295 ErrPrint("failed to send a multicast packet: %d\n", ret_p);
297 packet_destroy(packet_service);
299 ErrPrint("failed to create a multicast packet\n");
303 int set_total = num_deleted / NOTIFICATION_DEL_PACKET_UNIT;
305 for (set = 0; set <= set_total; set++) {
306 packet_service = create_packet_from_deleted_list(num_deleted,
307 list_deleted, set * NOTIFICATION_DEL_PACKET_UNIT);
309 if (packet_service) {
310 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
311 ErrPrint("failed to send a multicast packet:%d\n", ret_p);
313 packet_destroy(packet_service);
315 ErrPrint("failed to create a multicast packet\n");
321 if (list_deleted != NULL) {
326 ErrPrint("Failed to get data from the packet");
330 static void _handler_service_register(struct tcb *tcb, struct packet *packet, void *data)
333 struct packet *packet_reply;
335 ret = tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
337 packet_reply = packet_create_reply(packet, "i", ret);
339 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
340 ErrPrint("failed to send reply packet:%d\n", ret);
342 packet_destroy(packet_reply);
344 ErrPrint("failed to create a reply packet\n");
351 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
355 static struct noti_service service_req_table[] = {
358 .handler = _handler_insert,
361 .cmd = "update_noti",
362 .handler = _handler_update,
365 .cmd = "refresh_noti",
366 .handler = _handler_refresh,
369 .cmd = "del_noti_single",
370 .handler = _handler_delete_single,
373 .cmd = "del_noti_multiple",
374 .handler = _handler_delete_multiple,
377 .cmd = "service_register",
378 .handler = _handler_service_register,
387 DbgPrint("TCB: %p is terminated\n", tcb);
391 command = packet_command(packet);
393 ErrPrint("Invalid command\n");
397 switch (packet_type(packet)) {
399 /* Need to send reply packet */
400 DbgPrint("%p REQ: Command: [%s]\n", tcb, command);
402 for (i = 0; service_req_table[i].cmd; i++) {
403 if (strcmp(service_req_table[i].cmd, command))
406 service_req_table[i].handler(tcb, packet, data);
411 case PACKET_REQ_NOACK:
416 ErrPrint("Packet type is not valid[%s]\n", command);
421 * return value has no meanning,
422 * it will be printed by dlogutil.
430 * Do not try to do anyother operation in these functions
432 HAPI int notification_service_init(void)
434 if (s_info.svc_ctx) {
435 ErrPrint("Already initialized\n");
436 return LB_STATUS_ERROR_ALREADY;
439 s_info.svc_ctx = service_common_create(NOTIFICATION_SOCKET, service_thread_main, NULL);
440 if (!s_info.svc_ctx) {
441 ErrPrint("Unable to activate service thread\n");
442 return LB_STATUS_ERROR_FAULT;
445 if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), NOTIFICATION_SMACK_LABEL, SMACK_LABEL_IPOUT) != 0) {
446 if (errno != EOPNOTSUPP) {
447 ErrPrint("Unable to set SMACK label(%d)\n", errno);
448 service_common_destroy(s_info.svc_ctx);
449 s_info.svc_ctx = NULL;
450 return LB_STATUS_ERROR_FAULT;
454 if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), NOTIFICATION_SMACK_LABEL, SMACK_LABEL_IPIN) != 0) {
455 if (errno != EOPNOTSUPP) {
456 ErrPrint("Unable to set SMACK label(%d)\n", errno);
457 service_common_destroy(s_info.svc_ctx);
458 s_info.svc_ctx = NULL;
459 return LB_STATUS_ERROR_FAULT;
463 DbgPrint("Successfully initiated\n");
464 return LB_STATUS_SUCCESS;
467 HAPI int notification_service_fini(void)
470 return LB_STATUS_ERROR_INVALID;
472 service_common_destroy(s_info.svc_ctx);
473 s_info.svc_ctx = NULL;
474 DbgPrint("Successfully Finalized\n");
475 return LB_STATUS_SUCCESS;