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