summaryrefslogtreecommitdiff
path: root/src/notification_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/notification_service.c')
-rw-r--r--src/notification_service.c388
1 files changed, 387 insertions, 1 deletions
diff --git a/src/notification_service.c b/src/notification_service.c
index 94fb941..2c2bcea 100644
--- a/src/notification_service.c
+++ b/src/notification_service.c
@@ -1,7 +1,7 @@
/*
* Copyright 2013 Samsung Electronics Co., Ltd
*
- * Licensed under the Flora License, Version 1.0 (the "License");
+ * Licensed under the Flora License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
@@ -13,4 +13,390 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <stdio.h>
+#include <Eina.h>
+
+#include <dlog.h>
+#include <livebox-errno.h>
+#include <packet.h>
+
+#include <notification_ipc.h>
+#include <notification_noti.h>
+#include <notification_error.h>
+
+#include "service_common.h"
+#include "debug.h"
+#include "util.h"
+#include "conf.h"
+
+#ifndef NOTIFICATION_ADDR
+#define NOTIFICATION_ADDR "/tmp/.notification.service"
+#endif
+
+#ifndef NOTIFICATION_DEL_PACKET_UNIT
+#define NOTIFICATION_DEL_PACKET_UNIT 10
+#endif
+
+static struct info {
+ Eina_List *context_list;
+ struct service_context *svc_ctx;
+} s_info = {
+ .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
+ .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
+};
+
+struct context {
+ struct tcb *tcb;
+ double seq;
+};
+
+struct noti_service {
+ const char *cmd;
+ void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
+};
+
+/*!
+ * FUNCTIONS to handle notifcation
+ */
+static inline int get_priv_id(int num_deleted, int *list_deleted, int index) {
+ if (index < num_deleted) {
+ return *(list_deleted + index);
+ } else {
+ return -1;
+ }
+}
+
+static inline char *get_string(char *string)
+{
+ if (string == NULL) {
+ return NULL;
+ }
+ if (string[0] == '\0') {
+ return NULL;
+ }
+
+ return string;
+}
+
+static inline struct packet *create_packet_from_deleted_list(int op_num, int *list, int start_index) {
+ return packet_create(
+ "del_noti_multiple",
+ "iiiiiiiiiii",
+ ((op_num - start_index) > NOTIFICATION_DEL_PACKET_UNIT) ? NOTIFICATION_DEL_PACKET_UNIT : op_num - start_index,
+ get_priv_id(op_num, list, start_index),
+ get_priv_id(op_num, list, start_index + 1),
+ get_priv_id(op_num, list, start_index + 2),
+ get_priv_id(op_num, list, start_index + 3),
+ get_priv_id(op_num, list, start_index + 4),
+ get_priv_id(op_num, list, start_index + 5),
+ get_priv_id(op_num, list, start_index + 6),
+ get_priv_id(op_num, list, start_index + 7),
+ get_priv_id(op_num, list, start_index + 8),
+ get_priv_id(op_num, list, start_index + 9)
+ );
+}
+
+/*!
+ * SERVICE HANDLER
+ */
+static void _handler_insert(struct tcb *tcb, struct packet *packet, void *data)
+{
+ int ret = 0;
+ int priv_id = 0;
+ struct packet *packet_reply = NULL;
+ struct packet *packet_service = NULL;
+ notification_h noti = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti != NULL) {
+ if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
+ ret = notification_noti_insert(noti);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ErrPrint("failed to insert a notification\n");
+ notification_free(noti);
+ return ;
+ }
+
+ notification_get_id(noti, NULL, &priv_id);
+ DbgPrint("priv_id: [%d]\n", priv_id);
+ packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
+ if (packet_reply) {
+ service_common_unicast_packet(tcb, packet_reply);
+ packet_destroy(packet_reply);
+ }
+
+ packet_service = notification_ipc_make_packet_from_noti(noti, "add_noti", 2);
+ if (packet_service != NULL) {
+ service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+ packet_destroy(packet_service);
+ }
+ } else {
+ ErrPrint("Failed to create the packet");
+ }
+ notification_free(noti);
+ }
+}
+
+static void _handler_update(struct tcb *tcb, struct packet *packet, void *data)
+{
+ int ret = 0;
+ int priv_id = 0;
+ struct packet *packet_reply = NULL;
+ struct packet *packet_service = NULL;
+ notification_h noti = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti != NULL) {
+ if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
+ ret = notification_noti_update(noti);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ErrPrint("failed to update a notification\n");
+ notification_free(noti);
+ return ;
+ }
+
+ notification_get_id(noti, NULL, &priv_id);
+ DbgPrint("priv_id: [%d]\n", priv_id);
+ packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
+ if (packet_reply) {
+ service_common_unicast_packet(tcb, packet_reply);
+ packet_destroy(packet_reply);
+ }
+
+ packet_service = notification_ipc_make_packet_from_noti(noti, "update_noti", 2);
+ if (packet_service != NULL) {
+ service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+ packet_destroy(packet_service);
+ }
+ } else {
+ ErrPrint("Failed to create the packet");
+ }
+ notification_free(noti);
+ }
+}
+
+static void _handler_refresh(struct tcb *tcb, struct packet *packet, void *data)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ struct packet *packet_reply = NULL;
+
+ packet_reply = packet_create_reply(packet, "i", ret);
+ if (packet_reply) {
+ service_common_unicast_packet(tcb, packet_reply);
+ packet_destroy(packet_reply);
+ }
+
+ service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE);
+}
+
+static void _handler_delete_single(struct tcb *tcb, struct packet *packet, void *data)
+{
+ int ret = 0;
+ int priv_id = 0;
+ struct packet *packet_reply = NULL;
+ struct packet *packet_service = NULL;
+ char *pkgname = NULL;
+
+ if (packet_get(packet, "si", &pkgname, &priv_id) == 2) {
+ pkgname = get_string(pkgname);
+
+ ret = notification_noti_delete_by_priv_id(pkgname, priv_id);
+
+ DbgPrint("priv_id: [%d]\n", priv_id);
+ packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
+ if (packet_reply) {
+ service_common_unicast_packet(tcb, packet_reply);
+ packet_destroy(packet_reply);
+ }
+
+ packet_service = packet_create("del_noti_single", "ii", 1, priv_id);
+ if (packet_service != NULL) {
+ service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+ packet_destroy(packet_service);
+ }
+ } else {
+ ErrPrint("Failed to get data from the packet");
+ }
+}
+
+static void _handler_delete_multiple(struct tcb *tcb, struct packet *packet, void *data)
+{
+ int ret = 0;
+ struct packet *packet_reply = NULL;
+ struct packet *packet_service = NULL;
+ char *pkgname = NULL;
+ notification_type_e type = 0;
+ int num_deleted = 0;
+ int *list_deleted = NULL;
+
+ if (packet_get(packet, "si", &pkgname, &type) == 2) {
+ pkgname = get_string(pkgname);
+ DbgPrint("pkgname: [%s] type: [%d]\n", pkgname, type);
+
+ ret = notification_noti_delete_all(type, pkgname, &num_deleted, &list_deleted);
+ DbgPrint("ret: [%d] num_deleted: [%d]\n", ret, num_deleted);
+
+ packet_reply = packet_create_reply(packet, "ii", ret, num_deleted);
+ if (packet_reply) {
+ service_common_unicast_packet(tcb, packet_reply);
+ packet_destroy(packet_reply);
+ }
+
+ if (num_deleted > 0) {
+ if (num_deleted <= NOTIFICATION_DEL_PACKET_UNIT) {
+ packet_service = create_packet_from_deleted_list(num_deleted, list_deleted, 0);
+
+ if (packet_service) {
+ service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+ packet_destroy(packet_service);
+ }
+ } else {
+ int set = 0;
+ int set_total = num_deleted / NOTIFICATION_DEL_PACKET_UNIT;
+
+ for (set = 0; set <= set_total; set++) {
+ packet_service = create_packet_from_deleted_list(num_deleted,
+ list_deleted, set * NOTIFICATION_DEL_PACKET_UNIT);
+
+ if (packet_service) {
+ service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+ packet_destroy(packet_service);
+ }
+ }
+ }
+ }
+
+ if (list_deleted != NULL) {
+ free(list_deleted);
+ list_deleted = NULL;
+ }
+ } else {
+ ErrPrint("Failed to get data from the packet");
+ }
+}
+
+static void _handler_service_register(struct tcb *tcb, struct packet *packet, void *data)
+{
+ struct packet *packet_reply;
+ int ret;
+
+ ret = tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
+
+ packet_reply = packet_create_reply(packet, "i", ret);
+ if (packet_reply) {
+ service_common_unicast_packet(tcb, packet_reply);
+ packet_destroy(packet_reply);
+ }
+}
+
+/*!
+ * SERVICE THREAD
+ */
+static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
+{
+ int i = 0;
+ const char *command;
+ static struct noti_service service_req_table[] = {
+ {
+ .cmd = "add_noti",
+ .handler = _handler_insert,
+ },
+ {
+ .cmd = "update_noti",
+ .handler = _handler_update,
+ },
+ {
+ .cmd = "refresh_noti",
+ .handler = _handler_refresh,
+ },
+ {
+ .cmd = "del_noti_single",
+ .handler = _handler_delete_single,
+ },
+ {
+ .cmd = "del_noti_multiple",
+ .handler = _handler_delete_multiple,
+ },
+ {
+ .cmd = "service_register",
+ .handler = _handler_service_register,
+ },
+ {
+ .cmd = NULL,
+ .handler = NULL,
+ },
+ };
+
+ DbgPrint("TCB: %p, Packet: %p\n", tcb, packet);
+
+ command = packet_command(packet);
+ if (!command) {
+ ErrPrint("Invalid command\n");
+ return -EINVAL;
+ }
+ DbgPrint("Command: %s, Packet type[%d]\n", command, packet_type(packet));
+
+ switch (packet_type(packet)) {
+ case PACKET_REQ:
+ /* Need to send reply packet */
+ DbgPrint("REQ: Command: [%s]\n", command);
+
+ for (i = 0; service_req_table[i].cmd; i++) {
+ if (strcmp(service_req_table[i].cmd, command))
+ continue;
+
+ service_req_table[i].handler(tcb, packet, data);
+ break;
+ }
+
+ break;
+ case PACKET_REQ_NOACK:
+ break;
+ case PACKET_ACK:
+ break;
+ default:
+ ErrPrint("Packet type is not valid[%s]\n", command);
+ return -EINVAL;
+ }
+
+ /*!
+ * return value has no meanning,
+ * it will be printed by dlogutil.
+ */
+ return 0;
+}
+
+
+/*!
+ * MAIN THREAD
+ * Do not try to do anyother operation in these functions
+ */
+HAPI int notification_service_init(void)
+{
+ if (s_info.svc_ctx) {
+ ErrPrint("Already initialized\n");
+ return LB_STATUS_ERROR_ALREADY;
+ }
+
+ s_info.svc_ctx = service_common_create(NOTIFICATION_ADDR, service_thread_main, NULL);
+ if (!s_info.svc_ctx) {
+ ErrPrint("Unable to activate service thread\n");
+ return LB_STATUS_ERROR_FAULT;
+ }
+
+ DbgPrint("Successfully initiated\n");
+ return LB_STATUS_SUCCESS;
+}
+
+HAPI int notification_service_fini(void)
+{
+ if (!s_info.svc_ctx)
+ return LB_STATUS_ERROR_INVALID;
+
+ service_common_destroy(s_info.svc_ctx);
+ DbgPrint("Successfully Finalized\n");
+ return LB_STATUS_SUCCESS;
+}
+
+/* End of a file */