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