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 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         time_t time;
365         time_t insert_time;
366         int flags_for_property;
367         int display_applist;
368         double progress_size;
369         double progress_percentage;
370         char *app_icon_path = NULL;
371         char *app_name = NULL;
372         char *temp_title = NULL;
373         char *temp_content = NULL;
374
375         if (noti == NULL) {
376                 NOTIFICATION_ERR("invalid data");
377                 return NOTIFICATION_ERROR_INVALID_DATA;
378         }
379
380         ret = packet_get(packet,
381                         "iiiiisssssssssssssisisisiiiiiiddssss",
382                         &type,
383                         &layout,
384                         &group_id,
385                         &internal_group_id,
386                         &priv_id,
387                         &caller_pkgname,
388                         &launch_pkgname,
389                         &args,
390                         &group_args,
391                         &b_execute_option,
392                         &b_service_responding,
393                         &b_service_single_launch,
394                         &b_service_multi_launch,
395                         &domain,
396                         &dir,
397                         &b_text,
398                         &b_key,
399                         &b_format_args,
400                         &num_format_args,
401                         &b_image_path,
402                         &sound_type,
403                         &sound_path,
404                         &vibration_type,
405                         &vibration_path,
406                         &led_operation,
407                         &led_argb,
408                         &time,
409                         &insert_time,
410                         &flags_for_property,
411                         &display_applist,
412                         &progress_size,
413                         &progress_percentage,
414                         &app_icon_path,
415                         &app_name,
416                         &temp_title,
417                         &temp_content);
418
419         if (ret != 36) {
420                 NOTIFICATION_ERR("failed to create a noti from packet");
421                 return NOTIFICATION_ERROR_INVALID_DATA;
422         }
423
424         /*!
425          * This is already allocated from the notification_create function.
426          * Before reallocate string to here.
427          * We have to release old one first.
428          */
429         free(noti->caller_pkgname);
430         noti->caller_pkgname = _dup_string(caller_pkgname);
431         noti->launch_pkgname = _dup_string(launch_pkgname);
432         noti->args = _create_bundle_from_string(args);
433         noti->group_args = _create_bundle_from_string(group_args);
434         noti->b_execute_option = _create_bundle_from_string(b_execute_option);
435         noti->b_service_responding = _create_bundle_from_string(b_service_responding);
436         noti->b_service_single_launch = _create_bundle_from_string(b_service_single_launch);
437         noti->b_service_multi_launch = _create_bundle_from_string(b_service_multi_launch);
438         noti->domain = _dup_string(domain);
439         noti->dir = _dup_string(dir);
440         noti->b_text = _create_bundle_from_string(b_text);
441         noti->b_key = _create_bundle_from_string(b_key);
442         noti->b_format_args = _create_bundle_from_string(b_format_args);
443         noti->b_image_path = _create_bundle_from_string(b_image_path);
444         noti->sound_path = _dup_string(sound_path);
445         noti->vibration_path = _dup_string(vibration_path);
446         noti->app_icon_path = _dup_string(app_icon_path);
447         noti->app_name = _dup_string(app_name);
448         noti->temp_title = _dup_string(temp_title);
449         noti->temp_content = _dup_string(temp_content);
450
451         noti->type = type;
452         noti->layout = layout;
453         noti->group_id = group_id;
454         noti->internal_group_id = internal_group_id;
455         noti->priv_id = priv_id;
456         noti->num_format_args = num_format_args;
457         noti->sound_type = sound_type;
458         noti->vibration_type = vibration_type;
459         noti->led_operation = led_operation;
460         noti->led_argb = led_argb;
461         noti->time = time;
462         noti->insert_time = insert_time;
463         noti->flags_for_property = flags_for_property;
464         noti->display_applist = display_applist;
465         noti->progress_size = progress_size;
466         noti->progress_percentage = progress_percentage;
467
468         return NOTIFICATION_ERROR_NONE;
469 }
470
471 EXPORT_API struct packet *notification_ipc_make_packet_from_noti(notification_h noti, const char *command, int packet_type)
472 {
473         struct packet *result = NULL;
474         char *args = NULL;
475         char *group_args = NULL;
476         char *b_image_path = NULL;
477         char *b_execute_option = NULL;
478         char *b_service_responding = NULL;
479         char *b_service_single_launch = NULL;
480         char *b_service_multi_launch = NULL;
481         char *b_text = NULL;
482         char *b_key = NULL;
483         char *b_format_args = NULL;
484         int flag_simmode = 0;
485         struct packet *(*func_to_create_packet)(const char *command, const char *fmt, ...);
486         const char *title_key = NULL;
487         char buf_key[32] = { 0, };
488
489         /* Decode bundle to insert DB */
490         if (noti->args) {
491                 bundle_encode(noti->args, (bundle_raw **) & args, NULL);
492         }
493         if (noti->group_args) {
494                 bundle_encode(noti->group_args, (bundle_raw **) & group_args,
495                               NULL);
496         }
497
498         if (noti->b_execute_option) {
499                 bundle_encode(noti->b_execute_option,
500                               (bundle_raw **) & b_execute_option, NULL);
501         }
502         if (noti->b_service_responding) {
503                 bundle_encode(noti->b_service_responding,
504                               (bundle_raw **) & b_service_responding, NULL);
505         }
506         if (noti->b_service_single_launch) {
507                 bundle_encode(noti->b_service_single_launch,
508                               (bundle_raw **) & b_service_single_launch, NULL);
509         }
510         if (noti->b_service_multi_launch) {
511                 bundle_encode(noti->b_service_multi_launch,
512                               (bundle_raw **) & b_service_multi_launch, NULL);
513         }
514
515         if (noti->b_text) {
516                 bundle_encode(noti->b_text, (bundle_raw **) & b_text, NULL);
517         }
518         if (noti->b_key) {
519                 bundle_encode(noti->b_key, (bundle_raw **) & b_key, NULL);
520         }
521         if (noti->b_format_args) {
522                 bundle_encode(noti->b_format_args,
523                               (bundle_raw **) & b_format_args, NULL);
524         }
525
526         if (noti->b_image_path) {
527                 bundle_encode(noti->b_image_path,
528                               (bundle_raw **) & b_image_path, NULL);
529         }
530
531         /* Check only simmode property is enable */
532         if (noti->flags_for_property & NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE) {
533                 flag_simmode = 1;
534         }
535
536         if (noti->b_key != NULL) {
537                 snprintf(buf_key, sizeof(buf_key), "%d",
538                          NOTIFICATION_TEXT_TYPE_TITLE);
539
540                 title_key = bundle_get_val(noti->b_key, buf_key);
541         }
542
543         if (title_key == NULL && noti->b_text != NULL) {
544                 snprintf(buf_key, sizeof(buf_key), "%d",
545                          NOTIFICATION_TEXT_TYPE_TITLE);
546
547                 title_key = bundle_get_val(noti->b_text, buf_key);
548         }
549
550         if (title_key == NULL) {
551                 title_key = noti->caller_pkgname;
552         }
553
554         if (packet_type == 1)
555                 func_to_create_packet = packet_create;
556         else if (packet_type == 2)
557                 func_to_create_packet = packet_create_noack;
558         else {
559                 goto out;
560         }
561
562         result = func_to_create_packet(command,
563                         "iiiiisssssssssssssisisisiiiiiiddssss",
564                         noti->type,
565                         noti->layout,
566                         noti->group_id,
567                         noti->internal_group_id,
568                         noti->priv_id,
569                         NOTIFICATION_CHECK_STR(noti->caller_pkgname),
570                         NOTIFICATION_CHECK_STR(noti->launch_pkgname),
571                         NOTIFICATION_CHECK_STR(args),
572                         NOTIFICATION_CHECK_STR(group_args),
573                         NOTIFICATION_CHECK_STR(b_execute_option),
574                         NOTIFICATION_CHECK_STR(b_service_responding),
575                         NOTIFICATION_CHECK_STR(b_service_single_launch),
576                         NOTIFICATION_CHECK_STR(b_service_multi_launch),
577                         NOTIFICATION_CHECK_STR(noti->domain),
578                         NOTIFICATION_CHECK_STR(noti->dir),
579                         NOTIFICATION_CHECK_STR(b_text),
580                         NOTIFICATION_CHECK_STR(b_key),
581                         NOTIFICATION_CHECK_STR(b_format_args),
582                         noti->num_format_args,
583                         NOTIFICATION_CHECK_STR(b_image_path),
584                         noti->sound_type,
585                         NOTIFICATION_CHECK_STR(noti->sound_path),
586                         noti->vibration_type,
587                         NOTIFICATION_CHECK_STR(noti->vibration_path),
588                         noti->led_operation,
589                         noti->led_argb,
590                         noti->time,
591                         noti->insert_time,
592                         noti->flags_for_property,
593                         noti->display_applist,
594                         noti->progress_size,
595                         noti->progress_percentage,
596                         NOTIFICATION_CHECK_STR(noti->app_icon_path),
597                         NOTIFICATION_CHECK_STR(noti->app_name),
598                         NOTIFICATION_CHECK_STR(noti->temp_title),
599                         NOTIFICATION_CHECK_STR(noti->temp_content));
600
601 out:
602         /* Free decoded data */
603         if (args) {
604                 free(args);
605         }
606         if (group_args) {
607                 free(group_args);
608         }
609
610         if (b_execute_option) {
611                 free(b_execute_option);
612         }
613         if (b_service_responding) {
614                 free(b_service_responding);
615         }
616         if (b_service_single_launch) {
617                 free(b_service_single_launch);
618         }
619         if (b_service_multi_launch) {
620                 free(b_service_multi_launch);
621         }
622
623         if (b_text) {
624                 free(b_text);
625         }
626         if (b_key) {
627                 free(b_key);
628         }
629         if (b_format_args) {
630                 free(b_format_args);
631         }
632
633         if (b_image_path) {
634                 free(b_image_path);
635         }
636
637         return result;
638 }
639
640 /*!
641  * functions to handler services
642  */
643 static struct packet *_handler_insert(pid_t pid, int handle, const struct packet *packet)
644 {
645         notification_h noti = NULL;
646
647         if (!packet) {
648                 NOTIFICATION_ERR("a packet is null");
649                 return NULL;
650         }
651         noti = notification_create(NOTIFICATION_TYPE_NOTI);
652         if (!noti) {
653                 NOTIFICATION_ERR("failed to create a notification");
654                 return NULL;
655         }
656         notification_ipc_make_noti_from_packet(noti, packet);
657
658         if (noti->flags_for_property
659                 & NOTIFICATION_PROP_DISABLE_UPDATE_ON_INSERT) {
660                 /* Disable changed cb */
661         } else {
662                 /* Enable changed cb */
663                 notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_INSERT, 1, &(noti->priv_id), 1, &noti);
664                 if (noti_op != NULL) {
665                         notification_call_changed_cb(noti_op, 1);
666                         free(noti_op);
667                 }
668         }
669         notification_free(noti);
670
671         return NULL;
672 }
673
674 static struct packet *_handler_update(pid_t pid, int handle, const struct packet *packet)
675 {
676         notification_h noti = NULL;
677
678         if (!packet) {
679                 NOTIFICATION_ERR("a packet is null");
680                 return NULL;
681         }
682
683         noti = notification_create(NOTIFICATION_TYPE_NOTI);
684         if (!noti) {
685                 NOTIFICATION_ERR("failed to create a notification");
686                 return NULL;
687         }
688
689         notification_ipc_make_noti_from_packet(noti, packet);
690
691         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_UPDATE, 1, &(noti->priv_id), 1, &noti);
692         if (noti_op != NULL) {
693                 notification_call_changed_cb(noti_op, 1);
694                 free(noti_op);
695         }
696
697         notification_free(noti);
698
699         return NULL;
700 }
701
702 static struct packet *_handler_refresh(pid_t pid, int handle, const struct packet *packet)
703 {
704         if (!packet) {
705                 NOTIFICATION_ERR("a packet is null");
706                 return NULL;
707         }
708         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_REFRESH, 1, NULL, 0, NULL);
709         if (noti_op != NULL) {
710                 notification_call_changed_cb(noti_op, 1);
711                 free(noti_op);
712         }
713
714         return NULL;
715 }
716
717 static struct packet *_handler_delete_single(pid_t pid, int handle, const struct packet *packet)
718 {
719         int num_deleted = 0;
720         int priv_id = NOTIFICATION_PRIV_ID_NONE;
721
722         if (!packet) {
723                 NOTIFICATION_ERR("a packet is null");
724                 return NULL;
725         }
726         if (packet_get(packet, "ii", &num_deleted, &priv_id) == 2) {
727                 notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_DELETE, 1, &priv_id, 1, NULL);
728                 if (noti_op != NULL) {
729                         notification_call_changed_cb(noti_op, 1);
730                         free(noti_op);
731                 }
732         }
733
734         return NULL;
735 }
736
737 static struct packet *_handler_delete_multiple(pid_t pid, int handle, const struct packet *packet)
738 {
739         int ret = 0;
740         int buf[10] = {0,};
741         int num_deleted = 0;
742
743         NOTIFICATION_ERR("delete_noti_multiple");
744
745         if (!packet) {
746                 NOTIFICATION_ERR("a packet is null");
747                 return NULL;
748         }
749         ret = packet_get(packet, "iiiiiiiiiii", &num_deleted,
750                         &(buf[0]),
751                         &(buf[1]),
752                         &(buf[2]),
753                         &(buf[3]),
754                         &(buf[4]),
755                         &(buf[5]),
756                         &(buf[6]),
757                         &(buf[7]),
758                         &(buf[8]),
759                         &(buf[9]));
760
761         NOTIFICATION_ERR("packet data count:%d", ret);
762         NOTIFICATION_ERR("packet data num deleted:%d", num_deleted);
763
764         int i = 0;
765         for (i = 0 ; i < 10 ; i++) {
766                 NOTIFICATION_ERR("packet data[%d]:%d",i, buf[i]);
767         }
768
769         if (ret == 11) {
770                 notification_op *noti_op = notification_ipc_create_op(
771                                 NOTIFICATION_OP_DELETE, num_deleted, buf, num_deleted, NULL);
772                 if (noti_op != NULL) {
773                         notification_call_changed_cb(noti_op, num_deleted);
774                         free(noti_op);
775                 }
776         }
777
778         return NULL;
779 }
780
781 static int _handler_service_register(pid_t pid, int handle, const struct packet *packet, void *data)
782 {
783         int ret;
784
785         if (!packet) {
786                 NOTIFICATION_ERR("Packet is not valid\n");
787                 ret = NOTIFICATION_ERROR_INVALID_DATA;
788         } else if (packet_get(packet, "i", &ret) != 1) {
789                 NOTIFICATION_ERR("Packet is not valid\n");
790                 ret = NOTIFICATION_ERROR_INVALID_DATA;
791         } else {
792                 if (ret == 0) {
793                         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_SERVICE_READY, 1, NULL, 1, NULL);
794                         if (noti_op != NULL) {
795                                 notification_call_changed_cb(noti_op, 1);
796                                 free(noti_op);
797                         }
798                 }
799         }
800         return ret;
801 }
802
803 /*!
804  * functions to initialize and register a monitor
805  */
806 static notification_error_e notification_ipc_monitor_register(void)
807 {
808         int ret;
809         struct packet *packet;
810         static struct method service_table[] = {
811                 {
812                         .cmd = "add_noti",
813                         .handler = _handler_insert,
814                 },
815                 {
816                         .cmd = "update_noti",
817                         .handler = _handler_update,
818                 },
819                 {
820                         .cmd = "refresh_noti",
821                         .handler = _handler_refresh,
822                 },
823                 {
824                         .cmd = "del_noti_single",
825                         .handler = _handler_delete_single,
826                 },
827                 {
828                         .cmd = "del_noti_multiple",
829                         .handler = _handler_delete_multiple,
830                 },
831                 {
832                         .cmd = NULL,
833                         .handler = NULL,
834                 },
835         };
836
837         if (s_info.initialized == 1) {
838                 return NOTIFICATION_ERROR_NONE;
839         } else {
840                 s_info.initialized = 1;
841         }
842
843         NOTIFICATION_ERR("register a service\n");
844
845         s_info.server_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table);
846         if (s_info.server_fd < 0) {
847                 NOTIFICATION_ERR("Failed to make a connection to the master\n");
848                 return NOTIFICATION_ERROR_IO;
849         }
850
851         packet = packet_create("service_register", "");
852         if (!packet) {
853                 NOTIFICATION_ERR("Failed to build a packet\n");
854                 return NOTIFICATION_ERROR_IO;
855         }
856
857         ret = com_core_packet_async_send(s_info.server_fd, packet, 1.0, _handler_service_register, NULL);
858         NOTIFICATION_DBG("Service register sent: %d\n", ret);
859         packet_destroy(packet);
860         if (ret != 0) {
861                 com_core_packet_client_fini(s_info.server_fd);
862                 s_info.server_fd = NOTIFICATION_ERROR_INVALID_DATA;
863                 ret = NOTIFICATION_ERROR_IO;
864         } else {
865                 ret = NOTIFICATION_ERROR_NONE;
866         }
867
868         NOTIFICATION_DBG("Server FD: %d\n", s_info.server_fd);
869         return ret;
870 }
871
872 notification_error_e notification_ipc_monitor_deregister(void)
873 {
874         if (s_info.initialized == 0) {
875                 return NOTIFICATION_ERROR_NONE;
876         }
877
878         com_core_packet_client_fini(s_info.server_fd);
879         s_info.server_fd = NOTIFICATION_ERROR_INVALID_DATA;
880
881         s_info.initialized = 0;
882
883         return NOTIFICATION_ERROR_NONE;
884 }
885
886 notification_error_e notification_ipc_monitor_init(void)
887 {
888         int ret = NOTIFICATION_ERROR_NONE;
889
890         if (notification_ipc_is_master_ready()) {
891                 ret = notification_ipc_monitor_register();
892         }
893
894         if (s_info.is_started_cb_set_svc == 0) {
895                 _set_master_started_cb(_master_started_cb_service);
896                 s_info.is_started_cb_set_svc = 1;
897         }
898
899         return ret;
900 }
901
902 notification_error_e notification_ipc_monitor_fini(void)
903 {
904         int ret = NOTIFICATION_ERROR_NONE;
905
906         if (s_info.is_started_cb_set_svc == 1) {
907                 _unset_master_started_cb(_master_started_cb_service);
908                 s_info.is_started_cb_set_svc = 0;
909         }
910
911         ret = notification_ipc_monitor_deregister();
912
913         return ret;
914 }
915
916 /*!
917  * functions to request the service
918  */
919 notification_error_e notification_ipc_request_insert(notification_h noti, int *priv_id)
920 {
921         int status = 0;
922         int id = NOTIFICATION_PRIV_ID_NONE;
923         struct packet *packet;
924         struct packet *result;
925
926         /* Initialize private ID */
927         noti->priv_id = NOTIFICATION_PRIV_ID_NONE;
928         noti->group_id = NOTIFICATION_GROUP_ID_NONE;
929         noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
930
931         packet = notification_ipc_make_packet_from_noti(noti, "add_noti", 1);
932         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
933                         packet,
934                         NOTIFICATION_IPC_TIMEOUT);
935         packet_destroy(packet);
936
937         if (result != NULL) {
938                 if (packet_get(result, "ii", &status, &id) != 2) {
939                         NOTIFICATION_ERR("Failed to get a result packet");
940                         packet_unref(result);
941                         return NOTIFICATION_ERROR_IO;
942                 }
943
944                 if (status != NOTIFICATION_ERROR_NONE) {
945                         return status;
946                 }
947         } else {
948                 notification_ipc_is_master_ready();
949                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
950         }
951
952         if (priv_id != NULL) {
953                 *priv_id = id;
954         }
955
956         return NOTIFICATION_ERROR_NONE;
957 }
958
959 notification_error_e notification_ipc_request_delete_single(notification_type_e type, char *pkgname, int priv_id)
960 {
961         int status = 0;
962         int id = NOTIFICATION_PRIV_ID_NONE;
963         struct packet *packet;
964         struct packet *result;
965
966         packet = packet_create("del_noti_single", "si", pkgname, priv_id);
967         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
968                         packet,
969                         NOTIFICATION_IPC_TIMEOUT);
970         packet_destroy(packet);
971
972         if (result != NULL) {
973                 if (packet_get(result, "ii", &status, &id) != 2) {
974                         NOTIFICATION_ERR("Failed to get a result packet");
975                         packet_unref(result);
976                         return NOTIFICATION_ERROR_IO;
977                 }
978         } else {
979                 notification_ipc_is_master_ready();
980                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
981         }
982
983         return status;
984 }
985
986 notification_error_e notification_ipc_request_delete_multiple(notification_type_e type, char *pkgname)
987 {
988         int status = 0;
989         int num_deleted = 0;
990         struct packet *packet;
991         struct packet *result;
992
993         packet = packet_create("del_noti_multiple", "si", pkgname, type);
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, &num_deleted) != 2) {
1001                         NOTIFICATION_ERR("Failed to get a result packet");
1002                         packet_unref(result);
1003                         return NOTIFICATION_ERROR_IO;
1004                 }
1005                 NOTIFICATION_ERR("num deleted:%d", num_deleted);
1006         } else {
1007                 notification_ipc_is_master_ready();
1008                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1009         }
1010
1011         return status;
1012 }
1013
1014 notification_error_e notification_ipc_request_update(notification_h noti)
1015 {
1016         int status = 0;
1017         int id = NOTIFICATION_PRIV_ID_NONE;
1018         struct packet *packet;
1019         struct packet *result;
1020
1021         packet = notification_ipc_make_packet_from_noti(noti, "update_noti", 1);
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, &id) != 2) {
1029                         NOTIFICATION_ERR("Failed to get a result packet");
1030                         packet_unref(result);
1031                         return NOTIFICATION_ERROR_IO;
1032                 }
1033         } else {
1034                 notification_ipc_is_master_ready();
1035                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1036         }
1037
1038         return status;
1039 }
1040
1041 notification_error_e notification_ipc_request_refresh(void)
1042 {
1043         int status = 0;
1044         struct packet *packet;
1045         struct packet *result;
1046
1047         packet = packet_create("refresh_noti", "i", NOTIFICATION_OP_REFRESH);
1048         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1049                         packet,
1050                         NOTIFICATION_IPC_TIMEOUT);
1051         packet_destroy(packet);
1052
1053         if (result != NULL) {
1054                 if (packet_get(result, "i", &status) != 1) {
1055                         NOTIFICATION_ERR("Failed to get a result packet");
1056                         packet_unref(result);
1057                         return NOTIFICATION_ERROR_IO;
1058                 }
1059         } else {
1060                 notification_ipc_is_master_ready();
1061                 return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1062         }
1063
1064         return status;
1065 }