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