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