Merge from tizen 2.4 latest.
[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_private.h>
37 #include <notification_debug.h>
38 #include <notification_setting_internal.h>
39
40 #define NOTIFICATION_IPC_TIMEOUT 0.0
41
42 #if !defined(VCONFKEY_MASTER_STARTED)
43 #define VCONFKEY_MASTER_STARTED "memory/data-provider-master/started"
44 #endif
45
46 static struct info {
47         int server_fd;
48         int server_cl_fd;
49         int server_cl_fd_ref_cnt;
50         int client_fd;
51         const char *socket_file;
52         struct {
53                 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);
54                 void *data;
55         } server_cb;
56         int initialized;
57         int is_started_cb_set_svc;
58         int is_started_cb_set_task;
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         .is_started_cb_set_task = 0,
68 };
69
70 typedef struct _task_list task_list;
71 struct _task_list {
72         task_list *prev;
73         task_list *next;
74
75         void (*task_cb) (void *data);
76         void *data;
77 };
78
79 typedef struct _result_cb_item {
80         void (*result_cb)(int priv_id, int result, void *data);
81         void *data;
82 } result_cb_item;
83
84 static task_list *g_task_list;
85
86 static int notification_ipc_monitor_register(void);
87 static int notification_ipc_monitor_deregister(void);
88 static void _do_deffered_task(void);
89 static void _master_started_cb_task(keynode_t *node, void *data);
90
91 static inline char *_string_get(char *string)
92 {
93         if (string == NULL) {
94                 return NULL;
95         }
96         if (string[0] == '\0') {
97                 return NULL;
98         }
99
100         return string;
101 }
102
103 /*!
104  * functions to check state of master
105  */
106 static inline void _set_master_started_cb(vconf_callback_fn cb) {
107         int ret = -1;
108
109         ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED,
110                         cb, NULL);
111         if (ret != 0) {
112                 NOTIFICATION_ERR("failed to notify key(%s) : %d",
113                                 VCONFKEY_MASTER_STARTED, ret);
114         }
115 }
116
117 static inline void _unset_master_started_cb(vconf_callback_fn cb) {
118         int ret = -1;
119
120         ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED,
121                         cb);
122         if (ret != 0) {
123                 NOTIFICATION_ERR("failed to notify key(%s) : %d",
124                                 VCONFKEY_MASTER_STARTED, ret);
125         }
126 }
127
128 int notification_ipc_is_master_ready(void)
129 {
130         int ret = -1, is_master_started = 0;
131
132         ret = vconf_get_bool(VCONFKEY_MASTER_STARTED, &is_master_started);
133         if (ret == 0 && is_master_started == 1) {
134                 NOTIFICATION_ERR("the master has been started");
135         } else {
136                 is_master_started = 0;
137                 NOTIFICATION_ERR("the master has been stopped");
138         }
139
140         return is_master_started;
141 }
142
143 int
144 notification_ipc_add_deffered_task(
145                 void (*deferred_task_cb)(void *data),
146                 void *user_data)
147 {
148         task_list *list = NULL;
149         task_list *list_new = NULL;
150
151         list_new =
152             (task_list *) malloc(sizeof(task_list));
153
154         if (list_new == NULL) {
155                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
156         }
157
158         if (s_info.is_started_cb_set_task == 0) {
159                 _set_master_started_cb(_master_started_cb_task);
160                 s_info.is_started_cb_set_task = 1;
161         }
162
163         list_new->next = NULL;
164         list_new->prev = NULL;
165
166         list_new->task_cb = deferred_task_cb;
167         list_new->data = user_data;
168
169         if (g_task_list == NULL) {
170                 g_task_list = list_new;
171         } else {
172                 list = g_task_list;
173
174                 while (list->next != NULL) {
175                         list = list->next;
176                 }
177
178                 list->next = list_new;
179                 list_new->prev = list;
180         }
181         return NOTIFICATION_ERROR_NONE;
182 }
183
184 int
185 notification_ipc_del_deffered_task(
186                 void (*deferred_task_cb)(void *data))
187 {
188         task_list *list_del = NULL;
189         task_list *list_prev = NULL;
190         task_list *list_next = NULL;
191
192         list_del = g_task_list;
193
194         if (list_del == NULL) {
195                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
196         }
197
198         while (list_del->prev != NULL) {
199                 list_del = list_del->prev;
200         }
201
202         do {
203                 if (list_del->task_cb == deferred_task_cb) {
204                         list_prev = list_del->prev;
205                         list_next = list_del->next;
206
207                         if (list_prev == NULL) {
208                                 g_task_list = list_next;
209                         } else {
210                                 list_prev->next = list_next;
211                         }
212
213                         if (list_next == NULL) {
214                                 if (list_prev != NULL) {
215                                         list_prev->next = NULL;
216                                 }
217                         } else {
218                                 list_next->prev = list_prev;
219                         }
220
221                         free(list_del);
222
223                         if (g_task_list == NULL) {
224                                 if (s_info.is_started_cb_set_task == 1) {
225                                         _unset_master_started_cb(_master_started_cb_task);
226                                         s_info.is_started_cb_set_task = 0;
227                                 }
228                         }
229
230                         return NOTIFICATION_ERROR_NONE;
231                 }
232                 list_del = list_del->next;
233         } while (list_del != NULL);
234
235         return NOTIFICATION_ERROR_INVALID_PARAMETER;
236 }
237
238 static void _do_deffered_task(void) {
239         task_list *list_do = NULL;
240         task_list *list_temp = NULL;
241
242         if (g_task_list == NULL) {
243                 return;
244         }
245
246         list_do = g_task_list;
247         g_task_list = NULL;
248         if (s_info.is_started_cb_set_task == 1) {
249                 _unset_master_started_cb(_master_started_cb_task);
250                 s_info.is_started_cb_set_task = 0;
251         }
252
253         while (list_do->prev != NULL) {
254                 list_do = list_do->prev;
255         }
256
257         while (list_do != NULL) {
258                 if (list_do->task_cb != NULL) {
259                         list_do->task_cb(list_do->data);
260                         NOTIFICATION_DBG("called:%p", list_do->task_cb);
261                 }
262                 list_temp = list_do->next;
263                 free(list_do);
264                 list_do = list_temp;
265         }
266 }
267
268 static void _master_started_cb_service(keynode_t *node,
269                 void *data) {
270         int ret = NOTIFICATION_ERROR_NONE;
271
272         if (notification_ipc_is_master_ready()) {
273                 NOTIFICATION_ERR("try to register a notification service");
274                 ret = notification_ipc_monitor_deregister();
275                 if (ret != NOTIFICATION_ERROR_NONE) {
276                         NOTIFICATION_ERR("failed to unregister a monitor");
277                 }
278                 ret = notification_ipc_monitor_register();
279                 if (ret != NOTIFICATION_ERROR_NONE) {
280                         NOTIFICATION_ERR("failed to register a monitor");
281                 }
282         } else {
283                 NOTIFICATION_ERR("try to unregister a notification service");
284                 ret = notification_ipc_monitor_deregister();
285                 if (ret != NOTIFICATION_ERROR_NONE) {
286                         NOTIFICATION_ERR("failed to deregister a monitor");
287                 }
288         }
289 }
290
291 static void _master_started_cb_task(keynode_t *node,
292                 void *data) {
293
294         if (notification_ipc_is_master_ready()) {
295                 _do_deffered_task();
296         }
297 }
298
299 /*!
300  * functions to create operation list
301  */
302 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)
303 {
304         int i = 0;
305         notification_op *op_list = NULL;
306
307         if (num_op <= 0) {
308                 return NULL;
309         }
310
311         op_list = (notification_op *)malloc(sizeof(notification_op) * num_op);
312
313         if (op_list == NULL) {
314                 NOTIFICATION_ERR("malloc failed");
315                 return NULL;
316         }
317
318         memset(op_list, 0x0, sizeof(notification_op) * num_op);
319
320         for (i = 0; i < num_op; i++) {
321                 (op_list + i)->type = type;
322                 if (list_priv_id != NULL) {
323                         (op_list + i)->priv_id = *(list_priv_id + i);
324                 }
325                 if (noti_list != NULL) {
326                         (op_list + i)->noti = *(noti_list + i);
327                 }
328         }
329
330         return op_list;
331 }
332
333 /*!
334  * utility functions creating notification packet
335  */
336 static inline char *_dup_string(const char *string)
337 {
338         char *ret;
339
340         if (string == NULL) {
341                 return NULL;
342         }
343         if (string[0] == '\0') {
344                 return NULL;
345         }
346
347         ret = strdup(string);
348         if (!ret)
349                 NOTIFICATION_ERR("Error: %s\n", strerror(errno));
350
351         return ret;
352 }
353
354 static inline bundle *_create_bundle_from_string(unsigned char *string)
355 {
356         if (string == NULL) {
357                 return NULL;
358         }
359         if (string[0] == '\0') {
360                 return NULL;
361         }
362
363         return bundle_decode(string, strlen((char *)string));
364 }
365
366 /*!
367  * functions creating notification packet
368  */
369 EXPORT_API int notification_ipc_make_noti_from_packet(notification_h noti, const struct packet *packet)
370 {
371         int i = 0;
372         int ret = 0;
373         int type;
374         int layout;
375         int group_id;
376         int internal_group_id;
377         int priv_id;
378         char *caller_pkgname = NULL;
379         char *launch_pkgname = NULL;
380         unsigned char *args = NULL;
381         unsigned char *group_args = NULL;
382         unsigned char *b_execute_option = NULL;
383         unsigned char *b_service_responding = NULL;
384         unsigned char *b_service_single_launch = NULL;
385         unsigned char *b_service_multi_launch = NULL;
386         unsigned char *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX] = { NULL, };
387         char *domain = NULL;
388         char *dir = NULL;
389         unsigned char *b_text = NULL;
390         unsigned char *b_key = NULL;
391         unsigned char *b_format_args = NULL;
392         int num_format_args;
393         unsigned char *b_image_path = NULL;
394         int sound_type;
395         char *sound_path = NULL;
396         int vibration_type;
397         char *vibration_path = NULL;
398         int led_operation;
399         int led_argb;
400         int led_on_ms;
401         int led_off_ms;
402         time_t time;
403         time_t insert_time;
404         int flags_for_property;
405         int display_applist;
406         double progress_size;
407         double progress_percentage;
408         char *app_icon_path = NULL;
409         char *app_name = NULL;
410         char *temp_title = NULL;
411         char *temp_content = NULL;
412         char *tag = NULL;
413         bool *ongoing_flag;
414         bool *auto_remove;
415
416         if (noti == NULL) {
417                 NOTIFICATION_ERR("invalid data");
418                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
419         }
420
421         ret = packet_get(packet,
422                         "iiiiisssssssssssssssssssssisisisiiiiiiiiddsssssii",
423                         &type,
424                         &layout,
425                         &group_id,
426                         &internal_group_id,
427                         &priv_id,
428                         &caller_pkgname,
429                         &launch_pkgname,
430                         &args,
431                         &group_args,
432                         &b_execute_option,
433                         &b_service_responding,
434                         &b_service_single_launch,
435                         &b_service_multi_launch,
436                         &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1],
437                         &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2],
438                         &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3],
439                         &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4],
440                         &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5],
441                         &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6],
442                         &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON],
443                         &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL],
444                         &domain,
445                         &dir,
446                         &b_text,
447                         &b_key,
448                         &b_format_args,
449                         &num_format_args,
450                         &b_image_path,
451                         &sound_type,
452                         &sound_path,
453                         &vibration_type,
454                         &vibration_path,
455                         &led_operation,
456                         &led_argb,
457                         &led_on_ms,
458                         &led_off_ms,
459                         &time,
460                         &insert_time,
461                         &flags_for_property,
462                         &display_applist,
463                         &progress_size,
464                         &progress_percentage,
465                         &app_icon_path,
466                         &app_name,
467                         &temp_title,
468                         &temp_content,
469                         &tag,
470                         &ongoing_flag,
471                         &auto_remove);
472
473         if (ret != 49) {
474                 NOTIFICATION_ERR("failed to create a noti from packet");
475                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
476         }
477
478         /*!
479          * This is already allocated from the notification_create function.
480          * Before reallocate string to here.
481          * We have to release old one first.
482          */
483         free(noti->caller_pkgname);
484         noti->caller_pkgname = _dup_string(caller_pkgname);
485         noti->launch_pkgname = _dup_string(launch_pkgname);
486         noti->args = _create_bundle_from_string(args);
487         noti->group_args = _create_bundle_from_string(group_args);
488         noti->b_execute_option = _create_bundle_from_string(b_execute_option);
489         noti->b_service_responding = _create_bundle_from_string(b_service_responding);
490         noti->b_service_single_launch = _create_bundle_from_string(b_service_single_launch);
491         noti->b_service_multi_launch = _create_bundle_from_string(b_service_multi_launch);
492         for (i = 0; i < NOTIFICATION_EVENT_TYPE_MAX; i++) {
493                 noti->b_event_handler[i] = _create_bundle_from_string(b_event_handler[i]);
494         }
495         noti->domain = _dup_string(domain);
496         noti->dir = _dup_string(dir);
497         noti->b_text = _create_bundle_from_string(b_text);
498         noti->b_key = _create_bundle_from_string(b_key);
499         noti->b_format_args = _create_bundle_from_string(b_format_args);
500         noti->b_image_path = _create_bundle_from_string(b_image_path);
501         noti->sound_path = _dup_string(sound_path);
502         noti->vibration_path = _dup_string(vibration_path);
503         noti->app_icon_path = _dup_string(app_icon_path);
504         noti->app_name = _dup_string(app_name);
505         noti->temp_title = _dup_string(temp_title);
506         noti->temp_content = _dup_string(temp_content);
507
508         noti->type = type;
509         noti->layout = layout;
510         noti->group_id = group_id;
511         noti->internal_group_id = internal_group_id;
512         noti->priv_id = priv_id;
513         noti->num_format_args = num_format_args;
514         noti->sound_type = sound_type;
515         noti->vibration_type = vibration_type;
516         noti->led_operation = led_operation;
517         noti->led_argb = led_argb;
518         noti->led_on_ms = led_on_ms;
519         noti->led_off_ms = led_off_ms;
520         noti->time = time;
521         noti->insert_time = insert_time;
522         noti->flags_for_property = flags_for_property;
523         noti->display_applist = display_applist;
524         noti->progress_size = progress_size;
525         noti->progress_percentage = progress_percentage;
526         noti->tag = _dup_string(tag);
527         noti->ongoing_flag = ongoing_flag;
528         noti->auto_remove = auto_remove;
529
530         return NOTIFICATION_ERROR_NONE;
531 }
532
533 EXPORT_API struct packet *notification_ipc_make_packet_from_noti(notification_h noti, const char *command, int packet_type)
534 {
535         int i = 0;
536         int b_encode_len = 0;
537         struct packet *result = NULL;
538         char *args = NULL;
539         char *group_args = NULL;
540         char *b_image_path = NULL;
541         char *b_execute_option = NULL;
542         char *b_service_responding = NULL;
543         char *b_service_single_launch = NULL;
544         char *b_service_multi_launch = NULL;
545         char *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX] = { NULL , };
546         char *b_text = NULL;
547         char *b_key = NULL;
548         char *b_format_args = NULL;
549         struct packet *(*func_to_create_packet)(const char *command, const char *fmt, ...);
550         char *title_key = NULL;
551         char buf_key[32] = { 0, };
552
553         /* Decode bundle to insert DB */
554         if (noti->args) {
555                 bundle_encode(noti->args, (bundle_raw **) & args, NULL);
556         }
557         if (noti->group_args) {
558                 bundle_encode(noti->group_args, (bundle_raw **) & group_args,
559                               &b_encode_len);
560         }
561
562         if (noti->b_execute_option) {
563                 bundle_encode(noti->b_execute_option,
564                               (bundle_raw **) & b_execute_option, &b_encode_len);
565         }
566         if (noti->b_service_responding) {
567                 bundle_encode(noti->b_service_responding,
568                               (bundle_raw **) & b_service_responding, &b_encode_len);
569         }
570         if (noti->b_service_single_launch) {
571                 bundle_encode(noti->b_service_single_launch,
572                               (bundle_raw **) & b_service_single_launch, &b_encode_len);
573         }
574         if (noti->b_service_multi_launch) {
575                 bundle_encode(noti->b_service_multi_launch,
576                               (bundle_raw **) & b_service_multi_launch, &b_encode_len);
577         }
578
579         for (i = 0; i < NOTIFICATION_EVENT_TYPE_MAX; i++) {
580                 if (noti->b_event_handler[i]) {
581                         bundle_encode(noti->b_event_handler[i],
582                                         (bundle_raw **) & b_event_handler[i], &b_encode_len);
583                 }
584         }
585
586         if (noti->b_text) {
587                 bundle_encode(noti->b_text, (bundle_raw **) & b_text, &b_encode_len);
588         }
589         if (noti->b_key) {
590                 bundle_encode(noti->b_key, (bundle_raw **) & b_key, &b_encode_len);
591         }
592         if (noti->b_format_args) {
593                 bundle_encode(noti->b_format_args,
594                               (bundle_raw **) & b_format_args, &b_encode_len);
595         }
596
597         if (noti->b_image_path) {
598                 bundle_encode(noti->b_image_path,
599                               (bundle_raw **) & b_image_path, &b_encode_len);
600         }
601
602         if (noti->b_key != NULL) {
603                 snprintf(buf_key, sizeof(buf_key), "%d",
604                          NOTIFICATION_TEXT_TYPE_TITLE);
605
606                 bundle_get_str(noti->b_key, buf_key, &title_key);
607         }
608
609         if (title_key == NULL && noti->b_text != NULL) {
610                 snprintf(buf_key, sizeof(buf_key), "%d",
611                          NOTIFICATION_TEXT_TYPE_TITLE);
612
613                 bundle_get_str(noti->b_text, buf_key, &title_key);
614         }
615
616         if (title_key == NULL) {
617                 title_key = noti->caller_pkgname;
618         }
619
620         if (packet_type == 1)
621                 func_to_create_packet = packet_create;
622         else if (packet_type == 2)
623                 func_to_create_packet = packet_create_noack;
624         else {
625                 goto out;
626         }
627
628         result = func_to_create_packet(command,
629                         "iiiiisssssssssssssssssssssisisisiiiiiiiiddsssssii",
630                         noti->type,
631                         noti->layout,
632                         noti->group_id,
633                         noti->internal_group_id,
634                         noti->priv_id,
635                         NOTIFICATION_CHECK_STR(noti->caller_pkgname),
636                         NOTIFICATION_CHECK_STR(noti->launch_pkgname),
637                         NOTIFICATION_CHECK_STR(args),
638                         NOTIFICATION_CHECK_STR(group_args),
639                         NOTIFICATION_CHECK_STR(b_execute_option),
640                         NOTIFICATION_CHECK_STR(b_service_responding),
641                         NOTIFICATION_CHECK_STR(b_service_single_launch),
642                         NOTIFICATION_CHECK_STR(b_service_multi_launch),
643                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1]),
644                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2]),
645                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3]),
646                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4]),
647                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5]),
648                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6]),
649                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON]),
650                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL]),
651                         NOTIFICATION_CHECK_STR(noti->domain),
652                         NOTIFICATION_CHECK_STR(noti->dir),
653                         NOTIFICATION_CHECK_STR(b_text),
654                         NOTIFICATION_CHECK_STR(b_key),
655                         NOTIFICATION_CHECK_STR(b_format_args),
656                         noti->num_format_args,
657                         NOTIFICATION_CHECK_STR(b_image_path),
658                         noti->sound_type,
659                         NOTIFICATION_CHECK_STR(noti->sound_path),
660                         noti->vibration_type,
661                         NOTIFICATION_CHECK_STR(noti->vibration_path),
662                         noti->led_operation,
663                         noti->led_argb,
664                         noti->led_on_ms,
665                         noti->led_off_ms,
666                         noti->time,
667                         noti->insert_time,
668                         noti->flags_for_property,
669                         noti->display_applist,
670                         noti->progress_size,
671                         noti->progress_percentage,
672                         NOTIFICATION_CHECK_STR(noti->app_icon_path),
673                         NOTIFICATION_CHECK_STR(noti->app_name),
674                         NOTIFICATION_CHECK_STR(noti->temp_title),
675                         NOTIFICATION_CHECK_STR(noti->temp_content),
676                         NOTIFICATION_CHECK_STR(noti->tag),
677                         noti->ongoing_flag,
678                         noti->auto_remove);
679
680 out:
681         /* Free decoded data */
682         if (args) {
683                 free(args);
684         }
685         if (group_args) {
686                 free(group_args);
687         }
688
689         if (b_execute_option) {
690                 free(b_execute_option);
691         }
692         if (b_service_responding) {
693                 free(b_service_responding);
694         }
695         if (b_service_single_launch) {
696                 free(b_service_single_launch);
697         }
698         if (b_service_multi_launch) {
699                 free(b_service_multi_launch);
700         }
701
702         for (i = 0; i < NOTIFICATION_EVENT_TYPE_MAX; i++) {
703                 if (b_event_handler[i]) {
704                         free(b_event_handler[i]);
705                 }
706         }
707
708         if (b_text) {
709                 free(b_text);
710         }
711         if (b_key) {
712                 free(b_key);
713         }
714         if (b_format_args) {
715                 free(b_format_args);
716         }
717
718         if (b_image_path) {
719                 free(b_image_path);
720         }
721
722         return result;
723 }
724
725 EXPORT_API struct packet *notification_ipc_make_reply_packet_from_noti(notification_h noti, struct packet *packet)
726 {
727         int i = 0;
728         int b_encode_len = 0;
729         struct packet *result = NULL;
730         char *args = NULL;
731         char *group_args = NULL;
732         char *b_image_path = NULL;
733         char *b_execute_option = NULL;
734         char *b_service_responding = NULL;
735         char *b_service_single_launch = NULL;
736         char *b_service_multi_launch = NULL;
737         char *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX] = { NULL , };
738         char *b_text = NULL;
739         char *b_key = NULL;
740         char *b_format_args = NULL;
741         char *title_key = NULL;
742         char buf_key[32] = { 0, };
743
744         /* Decode bundle to insert DB */
745         if (noti->args) {
746                 bundle_encode(noti->args, (bundle_raw **) & args, &b_encode_len);
747         }
748         if (noti->group_args) {
749                 bundle_encode(noti->group_args, (bundle_raw **) & group_args,
750                               &b_encode_len);
751         }
752
753         if (noti->b_execute_option) {
754                 bundle_encode(noti->b_execute_option,
755                               (bundle_raw **) & b_execute_option, &b_encode_len);
756         }
757         if (noti->b_service_responding) {
758                 bundle_encode(noti->b_service_responding,
759                               (bundle_raw **) & b_service_responding, &b_encode_len);
760         }
761         if (noti->b_service_single_launch) {
762                 bundle_encode(noti->b_service_single_launch,
763                               (bundle_raw **) & b_service_single_launch, &b_encode_len);
764         }
765         if (noti->b_service_multi_launch) {
766                 bundle_encode(noti->b_service_multi_launch,
767                               (bundle_raw **) & b_service_multi_launch, &b_encode_len);
768         }
769
770         for (i = 0; i < NOTIFICATION_EVENT_TYPE_MAX; i++) {
771                 if (noti->b_event_handler[i]) {
772                         bundle_encode(noti->b_event_handler[i],
773                                         (bundle_raw **) & b_event_handler[i], &b_encode_len);
774                 }
775         }
776
777         if (noti->b_text) {
778                 bundle_encode(noti->b_text, (bundle_raw **) & b_text, &b_encode_len);
779         }
780         if (noti->b_key) {
781                 bundle_encode(noti->b_key, (bundle_raw **) & b_key, &b_encode_len);
782         }
783         if (noti->b_format_args) {
784                 bundle_encode(noti->b_format_args,
785                               (bundle_raw **) & b_format_args, &b_encode_len);
786         }
787
788         if (noti->b_image_path) {
789                 bundle_encode(noti->b_image_path,
790                               (bundle_raw **) & b_image_path, &b_encode_len);
791         }
792
793         if (noti->b_key != NULL) {
794                 snprintf(buf_key, sizeof(buf_key), "%d",
795                          NOTIFICATION_TEXT_TYPE_TITLE);
796
797                 bundle_get_str(noti->b_key, buf_key, &title_key);
798         }
799
800         if (title_key == NULL && noti->b_text != NULL) {
801                 snprintf(buf_key, sizeof(buf_key), "%d",
802                          NOTIFICATION_TEXT_TYPE_TITLE);
803
804                 bundle_get_str(noti->b_text, buf_key, &title_key);
805         }
806
807         if (title_key == NULL) {
808                 title_key = noti->caller_pkgname;
809         }
810
811         result = packet_create_reply(packet,
812                         "iiiiisssssssssssssssssssssisisisiiiiiiiiddsssssii",
813                         noti->type,
814                         noti->layout,
815                         noti->group_id,
816                         noti->internal_group_id,
817                         noti->priv_id,
818                         NOTIFICATION_CHECK_STR(noti->caller_pkgname),
819                         NOTIFICATION_CHECK_STR(noti->launch_pkgname),
820                         NOTIFICATION_CHECK_STR(args),
821                         NOTIFICATION_CHECK_STR(group_args),
822                         NOTIFICATION_CHECK_STR(b_execute_option),
823                         NOTIFICATION_CHECK_STR(b_service_responding),
824                         NOTIFICATION_CHECK_STR(b_service_single_launch),
825                         NOTIFICATION_CHECK_STR(b_service_multi_launch),
826                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1]),
827                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2]),
828                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3]),
829                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4]),
830                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5]),
831                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6]),
832                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON]),
833                         NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL]),
834                         NOTIFICATION_CHECK_STR(noti->domain),
835                         NOTIFICATION_CHECK_STR(noti->dir),
836                         NOTIFICATION_CHECK_STR(b_text),
837                         NOTIFICATION_CHECK_STR(b_key),
838                         NOTIFICATION_CHECK_STR(b_format_args),
839                         noti->num_format_args,
840                         NOTIFICATION_CHECK_STR(b_image_path),
841                         noti->sound_type,
842                         NOTIFICATION_CHECK_STR(noti->sound_path),
843                         noti->vibration_type,
844                         NOTIFICATION_CHECK_STR(noti->vibration_path),
845                         noti->led_operation,
846                         noti->led_argb,
847                         noti->led_on_ms,
848                         noti->led_off_ms,
849                         noti->time,
850                         noti->insert_time,
851                         noti->flags_for_property,
852                         noti->display_applist,
853                         noti->progress_size,
854                         noti->progress_percentage,
855                         NOTIFICATION_CHECK_STR(noti->app_icon_path),
856                         NOTIFICATION_CHECK_STR(noti->app_name),
857                         NOTIFICATION_CHECK_STR(noti->temp_title),
858                         NOTIFICATION_CHECK_STR(noti->temp_content),
859                         NOTIFICATION_CHECK_STR(noti->tag),
860                         noti->ongoing_flag,
861                         noti->auto_remove);
862
863         /* Free decoded data */
864         if (args) {
865                 free(args);
866         }
867         if (group_args) {
868                 free(group_args);
869         }
870
871         if (b_execute_option) {
872                 free(b_execute_option);
873         }
874         if (b_service_responding) {
875                 free(b_service_responding);
876         }
877         if (b_service_single_launch) {
878                 free(b_service_single_launch);
879         }
880         if (b_service_multi_launch) {
881                 free(b_service_multi_launch);
882         }
883
884         for (i = 0; i < NOTIFICATION_EVENT_TYPE_MAX; i++) {
885                 if (b_event_handler[i]) {
886                         free(b_event_handler[i]);
887                 }
888         }
889
890         if (b_text) {
891                 free(b_text);
892         }
893         if (b_key) {
894                 free(b_key);
895         }
896         if (b_format_args) {
897                 free(b_format_args);
898         }
899
900         if (b_image_path) {
901                 free(b_image_path);
902         }
903
904         return result;
905 }
906
907 /*!
908  * functions to handler services
909  */
910 static struct packet *_handler_insert(pid_t pid, int handle, const struct packet *packet)
911 {
912         notification_h noti = NULL;
913
914         if (!packet) {
915                 NOTIFICATION_ERR("a packet is null");
916                 return NULL;
917         }
918         noti = notification_create(NOTIFICATION_TYPE_NOTI);
919         if (!noti) {
920                 NOTIFICATION_ERR("failed to create a notification");
921                 return NULL;
922         }
923         notification_ipc_make_noti_from_packet(noti, packet);
924
925         if (noti->flags_for_property
926                 & NOTIFICATION_PROP_DISABLE_UPDATE_ON_INSERT) {
927                 /* Disable changed cb */
928         } else {
929                 /* Enable changed cb */
930                 notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_INSERT, 1, &(noti->priv_id), 1, &noti);
931                 if (noti_op != NULL) {
932                         notification_call_changed_cb(noti_op, 1);
933                         free(noti_op);
934                 }
935         }
936         notification_free(noti);
937
938         return NULL;
939 }
940
941 static struct packet *_handler_update(pid_t pid, int handle, const struct packet *packet)
942 {
943         notification_h noti = NULL;
944
945         if (!packet) {
946                 NOTIFICATION_ERR("a packet is null");
947                 return NULL;
948         }
949
950         noti = notification_create(NOTIFICATION_TYPE_NOTI);
951         if (!noti) {
952                 NOTIFICATION_ERR("failed to create a notification");
953                 return NULL;
954         }
955
956         notification_ipc_make_noti_from_packet(noti, packet);
957
958         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_UPDATE, 1, &(noti->priv_id), 1, &noti);
959         if (noti_op != NULL) {
960                 notification_call_changed_cb(noti_op, 1);
961                 free(noti_op);
962         }
963
964         notification_free(noti);
965
966         return NULL;
967 }
968
969 static struct packet *_handler_refresh(pid_t pid, int handle, const struct packet *packet)
970 {
971         if (!packet) {
972                 NOTIFICATION_ERR("a packet is null");
973                 return NULL;
974         }
975         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_REFRESH, 1, NULL, 0, NULL);
976         if (noti_op != NULL) {
977                 notification_call_changed_cb(noti_op, 1);
978                 free(noti_op);
979         }
980
981         return NULL;
982 }
983
984 static struct packet *_handler_delete_single(pid_t pid, int handle, const struct packet *packet)
985 {
986         int num_deleted = 0;
987         int priv_id = NOTIFICATION_PRIV_ID_NONE;
988
989         if (!packet) {
990                 NOTIFICATION_ERR("a packet is null");
991                 return NULL;
992         }
993         if (packet_get(packet, "ii", &num_deleted, &priv_id) == 2) {
994                 notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_DELETE, 1, &priv_id, 1, NULL);
995                 if (noti_op != NULL) {
996                         notification_call_changed_cb(noti_op, 1);
997                         free(noti_op);
998                 }
999         }
1000
1001         return NULL;
1002 }
1003
1004 static struct packet *_handler_delete_multiple(pid_t pid, int handle, const struct packet *packet)
1005 {
1006         int ret = 0;
1007         int buf[10] = {0,};
1008         int num_deleted = 0;
1009
1010         NOTIFICATION_INFO("delete_noti_multiple");
1011
1012         if (!packet) {
1013                 NOTIFICATION_ERR("a packet is null");
1014                 return NULL;
1015         }
1016         ret = packet_get(packet, "iiiiiiiiiii", &num_deleted,
1017                         &(buf[0]),
1018                         &(buf[1]),
1019                         &(buf[2]),
1020                         &(buf[3]),
1021                         &(buf[4]),
1022                         &(buf[5]),
1023                         &(buf[6]),
1024                         &(buf[7]),
1025                         &(buf[8]),
1026                         &(buf[9]));
1027
1028         NOTIFICATION_INFO("packet data count:%d", ret);
1029         NOTIFICATION_INFO("packet data num deleted:%d", num_deleted);
1030
1031         int i = 0;
1032         for (i = 0 ; i < 10 ; i++) {
1033                 NOTIFICATION_INFO("packet data[%d]:%d",i, buf[i]);
1034         }
1035
1036         if (ret == 11) {
1037                 notification_op *noti_op = notification_ipc_create_op(
1038                                 NOTIFICATION_OP_DELETE, num_deleted, buf, num_deleted, NULL);
1039                 if (noti_op == NULL) {
1040                         NOTIFICATION_ERR("notification_ipc_create_op failed");
1041                         return NULL;
1042                 }
1043                 notification_call_changed_cb(noti_op, num_deleted);
1044                 free(noti_op);
1045         }
1046
1047         return NULL;
1048 }
1049
1050 static int _handler_service_register(pid_t pid, int handle, const struct packet *packet, void *data)
1051 {
1052         int ret;
1053
1054         if (!packet) {
1055                 NOTIFICATION_ERR("Packet is not valid\n");
1056                 ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
1057         } else if (packet_get(packet, "i", &ret) != 1) {
1058                 NOTIFICATION_ERR("Packet is not valid\n");
1059                 ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
1060         } else {
1061                 if (ret == 0) {
1062                         notification_op *noti_op = notification_ipc_create_op(NOTIFICATION_OP_SERVICE_READY, 1, NULL, 1, NULL);
1063                         if (noti_op != NULL) {
1064                                 notification_call_changed_cb(noti_op, 1);
1065                                 free(noti_op);
1066                         }
1067                 }
1068         }
1069         return ret;
1070 }
1071
1072 /*!
1073  * functions to initialize and register a monitor
1074  */
1075 static int notification_ipc_monitor_register(void)
1076 {
1077         int ret;
1078         struct packet *packet;
1079         static struct method service_table[] = {
1080                 {
1081                         .cmd = "add_noti",
1082                         .handler = _handler_insert,
1083                 },
1084                 {
1085                         .cmd = "update_noti",
1086                         .handler = _handler_update,
1087                 },
1088                 {
1089                         .cmd = "refresh_noti",
1090                         .handler = _handler_refresh,
1091                 },
1092                 {
1093                         .cmd = "del_noti_single",
1094                         .handler = _handler_delete_single,
1095                 },
1096                 {
1097                         .cmd = "del_noti_multiple",
1098                         .handler = _handler_delete_multiple,
1099                 },
1100                 {
1101                         .cmd = NULL,
1102                         .handler = NULL,
1103                 },
1104         };
1105
1106         if (s_info.initialized == 1) {
1107                 return NOTIFICATION_ERROR_NONE;
1108         } else {
1109                 s_info.initialized = 1;
1110         }
1111
1112         NOTIFICATION_ERR("register a service\n");
1113
1114         com_core_packet_use_thread(1);
1115         s_info.server_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table);
1116         if (s_info.server_fd < 0) {
1117                 NOTIFICATION_ERR("Failed to make a connection to the master\n");
1118                 return NOTIFICATION_ERROR_IO_ERROR;
1119         }
1120
1121         packet = packet_create("service_register", "");
1122         if (!packet) {
1123                 NOTIFICATION_ERR("Failed to build a packet\n");
1124                 com_core_packet_client_fini(s_info.server_fd);
1125                 return NOTIFICATION_ERROR_IO_ERROR;
1126         }
1127
1128         ret = com_core_packet_async_send(s_info.server_fd, packet, 1.0, _handler_service_register, NULL);
1129         NOTIFICATION_DBG("Service register sent: %d\n", ret);
1130         packet_destroy(packet);
1131         if (ret != 0) {
1132                 com_core_packet_client_fini(s_info.server_fd);
1133                 s_info.server_fd = NOTIFICATION_ERROR_INVALID_PARAMETER;
1134                 ret = NOTIFICATION_ERROR_IO_ERROR;
1135         } else {
1136                 ret = NOTIFICATION_ERROR_NONE;
1137         }
1138
1139         NOTIFICATION_DBG("Server FD: %d\n", s_info.server_fd);
1140         return ret;
1141 }
1142
1143 int notification_ipc_monitor_deregister(void)
1144 {
1145         if (s_info.initialized == 0) {
1146                 return NOTIFICATION_ERROR_NONE;
1147         }
1148
1149         com_core_packet_client_fini(s_info.server_fd);
1150         s_info.server_fd = NOTIFICATION_ERROR_INVALID_PARAMETER;
1151
1152         s_info.initialized = 0;
1153
1154         return NOTIFICATION_ERROR_NONE;
1155 }
1156
1157 int notification_ipc_monitor_init(void)
1158 {
1159         int ret = NOTIFICATION_ERROR_NONE;
1160
1161         if (notification_ipc_is_master_ready()) {
1162                 ret = notification_ipc_monitor_register();
1163         }
1164
1165         if (s_info.is_started_cb_set_svc == 0) {
1166                 _set_master_started_cb(_master_started_cb_service);
1167                 s_info.is_started_cb_set_svc = 1;
1168         }
1169
1170         return ret;
1171 }
1172
1173 int notification_ipc_monitor_fini(void)
1174 {
1175         int ret = NOTIFICATION_ERROR_NONE;
1176
1177         if (s_info.is_started_cb_set_svc == 1) {
1178                 _unset_master_started_cb(_master_started_cb_service);
1179                 s_info.is_started_cb_set_svc = 0;
1180         }
1181
1182         ret = notification_ipc_monitor_deregister();
1183
1184         return ret;
1185 }
1186
1187 /*!
1188  * functions to request the service
1189  */
1190 int notification_ipc_request_insert(notification_h noti, int *priv_id)
1191 {
1192         int status = 0;
1193         int id = NOTIFICATION_PRIV_ID_NONE;
1194         struct packet *packet;
1195         struct packet *result;
1196
1197         /* Initialize private ID */
1198         noti->priv_id = NOTIFICATION_PRIV_ID_NONE;
1199         noti->group_id = NOTIFICATION_GROUP_ID_NONE;
1200         noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
1201
1202         packet = notification_ipc_make_packet_from_noti(noti, "add_noti", 1);
1203         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1204                         packet,
1205                         NOTIFICATION_IPC_TIMEOUT);
1206         packet_destroy(packet);
1207
1208         if (result != NULL) {
1209                 if (packet_get(result, "ii", &status, &id) != 2) {
1210                         NOTIFICATION_ERR("Failed to get a result packet");
1211                         packet_unref(result);
1212                         return NOTIFICATION_ERROR_IO_ERROR;
1213                 }
1214
1215                 if (status != NOTIFICATION_ERROR_NONE) {
1216                         packet_unref(result);
1217                         return status;
1218                 }
1219                 packet_unref(result);
1220         } else {
1221                 NOTIFICATION_ERR("failed to receive answer(insert)");
1222                 if (notification_ipc_is_master_ready() == 1) {
1223                         return NOTIFICATION_ERROR_PERMISSION_DENIED;
1224                 }
1225                 else {
1226                         return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1227                 }
1228         }
1229
1230         if (priv_id != NULL) {
1231                 *priv_id = id;
1232         }
1233
1234         return NOTIFICATION_ERROR_NONE;
1235 }
1236
1237 int notification_ipc_request_delete_single(notification_type_e type, char *pkgname, int priv_id)
1238 {
1239         int status = 0;
1240         int id = NOTIFICATION_PRIV_ID_NONE;
1241         struct packet *packet;
1242         struct packet *result;
1243
1244         packet = packet_create("del_noti_single", "si", pkgname, priv_id);
1245         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1246                         packet,
1247                         NOTIFICATION_IPC_TIMEOUT);
1248         packet_destroy(packet);
1249
1250         if (result != NULL) {
1251                 if (packet_get(result, "ii", &status, &id) != 2) {
1252                         NOTIFICATION_ERR("Failed to get a result packet");
1253                         packet_unref(result);
1254                         return NOTIFICATION_ERROR_IO_ERROR;
1255                 }
1256                 packet_unref(result);
1257         } else {
1258                 NOTIFICATION_ERR("failed to receive answer(delete)");
1259                 if (notification_ipc_is_master_ready() == 1) {
1260                         return NOTIFICATION_ERROR_PERMISSION_DENIED;
1261                 }
1262                 else {
1263                         return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1264                 }
1265         }
1266
1267         return status;
1268 }
1269
1270 int notification_ipc_request_delete_multiple(notification_type_e type, char *pkgname)
1271 {
1272         int status = 0;
1273         int num_deleted = 0;
1274         struct packet *packet;
1275         struct packet *result;
1276
1277         packet = packet_create("del_noti_multiple", "si", pkgname, type);
1278         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1279                         packet,
1280                         NOTIFICATION_IPC_TIMEOUT);
1281         packet_destroy(packet);
1282
1283         if (result != NULL) {
1284                 if (packet_get(result, "ii", &status, &num_deleted) != 2) {
1285                         NOTIFICATION_ERR("Failed to get a result packet");
1286                         packet_unref(result);
1287                         return NOTIFICATION_ERROR_IO_ERROR;
1288                 }
1289                 NOTIFICATION_ERR("num deleted:%d", num_deleted);
1290                 packet_unref(result);
1291         } else {
1292                 NOTIFICATION_ERR("failed to receive answer(delete multiple)");
1293                 if (notification_ipc_is_master_ready() == 1) {
1294                         return NOTIFICATION_ERROR_PERMISSION_DENIED;
1295                 }
1296                 else {
1297                         return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1298                 }
1299         }
1300
1301         return status;
1302 }
1303
1304 int notification_ipc_request_update(notification_h noti)
1305 {
1306         int status = 0;
1307         int id = NOTIFICATION_PRIV_ID_NONE;
1308         struct packet *packet;
1309         struct packet *result;
1310
1311         packet = notification_ipc_make_packet_from_noti(noti, "update_noti", 1);
1312         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1313                         packet,
1314                         NOTIFICATION_IPC_TIMEOUT);
1315         packet_destroy(packet);
1316
1317         if (result != NULL) {
1318                 if (packet_get(result, "ii", &status, &id) != 2) {
1319                         NOTIFICATION_ERR("Failed to get a result packet");
1320                         packet_unref(result);
1321                         return NOTIFICATION_ERROR_IO_ERROR;
1322                 }
1323                 packet_unref(result);
1324         } else {
1325                 NOTIFICATION_ERR("failed to receive answer(update)");
1326                 if (notification_ipc_is_master_ready() == 1) {
1327                         return NOTIFICATION_ERROR_PERMISSION_DENIED;
1328                 }
1329                 else {
1330                         return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1331                 }
1332         }
1333
1334         return status;
1335 }
1336
1337 static int _notification_ipc_update_cb(pid_t pid, int handle, const struct packet *packet, void *data)
1338 {
1339         int status = 0;
1340         int id = NOTIFICATION_PRIV_ID_NONE;
1341         result_cb_item *cb_item = (result_cb_item *)data;
1342
1343         if (cb_item == NULL) {
1344                 NOTIFICATION_ERR("Failed to get a callback item");
1345                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1346         }
1347         s_info.server_cl_fd_ref_cnt = (s_info.server_cl_fd_ref_cnt <= 1) ? 0 : s_info.server_cl_fd_ref_cnt - 1;
1348         if (s_info.server_cl_fd_ref_cnt <= 0) {
1349                 NOTIFICATION_DBG("REFCNT: %d (fd: %d)", s_info.server_cl_fd_ref_cnt, s_info.server_cl_fd);
1350                 int fd_temp = s_info.server_cl_fd;
1351                 s_info.server_cl_fd = -1;
1352                 com_core_packet_client_fini(fd_temp);
1353                 NOTIFICATION_DBG("FD(%d) finalized", fd_temp);
1354         }
1355
1356         if (packet != NULL) {
1357                 if (packet_get(packet, "ii", &status, &id) != 2) {
1358                         NOTIFICATION_ERR("Failed to get a result packet");
1359                         status = NOTIFICATION_ERROR_IO_ERROR;
1360                 }
1361         }
1362
1363         if (cb_item->result_cb != NULL) {
1364                 cb_item->result_cb(id, status, cb_item->data);
1365         }
1366         free(cb_item);
1367
1368         return status;
1369 }
1370
1371 int notification_ipc_request_update_async(notification_h noti,
1372                 void (*result_cb)(int priv_id, int result, void *data), void *user_data)
1373 {
1374         int ret = NOTIFICATION_ERROR_NONE;
1375         int ret_con = 0;
1376         struct packet *packet = NULL;
1377         result_cb_item *cb_item = NULL;
1378
1379         packet = notification_ipc_make_packet_from_noti(noti, "update_noti", 1);
1380         if (packet == NULL) {
1381                 ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
1382                 goto fail;
1383         }
1384
1385         cb_item = calloc(1, sizeof(result_cb_item));
1386         if (cb_item == NULL) {
1387                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
1388                 goto fail;
1389         }
1390
1391         if (s_info.server_cl_fd < 0) {
1392                 com_core_packet_use_thread(1);
1393                 s_info.server_cl_fd = com_core_packet_client_init(s_info.socket_file, 0, NULL);
1394                 if (s_info.server_cl_fd < 0) {
1395                         NOTIFICATION_DBG("Failed to init client: %d", s_info.server_cl_fd);
1396                 if (notification_ipc_is_master_ready() == 1) {
1397                         ret = NOTIFICATION_ERROR_PERMISSION_DENIED;
1398                 }
1399                 else {
1400                         ret =  NOTIFICATION_ERROR_SERVICE_NOT_READY;
1401                 }
1402                         goto fail;
1403                 }
1404                 s_info.server_cl_fd_ref_cnt = 1;
1405         } else {
1406                 s_info.server_cl_fd_ref_cnt++;
1407         }
1408
1409         cb_item->result_cb = result_cb;
1410         cb_item->data = user_data;
1411
1412         NOTIFICATION_INFO("Connection count:%d, fd:%d", s_info.server_cl_fd_ref_cnt, s_info.server_cl_fd);
1413
1414         ret_con = com_core_packet_async_send(s_info.server_cl_fd, packet, 0.0f,
1415                         _notification_ipc_update_cb, cb_item);
1416         if (ret_con < 0) {
1417                 NOTIFICATION_ERR("Failed to request update, %d\n", ret_con);
1418                 s_info.server_cl_fd_ref_cnt = (s_info.server_cl_fd_ref_cnt <= 1) ? 0 : s_info.server_cl_fd_ref_cnt - 1;
1419                 if (s_info.server_cl_fd_ref_cnt <= 0) {
1420                         int fd_temp = s_info.server_cl_fd;
1421                         s_info.server_cl_fd = -1;
1422                         com_core_packet_client_fini(fd_temp);
1423                         NOTIFICATION_INFO("FD(%d) finalized", fd_temp);
1424                 }
1425                 ret = NOTIFICATION_ERROR_IO_ERROR;
1426                 goto fail;
1427         } else {
1428                 ret = NOTIFICATION_ERROR_NONE;
1429                 goto success;
1430         }
1431
1432 fail:
1433         if (cb_item) free(cb_item);
1434         NOTIFICATION_ERR("Err: %d\n", ret);
1435
1436 success:
1437         if (packet) packet_destroy(packet);
1438
1439         return ret;
1440 }
1441
1442 int notification_ipc_request_refresh(void)
1443 {
1444         int status = 0;
1445         struct packet *packet;
1446         struct packet *result;
1447
1448         packet = packet_create("refresh_noti", "i", NOTIFICATION_OP_REFRESH);
1449         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1450                         packet,
1451                         NOTIFICATION_IPC_TIMEOUT);
1452         packet_destroy(packet);
1453
1454         if (result != NULL) {
1455                 if (packet_get(result, "i", &status) != 1) {
1456                         NOTIFICATION_ERR("Failed to get a result packet");
1457                         packet_unref(result);
1458                         return NOTIFICATION_ERROR_IO_ERROR;
1459                 }
1460                 packet_unref(result);
1461         } else {
1462                 NOTIFICATION_ERR("failed to receive answer(refresh)");
1463                 if (notification_ipc_is_master_ready() == 1) {
1464                         return NOTIFICATION_ERROR_PERMISSION_DENIED;
1465                 }
1466                 else {
1467                         return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1468                 }
1469         }
1470
1471         return status;
1472 }
1473
1474
1475 int notification_ipc_update_setting(notification_setting_h setting)
1476 {
1477         int status = 0;
1478         int ret = 0;
1479         struct packet *packet;
1480         struct packet *result;
1481
1482         packet = packet_create("update_noti_setting", "siii", setting->package_name, (int)(setting->allow_to_notify), (int)(setting->do_not_disturb_except), (int)(setting->visibility_class));
1483         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1484                 packet,
1485                 NOTIFICATION_IPC_TIMEOUT);
1486         packet_destroy(packet);
1487
1488         if (result != NULL) {
1489                 if (packet_get(result, "ii", &status, &ret) != 2) {
1490                         NOTIFICATION_ERR("Failed to get a result packet");
1491                         packet_unref(result);
1492                         return NOTIFICATION_ERROR_IO_ERROR;
1493                 }
1494                 packet_unref(result);
1495         } else {
1496                 NOTIFICATION_ERR("failed to receive answer(delete)");
1497                 if (notification_ipc_is_master_ready() == 1) {
1498                         return NOTIFICATION_ERROR_PERMISSION_DENIED;
1499                 }
1500                 else {
1501                         return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1502                 }
1503         }
1504
1505         return status;
1506 }
1507
1508 int notification_ipc_update_system_setting(notification_system_setting_h system_setting)
1509 {
1510         int status = 0;
1511         int ret = 0;
1512         struct packet *packet = NULL;
1513         struct packet *result = NULL;
1514
1515         packet = packet_create("update_noti_sys_setting", "ii", (int)(system_setting->do_not_disturb), (int)(system_setting->visibility_class));
1516         if (packet == NULL) {
1517                 NOTIFICATION_ERR("packet_create failed.");
1518                 goto out;
1519         }
1520         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR, packet, NOTIFICATION_IPC_TIMEOUT);
1521         packet_destroy(packet);
1522
1523         if (result != NULL) {
1524                 if (packet_get(result, "ii", &status, &ret) != 2) {
1525                         NOTIFICATION_ERR("Failed to get a result packet");
1526                         status = NOTIFICATION_ERROR_IO_ERROR;
1527                         goto out;
1528                 }
1529
1530         } else {
1531                 NOTIFICATION_ERR("failed to receive answer(delete)");
1532                 if (notification_ipc_is_master_ready() == 1) {
1533                         status = NOTIFICATION_ERROR_PERMISSION_DENIED;
1534                         goto out;
1535                 }
1536                 else {
1537                         status = NOTIFICATION_ERROR_SERVICE_NOT_READY;
1538                         goto out;
1539                 }
1540         }
1541 out:
1542         if (result) {
1543                 packet_unref(result);
1544         }
1545
1546         return status;
1547 }
1548
1549 int notification_ipc_noti_setting_property_set(const char *pkgname, const char *property, const char *value)
1550 {
1551         int status = 0;
1552         int ret = 0;
1553         struct packet *packet;
1554         struct packet *result;
1555
1556         packet = packet_create("set_noti_property", "sss", pkgname, property, value);
1557         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1558                         packet,
1559                         NOTIFICATION_IPC_TIMEOUT);
1560         packet_destroy(packet);
1561
1562         if (result != NULL) {
1563                 if (packet_get(result, "ii", &status, &ret) != 2) {
1564                         NOTIFICATION_ERR("Failed to get a result packet");
1565                         packet_unref(result);
1566                         return NOTIFICATION_ERROR_IO_ERROR;
1567                 }
1568                 packet_unref(result);
1569         } else {
1570                 NOTIFICATION_ERR("failed to receive answer(delete)");
1571                 if (notification_ipc_is_master_ready() == 1) {
1572                         return NOTIFICATION_ERROR_PERMISSION_DENIED;
1573                 }
1574                 else {
1575                         return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1576                 }
1577         }
1578
1579         return status;
1580 }
1581
1582 int notification_ipc_noti_setting_property_get(const char *pkgname, const char *property, char **value)
1583 {
1584         int status = 0;
1585         char *ret = NULL;
1586         struct packet *packet;
1587         struct packet *result;
1588
1589         packet = packet_create("get_noti_property", "ss", pkgname, property);
1590         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1591                         packet,
1592                         NOTIFICATION_IPC_TIMEOUT);
1593         packet_destroy(packet);
1594
1595         if (result != NULL) {
1596                 if (packet_get(result, "is", &status, &ret) != 2) {
1597                         NOTIFICATION_ERR("Failed to get a result packet");
1598                         packet_unref(result);
1599                         return NOTIFICATION_ERROR_IO_ERROR;
1600                 }
1601                 if (status == NOTIFICATION_ERROR_NONE && ret != NULL) {
1602                         *value = strdup(ret);
1603                 }
1604                 packet_unref(result);
1605         } else {
1606                 NOTIFICATION_ERR("failed to receive answer(delete)");
1607                 if (notification_ipc_is_master_ready() == 1) {
1608                         return NOTIFICATION_ERROR_PERMISSION_DENIED;
1609                 }
1610                 else {
1611                         return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1612                 }
1613         }
1614
1615         return status;
1616 }
1617
1618 int notification_ipc_request_load_noti_by_tag(notification_h noti, const char *pkgname, const char *tag)
1619 {
1620         struct packet *packet;
1621         struct packet *result;
1622
1623         packet = packet_create("load_noti_by_tag", "ss", pkgname, tag);
1624         result = com_core_packet_oneshot_send(NOTIFICATION_ADDR,
1625                         packet,
1626                         NOTIFICATION_IPC_TIMEOUT);
1627         packet_destroy(packet);
1628
1629         if (result != NULL) {
1630                 if (notification_ipc_make_noti_from_packet(noti, result) != NOTIFICATION_ERROR_NONE) {
1631                         NOTIFICATION_ERR("Failed to get a result packet");
1632                         packet_unref(result);
1633                         return NOTIFICATION_ERROR_IO_ERROR;
1634                 }
1635
1636                 packet_unref(result);
1637         } else {
1638                 NOTIFICATION_ERR("failed to receive answer(load noti by tag)");
1639                 if (notification_ipc_is_master_ready() == 1) {
1640                         return NOTIFICATION_ERROR_PERMISSION_DENIED;
1641                 }
1642                 else {
1643                         return NOTIFICATION_ERROR_SERVICE_NOT_READY;
1644                 }
1645         }
1646
1647         return NOTIFICATION_ERROR_NONE;
1648 }
1649