[FIX] prevent issue
[platform/core/system/swap-manager.git] / daemon / daemon.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12  * Nikita Kalyazin    <n.kalyazin@samsung.com>
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * - Samsung RnD Institute Russia
29  *
30  */
31 #define __STDC_FORMAT_MACROS
32 #include <stdio.h>
33 #include <stdlib.h>             // for realpath
34 #include <string.h>             // for strtok, strcpy, strncpy
35 #include <limits.h>             // for realpath
36 #include <inttypes.h>
37
38 #include <errno.h>              // for errno
39 #include <sys/types.h>          // for accept, mkdir, opendir, readdir
40 #include <sys/socket.h>         // for accept
41 #include <sys/stat.h>           // for mkdir
42 #include <sys/eventfd.h>        // for eventfd
43 #include <sys/timerfd.h>        // for timerfd
44 #include <unistd.h>             // for access, sleep
45 #include <stdbool.h>
46
47 #include <ctype.h>
48
49 #include <fcntl.h>
50
51 #include <assert.h>
52
53 #include <Ecore.h>
54
55 #include "daemon.h"
56 #include "sys_stat.h"
57 #include "utils.h"
58 #include "da_protocol.h"
59 #include "da_inst.h"
60 #include "da_data.h"
61 #include "input_events.h"
62 #include "smack.h"
63 #include "debug.h"
64
65 #define DA_WORK_DIR                     "/home/developer/sdk_tools/da/"
66 #define DA_READELF_PATH                 "/home/developer/sdk_tools/da/readelf"
67 #define SCREENSHOT_DIR                  "/tmp/da"
68
69 #define MAX_APP_LAUNCH_TIME             60
70 #define MAX_CONNECT_TIMEOUT_TIME        5*60
71
72
73 // =============================================================================
74 // start and terminate control functions
75 // =============================================================================
76
77 static Ecore_Fd_Handler *launch_timer_handler;
78 static pthread_mutex_t launch_timer_mutex = PTHREAD_MUTEX_INITIALIZER;
79
80 static void launch_timer_lock()
81 {
82         LOGI("lock launch_timer_mutex\n");
83         pthread_mutex_lock(&launch_timer_mutex);
84         LOGI("locked launch_timer_mutex\n");
85 }
86
87 static void launch_timer_unlock()
88 {
89         pthread_mutex_unlock(&launch_timer_mutex);
90         LOGI("unlock launch_timer_mutex\n");
91 }
92
93 //stop application launch timer
94 static int stop_app_launch_timer()
95 {
96         int res = 0;
97         launch_timer_lock();
98
99         if (manager.app_launch_timerfd > 0) {
100                 ecore_main_fd_handler_del(launch_timer_handler);
101                 if (close(manager.app_launch_timerfd)) {
102                         LOGE("close app_launch_timerfd failed\n");
103                         res = 1;
104                 }
105                 manager.app_launch_timerfd = -1;
106         } else {
107                 LOGW("trying to stop app launch timer when it stoped\n");
108         }
109
110         launch_timer_unlock();
111         return res;
112 }
113
114 static Eina_Bool launch_timer_cb(void *data, Ecore_Fd_Handler *fd_handler)
115 {
116         LOGE("Failed to launch application\n");
117         if (stop_app_launch_timer())
118                 LOGE("cannot stop app launch timer\n");
119
120         return ECORE_CALLBACK_CANCEL;
121 }
122
123 //start application launch timer function
124 static int start_app_launch_timer(int apps_count)
125 {
126         int res = 0;
127
128         assert(apps_count >= 0 && "negative apps count");
129
130         if (apps_count == 0)
131                 return res;
132
133         if (manager.app_launch_timerfd > 0) {
134                 LOGI("stop previous app launch timer\n");
135                 stop_app_launch_timer();
136         }
137
138         launch_timer_lock();
139
140         manager.app_launch_timerfd =
141             timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
142         if (manager.app_launch_timerfd > 0) {
143                 struct itimerspec ctime;
144                 ctime.it_value.tv_sec = MAX_APP_LAUNCH_TIME * apps_count;
145                 ctime.it_value.tv_nsec = 0;
146                 ctime.it_interval.tv_sec = 0;
147                 ctime.it_interval.tv_nsec = 0;
148                 if (timerfd_settime(manager.app_launch_timerfd, 0, &ctime, NULL) < 0) {
149                         LOGE("fail to set app launch timer\n");
150                         res = -1;
151                         goto unlock_and_stop;
152                 } else {
153                         launch_timer_handler =
154                                 ecore_main_fd_handler_add(manager.app_launch_timerfd,
155                                                           ECORE_FD_READ,
156                                                           launch_timer_cb,
157                                                           NULL,
158                                                           NULL, NULL);
159                         if (!launch_timer_handler) {
160                                 LOGE("fail to add app launch timer fd to \n");
161                                 res = -2;
162                                 goto unlock_and_stop;
163                         } else {
164                                 LOGI("application launch time started\n");
165                         }
166                 }
167         } else {
168                 LOGE("cannot create launch timer\n");
169                 res = -3;
170         }
171
172         launch_timer_unlock();
173         return res;
174
175 unlock_and_stop:
176         launch_timer_unlock();
177
178         stop_app_launch_timer();
179         return res;
180 }
181
182 static inline void inc_apps_to_run()
183 {
184         manager.apps_to_run++;
185 }
186
187 static inline void dec_apps_to_run()
188 {
189         if (manager.apps_to_run > 0)
190                 manager.apps_to_run--;
191 }
192
193 static inline int get_apps_to_run()
194 {
195         return manager.apps_to_run;
196 }
197
198 static int kill_app_by_info(const struct app_info_t *app_info)
199 {
200         int res = 0;
201
202         if (app_info == NULL) {
203                 LOGE("Cannot exec app. app_info is NULL");
204                 return -1;
205         }
206
207         switch (app_info->app_type) {
208         case APP_TYPE_TIZEN:
209                 res = kill_app(app_info->exe_path);
210                 break;
211         case APP_TYPE_RUNNING:
212                 // TODO: nothing, it's running
213                 LOGI("already started\n");
214                 break;
215         case APP_TYPE_COMMON:
216                 res = kill_app(app_info->exe_path);
217                 break;
218         case APP_TYPE_WEB:
219                 /* do nothing (it is restarted by itself) */
220                 break;
221         default:
222                 LOGE("Unknown app type %d\n", app_info->app_type);
223                 res = -1;
224                 break;
225         }
226
227         return res;
228 }
229
230 static int exec_app(const struct app_info_t *app_info)
231 {
232         int res = 0;
233
234         if (app_info == NULL) {
235                 LOGE("Cannot exec app. app_info is NULL");
236                 return -1;
237         }
238
239         switch (app_info->app_type) {
240         case APP_TYPE_TIZEN:
241                 if (exec_app_tizen(app_info->app_id, app_info->exe_path)) {
242                         LOGE("Cannot exec tizen app %s\n", app_info->app_id);
243                         res = -1;
244                 } else {
245                         inc_apps_to_run();
246                 }
247                 break;
248         case APP_TYPE_RUNNING:
249                 // TODO: nothing, it's running
250                 LOGI("already started\n");
251                 break;
252         case APP_TYPE_COMMON:
253                 if (exec_app_common(app_info->exe_path)) {
254                         LOGE("Cannot exec common app %s\n", app_info->exe_path);
255                         res = -1;
256                 } else {
257                         inc_apps_to_run();
258                 }
259                 break;
260         case APP_TYPE_WEB:
261                 if (exec_app_web(app_info->app_id)) {
262                         LOGE("Cannot exec web app %s\n", app_info->app_id);
263                         res = -1;
264                 }
265                 break;
266         default:
267                 LOGE("Unknown app type %d\n", app_info->app_type);
268                 res = -1;
269                 break;
270         }
271
272         LOGI("ret=%d\n", res);
273         return res;
274 }
275
276 // just send stop message to all target process
277 static void terminate_all_target()
278 {
279         struct msg_target_t msg = {
280                 .type = MSG_STOP,
281                 .length = 0
282         };
283
284         target_send_msg_to_all(&msg);
285 }
286
287 // terminate all target and wait for threads
288 void terminate_all()
289 {
290         terminate_all_target();
291
292         // wait for all other thread exit
293         target_wait_all();
294 }
295
296 // terminate all profiling by critical error
297 // TODO: don't send data to host
298 static void terminate_error(char *errstr, int send_to_host)
299 {
300         LOGE("termination all with err '%s'\n", errstr);
301         struct msg_data_t *msg = NULL;
302         if (send_to_host != 0) {
303                 msg = gen_message_error(errstr);
304                 if (msg) {
305                         if (write_to_buf(msg) != 0)
306                                 LOGE("write to buf fail\n");
307                         free_msg_data(msg);
308                 } else {
309                         LOGI("cannot generate error message\n");
310                 }
311         }
312         terminate_all();
313 }
314
315 static Ecore_Fd_Handler *connect_timer_handler;
316
317 static Eina_Bool connect_timer_cb(void *data, Ecore_Fd_Handler *fd_handler)
318 {
319         terminate_error("no incoming connections", 1);
320         close(manager.connect_timeout_timerfd);
321         manager.connect_timeout_timerfd = -1;
322         LOGE("No connection in %d sec. shutdown.\n",
323              MAX_CONNECT_TIMEOUT_TIME);
324         ecore_main_loop_quit();
325
326         return ECORE_CALLBACK_CANCEL;
327 }
328
329 static int launch_timer_start(void)
330 {
331         int res = 0;
332
333         manager.connect_timeout_timerfd =
334             timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
335         if (manager.connect_timeout_timerfd > 0) {
336                 struct itimerspec ctime;
337                 ctime.it_value.tv_sec = MAX_CONNECT_TIMEOUT_TIME;
338                 ctime.it_value.tv_nsec = 0;
339                 ctime.it_interval.tv_sec = 0;
340                 ctime.it_interval.tv_nsec = 0;
341                 if (timerfd_settime(manager.connect_timeout_timerfd, 0, &ctime, NULL) < 0) {
342                         LOGE("fail to set connect timeout timer\n");
343                         close(manager.connect_timeout_timerfd);
344                         manager.connect_timeout_timerfd = -1;
345                 } else {
346                         connect_timer_handler =
347                                 ecore_main_fd_handler_add(manager.connect_timeout_timerfd,
348                                                           ECORE_FD_READ,
349                                                           connect_timer_cb,
350                                                           NULL,
351                                                           NULL, NULL);
352                         if (!connect_timer_handler) {
353                                 LOGE("fail to add app connection timeout timer fd\n");
354                                 close(manager.connect_timeout_timerfd);
355                                 manager.connect_timeout_timerfd = -1;
356                         } else {
357                                 LOGI("connection timeout timer started\n");
358                         }
359                 }
360         } else {
361                 LOGE("cannot create connection timeout timer\n");
362         }
363
364         LOGI("ret=%d\n", res);
365         return res;
366 }
367
368 int prepare_profiling(void)
369 {
370         struct app_list_t *app = NULL;
371         const struct app_info_t *app_info = NULL;
372
373         app_info = app_info_get_first(&app);
374         if (app_info == NULL) {
375                 LOGE("No app info found\n");
376                 return -1;
377         }
378
379         //all apps
380         while (app_info != NULL) {
381                 if (kill_app_by_info(app_info) != 0) {
382                         LOGE("kill app failed\n");
383                         return -1;
384                 }
385                 app_info = app_info_get_next(&app);
386         }
387         //init rw for systeminfo
388         //init recv send network systeminfo
389         sys_stat_prepare();
390         return 0;
391
392 }
393
394 int start_profiling(void)
395 {
396         struct app_list_t *app = NULL;
397         const struct app_info_t *app_info = NULL;
398         int res = 0;
399
400         app_info = app_info_get_first(&app);
401         if (app_info == NULL) {
402                 LOGE("No app info found\n");
403                 return -1;
404         }
405         // remove previous screen capture files
406         remove_indir(SCREENSHOT_DIR);
407         if (mkdir(SCREENSHOT_DIR, 0777) == -1 && errno != EEXIST) {
408                 GETSTRERROR(errno, buf);
409                 LOGW("Failed to create directory for screenshot : %s\n", buf);
410         }
411
412         set_label_for_all(SCREENSHOT_DIR);
413
414         if (samplingStart() < 0) {
415                 LOGE("Cannot start sampling\n");
416                 res = -1;
417                 goto exit;
418         }
419
420         if (IS_OPT_SET(FL_RECORDING))
421                 add_input_events();
422
423         while (app_info != NULL) {
424                 if (exec_app(app_info)) {
425                         LOGE("Cannot exec app\n");
426                         res = -1;
427                         goto recording_stop;
428                 }
429                 app_info = app_info_get_next(&app);
430         }
431
432         if (start_app_launch_timer(get_apps_to_run()) < 0) {
433                 res = -1;
434                 goto recording_stop;
435         }
436
437         goto exit;
438
439  recording_stop:
440         if (IS_OPT_SET(FL_RECORDING))
441                 del_input_events();
442         samplingStop();
443
444  exit:
445         LOGI("return %d\n", res);
446         return res;
447 }
448
449 void stop_profiling(void)
450 {
451         if (IS_OPT_SET(FL_RECORDING))
452                 del_input_events();
453         samplingStop();
454 }
455
456 static void reconfigure_recording(struct conf_t conf)
457 {
458         uint64_t old_features = prof_session.conf.use_features0;
459         uint64_t new_features = conf.use_features0;
460         uint64_t to_enable = (new_features ^ old_features) & new_features;
461         uint64_t to_disable = (new_features ^ old_features) & old_features;
462
463         if (IS_OPT_SET_IN(FL_RECORDING, to_disable)) {
464                 del_input_events();
465                 prof_session.conf.use_features0 &= ~FL_RECORDING;
466         }
467
468         if (IS_OPT_SET_IN(FL_RECORDING, to_enable)) {
469                 add_input_events();
470                 prof_session.conf.use_features0 |= FL_RECORDING;
471         }
472
473 }
474
475 int reconfigure(struct conf_t conf)
476 {
477         reconfigure_recording(conf);
478
479         samplingStop();
480         memcpy(&prof_session.conf, &conf, sizeof(conf));
481         if (samplingStart() < 0) {
482                 LOGE("Cannot start sampling\n");
483                 return -1;
484         }
485
486         return 0;
487 }
488
489
490 static int file2str(const char *filename, char *buf, int len)
491 {
492         int fd, num_read;
493
494         fd = open(filename, O_RDONLY, 0);
495         if (fd == -1)
496                 return -1;
497
498         num_read = read(fd, buf, len - 1);
499
500         close(fd);
501
502         if (num_read <= 0)
503                 return -1;
504
505         buf[num_read] = '\0';
506
507         return num_read;
508 }
509
510 static pid_t get_lpad_pid(pid_t pid)
511 {
512         static pid_t lpad_pid = UNKNOWN_PID;
513         static const char lpad_path[] = DEBUG_LAUNCH_PRELOAD_PATH;
514         enum { lpad_path_len = sizeof(lpad_path) };
515
516         if (lpad_pid == UNKNOWN_PID) {
517                 char fname[64];
518                 char buf[lpad_path_len];
519
520                 snprintf(fname, sizeof(fname), "/proc/%d/cmdline", pid);
521                 if (-1 == file2str(fname, buf, lpad_path_len))
522                         return lpad_pid;
523
524                 buf[lpad_path_len - 1] = '\0';
525
526                 if (strncmp(buf, lpad_path, lpad_path_len - 1) == 0)
527                         lpad_pid = pid;
528         }
529
530         return lpad_pid;
531 }
532
533 static pid_t get_current_pid(void)
534 {
535         static pid_t pid = UNKNOWN_PID;
536
537         if (pid == UNKNOWN_PID)
538                 pid = getpid();
539
540         return pid;
541 }
542
543 static void target_set_type(struct target *t)
544 {
545         pid_t ppid = target_get_ppid(t);
546         enum app_type_t app_type = APP_TYPE_UNKNOWN;
547
548         if (get_current_pid() == ppid) {
549                 app_type = APP_TYPE_COMMON;
550         } else if (get_lpad_pid(ppid) == ppid) {
551                 app_type = APP_TYPE_TIZEN;
552         }
553
554         t->app_type = app_type;
555 }
556
557
558 static int target_event_pid_handler(struct target *target)
559 {
560         struct app_list_t *app = NULL;
561         struct app_info_t *app_info = NULL;
562
563         target_set_type(target);
564
565         /* posible need some process check right there before start_replay >> */
566         app_info = app_info_get_first(&app);
567         if (app_info == NULL) {
568                 LOGE("No app info found\n");
569                 return -1;
570         }
571
572         while (app_info != NULL) {
573                 if (is_same_app_process(app_info->exe_path,
574                                         target_get_pid(target)))
575                         break;
576                 app_info = app_info_get_next(&app);
577         }
578
579         if (app_info == NULL) {
580                 LOGE("pid %d not found in app list\n",
581                      target_get_pid(target));
582                 return -1;
583         }
584
585         if (start_replay() != 0) {
586                 LOGE("Cannot start replay thread\n");
587                 return -1;
588         }
589         /* posible need some process check right there before start_replay << */
590
591         target->initial_log = 1;
592
593         return 0;
594 }
595
596 static int target_event_stop_handler(struct target *target)
597 {
598         int cnt;
599         enum app_type_t app_type = target->app_type;
600
601         LOGI("target[%p] close, pid(%d) : (remaining %d target)\n",
602              target, target_get_pid(target), target_cnt_get() - 1);
603
604         ecore_main_fd_handler_del(target->handler);
605
606         target_wait(target);
607         target_dtor(target);
608         // all target client are closed
609         cnt = target_cnt_sub_and_fetch();
610         if (0 == cnt) {
611                 switch (app_type) {
612                 case APP_TYPE_TIZEN:
613                 case APP_TYPE_COMMON:
614                         LOGI("all targets are stopped\n");
615                         if (stop_all() != ERR_NO)
616                                 LOGE("Stop failed\n");
617                         return -11;
618                 }
619         }
620
621         return 0;
622 }
623
624 // return 0 if normal case
625 // return plus value if non critical error occur
626 // return minus value if critical error occur
627 // return -11 if all target process closed
628 static int target_event_handler(struct target *t, uint64_t msg)
629 {
630         int err = 0;
631         if (msg & EVENT_PID)
632                 err = target_event_pid_handler(t);
633         if (err)
634                 return err;
635
636         if (msg & EVENT_STOP || msg & EVENT_ERROR)
637                 err = target_event_stop_handler(t);
638
639         return err;
640 }
641
642 static Eina_Bool target_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
643 {
644         uint64_t u;
645         ssize_t recvLen;
646         struct target *target = (struct target *)data;
647
648         recvLen = read(target->event_fd, &u, sizeof(uint64_t));
649         if (recvLen != sizeof(uint64_t)) {
650                 // maybe closed, but ignoring is more safe then
651                 // removing fd from event loop
652         } else {
653                 if (-11 == target_event_handler(target, u)) {
654                         LOGI("all target process is closed\n");
655                 }
656         }
657
658         return ECORE_CALLBACK_RENEW;
659 }
660
661 /**
662  * return 0 if normal case
663  * return plus value if non critical error occur
664  * return minus value if critical error occur
665  */
666 static int targetServerHandler(void)
667 {
668         int err;
669         struct msg_target_t log;
670         struct target *target;
671
672         target = target_ctor();
673         if (target == NULL) {
674                 LOGW("(target == NULL) no more target can connected\n");
675                 return 1;
676         }
677
678         err = target_accept(target, manager.target_server_socket);
679         if (err == 0) {
680                 /* send config message to target process */
681                 log.type = MSG_OPTION;
682                 log.length = snprintf(log.data, sizeof(log.data), "%llu",
683                                       prof_session.conf.use_features0) + 1;
684                 if (target_send_msg(target, &log) != 0)
685                         LOGE("fail to send data to target %p\n", target);
686
687                 /* send current instrument maps */
688                 send_maps_inst_msg_to(target);
689
690                 // make event fd
691                 target->event_fd = eventfd(EFD_CLOEXEC, EFD_NONBLOCK);
692                 if (target->event_fd == -1) {
693                         // fail to make event fd
694                         LOGE("fail to make event fd for target[%p]\n", target);
695                         goto TARGET_CONNECT_FAIL;
696                 }
697
698                 target->handler =
699                         ecore_main_fd_handler_add(target->event_fd,
700                                                   ECORE_FD_READ,
701                                                   target_event_cb,
702                                                   (void *)target,
703                                                   NULL, NULL);
704                 if (!target->handler) {
705                         LOGE("fail to add event fd for target[%p]\n", target);
706                         goto TARGET_CONNECT_FAIL;
707                 }
708
709                 // make recv thread for target
710                 if (makeRecvThread(target) != 0) {
711                         // fail to make recv thread
712                         LOGE("fail to make recv thread for target[%p]\n",
713                              target);
714                         ecore_main_fd_handler_del(target->handler);
715                         goto TARGET_CONNECT_FAIL;
716                 }
717
718                 dec_apps_to_run();
719
720                 if ((manager.app_launch_timerfd > 0) && (get_apps_to_run() == 0)) {
721                         if (stop_app_launch_timer())
722                                 LOGE("cannot stop app launch timer\n");
723                 }
724
725                 LOGI("target connected target[%p](running %d target)\n",
726                      target, target_cnt_get() + 1);
727
728                 target_cnt_set(target_cnt_get() + 1);
729                 return 0;
730         } else {
731                 // accept error
732                 LOGE("Failed to accept at target server socket\n");
733         }
734
735  TARGET_CONNECT_FAIL:
736         if (target_cnt_get() == 0) {
737                 // if this connection is main connection
738                 return -1;
739         } else {
740                 // if this connection is not main connection then ignore process by error
741                 target_dtor(target);
742                 return 1;
743         }
744 }
745
746 static void recv_msg_tail(int fd, uint32_t len)
747 {
748         char buf[512];
749         uint32_t blocks;
750         int recv_len;
751
752         for (blocks = len / sizeof(buf); blocks != 0; blocks--) {
753                 recv_len = recv(fd, buf, sizeof(buf), MSG_WAITALL);
754                 if (recv_len != sizeof(buf))
755                         goto error_ret;
756         }
757
758         len = len % sizeof(buf);
759         if (len != 0) {
760                 recv_len = recv(fd, buf, len, MSG_WAITALL);
761                 if (recv_len == -1)
762                         goto error_ret;
763         }
764
765         return;
766
767 error_ret:
768         LOGE("error or close request from host. recv_len = %d\n",
769              recv_len);
770         return;
771 }
772
773 static Ecore_Fd_Handler *host_ctrl_handler;
774 static Ecore_Fd_Handler *host_data_handler;
775
776 // return plus value if non critical error occur
777 // return minus value if critical error occur
778 // return -11 if socket closed
779 static int controlSocketHandler(int efd)
780 {
781         ssize_t recv_len;
782         struct msg_t msg_head;
783         struct msg_t *msg;
784         int res = 0;
785
786         if (manager.connect_timeout_timerfd >= 0) {
787                 LOGI("release connect timeout timer\n");
788                 close(manager.connect_timeout_timerfd);
789                 manager.connect_timeout_timerfd = -1;
790         }
791         // Receive header
792         recv_len = recv(manager.host.control_socket,
793                         &msg_head, MSG_CMD_HDR_LEN, 0);
794
795         // error or close request from host
796         if (recv_len == -1 || recv_len == 0) {
797                 LOGW("error or close request from host. "
798                      "MSG_ID = 0x%08X; recv_len = %d\n",
799                      msg_head.id, recv_len);
800                 return -11;
801         } else {
802                 if (msg_head.len > HOST_CTL_MSG_MAX_LEN) {
803                         LOGE("Too long message. size = %u\n", msg_head.len);
804                         recv_msg_tail(manager.host.control_socket, msg_head.len);
805                         sendACKToHost(msg_head.id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
806                         return -1;
807                 }
808                 msg = malloc(MSG_CMD_HDR_LEN + msg_head.len);
809                 if (!msg) {
810                         LOGE("Cannot alloc msg\n");
811                         recv_msg_tail(manager.host.control_socket, msg_head.len);
812                         sendACKToHost(msg_head.id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
813                         return -1;
814                 }
815                 msg->id = msg_head.id;
816                 msg->len = msg_head.len;
817                 if (msg->len > 0) {
818                         // Receive payload (if exists)
819                         recv_len = recv(manager.host.control_socket,
820                                         msg->payload, msg->len, MSG_WAITALL);
821                         if (recv_len == -1) {
822                                 LOGE("error or close request from host. recv_len = %d\n",
823                                      recv_len);
824                                 free(msg);
825                                 return -11;
826                         }
827                 }
828                 printBuf((char *)msg, MSG_CMD_HDR_LEN + msg->len);
829                 res = host_message_handler(msg);
830                 free(msg);
831         }
832
833         return res;
834 }
835
836 static Eina_Bool host_ctrl_cb(void *data, Ecore_Fd_Handler *fd_handler)
837 {
838         int result = controlSocketHandler(manager.efd);
839         if (result == -11) {
840                 // socket close
841                 //if the host disconnected.
842                 //In all other cases daemon must report an error and continue the loop
843                 //close connect_timeoutt and host socket and quit
844                 LOGI("Connection closed. Termination. (%d)\n",
845                      manager.host.control_socket);
846                 manager.host.data_socket = -1; //splice will fail without that
847                 ecore_main_loop_quit();
848         } else if (result < 0) {
849                 LOGE("Control socket handler. err #%d\n", result);
850         }
851
852         return ECORE_CALLBACK_RENEW;
853 }
854
855 static Eina_Bool host_data_cb(void *data, Ecore_Fd_Handler *fd_handler)
856 {
857         ssize_t recvLen;
858         char recvBuf[32];
859
860         recvLen = recv(manager.host.data_socket, recvBuf, 32, MSG_DONTWAIT);
861         if (recvLen == 0) {
862                 // close data socket
863                 ecore_main_fd_handler_del(host_data_handler);
864                 close(manager.host.data_socket);
865                 manager.host.data_socket = -1;
866                 // TODO: finish transfer thread
867         }
868
869         LOGI("host message from data socket %d\n", recvLen);
870
871         return ECORE_CALLBACK_RENEW;
872 }
873
874 // return 0 if normal case
875 // return plus value if non critical error occur
876 // return minus value if critical error occur
877 static int hostServerHandler(void)
878 {
879         static int hostserverorder = 0;
880         int csocket;
881
882         if (hostserverorder > 1)        // control and data socket connected already
883                 return 1;               // ignore
884
885         csocket = accept4(manager.host_server_socket, NULL, NULL, SOCK_CLOEXEC);
886
887         if (csocket >= 0) {
888                 // accept succeed
889
890                 if (hostserverorder == 0) {
891                         manager.host.control_socket = csocket;
892                         unlink_portfile();
893                         LOGI("host control socket connected = %d\n", csocket);
894                         host_ctrl_handler =
895                                 ecore_main_fd_handler_add(manager.host.control_socket,
896                                                           ECORE_FD_READ,
897                                                           host_ctrl_cb,
898                                                           NULL,
899                                                           NULL, NULL);
900                         if (!host_ctrl_handler) {
901                                 LOGE("Failed to add host control socket fd\n");
902                                 close(csocket);
903                                 return -1;
904                         }
905                 } else {
906                         manager.host.data_socket = csocket;
907                         LOGI("host data socket connected = %d\n", csocket);
908
909                         host_data_handler =
910                                 ecore_main_fd_handler_add(manager.host.data_socket,
911                                                           ECORE_FD_READ,
912                                                           host_data_cb,
913                                                           NULL,
914                                                           NULL, NULL);
915                         if (!host_data_handler) {
916                                 LOGE("Failed to add host data socket fd\n");
917                                 close(csocket);
918                                 return -1;
919                         }
920                 }
921
922                 hostserverorder++;
923                 return 0;
924         } else {
925                 // accept error
926                 LOGE("Failed to accept from host server socket\n");
927                 return -1;
928         }
929 }
930
931 static Ecore_Fd_Handler *host_connect_handler;
932 static Ecore_Fd_Handler *target_connect_handler;
933
934 static Eina_Bool host_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
935 {
936         // connect request from host
937         int result = hostServerHandler();
938         if (result < 0) {
939                 LOGE("Internal DA framework error (hostServerHandler)\n");
940         }
941
942         return ECORE_CALLBACK_RENEW;
943 }
944
945 static Eina_Bool target_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
946 {
947         if (targetServerHandler() < 0) {
948                 // critical error
949                 terminate_error("Internal DA framework error, "
950                                 "Please re-run the profiling "
951                                 "(targetServerHandler)\n", 1);
952         }
953
954         return ECORE_CALLBACK_RENEW;
955 }
956
957 static bool initialize_events(void)
958 {
959         host_connect_handler =
960                 ecore_main_fd_handler_add(manager.host_server_socket,
961                                           ECORE_FD_READ,
962                                           host_connect_cb,
963                                           NULL,
964                                           NULL, NULL);
965         if (!host_connect_handler) {
966                 LOGE("Host server socket add error\n");
967                 return false;
968         }
969
970         target_connect_handler =
971                 ecore_main_fd_handler_add(manager.target_server_socket,
972                                           ECORE_FD_READ,
973                                           target_connect_cb,
974                                           NULL,
975                                           NULL, NULL);
976         if (!target_connect_handler) {
977                 LOGE("Target server socket add error\n");
978                 return false;
979         }
980
981         return true;
982 }
983
984 // return 0 for normal case
985 int daemonLoop(void)
986 {
987         int return_value = 0;
988
989         ecore_init();
990
991         if (init_input_events() == -1) {
992                 return_value = -1;
993                 goto END_EVENT;
994         }
995
996         if (!initialize_events()) {
997                 return_value = -1;
998                 goto END_EFD;
999         }
1000
1001         if (launch_timer_start() < 0) {
1002                 LOGE("Launch timer start failed\n");
1003                 return_value = -1;
1004                 goto END_EFD;
1005         }
1006
1007         init_prof_session(&prof_session);
1008
1009         ecore_main_loop_begin();
1010         ecore_shutdown();
1011
1012  END_EFD:
1013         LOGI("close efd\n");
1014         close(manager.efd);
1015  END_EVENT:
1016         return return_value;
1017 }