Update spec
[platform/framework/web/livebox-viewer.git] / src / client.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <errno.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <pthread.h>
23
24 #include <dlog.h>
25 #include <glib.h>
26
27 #include <vconf.h>
28 #include <vconf-keys.h>
29
30 #include <packet.h>
31 #include <com-core.h>
32 #include <com-core_packet.h>
33 #include <livebox-errno.h>
34 #include <livebox-service.h>
35 #include <secure_socket.h>
36
37 #include "debug.h"
38 #include "client.h"
39 #include "livebox.h"
40 #include "livebox_internal.h"
41 #include "desc_parser.h"
42 #include "fb.h"
43 #include "util.h"
44 #include "master_rpc.h"
45 #include "conf.h"
46 #include "file_service.h"
47 #include "dlist.h"
48 #include <tzplatform_config.h>
49
50 #define CLIENT_SOCKET tzplatform_mkpath(TZ_USER_SHARE,"live_magazine/.client.socket")
51
52 int errno;
53
54 static struct info {
55         int fd;
56         guint timer_id;
57         char *client_addr;
58 } s_info = {
59         .fd = -1,
60         .timer_id = 0,
61         .client_addr = NULL,
62 };
63
64 static struct packet *master_fault_package(pid_t pid, int handle, const struct packet *packet)
65 {
66         const char *pkgname;
67         const char *id;
68         const char *function;
69
70         if (packet_get(packet, "sss", &pkgname, &id, &function) != 3) {
71                 ErrPrint("Invalid arguments\n");
72                 return NULL;
73         }
74
75         DbgPrint("[%s]\n", pkgname);
76         master_rpc_clear_fault_package(pkgname);
77         lb_invoke_fault_handler(LB_FAULT_DEACTIVATED, pkgname, id, function);
78         return NULL;
79 }
80
81 static struct packet *master_hold_scroll(pid_t pid, int handle, const struct packet *packet)
82 {
83         struct livebox_common *common;
84         struct livebox *livebox;
85         const char *pkgname;
86         const char *id;
87         int seize;
88         int ret;
89         struct dlist *l;
90
91         ret = packet_get(packet, "ssi", &pkgname, &id, &seize);
92         if (ret != 3) {
93                 ErrPrint("Invalid argument\n");
94                 goto out;
95         }
96
97         common = lb_find_common_handle(pkgname, id);
98         if (!common) {
99                 ErrPrint("Instance(%s) is not exists\n", id);
100                 goto out;
101         }
102
103         DbgPrint("HOLD: [%s] seize(%d)\n", id, seize);
104         seize = seize ? LB_EVENT_HOLD_SCROLL : LB_EVENT_RELEASE_SCROLL;
105         dlist_foreach(common->livebox_list, l, livebox) {
106                 lb_invoke_event_handler(livebox, seize);
107         }
108
109 out:
110         return NULL;
111 }
112
113 static struct packet *master_pinup(pid_t pid, int handle, const struct packet *packet)
114 {
115         const char *pkgname;
116         const char *id;
117         const char *content;
118         struct livebox *handler;
119         struct dlist *l;
120         struct dlist *n;
121         struct livebox_common *common;
122         char *new_content;
123         int ret;
124         int status;
125         int pinup;
126
127         ret = packet_get(packet, "iisss", &status, &pinup, &pkgname, &id, &content);
128         if (ret != 5) {
129                 ErrPrint("Invalid argument\n");
130                 goto out;
131         }
132
133         common = lb_find_common_handle(pkgname, id);
134         if (!common) {
135                 ErrPrint("Instance (%s) is not exists\n", id);
136                 goto out;
137         }
138
139         if (status == (int)LB_STATUS_SUCCESS) {
140                 new_content = strdup(content);
141                 if (new_content) {
142                         free(common->content);
143                         common->content = new_content;
144                         common->is_pinned_up = pinup;
145                 } else {
146                         ErrPrint("Heap: %s\n", strerror(errno));
147                         status = LB_STATUS_ERROR_MEMORY;
148                 }
149         }
150
151         common->request.pinup = 0;
152
153         dlist_foreach_safe(common->livebox_list, l, n, handler) {
154                 if (handler->cbs.pinup.cb) {
155                         ret_cb_t cb;
156                         void *cbdata;
157
158                         /* Make sure that user can call pinup API in its result callback */
159                         cb = handler->cbs.pinup.cb;
160                         cbdata = handler->cbs.pinup.data;
161
162                         handler->cbs.pinup.cb = NULL;
163                         handler->cbs.pinup.data = NULL;
164
165                         cb(handler, status, cbdata);
166                 } else if (status == (int)LB_STATUS_SUCCESS) {
167                         lb_invoke_event_handler(handler, LB_EVENT_PINUP_CHANGED);
168                 }
169         }
170
171 out:
172         return NULL;
173 }
174
175 static struct packet *master_deleted(pid_t pid, int handle, const struct packet *packet)
176 {
177         const char *pkgname;
178         const char *id;
179         double timestamp;
180         struct livebox *handler;
181         struct livebox_common *common;
182         struct dlist *l;
183         struct dlist *n;
184         int reason;
185
186         if (packet_get(packet, "ssdi", &pkgname, &id, &timestamp, &reason) != 4) {
187                 ErrPrint("Invalid arguemnt\n");
188                 goto out;
189         }
190
191         DbgPrint("[%s]\n", pkgname);
192         common = lb_find_common_handle_by_timestamp(timestamp);
193         if (!common) {
194                 /*!
195                  * \note
196                  * This can be happens only if the user delete a livebox
197                  * right after create it before receive created event.
198                  */
199                 goto out;
200         }
201
202         /*!< Check validity of this "handler" */
203         if (common->state != CREATE) {
204                 if (common->state != DELETE) {
205                         /*!
206                          * \note
207                          * This is not possible
208                          */
209                         ErrPrint("Already deleted handler (%s - %s)\n", pkgname, id);
210                         return NULL;
211                 }
212         }
213
214         common->request.deleted = 0;
215         /*!
216          * We should change the state of "common handler' before handling the callbacks.
217          * Because if user tries to create a new handle in the callbacks,
218          * find_sharable_common_handle will returns destroying object.
219          * Then we will get panic.
220          * To prevent it, we should change its state first.
221          */
222         common->state = DELETE;
223
224         dlist_foreach_safe(common->livebox_list, l, n, handler) {
225                 if (handler->cbs.created.cb) {
226                         ret_cb_t cb;
227                         void *cbdata;
228                         /*!
229                          * \note
230                          *
231                          * "if (handler->id == NULL) {"
232                          *
233                          * The instance is not created yet.
234                          * But the master forcely destroy it and send destroyed event to this
235                          * without the created event.
236                          *
237                          * It could be destroyed when a slave has critical error(fault)
238                          * before creating an instance successfully.
239                          */
240                         if (handler->cbs.created.cb == handler->cbs.deleted.cb) {
241                                 if (handler->cbs.created.data != handler->cbs.deleted.data) {
242                                         DbgPrint("cb is same but cbdata is different (%s - %s)\n", pkgname, id);
243                                 }
244
245                                 handler->cbs.deleted.cb = NULL;
246                                 handler->cbs.deleted.data = NULL;
247                         }
248
249                         cb = handler->cbs.created.cb;
250                         cbdata = handler->cbs.created.data;
251
252                         handler->cbs.created.cb = NULL;
253                         handler->cbs.created.data = NULL;
254
255                         if (reason == (int)LB_STATUS_SUCCESS) {
256                                 reason = LB_STATUS_ERROR_CANCEL;
257                         }
258
259                         cb(handler, reason, cbdata);
260                 } else if (common->id) {
261                         if (handler->cbs.deleted.cb) {
262                                 ret_cb_t cb;
263                                 void *cbdata;
264
265                                 cb = handler->cbs.deleted.cb;
266                                 cbdata = handler->cbs.deleted.data;
267
268                                 handler->cbs.deleted.cb = NULL;
269                                 handler->cbs.deleted.data = NULL;
270
271                                 cb(handler, reason, cbdata);
272                         } else {
273                                 lb_invoke_event_handler(handler, LB_EVENT_DELETED);
274                         }
275                 }
276
277                 /* Just try to delete it, if a user didn't remove it from the live box list */
278                 lb_unref(handler, 1);
279         }
280
281 out:
282         return NULL;
283 }
284
285 static struct packet *master_lb_update_begin(pid_t pid, int handle, const struct packet *packet)
286 {
287         struct livebox *handler;
288         struct livebox_common *common;
289         const char *pkgname;
290         const char *id;
291         const char *content;
292         const char *title;
293         const char *fbfile;
294         double priority;
295         int ret;
296
297         ret = packet_get(packet, "ssdsss", &pkgname, &id, &priority, &content, &title, &fbfile);
298         if (ret != 6) {
299                 ErrPrint("Invalid argument\n");
300                 goto out;
301         }
302
303         common = lb_find_common_handle(pkgname, id);
304         if (!common) {
305                 ErrPrint("Instance[%s] is not exists\n", id);
306                 goto out;
307         }
308
309         if (common->state != CREATE) {
310                 ErrPrint("(%s) is not created\n", id);
311                 goto out;
312         }
313
314         lb_set_priority(common, priority);
315         lb_set_content(common, content);
316         lb_set_title(common, title);
317
318         /*!
319          * \NOTE
320          * Width & Height is not changed in this case.
321          * If the active update is began, the size should not be changed,
322          * And if the size is changed, the provider should finish the updating first.
323          * And then begin updating again after change its size.
324          */
325         if (lb_get_lb_fb(common)) {
326                 (void)lb_set_lb_fb(common, fbfile);
327
328                 ret = lb_sync_lb_fb(common);
329
330                 if (ret != (int)LB_STATUS_SUCCESS) {
331                         ErrPrint("Failed to do sync FB (%s - %s) (%d)\n", pkgname, fbfile, ret);
332                 } else {
333                         struct dlist *l;
334                         dlist_foreach(common->livebox_list, l, handler) {
335                                 lb_invoke_event_handler(handler, LB_EVENT_LB_UPDATE_BEGIN);
336                         }
337                 }
338         } else {
339                 ErrPrint("Invalid request[%s], %s\n", id, fbfile);
340         }
341
342 out:
343         return NULL;
344 }
345
346 static struct packet *master_pd_update_begin(pid_t pid, int handle, const struct packet *packet)
347 {
348         struct livebox *handler;
349         struct livebox_common *common;
350         const char *pkgname;
351         const char *id;
352         const char *fbfile;
353         int ret;
354
355         ret = packet_get(packet, "sss", &pkgname, &id, &fbfile);
356         if (ret != 2) {
357                 ErrPrint("Invalid argument\n");
358                 goto out;
359         }
360
361         common = lb_find_common_handle(pkgname, id);
362         if (!common) {
363                 ErrPrint("Instance[%s] is not exists\n", id);
364                 goto out;
365         }
366
367         if (common->state != CREATE) {
368                 ErrPrint("[%s] is not created\n", id);
369                 goto out;
370         }
371
372         if (lb_get_pd_fb(common)) {
373                 (void)lb_set_pd_fb(common, fbfile);
374
375                 ret = lb_sync_pd_fb(common);
376                 if (ret != (int)LB_STATUS_SUCCESS) {
377                         ErrPrint("Failed to do sync FB (%s - %s) (%d)\n", pkgname, fbfile, ret);
378                 } else {
379                         struct dlist *l;
380                         dlist_foreach(common->livebox_list, l, handler) {
381                                 lb_invoke_event_handler(handler, LB_EVENT_PD_UPDATE_BEGIN);
382                         }
383                 }
384         } else {
385                 ErrPrint("Invalid request[%s], %s\n", id, fbfile);
386         }
387
388 out:
389         return NULL;
390 }
391
392 static struct packet *master_lb_update_end(pid_t pid, int handle, const struct packet *packet)
393 {
394         struct livebox *handler;
395         struct livebox_common *common;
396         const char *pkgname;
397         const char *id;
398         int ret;
399
400         ret = packet_get(packet, "ss", &pkgname, &id);
401         if (ret != 2) {
402                 ErrPrint("Invalid argument\n");
403                 goto out;
404         }
405
406         common = lb_find_common_handle(pkgname, id);
407         if (!common) {
408                 ErrPrint("Instance[%s] is not exists\n", id);
409                 goto out;
410         }
411
412         if (common->state != CREATE) {
413                 ErrPrint("[%s] is not created\n", id);
414                 goto out;
415         }
416
417         if (lb_get_lb_fb(common)) {
418                 struct dlist *l;
419                 dlist_foreach(common->livebox_list, l, handler) {
420                         lb_invoke_event_handler(handler, LB_EVENT_LB_UPDATE_END);
421                 }
422         } else {
423                 ErrPrint("Invalid request[%s]\n", id);
424         }
425
426 out:
427         return NULL;
428 }
429
430 static struct packet *master_key_status(pid_t pid, int handle, const struct packet *packet)
431 {
432         struct livebox *handler;
433         struct livebox_common *common;
434         struct dlist *l;
435         const char *pkgname;
436         const char *id;
437         int ret;
438         int status;
439
440         ret = packet_get(packet, "ssi", &pkgname, &id, &status);
441         if (ret != 3) {
442                 ErrPrint("Invalid argument\n");
443                 goto out;
444         }
445
446         common = lb_find_common_handle(pkgname, id);
447         if (!common) {
448                 ErrPrint("Instance[%s] is not exists\n", id);
449                 goto out;
450         }
451
452         if (common->state != CREATE) {
453                 ErrPrint("[%s] is not created\n", id);
454                 goto out;
455         }
456
457         common->request.key_event = 0;
458         dlist_foreach(common->livebox_list, l, handler) {
459                 if (handler->cbs.key_event.cb) {
460                         ret_cb_t cb;
461                         void *cbdata;
462
463                         cb = handler->cbs.key_event.cb;
464                         cbdata = handler->cbs.key_event.data;
465
466                         handler->cbs.key_event.cb = NULL;
467                         handler->cbs.key_event.data = NULL;
468
469                         cb(handler, status, cbdata);
470                 } else {
471                         ErrPrint("Invalid event[%s]\n", id);
472                 }
473         }
474
475 out:
476         return NULL;
477 }
478
479 static struct packet *master_request_close_pd(pid_t pid, int handle, const struct packet *packet)
480 {
481         struct livebox *handler;
482         struct livebox_common *common;
483         struct dlist *l;
484         const char *pkgname;
485         const char *id;
486         int ret;
487         int reason;
488
489         ret = packet_get(packet, "ssi", &pkgname, &id, &reason);
490         if (ret != 3) {
491                 ErrPrint("Invalid argument\n");
492                 goto out;
493         }
494
495         common = lb_find_common_handle(pkgname, id);
496         if (!common) {
497                 ErrPrint("Instance[%s] is not exists\n", id);
498                 goto out;
499         }
500
501         if (common->state != CREATE) {
502                 ErrPrint("[%s] is not created\n", id);
503                 goto out;
504         }
505
506         if (!common->is_pd_created) {
507                 DbgPrint("PD is not created, closing what?(%s)\n", id);
508                 goto out;
509         }
510
511         DbgPrint("Reason: %d\n", reason);
512
513         dlist_foreach(common->livebox_list, l, handler) {
514                 lb_invoke_event_handler(handler, LB_EVENT_REQUEST_CLOSE_PD);
515         }
516 out:
517         return NULL;
518 }
519
520 static struct packet *master_access_status(pid_t pid, int handle, const struct packet *packet)
521 {
522         struct livebox *handler;
523         struct livebox_common *common;
524         struct dlist *l;
525         const char *pkgname;
526         const char *id;
527         int ret;
528         int status;
529
530         ret = packet_get(packet, "ssi", &pkgname, &id, &status);
531         if (ret != 3) {
532                 ErrPrint("Invalid argument\n");
533                 goto out;
534         }
535
536         common = lb_find_common_handle(pkgname, id);
537         if (!common) {
538                 ErrPrint("Instance[%s] is not exists\n", id);
539                 goto out;
540         }
541
542         if (common->state != CREATE) {
543                 ErrPrint("[%s] is not created\n", id);
544                 goto out;
545         }
546
547         common->request.access_event = 0;
548         dlist_foreach(common->livebox_list, l, handler) {
549                 if (handler->cbs.access_event.cb) {
550                         ret_cb_t cb;
551                         void *cbdata;
552
553                         cb = handler->cbs.access_event.cb;
554                         cbdata = handler->cbs.access_event.data;
555
556                         handler->cbs.access_event.cb = NULL;
557                         handler->cbs.access_event.data = NULL;
558
559                         cb(handler, status, cbdata);
560                 }
561         }
562 out:
563         return NULL;
564 }
565
566 static struct packet *master_pd_update_end(pid_t pid, int handle, const struct packet *packet)
567 {
568         struct livebox *handler;
569         struct livebox_common *common;
570         const char *pkgname;
571         const char *id;
572         int ret;
573
574         ret = packet_get(packet, "ss", &pkgname, &id);
575         if (ret != 2) {
576                 ErrPrint("Invalid argument\n");
577                 goto out;
578         }
579
580         common = lb_find_common_handle(pkgname, id);
581         if (!common) {
582                 ErrPrint("Instance[%s] is not exists\n", id);
583                 goto out;
584         }
585
586         if (common->state != CREATE) {
587                 ErrPrint("[%s] is not created\n", id);
588                 goto out;
589         }
590
591         if (lb_get_lb_fb(common)) {
592                 struct dlist *l;
593
594                 dlist_foreach(common->livebox_list, l, handler) {
595                         lb_invoke_event_handler(handler, LB_EVENT_PD_UPDATE_END);
596                 }
597         } else {
598                 ErrPrint("Invalid request[%s]", id);
599         }
600
601 out:
602         return NULL;
603 }
604
605 static struct packet *master_lb_updated(pid_t pid, int handle, const struct packet *packet)
606 {
607         const char *pkgname;
608         const char *id;
609         const char *fbfile;
610         const char *content;
611         const char *title;
612         const char *safe_file;
613         const char *icon;
614         const char *name;
615         struct livebox *handler;
616         struct livebox_common *common;
617         int lb_w;
618         int lb_h;
619         double priority;
620         int ret;
621
622         ret = packet_get(packet, "sssiidsssss",
623                                 &pkgname, &id,
624                                 &fbfile, &lb_w, &lb_h,
625                                 &priority, &content, &title,
626                                 &safe_file, &icon, &name);
627         if (ret != 11) {
628                 ErrPrint("Invalid argument\n");
629                 goto out;
630         }
631
632         common = lb_find_common_handle(pkgname, id);
633         if (!common) {
634                 ErrPrint("instance(%s) is not exists\n", id);
635                 goto out;
636         }
637
638         if (common->state != CREATE) {
639                 /*!
640                  * \note
641                  * Already deleted by the user.
642                  * Don't try to notice anything with this, Just ignore all events
643                  * Beacuse the user doesn't wants know about this anymore
644                  */
645                 ErrPrint("(%s) is not exists, but updated\n", id);
646                 goto out;
647         }
648
649         lb_set_priority(common, priority);
650         lb_set_content(common, content);
651         lb_set_title(common, title);
652         lb_set_size(common, lb_w, lb_h);
653         lb_set_filename(common, safe_file);
654
655         if (lb_text_lb(common)) {
656                 const char *common_filename;
657
658                 common_filename = common->filename ? common->filename : util_uri_to_path(common->id); 
659
660                 (void)parse_desc(common, common_filename, 0);
661                 /*!
662                  * \note
663                  * DESC parser will call the "text event callback".
664                  * Don't need to call global event callback in this case.
665                  */
666                 goto out;
667         } else if (lb_get_lb_fb(common)) {
668                 /*!
669                  * \todo
670                  * replace this with "flag" instead of "callback address"
671                  */
672                 if (conf_frame_drop_for_resizing() && common->request.size_changed) {
673                         /* Just for skipping the update event callback call, After request to resize buffer, update event will be discarded */
674                         DbgPrint("Discards obsoloted update event\n");
675                         ret = LB_STATUS_ERROR_BUSY;
676                 } else {
677                         (void)lb_set_lb_fb(common, fbfile);
678
679                         if (!conf_manual_sync()) {
680                                 ret = lb_sync_lb_fb(common);
681                                 if (ret != (int)LB_STATUS_SUCCESS) {
682                                         ErrPrint("Failed to do sync FB (%s - %s) (%d)\n", pkgname, util_basename(util_uri_to_path(id)), ret);
683                                 }
684                         } else {
685                                 ret = LB_STATUS_SUCCESS;
686                         }
687                 }
688         } else {
689                 ret = LB_STATUS_SUCCESS;
690         }
691
692         if (ret == (int)LB_STATUS_SUCCESS) {
693                 struct dlist *l;
694                 struct dlist *n;
695
696                 dlist_foreach_safe(common->livebox_list, l, n, handler) {
697                         lb_invoke_event_handler(handler, LB_EVENT_LB_UPDATED);
698                 }
699         }
700
701 out:
702         return NULL;
703 }
704
705 static struct packet *master_pd_created(pid_t pid, int handle, const struct packet *packet)
706 {
707         struct livebox *handler;
708         struct livebox_common *common;
709         const char *pkgname;
710         const char *id;
711         const char *buf_id;
712         struct dlist *l;
713         struct dlist *n;
714         int width;
715         int height;
716         int ret;
717         int status;
718
719         ret = packet_get(packet, "sssiii", &pkgname, &id, &buf_id, &width, &height, &status);
720         if (ret != 6) {
721                 ErrPrint("Invalid argument\n");
722                 goto out;
723         }
724
725         DbgPrint("[%s]\n", pkgname);
726         common = lb_find_common_handle(pkgname, id);
727         if (!common) {
728                 ErrPrint("Instance(%s) is not exists\n", id);
729                 goto out;
730         }
731
732         if (common->state != CREATE) {
733                 ErrPrint("Instance(%s) is not created\n", id);
734                 goto out;
735         }
736
737         if (!common->request.pd_created) {
738                 ErrPrint("PD create request is canceled\n");
739                 goto out;
740         }
741
742         common->is_pd_created = (status == (int)LB_STATUS_SUCCESS);
743         common->request.pd_created = 0;
744
745         if (common->is_pd_created) {
746                 lb_set_pdsize(common, width, height);
747                 if (lb_text_pd(common)) {
748                         DbgPrint("Text TYPE does not need to handle this\n");
749                 } else {
750                         (void)lb_set_pd_fb(common, buf_id);
751
752                         switch (common->pd.type) {
753                         case _PD_TYPE_SCRIPT:
754                         case _PD_TYPE_BUFFER:
755                                 switch (fb_type(lb_get_pd_fb(common))) {
756                                 case BUFFER_TYPE_FILE:
757                                 case BUFFER_TYPE_SHM:
758                                         lb_create_lock_file(common, 1);
759                                         break;
760                                 case BUFFER_TYPE_PIXMAP:
761                                 case BUFFER_TYPE_ERROR:
762                                 default:
763                                         break;
764                                 }
765                                 break;
766                         case _PD_TYPE_TEXT:
767                         default:
768                                 break;
769                         }
770
771                         ret = lb_sync_pd_fb(common);
772                         if (ret < 0) {
773                                 ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
774                         }
775                 }
776         }
777
778         DbgPrint("PERF_DBOX\n");
779         dlist_foreach_safe(common->livebox_list, l, n, handler) {
780                 if (handler->cbs.pd_created.cb) {
781                         ret_cb_t cb;
782                         void *cbdata;
783
784                         cb = handler->cbs.pd_created.cb;
785                         cbdata = handler->cbs.pd_created.data;
786
787                         handler->cbs.pd_created.cb = NULL;
788                         handler->cbs.pd_created.data = NULL;
789
790                         /*!
791                          * Before call the Callback function,
792                          * pd_create_cb must be reset.
793                          * Because, in the create callback, user can call create_pd function again.
794                          */
795                         cb(handler, status, cbdata);
796                 } else if (status == (int)LB_STATUS_SUCCESS) {
797                         lb_invoke_event_handler(handler, LB_EVENT_PD_CREATED);
798                 } 
799         }
800
801 out:
802         return NULL;
803 }
804
805 static struct packet *master_pd_destroyed(pid_t pid, int handle, const struct packet *packet)
806 {
807         struct livebox *handler;
808         struct dlist *l;
809         struct livebox_common *common;
810         const char *pkgname;
811         const char *id;
812         int ret;
813         int status;
814
815         ret = packet_get(packet, "ssi", &pkgname, &id, &status);
816         if (ret != 3) {
817                 ErrPrint("Invalid argument\n");
818                 goto out;
819         }
820
821         DbgPrint("[%s]\n", pkgname);
822         common = lb_find_common_handle(pkgname, id);
823         if (!common) {
824                 ErrPrint("Instance(%s) is not exists\n", id);
825                 goto out;
826         }
827
828         if (common->state != CREATE) {
829                 ErrPrint("Instance(%s) is not created\n", id);
830                 goto out;
831         }
832
833         if (common->is_pd_created == 0) {
834                 ErrPrint("PD is not created, event is ignored\n");
835                 goto out;
836         }
837
838         common->is_pd_created = 0;
839         common->request.pd_destroyed = 0;
840
841         dlist_foreach(common->livebox_list, l, handler) {
842                 if (handler->cbs.pd_destroyed.cb) {
843                         ret_cb_t cb;
844                         void *cbdata;
845
846                         cb = handler->cbs.pd_destroyed.cb;
847                         cbdata = handler->cbs.pd_destroyed.data;
848
849                         handler->cbs.pd_destroyed.cb = NULL;
850                         handler->cbs.pd_destroyed.data = NULL;
851
852                         /*!
853                          * Before call the Callback function,
854                          * pd_destroyed_cb must be reset.
855                          * Because, in the create callback, user can call destroy_pd function again.
856                          */
857                         cb(handler, status, cbdata);
858                 } else if (status == (int)LB_STATUS_SUCCESS) {
859                         lb_invoke_event_handler(handler, LB_EVENT_PD_DESTROYED);
860                 }
861         }
862
863         /*!
864          * \note
865          * Lock file should be deleted after all callbacks are processed.
866          */
867         switch (common->pd.type) {
868         case _PD_TYPE_SCRIPT:
869         case _PD_TYPE_BUFFER:
870                 switch (fb_type(lb_get_pd_fb(common))) {
871                 case BUFFER_TYPE_FILE:
872                 case BUFFER_TYPE_SHM:
873                         lb_destroy_lock_file(common, 1);
874                         break;
875                 case BUFFER_TYPE_PIXMAP:
876                 case BUFFER_TYPE_ERROR:
877                 default:
878                         break;
879                 }
880                 break;
881         case _PD_TYPE_TEXT:
882         default:
883                 break;
884         }
885
886 out:
887         return NULL;
888 }
889
890 static struct packet *master_pd_updated(pid_t pid, int handle, const struct packet *packet)
891 {
892         const char *pkgname;
893         const char *id;
894         const char *descfile;
895         const char *fbfile;
896         int ret;
897         struct livebox *handler;
898         struct livebox_common *common;
899         struct dlist *l;
900         int pd_w;
901         int pd_h;
902
903         ret = packet_get(packet, "ssssii",
904                                 &pkgname, &id,
905                                 &descfile, &fbfile,
906                                 &pd_w, &pd_h);
907         if (ret != 6) {
908                 ErrPrint("Invalid argument\n");
909                 goto out;
910         }
911
912         DbgPrint("[%s]\n", pkgname);
913         common = lb_find_common_handle(pkgname, id);
914         if (!common) {
915                 ErrPrint("Instance(%s) is not exists\n", id);
916                 goto out;
917         }
918
919         if (common->state != CREATE) {
920                 /*!
921                  * \note
922                  * This handler is already deleted by the user.
923                  * So don't try to notice anything about this anymore.
924                  * Just ignore all events.
925                  */
926                 ErrPrint("Instance(%s) is not created\n", id);
927                 goto out;
928         }
929
930         lb_set_pdsize(common, pd_w, pd_h);
931
932         if (lb_text_pd(common)) {
933                 (void)parse_desc(common, descfile, 1);
934         } else {
935                 if (conf_frame_drop_for_resizing() && common->request.size_changed) {
936                         /* Just for skipping the update event callback call, After request to resize buffer, update event will be discarded */
937                         DbgPrint("Discards obsoloted update event\n");
938                 } else {
939                         (void)lb_set_pd_fb(common, fbfile);
940
941                          if (!conf_manual_sync()) {
942                                 ret = lb_sync_pd_fb(common);
943                                 if (ret < 0) {
944                                         ErrPrint("Failed to do sync FB (%s - %s), %d\n", pkgname, util_basename(util_uri_to_path(id)), ret);
945                                 } else {
946                                         dlist_foreach(common->livebox_list, l, handler) {
947                                                 lb_invoke_event_handler(handler, LB_EVENT_PD_UPDATED);
948                                         }
949                                 }
950                         } else {
951                                 dlist_foreach(common->livebox_list, l, handler) {
952                                         lb_invoke_event_handler(handler, LB_EVENT_PD_UPDATED);
953                                 }
954                         }
955                 }
956         }
957
958 out:
959         return NULL;
960 }
961
962 static struct packet *master_update_mode(pid_t pid, int handle, const struct packet *packet)
963 {
964         struct livebox *handler;
965         struct livebox_common *common;
966         struct dlist *l;
967         struct dlist *n;
968         const char *pkgname;
969         const char *id;
970         int active_mode;
971         int status;
972         int ret;
973
974         if (!packet) {
975                 ErrPrint("Invalid packet\n");
976                 goto out;
977         }
978
979         ret = packet_get(packet, "ssii", &pkgname, &id, &status, &active_mode);
980         if (ret != 4) {
981                 ErrPrint("Invalid argument\n");
982                 goto out;
983         }
984
985         common = lb_find_common_handle(pkgname, id);
986         if (!common) {
987                 ErrPrint("Livebox(%s) is not found\n", id);
988                 goto out;
989         }
990
991         if (common->state != CREATE) {
992                 ErrPrint("Livebox(%s) is not created yet\n", id);
993                 goto out;
994         }
995
996         if (status == (int)LB_STATUS_SUCCESS) {
997                 lb_set_update_mode(common, active_mode);
998         }
999
1000         common->request.update_mode = 0;
1001         dlist_foreach_safe(common->livebox_list, l, n, handler) {
1002                 if (handler->cbs.update_mode.cb) {
1003                         ret_cb_t cb;
1004                         void *cbdata;
1005
1006                         cb = handler->cbs.update_mode.cb;
1007                         cbdata = handler->cbs.update_mode.data;
1008
1009                         handler->cbs.update_mode.cb = NULL;
1010                         handler->cbs.update_mode.data = NULL;
1011
1012                         cb(handler, status, cbdata);
1013                 } else if (status == (int)LB_STATUS_SUCCESS) {
1014                         lb_invoke_event_handler(handler, LB_EVENT_UPDATE_MODE_CHANGED);
1015                 }
1016         }
1017
1018 out:
1019         return NULL;
1020 }
1021
1022 static struct packet *master_size_changed(pid_t pid, int handle, const struct packet *packet)
1023 {
1024         struct livebox *handler;
1025         struct livebox_common *common;
1026         const char *pkgname;
1027         const char *id;
1028         const char *fbfile;
1029         int status;
1030         int ret;
1031         int w;
1032         int h;
1033         int is_pd;
1034
1035         if (!packet) {
1036                 ErrPrint("Invalid packet\n");
1037                 goto out;
1038         }
1039
1040         ret = packet_get(packet, "sssiiii", &pkgname, &id, &fbfile, &is_pd, &w, &h, &status);
1041         if (ret != 7) {
1042                 ErrPrint("Invalid argument\n");
1043                 goto out;
1044         }
1045
1046         common = lb_find_common_handle(pkgname, id);
1047         if (!common) {
1048                 ErrPrint("Livebox(%s) is not found\n", id);
1049                 goto out;
1050         }
1051
1052         if (common->state != CREATE) {
1053                 ErrPrint("Livebox(%s) is not created yet\n", id);
1054                 goto out;
1055         }
1056
1057         common->request.size_changed = 0;
1058         if (is_pd) {
1059                 /*!
1060                  * \NOTE
1061                  * PD is not able to resized by the client.
1062                  * PD is only can be managed by the provider.
1063                  * So the PD has no private resized event handler.
1064                  * Notify it via global event handler only.
1065                  */
1066                 if (status == (int)LB_STATUS_SUCCESS) {
1067                         struct dlist *l;
1068
1069                         lb_set_pdsize(common, w, h);
1070                         dlist_foreach(common->livebox_list, l, handler) {
1071                                 lb_invoke_event_handler(handler, LB_EVENT_PD_SIZE_CHANGED);
1072                         }
1073                 } else {
1074                         ErrPrint("This is not possible. PD Size is changed but the return value is not ZERO (%d)\n", status);
1075                 }
1076         } else {
1077                 struct dlist *l;
1078                 struct dlist *n;
1079
1080                 if (status == (int)LB_STATUS_SUCCESS) {
1081                         lb_set_size(common, w, h);
1082
1083                         /*!
1084                          * \NOTE
1085                          * If there is a created LB FB, 
1086                          * Update it too.
1087                          */
1088                         if (lb_get_lb_fb(common)) {
1089                                 (void)lb_set_lb_fb(common, fbfile);
1090
1091                                 ret = lb_sync_lb_fb(common);
1092                                 if (ret < 0) {
1093                                         ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
1094                                 }
1095
1096                                 /* Just update the size info only. */
1097                         }
1098                 }
1099
1100                 /*!
1101                  * \NOTE
1102                  * I cannot believe client.
1103                  * So I added some log before & after call the user callback.
1104                  */
1105                 dlist_foreach_safe(common->livebox_list, l, n, handler) {
1106                         if (handler->cbs.size_changed.cb) {
1107                                 ret_cb_t cb;
1108                                 void *cbdata;
1109
1110                                 cb = handler->cbs.size_changed.cb;
1111                                 cbdata = handler->cbs.size_changed.data;
1112
1113                                 handler->cbs.size_changed.cb = NULL;
1114                                 handler->cbs.size_changed.data = NULL;
1115
1116                                 cb(handler, status, cbdata);
1117                         } else if (status == (int)LB_STATUS_SUCCESS) {
1118                                 lb_invoke_event_handler(handler, LB_EVENT_LB_SIZE_CHANGED);
1119                         }
1120                 }
1121         }
1122
1123 out:
1124         return NULL;
1125 }
1126
1127 static struct packet *master_period_changed(pid_t pid, int handle, const struct packet *packet)
1128 {
1129         struct livebox *handler;
1130         struct livebox_common *common;
1131         struct dlist *l;
1132         struct dlist *n;
1133         const char *pkgname;
1134         const char *id;
1135         int ret;
1136         double period;
1137         int status;
1138
1139         ret = packet_get(packet, "idss", &status, &period, &pkgname, &id);
1140         if (ret != 4) {
1141                 ErrPrint("Invalid argument\n");
1142                 goto out;
1143         }
1144
1145         common = lb_find_common_handle(pkgname, id);
1146         if (!common) {
1147                 ErrPrint("Livebox(%s) is not found\n", id);
1148                 goto out;
1149         }
1150
1151         if (common->state != CREATE) {
1152                 ErrPrint("Livebox(%s) is not created\n", id);
1153                 goto out;
1154         }
1155
1156         if (status == (int)LB_STATUS_SUCCESS) {
1157                 lb_set_period(common, period);
1158         }
1159
1160         common->request.period_changed = 0;
1161
1162         dlist_foreach_safe(common->livebox_list, l, n, handler) {
1163                 if (handler->cbs.period_changed.cb) {
1164                         ret_cb_t cb;
1165                         void *cbdata;
1166
1167                         cb = handler->cbs.period_changed.cb;
1168                         cbdata = handler->cbs.period_changed.data;
1169
1170                         handler->cbs.period_changed.cb = NULL;
1171                         handler->cbs.period_changed.data = NULL;
1172
1173                         cb(handler, status, cbdata);
1174                 } else if (status == (int)LB_STATUS_SUCCESS) {
1175                         lb_invoke_event_handler(handler, LB_EVENT_PERIOD_CHANGED);
1176                 }
1177         }
1178
1179 out:
1180         return NULL;
1181 }
1182
1183 static struct packet *master_group_changed(pid_t pid, int handle, const struct packet *packet)
1184 {
1185         struct livebox *handler;
1186         struct livebox_common *common;
1187         struct dlist *l;
1188         struct dlist *n;
1189         const char *pkgname;
1190         const char *id;
1191         int ret;
1192         const char *cluster;
1193         const char *category;
1194         int status;
1195
1196         ret = packet_get(packet, "ssiss", &pkgname, &id, &status, &cluster, &category);
1197         if (ret != 5) {
1198                 ErrPrint("Invalid argument\n");
1199                 goto out;
1200         }
1201
1202         common = lb_find_common_handle(pkgname, id);
1203         if (!common) {
1204                 ErrPrint("Livebox(%s) is not exists\n", id);
1205                 goto out;
1206         }
1207
1208         if (common->state != CREATE) {
1209                 /*!
1210                  * \note
1211                  * Do no access this handler,
1212                  * You cannot believe this handler anymore.
1213                  */
1214                 ErrPrint("Livebox(%s) is not created\n", id);
1215                 goto out;
1216         }
1217
1218         if (status == (int)LB_STATUS_SUCCESS) {
1219                 (void)lb_set_group(common, cluster, category);
1220         }
1221
1222         common->request.group_changed = 0;
1223
1224         dlist_foreach_safe(common->livebox_list, l, n, handler) {
1225                 if (handler->cbs.group_changed.cb) {
1226                         ret_cb_t cb;
1227                         void *cbdata;
1228
1229                         cb = handler->cbs.group_changed.cb;
1230                         cbdata = handler->cbs.group_changed.data;
1231
1232                         handler->cbs.group_changed.cb = NULL;
1233                         handler->cbs.group_changed.data = NULL;
1234
1235                         cb(handler, status, cbdata);
1236                 } else if (status == (int)LB_STATUS_SUCCESS) {
1237                         lb_invoke_event_handler(handler, LB_EVENT_GROUP_CHANGED);
1238                 }
1239         }
1240
1241 out:
1242         return NULL;
1243 }
1244
1245 static struct packet *master_created(pid_t pid, int handle, const struct packet *packet)
1246 {
1247         struct livebox *handler;
1248         struct livebox_common *common;
1249         struct dlist *l;
1250
1251         int lb_w;
1252         int lb_h;
1253         int pd_w;
1254         int pd_h;
1255         const char *pkgname;
1256         const char *id;
1257
1258         const char *content;
1259         const char *cluster;
1260         const char *category;
1261         const char *lb_fname;
1262         const char *pd_fname;
1263         const char *title;
1264
1265         double timestamp;
1266         const char *auto_launch;
1267         double priority;
1268         int size_list;
1269         int user;
1270         int pinup_supported;
1271         enum lb_type lb_type;
1272         enum pd_type pd_type;
1273         double period;
1274         int is_pinned_up;
1275
1276         int old_state = DESTROYED;
1277
1278         int ret;
1279
1280         ret = packet_get(packet, "dsssiiiisssssdiiiiidsi",
1281                         &timestamp,
1282                         &pkgname, &id, &content,
1283                         &lb_w, &lb_h, &pd_w, &pd_h,
1284                         &cluster, &category, &lb_fname, &pd_fname,
1285                         &auto_launch, &priority, &size_list, &user, &pinup_supported,
1286                         &lb_type, &pd_type, &period, &title, &is_pinned_up);
1287         if (ret != 22) {
1288                 ErrPrint("Invalid argument\n");
1289                 ret = LB_STATUS_ERROR_INVALID;
1290                 goto out;
1291         }
1292
1293         ErrPrint("[%lf] pkgname: %s, id: %s, content: %s, "
1294                 "pd_w: %d, pd_h: %d, lb_w: %d, lb_h: %d, "
1295                 "cluster: %s, category: %s, lb_fname: \"%s\", pd_fname: \"%s\", "
1296                 "auto_launch: %s, priority: %lf, size_list: %d, user: %d, pinup: %d, "
1297                 "lb_type: %d, pd_type: %d, period: %lf, title: [%s], is_pinned_up: %d\n",
1298                 timestamp, pkgname, id, content,
1299                 pd_w, pd_h, lb_w, lb_h,
1300                 cluster, category, lb_fname, pd_fname,
1301                 auto_launch, priority, size_list, user, pinup_supported,
1302                 lb_type, pd_type, period, title, is_pinned_up);
1303
1304         common = lb_find_common_handle_by_timestamp(timestamp);
1305         if (!common) {
1306                 handler = lb_new_livebox(pkgname, id, timestamp, cluster, category);
1307                 if (!handler) {
1308                         ErrPrint("Failed to create a new livebox\n");
1309                         ret = LB_STATUS_ERROR_FAULT;
1310                         goto out;
1311                 }
1312                 common = handler->common;
1313                 old_state = common->state;
1314         } else {
1315                 if (common->state != CREATE) {
1316                         if (common->state != DELETE) {
1317                                 /*!
1318                                  * \note
1319                                  * This is not possible!!!
1320                                  */
1321                                 ErrPrint("Invalid handler\n");
1322                                 ret = LB_STATUS_ERROR_INVALID;
1323                                 goto out;
1324                         }
1325
1326                         /*!
1327                          * \note
1328                          * After get the delete states,
1329                          * call the create callback with deleted result.
1330                          */
1331                 }
1332
1333                 old_state = common->state;
1334
1335                 if (common->id) {
1336                         ErrPrint("Already created: timestamp[%lf] "
1337                                 "pkgname[%s], id[%s] content[%s] "
1338                                 "cluster[%s] category[%s] lb_fname[%s] pd_fname[%s]\n",
1339                                         timestamp, pkgname, id,
1340                                         content, cluster, category,
1341                                         lb_fname, pd_fname);
1342
1343                         ret = LB_STATUS_ERROR_ALREADY;
1344                         goto out;
1345                 }
1346
1347                 lb_set_id(common, id);
1348         }
1349
1350         common->request.created = 0;
1351         lb_set_size(common, lb_w, lb_h);
1352         common->lb.type = lb_type;
1353         common->is_pinned_up = is_pinned_up;
1354
1355         switch (lb_type) {
1356         case _LB_TYPE_FILE:
1357                 break;
1358         case _LB_TYPE_SCRIPT:
1359         case _LB_TYPE_BUFFER:
1360                 if (!strlen(lb_fname)) {
1361                         break;
1362                 }
1363                 (void)lb_set_lb_fb(common, lb_fname);
1364
1365                 /*!
1366                  * \note
1367                  * Livebox should create the lock file from here.
1368                  * Even if the old_state == DELETE,
1369                  * the lock file will be deleted from deleted event callback.
1370                  */
1371                 switch (fb_type(lb_get_lb_fb(common))) {
1372                 case BUFFER_TYPE_FILE:
1373                 case BUFFER_TYPE_SHM:
1374                         lb_create_lock_file(common, 0);
1375                         break;
1376                 case BUFFER_TYPE_PIXMAP:
1377                 case BUFFER_TYPE_ERROR:
1378                 default:
1379                         break;
1380                 }
1381
1382                 ret = lb_sync_lb_fb(common);
1383                 if (ret < 0) {
1384                         ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
1385                 }
1386                 break;
1387         case _LB_TYPE_TEXT:
1388                 lb_set_text_lb(common);
1389                 break;
1390         default:
1391                 break;
1392         }
1393
1394         common->pd.type = pd_type;
1395         lb_set_pdsize(common, pd_w, pd_h);
1396         lb_set_default_pdsize(common, pd_w, pd_h);
1397         switch (pd_type) {
1398         case _PD_TYPE_SCRIPT:
1399         case _PD_TYPE_BUFFER:
1400                 if (!strlen(pd_fname)) {
1401                         break;
1402                 }
1403
1404                 lb_set_pd_fb(common, pd_fname);
1405
1406                 ret = lb_sync_pd_fb(common);
1407                 if (ret < 0) {
1408                         ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
1409                 }
1410
1411                 /*!
1412                  * \brief
1413                  * PD doesn't need to create the lock file from here.
1414                  * Just create it from PD_CREATED event.
1415                  */
1416
1417                 break;
1418         case _PD_TYPE_TEXT:
1419                 lb_set_text_pd(common);
1420                 break;
1421         default:
1422                 break;
1423         }
1424
1425         lb_set_priority(common, priority);
1426
1427         lb_set_size_list(common, size_list);
1428         lb_set_group(common, cluster, category);
1429
1430         lb_set_content(common, content);
1431         lb_set_title(common, title);
1432
1433         lb_set_user(common, user);
1434
1435         lb_set_auto_launch(common, auto_launch);
1436         lb_set_pinup(common, pinup_supported);
1437
1438         lb_set_period(common, period);
1439
1440         ret = 0;
1441
1442         if (common->state == CREATE) {
1443                 dlist_foreach(common->livebox_list, l, handler) {
1444                         /*!
1445                          * \note
1446                          * These callback can change the handler->state.
1447                          * So we have to use the "old_state" which stored state before call these callbacks
1448                          */
1449
1450                         if (handler->cbs.created.cb) {
1451                                 ret_cb_t cb;
1452                                 void *cbdata;
1453
1454                                 cb = handler->cbs.created.cb;
1455                                 cbdata = handler->cbs.created.data;
1456
1457                                 handler->cbs.created.cb = NULL;
1458                                 handler->cbs.created.data = NULL;
1459
1460                                 cb(handler, ret, cbdata);
1461                         } else {
1462                                 lb_invoke_event_handler(handler, LB_EVENT_CREATED);
1463                         }
1464                 }
1465         }
1466
1467 out:
1468         if (ret == 0 && old_state == DELETE) {
1469                 struct dlist *n;
1470
1471                 DbgPrint("Take place an unexpected case [%d]\n", common->refcnt);
1472                 dlist_foreach_safe(common->livebox_list, l, n, handler) {
1473                         if (handler->cbs.created.cb) {
1474                                 if (!handler->common->request.deleted) {
1475                                         if (lb_send_delete(handler, common->delete_type, handler->cbs.created.cb, handler->cbs.created.data) < 0) {
1476                                                 /*!
1477                                                  * \note
1478                                                  * Already sent or something else happens.
1479                                                  * Callback will be called in any cases
1480                                                  */
1481                                         }
1482                                 } else if (handler->state != DELETE) {
1483                                         handler->cbs.created.cb(handler, LB_STATUS_ERROR_CANCEL, handler->cbs.created.data);
1484                                         lb_unref(handler, 1);
1485                                 }
1486                         } else {
1487                                 lb_invoke_event_handler(handler, LB_EVENT_DELETED);
1488                                 lb_unref(handler, 1);
1489                         }
1490                 }
1491
1492                 /*!
1493                  * \note
1494                  * handler->cbs.created.cb = NULL;
1495                  * handler->cbs.created.data = NULL;
1496                  *
1497                  * Do not clear this to use this from the deleted event callback.
1498                  * if this value is not cleared when the deleted event callback check it,
1499                  * it means that the created function is not called yet.
1500                  * Then the call the deleted event callback with LB_STATUS_ERROR_CANCEL errno.
1501                  */
1502         }
1503
1504         return NULL;
1505 }
1506
1507 static struct method s_table[] = {
1508         {
1509                 .cmd = "lb_updated", /* pkgname, id, lb_w, lb_h, priority, ret */
1510                 .handler = master_lb_updated,
1511         },
1512         {
1513                 .cmd = "pd_updated", /* pkgname, id, descfile, pd_w, pd_h, ret */
1514                 .handler = master_pd_updated,
1515         },
1516         {
1517                 .cmd = "pd_created",
1518                 .handler = master_pd_created,
1519         },
1520         {
1521                 .cmd = "pd_destroyed",
1522                 .handler = master_pd_destroyed,
1523         },
1524         {
1525                 .cmd = "fault_package", /* pkgname, id, function, ret */
1526                 .handler = master_fault_package,
1527         },
1528         {
1529                 .cmd = "deleted", /* pkgname, id, timestamp, ret */
1530                 .handler = master_deleted,
1531         },
1532         {
1533                 .cmd = "created", /* timestamp, pkgname, id, content, lb_w, lb_h, pd_w, pd_h, cluster, category, lb_file, pd_file, auto_launch, priority, size_list, is_user, pinup_supported, text_lb, text_pd, period, ret */
1534                 .handler = master_created,
1535         },
1536         {
1537                 .cmd = "group_changed",
1538                 .handler = master_group_changed,
1539         },
1540         {
1541                 .cmd = "period_changed",
1542                 .handler = master_period_changed,
1543         },
1544         {
1545                 .cmd = "size_changed",
1546                 .handler = master_size_changed,
1547         },
1548         {
1549                 .cmd = "pinup",
1550                 .handler = master_pinup,
1551         },
1552         {
1553                 .cmd = "scroll",
1554                 .handler = master_hold_scroll,
1555         },
1556
1557         {
1558                 .cmd = "update_mode",
1559                 .handler = master_update_mode,
1560         },
1561
1562         {
1563                 .cmd = "lb_update_begin",
1564                 .handler = master_lb_update_begin,
1565         },
1566         {
1567                 .cmd = "lb_update_end",
1568                 .handler = master_lb_update_end,
1569         },
1570
1571         {
1572                 .cmd = "pd_update_begin",
1573                 .handler = master_pd_update_begin,
1574         },
1575         {
1576                 .cmd = "pd_update_end",
1577                 .handler = master_pd_update_end,
1578         },
1579
1580         {
1581                 .cmd = "access_status",
1582                 .handler = master_access_status,
1583         },
1584         {
1585                 .cmd = "key_status",
1586                 .handler = master_key_status,
1587         },
1588         {
1589                 .cmd = "close_pd",
1590                 .handler = master_request_close_pd,
1591         },
1592
1593         {
1594                 .cmd = NULL,
1595                 .handler = NULL,
1596         },
1597 };
1598
1599 static void acquire_cb(struct livebox *handler, const struct packet *result, void *data)
1600 {
1601         if (!result) {
1602                 DbgPrint("Result packet is not valid\n");
1603         } else {
1604                 int ret;
1605
1606                 if (packet_get(result, "i", &ret) != 1) {
1607                         ErrPrint("Invalid argument\n");
1608                 } else {
1609                         DbgPrint("Acquire returns: %d\n", ret);
1610                 }
1611         }
1612
1613         return;
1614 }
1615
1616 static inline int make_connection(void)
1617 {
1618         struct packet *packet;
1619         int ret;
1620
1621         DbgPrint("Let's making connection!\n");
1622
1623         s_info.fd = com_core_packet_client_init(client_addr(), 0, s_table);
1624         if (s_info.fd < 0) {
1625                 ErrPrint("Try this again later\n");
1626                 return LB_STATUS_ERROR_IO;
1627         }
1628
1629         packet = packet_create("acquire", "d", util_timestamp());
1630         if (!packet) {
1631                 com_core_packet_client_fini(s_info.fd);
1632                 s_info.fd = -1;
1633                 return LB_STATUS_ERROR_FAULT;
1634         }
1635
1636         ret = master_rpc_async_request(NULL, packet, 1, acquire_cb, NULL);
1637         if (ret < 0) {
1638                 ErrPrint("Master RPC returns %d\n", ret);
1639                 com_core_packet_client_fini(s_info.fd);
1640                 s_info.fd = -1;
1641                 return LB_STATUS_ERROR_IO;
1642         }
1643
1644         return LB_STATUS_SUCCESS;
1645 }
1646
1647 static int connected_cb(int handle, void *data)
1648 {
1649         master_rpc_check_and_fire_consumer();
1650         return 0;
1651 }
1652
1653 static void master_started_cb(keynode_t *node, void *data)
1654 {
1655         int state = 0;
1656
1657         if (vconf_get_bool(VCONFKEY_MASTER_STARTED, &state) < 0) {
1658                 ErrPrint("Unable to get [%s]\n", VCONFKEY_MASTER_STARTED);
1659         }
1660
1661         DbgPrint("Master state: %d\n", state);
1662         if (state == 1 && make_connection() == (int)LB_STATUS_SUCCESS) {
1663                 int ret;
1664                 ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb);
1665                 if (ret < 0) {
1666                         DbgPrint("master_started vconf key de-registered [%d]\n", ret);
1667                 }
1668         }
1669 }
1670
1671 static gboolean timeout_cb(gpointer data)
1672 {
1673         if (vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL) < 0) {
1674                 ErrPrint("Failed to add vconf for monitoring service state\n");
1675         } else {
1676                 DbgPrint("vconf event callback is registered\n");
1677         }
1678
1679         master_started_cb(NULL, NULL);
1680
1681         s_info.timer_id = 0;
1682         return FALSE;
1683 }
1684
1685 static int disconnected_cb(int handle, void *data)
1686 {
1687         if (s_info.fd != handle) {
1688                 /*!< This handle is not my favor */
1689                 return 0;
1690         }
1691
1692         s_info.fd = -1; /*!< Disconnected */
1693
1694         master_rpc_clear_all_request();
1695         lb_invoke_fault_handler(LB_FAULT_PROVIDER_DISCONNECTED, MASTER_PKGNAME, "default", "disconnected");
1696
1697         lb_delete_all();
1698
1699         /* Try to reconnect after 1 sec later */
1700         if (!s_info.timer_id) {
1701                 DbgPrint("Reconnecting timer is added\n");
1702                 s_info.timer_id = g_timeout_add(1000, timeout_cb, NULL);
1703                 if (s_info.timer_id == 0) {
1704                         ErrPrint("Unable to add reconnecting timer\n");
1705                         return 0;
1706                 }
1707         } else {
1708                 ErrPrint("Reconnecting timer is already exists\n");
1709         }
1710
1711         return 0;
1712 }
1713
1714 int client_init(int use_thread)
1715 {
1716         com_core_packet_use_thread(use_thread);
1717
1718         s_info.client_addr = vconf_get_str(VCONFKEY_MASTER_CLIENT_ADDR);
1719         if (!s_info.client_addr) {
1720                 s_info.client_addr = strdup(CLIENT_SOCKET);
1721                 if (!s_info.client_addr) {
1722                         ErrPrint("Heap: %s\n", strerror(errno));
1723                         return -ENOMEM;
1724                 }
1725         }
1726
1727         (void)file_service_init();
1728
1729         DbgPrint("Server Address: %s\n", s_info.client_addr);
1730
1731         com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
1732         com_core_add_event_callback(CONNECTOR_CONNECTED, connected_cb, NULL);
1733         if (vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL) < 0) {
1734                 ErrPrint("Failed to add vconf for service state\n");
1735         } else {
1736                 DbgPrint("vconf event callback is registered\n");
1737         }
1738
1739         master_started_cb(NULL, NULL);
1740         return 0;
1741 }
1742
1743 int client_fd(void)
1744 {
1745         return s_info.fd;
1746 }
1747
1748 const char *client_addr(void)
1749 {
1750         return s_info.client_addr;
1751 }
1752
1753 int client_fini(void)
1754 {
1755         int ret;
1756
1757         (void)file_service_fini();
1758
1759         ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb);
1760         if (ret < 0) {
1761                 DbgPrint("Ignore vconf key: %d\n", ret);
1762         }
1763
1764         com_core_del_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
1765         com_core_del_event_callback(CONNECTOR_CONNECTED, connected_cb, NULL);
1766         com_core_packet_client_fini(s_info.fd);
1767         s_info.fd = -1;
1768         free(s_info.client_addr);
1769         s_info.client_addr = NULL;
1770         return LB_STATUS_SUCCESS;
1771 }
1772
1773 /* End of a file */