Fixed memory leaks
[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 1.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 client_fd;
48         const char *socket_file;
49         struct {
50                 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);
51                 void *data;
52         } server_cb;
53         int initialized;
54         int is_started_cb_set_svc;
55         int is_started_cb_set_task;
56 } s_info = {
57         .server_fd = -1,
58         .client_fd = -1,
59         .socket_file = NOTIFICATION_ADDR,
60         .initialized = 0,
61         .is_started_cb_set_svc = 0,
62         .is_started_cb_set_task = 0,
63 };
64
65 typedef struct _task_list task_list;
66 struct _task_list {
67         task_list *prev;
68         task_list *next;
69
70         void (*task_cb) (void *data);
71         void *data;
72 };
73
74 static task_list *g_task_list;
75
76 static notification_error_e notification_ipc_monitor_register(void);
77 static notification_error_e notification_ipc_monitor_deregister(void);
78 static void _do_deffered_task(void);
79 static void _master_started_cb_task(keynode_t *node, void *data);
80
81 /*!
82  * functions to check state of master
83  */
84 static inline void _set_master_started_cb(vconf_callback_fn cb) {
85         int ret = -1;
86
87         ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED,
88                         cb, NULL);
89         if (ret != 0) {
90                 NOTIFICATION_ERR("failed to notify key(%s) : %d",
91                                 VCONFKEY_MASTER_STARTED, ret);
92         }
93 }
94
95 static inline void _unset_master_started_cb(vconf_callback_fn cb) {
96         int ret = -1;
97
98         ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED,
99                         cb);
100         if (ret != 0) {
101                 NOTIFICATION_ERR("failed to notify key(%s) : %d",
102                                 VCONFKEY_MASTER_STARTED, ret);
103         }
104 }
105
106 int notification_ipc_is_master_ready(void)
107 {
108         int ret = -1, is_master_started = 0;
109
110         ret = vconf_get_bool(VCONFKEY_MASTER_STARTED, &is_master_started);
111         if (ret == 0 && is_master_started == 1) {
112                 NOTIFICATION_ERR("the master has been started");
113         } else {
114                 is_master_started = 0;
115                 NOTIFICATION_ERR("the master has been stopped");
116         }
117
118         return is_master_started;
119 }
120
121 notification_error_e
122 notification_ipc_add_deffered_task(
123                 void (*deffered_task_cb)(void *data),
124                 void *user_data)
125 {
126         task_list *list = NULL;
127         task_list *list_new = NULL;
128
129         list_new =
130             (task_list *) malloc(sizeof(task_list));
131
132         if (list_new == NULL) {
133                 return NOTIFICATION_ERROR_NO_MEMORY;
134         }
135
136         if (s_info.is_started_cb_set_task == 0) {
137                 _set_master_started_cb(_master_started_cb_task);
138                 s_info.is_started_cb_set_task = 1;
139         }
140
141         list_new->next = NULL;
142         list_new->prev = NULL;
143
144         list_new->task_cb = deffered_task_cb;
145         list_new->data = user_data;
146
147         if (g_task_list == NULL) {
148                 g_task_list = list_new;
149         } else {
150                 list = g_task_list;
151
152                 while (list->next != NULL) {
153                         list = list->next;
154                 }
155
156                 list->next = list_new;
157                 list_new->prev = list;
158         }
159         return NOTIFICATION_ERROR_NONE;
160 }
161
162 notification_error_e
163 notification_ipc_del_deffered_task(
164                 void (*deffered_task_cb)(void *data))
165 {
166         task_list *list_del = NULL;
167         task_list *list_prev = NULL;
168         task_list *list_next = NULL;
169
170         list_del = g_task_list;
171
172         if (list_del == NULL) {
173                 return NOTIFICATION_ERROR_INVALID_DATA;
174         }
175
176         while (list_del->prev != NULL) {
177                 list_del = list_del->prev;
178         }
179
180         do {
181                 if (list_del->task_cb == deffered_task_cb) {
182                         list_prev = list_del->prev;
183                         list_next = list_del->next;
184
185                         if (list_prev == NULL) {
186                                 g_task_list = list_next;
187                         } else {
188                                 list_prev->next = list_next;
189                         }
190
191                         if (list_next == NULL) {
192                                 if (list_prev != NULL) {
193                                         list_prev->next = NULL;
194                                 }
195                         } else {
196                                 list_next->prev = list_prev;
197                         }
198
199                         free(list_del);
200
201                         if (g_task_list == NULL) {
202                                 if (s_info.is_started_cb_set_task == 1) {
203                                         _unset_master_started_cb(_master_started_cb_task);
204                                         s_info.is_started_cb_set_task = 0;
205                                 }
206                         }
207
208                         return NOTIFICATION_ERROR_NONE;
209                 }
210                 list_del = list_del->next;
211         } while (list_del != NULL);
212
213         return NOTIFICATION_ERROR_INVALID_DATA;
214 }
215
216 static void _do_deffered_task(void) {
217         task_list *list_do = NULL;
218         task_list *list_temp = NULL;
219
220         if (g_task_list == NULL) {
221                 return;
222         }
223
224         list_do = g_task_list;
225         g_task_list = NULL;
226         if (s_info.is_started_cb_set_task == 1) {
227                 _unset_master_started_cb(_master_started_cb_task);
228                 s_info.is_started_cb_set_task = 0;
229         }
230
231         while (list_do->prev != NULL) {
232                 list_do = list_do->prev;
233         }
234
235         while (list_do != NULL) {
236                 if (list_do->task_cb != NULL) {
237                         list_do->task_cb(list_do->data);
238                         NOTIFICATION_DBG("called:%p", list_do->task_cb);
239                 }
240                 list_temp = list_do->next;
241                 free(list_do);
242                 list_do = list_temp;
243         }
244 }
245
246 static void _master_started_cb_service(keynode_t *node,
247                 void *data) {
248         int ret = NOTIFICATION_ERROR_NONE;
249
250         if (notification_ipc_is_master_ready()) {
251                 ret = notification_ipc_monitor_register();
252                 if (ret != NOTIFICATION_ERROR_NONE) {
253                         NOTIFICATION_ERR("failed to register a monitor");
254                 }
255         } else {
256                 ret = notification_ipc_monitor_deregister();
257                 if (ret != NOTIFICATION_ERROR_NONE) {
258                         NOTIFICATION_ERR("failed to deregister a monitor");
259                 }
260         }
261 }
262
263 static void _master_started_cb_task(keynode_t *node,
264                 void *data) {
265
266         if (notification_ipc_is_master_ready()) {
267                 _do_deffered_task();
268         }
269 }
270
271 /*!
272  * functions to create operation list
273  */
274 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)
275 {
276         int i = 0;
277         notification_op *op_list = NULL;
278
279         if (num_op <= 0) {
280                 return NULL;
281         }
282
283         op_list = (notification_op *)malloc(sizeof(notification_op) * num_op);
284         memset(op_list, 0x0, sizeof(notification_op) * num_op);
285
286         for (i = 0; i < num_op; i++) {
287                 (op_list + i)->type = type;
288                 if (list_priv_id != NULL) {
289                         (op_list + i)->priv_id = *(list_priv_id + i);
290                 }
291                 if (noti_list != NULL) {
292                         (op_list + i)->noti = *(noti_list + i);
293                 }
294         }
295
296         return op_list;
297 }
298
299 /*!
300  * utility functions creating notification packet
301  */
302 static inline char *_dup_string(const char *string)
303 {
304         char *ret;
305
306         if (string == NULL) {
307                 return NULL;
308         }
309         if (string[0] == '\0') {
310                 return NULL;
311         }
312
313         ret = strdup(string);
314         if (!ret)
315                 NOTIFICATION_ERR("Error: %s\n", strerror(errno));
316
317         return ret;
318 }
319
320 static inline bundle *_create_bundle_from_string(unsigned char *string)
321 {
322         if (string == NULL) {
323                 return NULL;
324         }
325         if (string[0] == '\0') {
326                 return NULL;
327         }
328
329         return bundle_decode(string, strlen((char *)string));
330 }
331
332 /*!
333  * functions creating notification packet
334  */
335 EXPORT_API notification_error_e notification_ipc_make_noti_from_packet(notification_h noti, const struct packet *packet)
336 {
337         int ret = 0;
338         int type;
339         int layout;
340         int group_id;
341         int internal_group_id;
342         int priv_id;
343         char *caller_pkgname = NULL;
344         char *launch_pkgname = NULL;
345         unsigned char *args = NULL;
346         unsigned char *group_args = NULL;
347         unsigned char *b_execute_option = NULL;
348         unsigned char *b_service_responding = NULL;
349         unsigned char *b_service_single_launch = NULL;
350         unsigned char *b_service_multi_launch = NULL;
351         char *domain = NULL;
352         char *dir = NULL;
353         unsigned char *b_text = NULL;
354         unsigned char *b_key = NULL;
355         unsigned char *b_format_args = NULL;
356         int num_format_args;
357         unsigned char *b_image_path = NULL;
358         int sound_type;
359         char *sound_path = NULL;
360         int vibration_type;
361         char *vibration_path = NULL;
362         int led_operation;
363         int led_argb;
364         int led_on_ms;
365         int led_off_ms;
366         time_t time;
367         time_t insert_time;
368         int flags_for_property;
369         int display_applist;
370         double progress_size;
371         double progress_percentage;
372         char *app_icon_path = NULL;
373         char *app_name = NULL;
374         char *temp_title = NULL;
375         char *temp_content = NULL;
376
377         if (noti == NULL) {
378                 NOTIFICATION_ERR("invalid data");
379                 return NOTIFICATION_ERROR_INVALID_DATA;
380         }
381
382         ret = packet_get(packet,
383                         "iiiiisssssssssssssisisisiiiiiiiiddssss",
384                         &type,
385                         &layout,
386                         &group_id,
387                         &internal_group_id,
388                         &priv_id,
389                         &caller_pkgname,
390                         &launch_pkgname,
391                         &args,
392                         &group_args,
393                         &b_execute_option,
394                         &b_service_responding,
395                         &b_service_single_launch,
396                         &b_service_multi_launch,
397                         &domain,
398                         &dir,
399                         &b_text,
400                         &b_key,
401                         &b_format_args,
402                         &num_format_args,
403                         &b_image_path,
404                         &sound_type,
405                         &sound_path,
406                         &vibration_type,
407                         &vibration_path,
408                         &led_operation,
409                         &led_argb,
410                         &led_on_ms,
411                         &led_off_ms,
412                         &time,
413                         &insert_time,
414                         &flags_for_property,
415                         &display_applist,
416                         &progress_size,
417                         &progress_percentage,
418                         &app_icon_path,
419                         &app_name,
420                         &temp_title,
421                         &temp_content);
422
423         if (ret != 38) {
424                 NOTIFICATION_ERR("failed to create a noti from packet");
425                 return NOTIFICATION_ERROR_INVALID_DATA;
426         }
427
428         /*!
429          * This is already allocated from the notification_create function.
430          * Before reallocate string to here.
431          * We have to release old one first.
432          */
433         free(noti->caller_pkgname);
434         noti->caller_pkgname = _dup_string(caller_pkgname);
435         noti->launch_pkgname = _dup_string(launch_pkgname);
436         noti->args = _create_bundle_from_string(args);
437         noti->group_args = _create_bundle_from_string(group_args);
438         noti->b_execute_option = _create_bundle_from_string(b_execute_option);
439         noti->b_service_responding = _create_bundle_from_string(b_service_responding);
440         noti->b_service_single_launch = _create_bundle_from_string(b_service_single_launch);
441         noti->b_service_multi_launch = _create_bundle_from_string(b_service_multi_launch);
442         noti->domain = _dup_string(domain);
443         noti->dir = _dup_string(dir);
444         noti->b_text = _create_bundle_from_string(b_text);
445         noti->b_key = _create_bundle_from_string(b_key);
446         noti->b_format_args = _create_bundle_from_string(b_format_args);
447         noti->b_image_path = _create_bundle_from_string(b_image_path);
448         noti->sound_path = _dup_string(sound_path);
449         noti->vibration_path = _dup_string(vibration_path);
450         noti->app_icon_path = _dup_string(app_icon_path);
451         noti->app_name = _dup_string(app_name);
452         noti->temp_title = _dup_string(temp_title);
453         noti->temp_content = _dup_string(temp_content);
454
455         noti->type = type;
456         noti->layout = layout;
457         noti->group_id = group_id;
458         noti->internal_group_id = internal_group_id;
459         noti->priv_id = priv_id;
460         noti->num_format_args = num_format_args;
461         noti->sound_type = sound_type;
462         noti->vibration_type = vibration_type;
463         noti->led_operation = led_operation;
464         noti->led_argb = led_argb;
465         noti->led_on_ms = led_on_ms;
466         noti->led_off_ms = led_off_ms;
467         noti->time = time;
468         noti->insert_time = insert_time;
469         noti->flags_for_property = flags_for_property;
470         noti->display_applist = display_applist;
471         noti->progress_size = progress_size;
472         noti->progress_percentage = progress_percentage;
473
474         return NOTIFICATION_ERROR_NONE;
475 }
476
477 EXPORT_API struct packet *notification_ipc_make_packet_from_noti(notification_h noti, const char *command, int packet_type)
478 {
479         struct packet *result = NULL;
480         char *args = NULL;
481         char *group_args = NULL;
482         char *b_image_path = NULL;
483         char *b_execute_option = NULL;
484         char *b_service_responding = NULL;
485         char *b_service_single_launch = NULL;
486         char *b_service_multi_launch = NULL;
487         char *b_text = NULL;
488         char *b_key = NULL;
489         char *b_format_args = NULL;
490         int flag_simmode = 0;
491         struct packet *(*func_to_create_packet)(const char *command, const char *fmt, ...);
492         const char *title_key = NULL;
493         char buf_key[32] = { 0, };
494
495         /* Decode bundle to insert DB */
496         if (noti->args) {
497                 bundle_encode(noti->args, (bundle_raw **) & args, NULL);
498         }
499         if (noti->group_args) {
500                 bundle_encode(noti->group_args, (bundle_raw **) & group_args,
501                               NULL);
502         }
503
504         if (noti->b_execute_option) {
505                 bundle_encode(noti->b_execute_option,
506                               (bundle_raw **) & b_execute_option, NULL);
507         }
508         if (noti->b_service_responding) {
509                 bundle_encode(noti->b_service_responding,
510                               (bundle_raw **) & b_service_responding, NULL);
511         }
512         if (noti->b_service_single_launch) {
513                 bundle_encode(noti->b_service_single_launch,
514                               (bundle_raw **) & b_service_single_launch, NULL);
515         }
516         if (noti->b_service_multi_launch) {
517                 bundle_encode(noti->b_service_multi_launch,
518                               (bundle_raw **) & b_service_multi_launch, NULL);
519         }
520
521         if (noti->b_text) {
522                 bundle_encode(noti->b_text, (bundle_raw **) & b_text, NULL);
523         }
524         if (noti->b_key) {
525                 bundle_encode(noti->b_key, (bundle_raw **) & b_key, NULL);
526         }
527         if (noti->b_format_args) {
528                 bundle_encode(noti->b_format_args,
529                               (bundle_raw **) & b_format_args, NULL);
530         }
531
532         if (noti->b_image_path) {
533                 bundle_encode(noti->b_image_path,
534                               (bundle_raw **) & b_image_path, NULL);
535         }
536
537         /* Check only simmode property is enable */
538         if (noti->flags_for_property & NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE) {
539                 flag_simmode = 1;
540         }
541
542         if (noti->b_key != NULL) {
543                 snprintf(buf_key, sizeof(buf_key), "%d",
544                          NOTIFICATION_TEXT_TYPE_TITLE);
545
546                 title_key = bundle_get_val(noti->b_key, buf_key);
547         }
548
549         if (title_key == NULL && noti->b_text != NULL) {
550                 snprintf(buf_key, sizeof(buf_key), "%d",
551                          NOTIFICATION_TEXT_TYPE_TITLE);
552
553                 title_key = bundle_get_val(noti->b_text, buf_key);
554         }
555
556         if (title_key == NULL) {
557                 title_key = noti->caller_pkgname;
558         }
559
560         if (packet_type == 1)
561                 func_to_create_packet = packet_create;
562         else if (packet_type == 2)
563                 func_to_create_packet = packet_create_noack;
564         else {
565                 goto out;
566         }
567
568         result = func_to_create_packet(command,
569                         "iiiiisssssssssssssisisisiiiiiiiiddssss",
570                         noti->type,
571                         noti->layout,
572                         noti->group_id,
573                         noti->internal_group_id,
574                         noti->priv_id,
575                         NOTIFICATION_CHECK_STR(noti->caller_pkgname),
576                         NOTIFICATION_CHECK_STR(noti->launch_pkgname),
577                         NOTIFICATION_CHECK_STR(args),
578                         NOTIFICATION_CHECK_STR(group_args),
579                         NOTIFICATION_CHECK_STR(b_execute_option),
580                         NOTIFICATION_CHECK_STR(b_service_responding),
581                         NOTIFICATION_CHECK_STR(b_service_single_launch),
582                         NOTIFICATION_CHECK_STR(b_service_multi_launch),
583                         NOTIFICATION_CHECK_STR(noti->domain),
584                         NOTIFICATION_CHECK_STR(noti->dir),
585                         NOTIFICATION_CHECK_STR(b_text),
586                         NOTIFICATION_CHECK_STR(b_key),
587                         NOTIFICATION_CHECK_STR(b_format_args),
588                         noti->num_format_args,
589                         NOTIFICATION_CHECK_STR(b_image_path),
590                         noti->sound_type,
591                         NOTIFICATION_CHECK_STR(noti->sound_path),
592                         noti->vibration_type,
593                         NOTIFICATION_CHECK_STR(noti->vibration_path),
594                         noti->led_operation,
595                         noti->led_argb,
596                         noti->led_on_ms,
597                         noti->led_off_ms,
598                         noti->time,
599                         noti->insert_time,
600                         noti->flags_for_property,
601                         noti->display_applist,
602                         noti->progress_size,
603                         noti->progress_percentage,
604                         NOTIFICATION_CHECK_STR(noti->app_icon_path),
605                         NOTIFICATION_CHECK_STR(noti->app_name),
606                         NOTIFICATION_CHECK_STR(noti->temp_title),
607                         NOTIFICATION_CHECK_STR(noti->temp_content));
608
609 out:
610         /* Free decoded data */
611         if (args) {
612                 free(args);
613         }
614         if (group_args) {
615                 free(group_args);
616         }
617
618         if (b_execute_option) {
619                 free(b_execute_option);
620         }
621         if (b_service_responding) {
622                 free(b_service_responding);
623         }
624         if (b_service_single_launch) {
625                 free(b_service_single_launch);
626         }
627         if (b_service_multi_launch) {
628                 free(b_service_multi_launch);
629         }
630
631         if (b_text) {
632                 free(b_text);
633         }
634         if (b_key) {
635                 free(b_key);
636         }
637         if (b_format_args) {
638                 free(b_format_args);
639         }
640
641         if (b_image_path) {
642                 free(b_image_path);
643         }
644
645         return result;
646 }
647
648 /*!
649  * functions to handler services
650  */
651 static struct packet *_handler_insert(pid_t pid, int handle, const struct packet *packet)
652 {
653         notification_h noti = NULL;
654
655         if (!packet) {
656                 NOTIFICATION_ERR("a packet is null");
657                 return NULL;
658         }
659         noti = notification_create(NOTIFICATION_TYPE_NOTI);
660         if (!noti) {
661                 NOTIFICATION_ERR("failed to create a notification");
662                 return NULL;
663         }
664         notification_ipc_make_noti_from_packet(noti, packet);
665
666         if (noti->flags_for_property
667                 & NOTIFICATION_PROP_DISABLE_UPDATE_ON_INSERT) {
668                 /* Disable changed cb */
669         } else {
670                 /* Enable changed cb */
671                 notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_INSERT, 1, &(noti->priv_id), 1, &noti);
672                 if (noti_op != NULL) {
673                         notification_call_changed_cb(noti_op, 1);
674                         free(noti_op);
675                 }
676         }
677         notification_free(noti);
678
679         return NULL;
680 }
681
682 static struct packet *_handler_update(pid_t pid, int handle, const struct packet *packet)
683 {
684         notification_h noti = NULL;
685
686         if (!packet) {
687                 NOTIFICATION_ERR("a packet is null");
688                 return NULL;
689         }
690
691         noti = notification_create(NOTIFICATION_TYPE_NOTI);
692         if (!noti) {
693                 NOTIFICATION_ERR("failed to create a notification");
694                 return NULL;
695         }
696
697         notification_ipc_make_noti_from_packet(noti, packet);
698
699         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_UPDATE, 1, &(noti->priv_id), 1, &noti);
700         if (noti_op != NULL) {
701                 notification_call_changed_cb(noti_op, 1);
702                 free(noti_op);
703         }
704
705         notification_free(noti);
706
707         return NULL;
708 }
709
710 static struct packet *_handler_refresh(pid_t pid, int handle, const struct packet *packet)
711 {
712         if (!packet) {
713                 NOTIFICATION_ERR("a packet is null");
714                 return NULL;
715         }
716         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_REFRESH, 1, NULL, 0, NULL);
717         if (noti_op != NULL) {
718                 notification_call_changed_cb(noti_op, 1);
719                 free(noti_op);
720         }
721
722         return NULL;
723 }
724
725 static struct packet *_handler_delete_single(pid_t pid, int handle, const struct packet *packet)
726 {
727         int num_deleted = 0;
728         int priv_id = NOTIFICATION_PRIV_ID_NONE;
729
730         if (!packet) {
731                 NOTIFICATION_ERR("a packet is null");
732                 return NULL;
733         }
734         if (packet_get(packet, "ii", &num_deleted, &priv_id) == 2) {
735                 notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_DELETE, 1, &priv_id, 1, NULL);
736                 if (noti_op != NULL) {
737                         notification_call_changed_cb(noti_op, 1);
738                         free(noti_op);
739                 }
740         }
741
742         return NULL;
743 }
744
745 static struct packet *_handler_delete_multiple(pid_t pid, int handle, const struct packet *packet)
746 {
747         int ret = 0;
748         int buf[10] = {0,};
749         int num_deleted = 0;
750
751         NOTIFICATION_ERR("delete_noti_multiple");
752
753         if (!packet) {
754                 NOTIFICATION_ERR("a packet is null");
755                 return NULL;
756         }
757         ret = packet_get(packet, "iiiiiiiiiii", &num_deleted,
758                         &(buf[0]),
759                         &(buf[1]),
760                         &(buf[2]),
761                         &(buf[3]),
762                         &(buf[4]),
763                         &(buf[5]),
764                         &(buf[6]),
765                         &(buf[7]),
766                         &(buf[8]),
767                         &(buf[9]));
768
769         NOTIFICATION_ERR("packet data count:%d", ret);
770         NOTIFICATION_ERR("packet data num deleted:%d", num_deleted);
771
772         int i = 0;
773         for (i = 0 ; i < 10 ; i++) {
774                 NOTIFICATION_ERR("packet data[%d]:%d",i, buf[i]);
775         }
776
777         if (ret == 11) {
778                 notification_op *noti_op = notification_ipc_create_op(
779                                 NOTIFICATION_OP_DELETE, num_deleted, buf, num_deleted, NULL);
780                 if (noti_op != NULL) {
781                         notification_call_changed_cb(noti_op, num_deleted);
782                         free(noti_op);
783                 }
784         }
785
786         return NULL;
787 }
788
789 static int _handler_service_register(pid_t pid, int handle, const struct packet *packet, void *data)
790 {
791         int ret;
792
793         if (!packet) {
794                 NOTIFICATION_ERR("Packet is not valid\n");
795                 ret = NOTIFICATION_ERROR_INVALID_DATA;
796         } else if (packet_get(packet, "i", &ret) != 1) {
797                 NOTIFICATION_ERR("Packet is not valid\n");
798                 ret = NOTIFICATION_ERROR_INVALID_DATA;
799         } else {
800                 if (ret == 0) {
801                         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_SERVICE_READY, 1, NULL, 1, NULL);
802                         if (noti_op != NULL) {
803                                 notification_call_changed_cb(noti_op, 1);
804                                 free(noti_op);
805                         }
806                 }
807         }
808         return ret;
809 }
810
811 /*!
812  * functions to initialize and register a monitor
813  */
814 static notification_error_e notification_ipc_monitor_register(void)
815 {
816         int ret;
817         struct packet *packet;
818         static struct method service_table[] = {
819                 {
820                         .cmd = "add_noti",
821                         .handler = _handler_insert,
822                 },
823                 {
824                         .cmd = "update_noti",
825                         .handler = _handler_update,
826                 },
827                 {
828                         .cmd = "refresh_noti",
829                         .handler = _handler_refresh,
830                 },
831                 {
832                         .cmd = "del_noti_single",
833                         .handler = _handler_delete_single,
834                 },
835                 {
836                         .cmd = "del_noti_multiple",
837                         .handler = _handler_delete_multiple,
838                 },
839                 {
840                         .cmd = NULL,
841                         .handler = NULL,
842                 },
843         };
844
845         if (s_info.initialized == 1) {
846                 return NOTIFICATION_ERROR_NONE;
847         } else {
848                 s_info.initialized = 1;
849         }
850
851         NOTIFICATION_ERR("register a service\n");
852
853         s_info.server_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table);
854         if (s_info.server_fd < 0) {
855                 NOTIFICATION_ERR("Failed to make a connection to the master\n");
856                 return NOTIFICATION_ERROR_IO;
857         }
858
859         packet = packet_create("service_register", "");
860         if (!packet) {
861                 NOTIFICATION_ERR("Failed to build a packet\n");
862                 return NOTIFICATION_ERROR_IO;
863         }
864
865         ret = com_core_packet_async_send(s_info.server_fd, packet, 1.0, _handler_service_register, NULL);
866         NOTIFICATION_DBG("Service register sent: %d\n", ret);
867         packet_destroy(packet);
868         if (ret != 0) {
869                 com_core_packet_client_fini(s_info.server_fd);
870                 s_info.server_fd = NOTIFICATION_ERROR_INVALID_DATA;
871                 ret = NOTIFICATION_ERROR_IO;
872         } else {
873                 ret = NOTIFICATION_ERROR_NONE;
874         }
875
876         NOTIFICATION_DBG("Server FD: %d\n", s_info.server_fd);
877         return ret;
878 }
879
880 notification_error_e notification_ipc_monitor_deregister(void)
881 {
882         if (s_info.initialized == 0) {
883                 return NOTIFICATION_ERROR_NONE;
884         }
885
886         com_core_packet_client_fini(s_info.server_fd);
887         s_info.server_fd = NOTIFICATION_ERROR_INVALID_DATA;
888
889         s_info.initialized = 0;
890
891         return NOTIFICATION_ERROR_NONE;
892 }
893
894 notification_error_e notification_ipc_monitor_init(void)
895 {
896         int ret = NOTIFICATION_ERROR_NONE;
897
898         if (notification_ipc_is_master_ready()) {
899                 ret = notification_ipc_monitor_register();
900         }
901
902         if (s_info.is_started_cb_set_svc == 0) {
903                 _set_master_started_cb(_master_started_cb_service);
904                 s_info.is_started_cb_set_svc = 1;
905         }
906
907         return ret;
908 }
909
910 notification_error_e notification_ipc_monitor_fini(void)
911 {
912         int ret = NOTIFICATION_ERROR_NONE;
913
914         if (s_info.is_started_cb_set_svc == 1) {
915                 _unset_master_started_cb(_master_started_cb_service);
916                 s_info.is_started_cb_set_svc = 0;
917         }
918
919         ret = notification_ipc_monitor_deregister();
920
921         return ret;
922 }
923
924 /*!
925  * functions to request the service
926  */
927 notification_error_e notification_ipc_request_insert(notification_h noti, int *priv_id)
928 {
929         int status = 0;
930         int id = NOTIFICATION_PRIV_ID_NONE;
931         struct packet *packet;
932         struct packet *result;
933
934         /* Initialize private ID */
935         noti->priv_id = NOTIFICATION_PRIV_ID_NONE;
936         noti->group_id = NOTIFICATION_GROUP_ID_NONE;
937         noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
938
939         packet = notification_ipc_make_packet_from_noti(noti, "add_noti", 1);
940         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
941                         packet,
942                         NOTIFICATION_IPC_TIMEOUT);
943         packet_destroy(packet);
944
945         if (result != NULL) {
946                 if (packet_get(result, "ii", &status, &id) != 2) {
947                         NOTIFICATION_ERR("Failed to get a result packet");
948                         packet_unref(result);
949                         return NOTIFICATION_ERROR_IO;
950                 }
951
952                 if (status != NOTIFICATION_ERROR_NONE) {
953                         packet_unref(result);
954                         return status;
955                 }
956                 packet_unref(result);
957         } else {
958                 notification_ipc_is_master_ready();
959                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
960         }
961
962         if (priv_id != NULL) {
963                 *priv_id = id;
964         }
965
966         return NOTIFICATION_ERROR_NONE;
967 }
968
969 notification_error_e notification_ipc_request_delete_single(notification_type_e type, char *pkgname, int priv_id)
970 {
971         int status = 0;
972         int id = NOTIFICATION_PRIV_ID_NONE;
973         struct packet *packet;
974         struct packet *result;
975
976         packet = packet_create("del_noti_single", "si", pkgname, priv_id);
977         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
978                         packet,
979                         NOTIFICATION_IPC_TIMEOUT);
980         packet_destroy(packet);
981
982         if (result != NULL) {
983                 if (packet_get(result, "ii", &status, &id) != 2) {
984                         NOTIFICATION_ERR("Failed to get a result packet");
985                         packet_unref(result);
986                         return NOTIFICATION_ERROR_IO;
987                 }
988                 packet_unref(result);
989         } else {
990                 notification_ipc_is_master_ready();
991                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
992         }
993
994         return status;
995 }
996
997 notification_error_e notification_ipc_request_delete_multiple(notification_type_e type, char *pkgname)
998 {
999         int status = 0;
1000         int num_deleted = 0;
1001         struct packet *packet;
1002         struct packet *result;
1003
1004         packet = packet_create("del_noti_multiple", "si", pkgname, type);
1005         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1006                         packet,
1007                         NOTIFICATION_IPC_TIMEOUT);
1008         packet_destroy(packet);
1009
1010         if (result != NULL) {
1011                 if (packet_get(result, "ii", &status, &num_deleted) != 2) {
1012                         NOTIFICATION_ERR("Failed to get a result packet");
1013                         packet_unref(result);
1014                         return NOTIFICATION_ERROR_IO;
1015                 }
1016                 NOTIFICATION_ERR("num deleted:%d", num_deleted);
1017                 packet_unref(result);
1018         } else {
1019                 notification_ipc_is_master_ready();
1020                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1021         }
1022
1023         return status;
1024 }
1025
1026 notification_error_e notification_ipc_request_update(notification_h noti)
1027 {
1028         int status = 0;
1029         int id = NOTIFICATION_PRIV_ID_NONE;
1030         struct packet *packet;
1031         struct packet *result;
1032
1033         packet = notification_ipc_make_packet_from_noti(noti, "update_noti", 1);
1034         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1035                         packet,
1036                         NOTIFICATION_IPC_TIMEOUT);
1037         packet_destroy(packet);
1038
1039         if (result != NULL) {
1040                 if (packet_get(result, "ii", &status, &id) != 2) {
1041                         NOTIFICATION_ERR("Failed to get a result packet");
1042                         packet_unref(result);
1043                         return NOTIFICATION_ERROR_IO;
1044                 }
1045                 packet_unref(result);
1046         } else {
1047                 notification_ipc_is_master_ready();
1048                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1049         }
1050
1051         return status;
1052 }
1053
1054 notification_error_e notification_ipc_request_refresh(void)
1055 {
1056         int status = 0;
1057         struct packet *packet;
1058         struct packet *result;
1059
1060         packet = packet_create("refresh_noti", "i", NOTIFICATION_OP_REFRESH);
1061         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1062                         packet,
1063                         NOTIFICATION_IPC_TIMEOUT);
1064         packet_destroy(packet);
1065
1066         if (result != NULL) {
1067                 if (packet_get(result, "i", &status) != 1) {
1068                         NOTIFICATION_ERR("Failed to get a result packet");
1069                         packet_unref(result);
1070                         return NOTIFICATION_ERROR_IO;
1071                 }
1072                 packet_unref(result);
1073         } else {
1074                 notification_ipc_is_master_ready();
1075                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1076         }
1077
1078         return status;
1079 }