sync with private git
[platform/core/api/notification.git] / src / notification_ipc.c
1 /*
2  *  libnotification
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungtaek Chung <seungtaek.chung@samsung.com>, Mi-Ju Lee <miju52.lee@samsung.com>, Xi Zhichan <zhichan.xi@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <errno.h>
26
27 #include <vconf.h>
28
29 #include <packet.h>
30 #include <com-core.h>
31 #include <com-core_packet.h>
32
33 #include <notification_ipc.h>
34 #include <notification_db.h>
35 #include <notification_type.h>
36 #include <notification_internal.h>
37 #include <notification_debug.h>
38
39 #define NOTIFICATION_IPC_TIMEOUT 0.0
40
41 #if !defined(VCONFKEY_MASTER_STARTED)
42 #define VCONFKEY_MASTER_STARTED "memory/data-provider-master/started"
43 #endif
44
45 static struct info {
46         int server_fd;
47         int server_cl_fd;
48         int server_cl_fd_ref_cnt;
49         int client_fd;
50         const char *socket_file;
51         struct {
52                 int (*request_cb)(const char *appid, const char *name, int type, const char *content, const char *icon, pid_t pid, double period, int allow_duplicate, void *data);
53                 void *data;
54         } server_cb;
55         int initialized;
56         int is_started_cb_set_svc;
57         int is_started_cb_set_task;
58 } s_info = {
59         .server_fd = -1,
60         .server_cl_fd = -1,
61         .server_cl_fd_ref_cnt = 0,
62         .client_fd = -1,
63         .socket_file = NOTIFICATION_ADDR,
64         .initialized = 0,
65         .is_started_cb_set_svc = 0,
66         .is_started_cb_set_task = 0,
67 };
68
69 typedef struct _task_list task_list;
70 struct _task_list {
71         task_list *prev;
72         task_list *next;
73
74         void (*task_cb) (void *data);
75         void *data;
76 };
77
78 typedef struct _result_cb_item {
79         void (*result_cb)(int priv_id, int result, void *data);
80         void *data;
81 } result_cb_item;
82
83 static task_list *g_task_list;
84
85 static notification_error_e notification_ipc_monitor_register(void);
86 static notification_error_e notification_ipc_monitor_deregister(void);
87 static void _do_deffered_task(void);
88 static void _master_started_cb_task(keynode_t *node, void *data);
89
90 /*!
91  * functions to check state of master
92  */
93 static inline void _set_master_started_cb(vconf_callback_fn cb) {
94         int ret = -1;
95
96         ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED,
97                         cb, NULL);
98         if (ret != 0) {
99                 NOTIFICATION_ERR("failed to notify key(%s) : %d",
100                                 VCONFKEY_MASTER_STARTED, ret);
101         }
102 }
103
104 static inline void _unset_master_started_cb(vconf_callback_fn cb) {
105         int ret = -1;
106
107         ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED,
108                         cb);
109         if (ret != 0) {
110                 NOTIFICATION_ERR("failed to notify key(%s) : %d",
111                                 VCONFKEY_MASTER_STARTED, ret);
112         }
113 }
114
115 int notification_ipc_is_master_ready(void)
116 {
117         int ret = -1, is_master_started = 0;
118
119         ret = vconf_get_bool(VCONFKEY_MASTER_STARTED, &is_master_started);
120         if (ret == 0 && is_master_started == 1) {
121                 NOTIFICATION_ERR("the master has been started");
122         } else {
123                 is_master_started = 0;
124                 NOTIFICATION_ERR("the master has been stopped");
125         }
126
127         return is_master_started;
128 }
129
130 notification_error_e
131 notification_ipc_add_deffered_task(
132                 void (*deffered_task_cb)(void *data),
133                 void *user_data)
134 {
135         task_list *list = NULL;
136         task_list *list_new = NULL;
137
138         list_new =
139             (task_list *) malloc(sizeof(task_list));
140
141         if (list_new == NULL) {
142                 return NOTIFICATION_ERROR_NO_MEMORY;
143         }
144
145         if (s_info.is_started_cb_set_task == 0) {
146                 _set_master_started_cb(_master_started_cb_task);
147                 s_info.is_started_cb_set_task = 1;
148         }
149
150         list_new->next = NULL;
151         list_new->prev = NULL;
152
153         list_new->task_cb = deffered_task_cb;
154         list_new->data = user_data;
155
156         if (g_task_list == NULL) {
157                 g_task_list = list_new;
158         } else {
159                 list = g_task_list;
160
161                 while (list->next != NULL) {
162                         list = list->next;
163                 }
164
165                 list->next = list_new;
166                 list_new->prev = list;
167         }
168         return NOTIFICATION_ERROR_NONE;
169 }
170
171 notification_error_e
172 notification_ipc_del_deffered_task(
173                 void (*deffered_task_cb)(void *data))
174 {
175         task_list *list_del = NULL;
176         task_list *list_prev = NULL;
177         task_list *list_next = NULL;
178
179         list_del = g_task_list;
180
181         if (list_del == NULL) {
182                 return NOTIFICATION_ERROR_INVALID_DATA;
183         }
184
185         while (list_del->prev != NULL) {
186                 list_del = list_del->prev;
187         }
188
189         do {
190                 if (list_del->task_cb == deffered_task_cb) {
191                         list_prev = list_del->prev;
192                         list_next = list_del->next;
193
194                         if (list_prev == NULL) {
195                                 g_task_list = list_next;
196                         } else {
197                                 list_prev->next = list_next;
198                         }
199
200                         if (list_next == NULL) {
201                                 if (list_prev != NULL) {
202                                         list_prev->next = NULL;
203                                 }
204                         } else {
205                                 list_next->prev = list_prev;
206                         }
207
208                         free(list_del);
209
210                         if (g_task_list == NULL) {
211                                 if (s_info.is_started_cb_set_task == 1) {
212                                         _unset_master_started_cb(_master_started_cb_task);
213                                         s_info.is_started_cb_set_task = 0;
214                                 }
215                         }
216
217                         return NOTIFICATION_ERROR_NONE;
218                 }
219                 list_del = list_del->next;
220         } while (list_del != NULL);
221
222         return NOTIFICATION_ERROR_INVALID_DATA;
223 }
224
225 static void _do_deffered_task(void) {
226         task_list *list_do = NULL;
227         task_list *list_temp = NULL;
228
229         if (g_task_list == NULL) {
230                 return;
231         }
232
233         list_do = g_task_list;
234         g_task_list = NULL;
235         if (s_info.is_started_cb_set_task == 1) {
236                 _unset_master_started_cb(_master_started_cb_task);
237                 s_info.is_started_cb_set_task = 0;
238         }
239
240         while (list_do->prev != NULL) {
241                 list_do = list_do->prev;
242         }
243
244         while (list_do != NULL) {
245                 if (list_do->task_cb != NULL) {
246                         list_do->task_cb(list_do->data);
247                         NOTIFICATION_DBG("called:%p", list_do->task_cb);
248                 }
249                 list_temp = list_do->next;
250                 free(list_do);
251                 list_do = list_temp;
252         }
253 }
254
255 static void _master_started_cb_service(keynode_t *node,
256                 void *data) {
257         int ret = NOTIFICATION_ERROR_NONE;
258
259         if (notification_ipc_is_master_ready()) {
260                 NOTIFICATION_ERR("try to register a notification service");
261                 ret = notification_ipc_monitor_deregister();
262                 if (ret != NOTIFICATION_ERROR_NONE) {
263                         NOTIFICATION_ERR("failed to unregister a monitor");
264                 }
265                 ret = notification_ipc_monitor_register();
266                 if (ret != NOTIFICATION_ERROR_NONE) {
267                         NOTIFICATION_ERR("failed to register a monitor");
268                 }
269         } else {
270                 NOTIFICATION_ERR("try to unregister a notification service");
271                 ret = notification_ipc_monitor_deregister();
272                 if (ret != NOTIFICATION_ERROR_NONE) {
273                         NOTIFICATION_ERR("failed to deregister a monitor");
274                 }
275         }
276 }
277
278 static void _master_started_cb_task(keynode_t *node,
279                 void *data) {
280
281         if (notification_ipc_is_master_ready()) {
282                 _do_deffered_task();
283         }
284 }
285
286 /*!
287  * functions to create operation list
288  */
289 notification_op *notification_ipc_create_op(notification_op_type_e type, int num_op, int *list_priv_id, int num_priv_id, notification_h *noti_list)
290 {
291         int i = 0;
292         notification_op *op_list = NULL;
293
294         if (num_op <= 0) {
295                 return NULL;
296         }
297
298         op_list = (notification_op *)malloc(sizeof(notification_op) * num_op);
299         memset(op_list, 0x0, sizeof(notification_op) * num_op);
300
301         for (i = 0; i < num_op; i++) {
302                 (op_list + i)->type = type;
303                 if (list_priv_id != NULL) {
304                         (op_list + i)->priv_id = *(list_priv_id + i);
305                 }
306                 if (noti_list != NULL) {
307                         (op_list + i)->noti = *(noti_list + i);
308                 }
309         }
310
311         return op_list;
312 }
313
314 /*!
315  * utility functions creating notification packet
316  */
317 static inline char *_dup_string(const char *string)
318 {
319         char *ret;
320
321         if (string == NULL) {
322                 return NULL;
323         }
324         if (string[0] == '\0') {
325                 return NULL;
326         }
327
328         ret = strdup(string);
329         if (!ret)
330                 NOTIFICATION_ERR("Error: %s\n", strerror(errno));
331
332         return ret;
333 }
334
335 static inline bundle *_create_bundle_from_string(unsigned char *string)
336 {
337         if (string == NULL) {
338                 return NULL;
339         }
340         if (string[0] == '\0') {
341                 return NULL;
342         }
343
344         return bundle_decode(string, strlen((char *)string));
345 }
346
347 /*!
348  * functions creating notification packet
349  */
350 EXPORT_API notification_error_e notification_ipc_make_noti_from_packet(notification_h noti, const struct packet *packet)
351 {
352         int ret = 0;
353         int type;
354         int layout;
355         int group_id;
356         int internal_group_id;
357         int priv_id;
358         char *caller_pkgname = NULL;
359         char *launch_pkgname = NULL;
360         unsigned char *args = NULL;
361         unsigned char *group_args = NULL;
362         unsigned char *b_execute_option = NULL;
363         unsigned char *b_service_responding = NULL;
364         unsigned char *b_service_single_launch = NULL;
365         unsigned char *b_service_multi_launch = NULL;
366         char *domain = NULL;
367         char *dir = NULL;
368         unsigned char *b_text = NULL;
369         unsigned char *b_key = NULL;
370         unsigned char *b_format_args = NULL;
371         int num_format_args;
372         unsigned char *b_image_path = NULL;
373         int sound_type;
374         char *sound_path = NULL;
375         int vibration_type;
376         char *vibration_path = NULL;
377         int led_operation;
378         int led_argb;
379         int led_on_ms;
380         int led_off_ms;
381         time_t time;
382         time_t insert_time;
383         int flags_for_property;
384         int display_applist;
385         double progress_size;
386         double progress_percentage;
387         char *app_icon_path = NULL;
388         char *app_name = NULL;
389         char *temp_title = NULL;
390         char *temp_content = NULL;
391
392         if (noti == NULL) {
393                 NOTIFICATION_ERR("invalid data");
394                 return NOTIFICATION_ERROR_INVALID_DATA;
395         }
396
397         ret = packet_get(packet,
398                         "iiiiisssssssssssssisisisiiiiiiiiddssss",
399                         &type,
400                         &layout,
401                         &group_id,
402                         &internal_group_id,
403                         &priv_id,
404                         &caller_pkgname,
405                         &launch_pkgname,
406                         &args,
407                         &group_args,
408                         &b_execute_option,
409                         &b_service_responding,
410                         &b_service_single_launch,
411                         &b_service_multi_launch,
412                         &domain,
413                         &dir,
414                         &b_text,
415                         &b_key,
416                         &b_format_args,
417                         &num_format_args,
418                         &b_image_path,
419                         &sound_type,
420                         &sound_path,
421                         &vibration_type,
422                         &vibration_path,
423                         &led_operation,
424                         &led_argb,
425                         &led_on_ms,
426                         &led_off_ms,
427                         &time,
428                         &insert_time,
429                         &flags_for_property,
430                         &display_applist,
431                         &progress_size,
432                         &progress_percentage,
433                         &app_icon_path,
434                         &app_name,
435                         &temp_title,
436                         &temp_content);
437
438         if (ret != 38) {
439                 NOTIFICATION_ERR("failed to create a noti from packet");
440                 return NOTIFICATION_ERROR_INVALID_DATA;
441         }
442
443         /*!
444          * This is already allocated from the notification_create function.
445          * Before reallocate string to here.
446          * We have to release old one first.
447          */
448         free(noti->caller_pkgname);
449         noti->caller_pkgname = _dup_string(caller_pkgname);
450         noti->launch_pkgname = _dup_string(launch_pkgname);
451         noti->args = _create_bundle_from_string(args);
452         noti->group_args = _create_bundle_from_string(group_args);
453         noti->b_execute_option = _create_bundle_from_string(b_execute_option);
454         noti->b_service_responding = _create_bundle_from_string(b_service_responding);
455         noti->b_service_single_launch = _create_bundle_from_string(b_service_single_launch);
456         noti->b_service_multi_launch = _create_bundle_from_string(b_service_multi_launch);
457         noti->domain = _dup_string(domain);
458         noti->dir = _dup_string(dir);
459         noti->b_text = _create_bundle_from_string(b_text);
460         noti->b_key = _create_bundle_from_string(b_key);
461         noti->b_format_args = _create_bundle_from_string(b_format_args);
462         noti->b_image_path = _create_bundle_from_string(b_image_path);
463         noti->sound_path = _dup_string(sound_path);
464         noti->vibration_path = _dup_string(vibration_path);
465         noti->app_icon_path = _dup_string(app_icon_path);
466         noti->app_name = _dup_string(app_name);
467         noti->temp_title = _dup_string(temp_title);
468         noti->temp_content = _dup_string(temp_content);
469
470         noti->type = type;
471         noti->layout = layout;
472         noti->group_id = group_id;
473         noti->internal_group_id = internal_group_id;
474         noti->priv_id = priv_id;
475         noti->num_format_args = num_format_args;
476         noti->sound_type = sound_type;
477         noti->vibration_type = vibration_type;
478         noti->led_operation = led_operation;
479         noti->led_argb = led_argb;
480         noti->led_on_ms = led_on_ms;
481         noti->led_off_ms = led_off_ms;
482         noti->time = time;
483         noti->insert_time = insert_time;
484         noti->flags_for_property = flags_for_property;
485         noti->display_applist = display_applist;
486         noti->progress_size = progress_size;
487         noti->progress_percentage = progress_percentage;
488
489         return NOTIFICATION_ERROR_NONE;
490 }
491
492 EXPORT_API struct packet *notification_ipc_make_packet_from_noti(notification_h noti, const char *command, int packet_type)
493 {
494         struct packet *result = NULL;
495         char *args = NULL;
496         char *group_args = NULL;
497         char *b_image_path = NULL;
498         char *b_execute_option = NULL;
499         char *b_service_responding = NULL;
500         char *b_service_single_launch = NULL;
501         char *b_service_multi_launch = NULL;
502         char *b_text = NULL;
503         char *b_key = NULL;
504         char *b_format_args = NULL;
505         int flag_simmode = 0;
506         struct packet *(*func_to_create_packet)(const char *command, const char *fmt, ...);
507         const char *title_key = NULL;
508         char buf_key[32] = { 0, };
509
510         /* Decode bundle to insert DB */
511         if (noti->args) {
512                 bundle_encode(noti->args, (bundle_raw **) & args, NULL);
513         }
514         if (noti->group_args) {
515                 bundle_encode(noti->group_args, (bundle_raw **) & group_args,
516                               NULL);
517         }
518
519         if (noti->b_execute_option) {
520                 bundle_encode(noti->b_execute_option,
521                               (bundle_raw **) & b_execute_option, NULL);
522         }
523         if (noti->b_service_responding) {
524                 bundle_encode(noti->b_service_responding,
525                               (bundle_raw **) & b_service_responding, NULL);
526         }
527         if (noti->b_service_single_launch) {
528                 bundle_encode(noti->b_service_single_launch,
529                               (bundle_raw **) & b_service_single_launch, NULL);
530         }
531         if (noti->b_service_multi_launch) {
532                 bundle_encode(noti->b_service_multi_launch,
533                               (bundle_raw **) & b_service_multi_launch, NULL);
534         }
535
536         if (noti->b_text) {
537                 bundle_encode(noti->b_text, (bundle_raw **) & b_text, NULL);
538         }
539         if (noti->b_key) {
540                 bundle_encode(noti->b_key, (bundle_raw **) & b_key, NULL);
541         }
542         if (noti->b_format_args) {
543                 bundle_encode(noti->b_format_args,
544                               (bundle_raw **) & b_format_args, NULL);
545         }
546
547         if (noti->b_image_path) {
548                 bundle_encode(noti->b_image_path,
549                               (bundle_raw **) & b_image_path, NULL);
550         }
551
552         /* Check only simmode property is enable */
553         if (noti->flags_for_property & NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE) {
554                 flag_simmode = 1;
555         }
556
557         if (noti->b_key != NULL) {
558                 snprintf(buf_key, sizeof(buf_key), "%d",
559                          NOTIFICATION_TEXT_TYPE_TITLE);
560
561                 title_key = bundle_get_val(noti->b_key, buf_key);
562         }
563
564         if (title_key == NULL && noti->b_text != NULL) {
565                 snprintf(buf_key, sizeof(buf_key), "%d",
566                          NOTIFICATION_TEXT_TYPE_TITLE);
567
568                 title_key = bundle_get_val(noti->b_text, buf_key);
569         }
570
571         if (title_key == NULL) {
572                 title_key = noti->caller_pkgname;
573         }
574
575         if (packet_type == 1)
576                 func_to_create_packet = packet_create;
577         else if (packet_type == 2)
578                 func_to_create_packet = packet_create_noack;
579         else {
580                 goto out;
581         }
582
583         result = func_to_create_packet(command,
584                         "iiiiisssssssssssssisisisiiiiiiiiddssss",
585                         noti->type,
586                         noti->layout,
587                         noti->group_id,
588                         noti->internal_group_id,
589                         noti->priv_id,
590                         NOTIFICATION_CHECK_STR(noti->caller_pkgname),
591                         NOTIFICATION_CHECK_STR(noti->launch_pkgname),
592                         NOTIFICATION_CHECK_STR(args),
593                         NOTIFICATION_CHECK_STR(group_args),
594                         NOTIFICATION_CHECK_STR(b_execute_option),
595                         NOTIFICATION_CHECK_STR(b_service_responding),
596                         NOTIFICATION_CHECK_STR(b_service_single_launch),
597                         NOTIFICATION_CHECK_STR(b_service_multi_launch),
598                         NOTIFICATION_CHECK_STR(noti->domain),
599                         NOTIFICATION_CHECK_STR(noti->dir),
600                         NOTIFICATION_CHECK_STR(b_text),
601                         NOTIFICATION_CHECK_STR(b_key),
602                         NOTIFICATION_CHECK_STR(b_format_args),
603                         noti->num_format_args,
604                         NOTIFICATION_CHECK_STR(b_image_path),
605                         noti->sound_type,
606                         NOTIFICATION_CHECK_STR(noti->sound_path),
607                         noti->vibration_type,
608                         NOTIFICATION_CHECK_STR(noti->vibration_path),
609                         noti->led_operation,
610                         noti->led_argb,
611                         noti->led_on_ms,
612                         noti->led_off_ms,
613                         noti->time,
614                         noti->insert_time,
615                         noti->flags_for_property,
616                         noti->display_applist,
617                         noti->progress_size,
618                         noti->progress_percentage,
619                         NOTIFICATION_CHECK_STR(noti->app_icon_path),
620                         NOTIFICATION_CHECK_STR(noti->app_name),
621                         NOTIFICATION_CHECK_STR(noti->temp_title),
622                         NOTIFICATION_CHECK_STR(noti->temp_content));
623
624 out:
625         /* Free decoded data */
626         if (args) {
627                 free(args);
628         }
629         if (group_args) {
630                 free(group_args);
631         }
632
633         if (b_execute_option) {
634                 free(b_execute_option);
635         }
636         if (b_service_responding) {
637                 free(b_service_responding);
638         }
639         if (b_service_single_launch) {
640                 free(b_service_single_launch);
641         }
642         if (b_service_multi_launch) {
643                 free(b_service_multi_launch);
644         }
645
646         if (b_text) {
647                 free(b_text);
648         }
649         if (b_key) {
650                 free(b_key);
651         }
652         if (b_format_args) {
653                 free(b_format_args);
654         }
655
656         if (b_image_path) {
657                 free(b_image_path);
658         }
659
660         return result;
661 }
662
663 /*!
664  * functions to handler services
665  */
666 static struct packet *_handler_insert(pid_t pid, int handle, const struct packet *packet)
667 {
668         notification_h noti = NULL;
669
670         if (!packet) {
671                 NOTIFICATION_ERR("a packet is null");
672                 return NULL;
673         }
674         noti = notification_create(NOTIFICATION_TYPE_NOTI);
675         if (!noti) {
676                 NOTIFICATION_ERR("failed to create a notification");
677                 return NULL;
678         }
679         notification_ipc_make_noti_from_packet(noti, packet);
680
681         if (noti->flags_for_property
682                 & NOTIFICATION_PROP_DISABLE_UPDATE_ON_INSERT) {
683                 /* Disable changed cb */
684         } else {
685                 /* Enable changed cb */
686                 notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_INSERT, 1, &(noti->priv_id), 1, &noti);
687                 if (noti_op != NULL) {
688                         notification_call_changed_cb(noti_op, 1);
689                         free(noti_op);
690                 }
691         }
692         notification_free(noti);
693
694         return NULL;
695 }
696
697 static struct packet *_handler_update(pid_t pid, int handle, const struct packet *packet)
698 {
699         notification_h noti = NULL;
700
701         if (!packet) {
702                 NOTIFICATION_ERR("a packet is null");
703                 return NULL;
704         }
705
706         noti = notification_create(NOTIFICATION_TYPE_NOTI);
707         if (!noti) {
708                 NOTIFICATION_ERR("failed to create a notification");
709                 return NULL;
710         }
711
712         notification_ipc_make_noti_from_packet(noti, packet);
713
714         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_UPDATE, 1, &(noti->priv_id), 1, &noti);
715         if (noti_op != NULL) {
716                 notification_call_changed_cb(noti_op, 1);
717                 free(noti_op);
718         }
719
720         notification_free(noti);
721
722         return NULL;
723 }
724
725 static struct packet *_handler_refresh(pid_t pid, int handle, const struct packet *packet)
726 {
727         if (!packet) {
728                 NOTIFICATION_ERR("a packet is null");
729                 return NULL;
730         }
731         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_REFRESH, 1, NULL, 0, NULL);
732         if (noti_op != NULL) {
733                 notification_call_changed_cb(noti_op, 1);
734                 free(noti_op);
735         }
736
737         return NULL;
738 }
739
740 static struct packet *_handler_delete_single(pid_t pid, int handle, const struct packet *packet)
741 {
742         int num_deleted = 0;
743         int priv_id = NOTIFICATION_PRIV_ID_NONE;
744
745         if (!packet) {
746                 NOTIFICATION_ERR("a packet is null");
747                 return NULL;
748         }
749         if (packet_get(packet, "ii", &num_deleted, &priv_id) == 2) {
750                 notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_DELETE, 1, &priv_id, 1, NULL);
751                 if (noti_op != NULL) {
752                         notification_call_changed_cb(noti_op, 1);
753                         free(noti_op);
754                 }
755         }
756
757         return NULL;
758 }
759
760 static struct packet *_handler_delete_multiple(pid_t pid, int handle, const struct packet *packet)
761 {
762         int ret = 0;
763         int buf[10] = {0,};
764         int num_deleted = 0;
765
766         NOTIFICATION_ERR("delete_noti_multiple");
767
768         if (!packet) {
769                 NOTIFICATION_ERR("a packet is null");
770                 return NULL;
771         }
772         ret = packet_get(packet, "iiiiiiiiiii", &num_deleted,
773                         &(buf[0]),
774                         &(buf[1]),
775                         &(buf[2]),
776                         &(buf[3]),
777                         &(buf[4]),
778                         &(buf[5]),
779                         &(buf[6]),
780                         &(buf[7]),
781                         &(buf[8]),
782                         &(buf[9]));
783
784         NOTIFICATION_ERR("packet data count:%d", ret);
785         NOTIFICATION_ERR("packet data num deleted:%d", num_deleted);
786
787         int i = 0;
788         for (i = 0 ; i < 10 ; i++) {
789                 NOTIFICATION_ERR("packet data[%d]:%d",i, buf[i]);
790         }
791
792         if (ret == 11) {
793                 notification_op *noti_op = notification_ipc_create_op(
794                                 NOTIFICATION_OP_DELETE, num_deleted, buf, num_deleted, NULL);
795                 if (noti_op != NULL) {
796                         notification_call_changed_cb(noti_op, num_deleted);
797                         free(noti_op);
798                 }
799         }
800
801         return NULL;
802 }
803
804 static int _handler_service_register(pid_t pid, int handle, const struct packet *packet, void *data)
805 {
806         int ret;
807
808         if (!packet) {
809                 NOTIFICATION_ERR("Packet is not valid\n");
810                 ret = NOTIFICATION_ERROR_INVALID_DATA;
811         } else if (packet_get(packet, "i", &ret) != 1) {
812                 NOTIFICATION_ERR("Packet is not valid\n");
813                 ret = NOTIFICATION_ERROR_INVALID_DATA;
814         } else {
815                 if (ret == 0) {
816                         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_SERVICE_READY, 1, NULL, 1, NULL);
817                         if (noti_op != NULL) {
818                                 notification_call_changed_cb(noti_op, 1);
819                                 free(noti_op);
820                         }
821                 }
822         }
823         return ret;
824 }
825
826 /*!
827  * functions to initialize and register a monitor
828  */
829 static notification_error_e notification_ipc_monitor_register(void)
830 {
831         int ret;
832         struct packet *packet;
833         static struct method service_table[] = {
834                 {
835                         .cmd = "add_noti",
836                         .handler = _handler_insert,
837                 },
838                 {
839                         .cmd = "update_noti",
840                         .handler = _handler_update,
841                 },
842                 {
843                         .cmd = "refresh_noti",
844                         .handler = _handler_refresh,
845                 },
846                 {
847                         .cmd = "del_noti_single",
848                         .handler = _handler_delete_single,
849                 },
850                 {
851                         .cmd = "del_noti_multiple",
852                         .handler = _handler_delete_multiple,
853                 },
854                 {
855                         .cmd = NULL,
856                         .handler = NULL,
857                 },
858         };
859
860         if (s_info.initialized == 1) {
861                 return NOTIFICATION_ERROR_NONE;
862         } else {
863                 s_info.initialized = 1;
864         }
865
866         NOTIFICATION_ERR("register a service\n");
867
868         com_core_packet_use_thread(1);
869         s_info.server_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table);
870         if (s_info.server_fd < 0) {
871                 NOTIFICATION_ERR("Failed to make a connection to the master\n");
872                 return NOTIFICATION_ERROR_IO;
873         }
874
875         packet = packet_create("service_register", "");
876         if (!packet) {
877                 NOTIFICATION_ERR("Failed to build a packet\n");
878                 com_core_packet_client_fini(s_info.server_fd);
879                 return NOTIFICATION_ERROR_IO;
880         }
881
882         ret = com_core_packet_async_send(s_info.server_fd, packet, 1.0, _handler_service_register, NULL);
883         NOTIFICATION_DBG("Service register sent: %d\n", ret);
884         packet_destroy(packet);
885         if (ret != 0) {
886                 com_core_packet_client_fini(s_info.server_fd);
887                 s_info.server_fd = NOTIFICATION_ERROR_INVALID_DATA;
888                 ret = NOTIFICATION_ERROR_IO;
889         } else {
890                 ret = NOTIFICATION_ERROR_NONE;
891         }
892
893         NOTIFICATION_DBG("Server FD: %d\n", s_info.server_fd);
894         return ret;
895 }
896
897 notification_error_e notification_ipc_monitor_deregister(void)
898 {
899         if (s_info.initialized == 0) {
900                 return NOTIFICATION_ERROR_NONE;
901         }
902
903         com_core_packet_client_fini(s_info.server_fd);
904         s_info.server_fd = NOTIFICATION_ERROR_INVALID_DATA;
905
906         s_info.initialized = 0;
907
908         return NOTIFICATION_ERROR_NONE;
909 }
910
911 notification_error_e notification_ipc_monitor_init(void)
912 {
913         int ret = NOTIFICATION_ERROR_NONE;
914
915         if (notification_ipc_is_master_ready()) {
916                 ret = notification_ipc_monitor_register();
917         }
918
919         if (s_info.is_started_cb_set_svc == 0) {
920                 _set_master_started_cb(_master_started_cb_service);
921                 s_info.is_started_cb_set_svc = 1;
922         }
923
924         return ret;
925 }
926
927 notification_error_e notification_ipc_monitor_fini(void)
928 {
929         int ret = NOTIFICATION_ERROR_NONE;
930
931         if (s_info.is_started_cb_set_svc == 1) {
932                 _unset_master_started_cb(_master_started_cb_service);
933                 s_info.is_started_cb_set_svc = 0;
934         }
935
936         ret = notification_ipc_monitor_deregister();
937
938         return ret;
939 }
940
941 /*!
942  * functions to request the service
943  */
944 notification_error_e notification_ipc_request_insert(notification_h noti, int *priv_id)
945 {
946         int status = 0;
947         int id = NOTIFICATION_PRIV_ID_NONE;
948         struct packet *packet;
949         struct packet *result;
950
951         /* Initialize private ID */
952         noti->priv_id = NOTIFICATION_PRIV_ID_NONE;
953         noti->group_id = NOTIFICATION_GROUP_ID_NONE;
954         noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
955
956         packet = notification_ipc_make_packet_from_noti(noti, "add_noti", 1);
957         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
958                         packet,
959                         NOTIFICATION_IPC_TIMEOUT);
960         packet_destroy(packet);
961
962         if (result != NULL) {
963                 if (packet_get(result, "ii", &status, &id) != 2) {
964                         NOTIFICATION_ERR("Failed to get a result packet");
965                         packet_unref(result);
966                         return NOTIFICATION_ERROR_IO;
967                 }
968
969                 if (status != NOTIFICATION_ERROR_NONE) {
970                         packet_unref(result);
971                         return status;
972                 }
973                 packet_unref(result);
974         } else {
975                 NOTIFICATION_ERR("failed to receive answer(insert)");
976                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
977         }
978
979         if (priv_id != NULL) {
980                 *priv_id = id;
981         }
982
983         return NOTIFICATION_ERROR_NONE;
984 }
985
986 notification_error_e notification_ipc_request_delete_single(notification_type_e type, char *pkgname, int priv_id)
987 {
988         int status = 0;
989         int id = NOTIFICATION_PRIV_ID_NONE;
990         struct packet *packet;
991         struct packet *result;
992
993         packet = packet_create("del_noti_single", "si", pkgname, priv_id);
994         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
995                         packet,
996                         NOTIFICATION_IPC_TIMEOUT);
997         packet_destroy(packet);
998
999         if (result != NULL) {
1000                 if (packet_get(result, "ii", &status, &id) != 2) {
1001                         NOTIFICATION_ERR("Failed to get a result packet");
1002                         packet_unref(result);
1003                         return NOTIFICATION_ERROR_IO;
1004                 }
1005                 packet_unref(result);
1006         } else {
1007                 NOTIFICATION_ERR("failed to receive answer(delete)");
1008                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1009         }
1010
1011         return status;
1012 }
1013
1014 notification_error_e notification_ipc_request_delete_multiple(notification_type_e type, char *pkgname)
1015 {
1016         int status = 0;
1017         int num_deleted = 0;
1018         struct packet *packet;
1019         struct packet *result;
1020
1021         packet = packet_create("del_noti_multiple", "si", pkgname, type);
1022         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1023                         packet,
1024                         NOTIFICATION_IPC_TIMEOUT);
1025         packet_destroy(packet);
1026
1027         if (result != NULL) {
1028                 if (packet_get(result, "ii", &status, &num_deleted) != 2) {
1029                         NOTIFICATION_ERR("Failed to get a result packet");
1030                         packet_unref(result);
1031                         return NOTIFICATION_ERROR_IO;
1032                 }
1033                 NOTIFICATION_ERR("num deleted:%d", num_deleted);
1034                 packet_unref(result);
1035         } else {
1036                 NOTIFICATION_ERR("failed to receive answer(delete multiple)");
1037                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1038         }
1039
1040         return status;
1041 }
1042
1043 notification_error_e notification_ipc_request_update(notification_h noti)
1044 {
1045         int status = 0;
1046         int id = NOTIFICATION_PRIV_ID_NONE;
1047         struct packet *packet;
1048         struct packet *result;
1049
1050         packet = notification_ipc_make_packet_from_noti(noti, "update_noti", 1);
1051         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1052                         packet,
1053                         NOTIFICATION_IPC_TIMEOUT);
1054         packet_destroy(packet);
1055
1056         if (result != NULL) {
1057                 if (packet_get(result, "ii", &status, &id) != 2) {
1058                         NOTIFICATION_ERR("Failed to get a result packet");
1059                         packet_unref(result);
1060                         return NOTIFICATION_ERROR_IO;
1061                 }
1062                 packet_unref(result);
1063         } else {
1064                 NOTIFICATION_ERR("failed to receive answer(update)");
1065                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1066         }
1067
1068         return status;
1069 }
1070
1071 static int _notification_ipc_update_cb(pid_t pid, int handle, const struct packet *packet, void *data)
1072 {
1073         int status = 0;
1074         int id = NOTIFICATION_PRIV_ID_NONE;
1075         result_cb_item *cb_item = (result_cb_item *)data;
1076
1077         if (cb_item == NULL) {
1078                 NOTIFICATION_ERR("Failed to get a callback item");
1079                 return NOTIFICATION_ERROR_INVALID_DATA;
1080         }
1081         s_info.server_cl_fd_ref_cnt = (s_info.server_cl_fd_ref_cnt <= 1) ? 0 : s_info.server_cl_fd_ref_cnt - 1;
1082         if (s_info.server_cl_fd_ref_cnt <= 0) {
1083                 NOTIFICATION_DBG("REFCNT: %d (fd: %d)", s_info.server_cl_fd_ref_cnt, s_info.server_cl_fd);
1084                 int fd_temp = s_info.server_cl_fd;
1085                 s_info.server_cl_fd = -1;
1086                 com_core_packet_client_fini(fd_temp);
1087                 NOTIFICATION_DBG("FD(%d) finalized", fd_temp);
1088         }
1089
1090         if (packet != NULL) {
1091                 if (packet_get(packet, "ii", &status, &id) != 2) {
1092                         NOTIFICATION_ERR("Failed to get a result packet");
1093                         status = NOTIFICATION_ERROR_IO;
1094                 }
1095         }
1096
1097         if (cb_item->result_cb != NULL) {
1098                 cb_item->result_cb(id, status, cb_item->data);
1099         }
1100         free(cb_item);
1101
1102         return status;
1103 }
1104
1105 notification_error_e notification_ipc_request_update_async(notification_h noti,
1106                 void (*result_cb)(int priv_id, int result, void *data), void *user_data)
1107 {
1108         int ret = NOTIFICATION_ERROR_NONE;
1109         int ret_con = 0;
1110         struct packet *packet = NULL;
1111         result_cb_item *cb_item = NULL;
1112
1113         packet = notification_ipc_make_packet_from_noti(noti, "update_noti", 1);
1114         if (packet == NULL) {
1115                 ret = NOTIFICATION_ERROR_INVALID_DATA;
1116                 goto fail;
1117         }
1118
1119         cb_item = calloc(1, sizeof(result_cb_item));
1120         if (cb_item == NULL) {
1121                 ret = NOTIFICATION_ERROR_NO_MEMORY;
1122                 goto fail;
1123         }
1124
1125         if (s_info.server_cl_fd < 0) {
1126                 com_core_packet_use_thread(1);
1127                 s_info.server_cl_fd = com_core_packet_client_init(s_info.socket_file, 0, NULL);
1128                 if (s_info.server_cl_fd < 0) {
1129                         NOTIFICATION_DBG("Failed to init client: %d", s_info.server_cl_fd);
1130                         ret = NOTIFICATION_ERROR_SERVICE_NOT_READY;
1131                         goto fail;
1132                 }
1133                 s_info.server_cl_fd_ref_cnt = 1;
1134         } else {
1135                 s_info.server_cl_fd_ref_cnt++;
1136         }
1137
1138         cb_item->result_cb = result_cb;
1139         cb_item->data = user_data;
1140
1141         NOTIFICATION_INFO("Connection count:%d, fd:%d", s_info.server_cl_fd_ref_cnt, s_info.server_cl_fd);
1142
1143         ret_con = com_core_packet_async_send(s_info.server_cl_fd, packet, 0.0f,
1144                         _notification_ipc_update_cb, cb_item);
1145         if (ret_con < 0) {
1146                 NOTIFICATION_ERR("Failed to request update, %d\n", ret_con);
1147                 s_info.server_cl_fd_ref_cnt = (s_info.server_cl_fd_ref_cnt <= 1) ? 0 : s_info.server_cl_fd_ref_cnt - 1;
1148                 if (s_info.server_cl_fd_ref_cnt <= 0) {
1149                         int fd_temp = s_info.server_cl_fd;
1150                         s_info.server_cl_fd = -1;
1151                         com_core_packet_client_fini(fd_temp);
1152                         NOTIFICATION_INFO("FD(%d) finalized", fd_temp);
1153                 }
1154                 ret = NOTIFICATION_ERROR_IO;
1155                 goto fail;
1156         } else {
1157                 ret = NOTIFICATION_ERROR_NONE;
1158                 goto success;
1159         }
1160
1161 fail:
1162         if (cb_item) free(cb_item);
1163         NOTIFICATION_ERR("Err: %d\n", ret);
1164
1165 success:
1166         if (packet) packet_destroy(packet);
1167
1168         return ret;
1169 }
1170
1171 notification_error_e notification_ipc_request_refresh(void)
1172 {
1173         int status = 0;
1174         struct packet *packet;
1175         struct packet *result;
1176
1177         packet = packet_create("refresh_noti", "i", NOTIFICATION_OP_REFRESH);
1178         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1179                         packet,
1180                         NOTIFICATION_IPC_TIMEOUT);
1181         packet_destroy(packet);
1182
1183         if (result != NULL) {
1184                 if (packet_get(result, "i", &status) != 1) {
1185                         NOTIFICATION_ERR("Failed to get a result packet");
1186                         packet_unref(result);
1187                         return NOTIFICATION_ERROR_IO;
1188                 }
1189                 packet_unref(result);
1190         } else {
1191                 NOTIFICATION_ERR("failed to receive answer(refresh)");
1192                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1193         }
1194
1195         return status;
1196 }
1197
1198 notification_error_e notification_ipc_noti_setting_property_set(const char *pkgname, const char *property, const char *value)
1199 {
1200         int status = 0;
1201         int ret = 0;
1202         struct packet *packet;
1203         struct packet *result;
1204
1205         packet = packet_create("set_noti_property", "sss", pkgname, property, value);
1206         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1207                         packet,
1208                         NOTIFICATION_IPC_TIMEOUT);
1209         packet_destroy(packet);
1210
1211         if (result != NULL) {
1212                 if (packet_get(result, "ii", &status, &ret) != 2) {
1213                         NOTIFICATION_ERR("Failed to get a result packet");
1214                         packet_unref(result);
1215                         return NOTIFICATION_ERROR_IO;
1216                 }
1217                 packet_unref(result);
1218         } else {
1219                 NOTIFICATION_ERR("failed to receive answer(delete)");
1220                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1221         }
1222
1223         return status;
1224 }
1225
1226 notification_error_e notification_ipc_noti_setting_property_get(const char *pkgname, const char *property, char **value)
1227 {
1228         int status = 0;
1229         char *ret = NULL;
1230         struct packet *packet;
1231         struct packet *result;
1232
1233         packet = packet_create("get_noti_property", "ss", pkgname, property);
1234         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1235                         packet,
1236                         NOTIFICATION_IPC_TIMEOUT);
1237         packet_destroy(packet);
1238
1239         if (result != NULL) {
1240                 if (packet_get(result, "is", &status, &ret) != 2) {
1241                         NOTIFICATION_ERR("Failed to get a result packet");
1242                         packet_unref(result);
1243                         return NOTIFICATION_ERROR_IO;
1244                 }
1245                 if (status == NOTIFICATION_ERROR_NONE && ret != NULL) {
1246                         *value = strdup(ret);
1247                 }
1248                 packet_unref(result);
1249         } else {
1250                 NOTIFICATION_ERR("failed to receive answer(delete)");
1251                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1252         }
1253
1254         return status;
1255 }