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