[IMPROVE] run app with arguments
[platform/core/system/swap-manager.git] / daemon / da_protocol.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
9  * Nikita Kalyazin    <n.kalyazin@samsung.com>
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  * Contributors:
24  * - Samsung RnD Institute Russia
25  *
26  */
27
28
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <errno.h>
34
35 #include <sys/types.h>
36 #include <sys/socket.h>
37
38 #include <sys/sysinfo.h>
39
40 #include "da_protocol.h"
41 #include "da_protocol_check.h"
42 #include "daemon.h"
43 #include "sys_stat.h"
44 #include "transfer_thread.h"
45 #include "elf.h"
46 #include "ioctl_commands.h"
47 #include "debug.h"
48
49 #include <sys/stat.h>
50 #include <fcntl.h>
51 #include <unistd.h>
52
53
54
55 void inline free_msg(struct msg_t *msg)
56 {
57         free(msg);
58 }
59 static uint32_t msg_size_with_out_replays = 0;
60
61 struct prof_session_t prof_session;
62
63 static void print_app_info( struct app_info_t *app_info);
64 static void print_conf(struct conf_t * conf);
65 //DEBUG FUNCTIONS
66 #define dstr(x) #x
67
68 #define check_and_return(par,check) if ( par == check ) {return dstr(check);}
69 #define check_2(a1,a2) check_and_return(ID,a1) else check_and_return(ID,a2)
70 #define check_4(a1,a2,a3,a4) check_2(a1,a2) else check_2(a3,a4)
71 #define check_8(a1,a2,a3,a4,a5,a6,a7,a8) check_4(a1,a2,a3,a4) else check_4(a5,a6,a7,a8)
72
73 #define check_all(a1, ...) check_and_return(ID,a1) //#else check_all(__VA_ARGS__)
74 char* msg_ID_str ( enum HostMessageT ID)
75 {
76         check_8(
77                 NMSG_KEEP_ALIVE,
78                 NMSG_START,
79                 NMSG_STOP,
80                 NMSG_CONFIG,
81                 0,
82                 NMSG_BINARY_INFO,
83                 NMSG_GET_TARGET_INFO,
84                 NMSG_SWAP_INST_ADD
85                 )
86         else
87         check_8(
88                 NMSG_SWAP_INST_REMOVE,
89                 NMSG_KEEP_ALIVE_ACK,
90                 NMSG_START_ACK,
91                 NMSG_STOP_ACK,
92
93                 NMSG_CONFIG_ACK,
94                 NMSG_BINARY_INFO_ACK,
95                 NMSG_SWAP_INST_ACK,
96                 NMSG_GET_TARGET_INFO_ACK
97                 )
98         else
99         check_8(
100                 NMSG_SWAP_INST_ADD_ACK,
101                 NMSG_SWAP_INST_REMOVE_ACK,
102                 NMSG_PROCESS_INFO,
103                 NMSG_TERMINATE,
104
105                 NMSG_ERROR,
106                 NMSG_SAMPLE,
107                 NMSG_SYSTEM,
108                 NMSG_IMAGE
109                 )
110         else
111         check_8(
112                 NMSG_RECORD,
113                 NMSG_FUNCTION_ENTRY,
114                 NMSG_FUNCTION_EXIT,
115                 NMSG_CONTEXT_SWITCH_ENTRY,
116
117                 NMSG_CONTEXT_SWITCH_EXIT,
118                 NMSG_PROBE,
119                 NMSG_PROBE_MEMORY,
120                 NMSG_PROBE_UICONTROL
121                 )
122         else
123         check_8(
124                 NMSG_PROBE_UIEVENT,
125                 NMSG_PROBE_RESOURCE,
126                 NMSG_PROBE_LIFECYCLE,
127                 NMSG_PROBE_SCREENSHOT,
128
129                 NMSG_PROBE_SCENE,
130                 NMSG_PROBE_THREAD,
131                 NMSG_PROBE_CUSTOM,
132                 NMSG_PROBE_SYNC
133         ) else
134         return "HZ";
135 }
136
137
138 static char *msgErrStr(enum ErrorCode err)
139 {
140         switch (err) {
141         case ERR_NO:
142                 return "success";
143         case ERR_LOCKFILE_CREATE_FAILED:
144                 return "lock file create failed";
145         case ERR_ALREADY_RUNNING:
146                 return "already running";
147         case ERR_INITIALIZE_SYSTEM_INFO_FAILED:
148                 return "initialize system info failed";
149         case ERR_HOST_SERVER_SOCKET_CREATE_FAILED:
150                 return "host server socket create failed";
151         case ERR_TARGET_SERVER_SOCKET_CREATE_FAILED:
152                 return "target server socket create failed";
153         case ERR_SIGNAL_MASK_SETTING_FAILED: //TODO del (old parametr)
154                 return "ERR SIGNAL MASK SETTING FAILED";
155         case ERR_WRONG_MESSAGE_FORMAT:
156                 return "wrong message format";
157         case ERR_WRONG_MESSAGE_TYPE:
158                 return "wrong message type";
159         case ERR_WRONG_MESSAGE_DATA:
160                 return "wrong message data";
161         case ERR_CANNOT_START_PROFILING:
162                 return "cannot start profiling";
163         case ERR_SERV_SOCK_CREATE:
164                 return "server socket creation failed (written in /tmp/da.port file)";
165         case ERR_SERV_SOCK_BIND:
166                 return "server socket bind failed (written in /tmp/da.port file)";
167         case ERR_SERV_SOCK_LISTEN:
168                 return "server socket listen failed (written in /tmp/da.port file)";
169         case ERR_UNKNOWN:
170         default:
171                 return "unknown error";
172         }
173         return "unknown error";
174 }
175
176
177 #define print_feature(f,in,to,delim) if (f & in)\
178                                                                 {\
179                                                                         sprintf(to, dstr(f) delim );\
180                                                                         to+=strlen( dstr(f) delim );\
181                                                                 }
182 #define print_feature_a(f) print_feature(f,feature,to,", ")
183 void feature_code_str(uint32_t feature, char * to)
184 {
185         print_feature_a(FL_CPU);
186         print_feature_a(FL_MEMORY);
187         print_feature_a(FL_FUNCTION_PROFILING);
188         print_feature_a(FL_MEMORY_ALLCATION_PROBING);
189         print_feature_a(FL_FILE_API_PROBING);
190         print_feature_a(FL_THREAD_API_PROBING);
191         print_feature_a(FL_OSP_UI_API_PROBING);
192         print_feature_a(FL_SCREENSHOT);
193         print_feature_a(FL_USER_EVENT);
194         print_feature_a(FL_RECORDING);
195         print_feature_a(FL_SYSTCALL_FILE);
196         print_feature_a(FL_SYSTCALL_IPC);
197         print_feature_a(FL_SYSTCALL_PROCESS);
198         print_feature_a(FL_SYSTCALL_SIGNAL);
199         print_feature_a(FL_SYSTCALL_NETWORK);
200         print_feature_a(FL_SYSTCALL_DESC);
201         print_feature_a(FL_CONTEXT_SWITCH);
202         print_feature_a(FL_NETWORK_API_PROBING);
203         print_feature_a(FL_OPENGL_API_PROBING);
204
205 }
206
207
208 //PARSE FUNCTIONS
209 inline uint32_t get_avail_msg_size(struct msg_buf_t *msg)
210 {
211         return (uint32_t)(msg->end - msg->cur_pos);
212 }
213
214 inline uint32_t get_msg_cur_size(struct msg_buf_t *msg)
215 {
216         return (uint32_t) (msg->cur_pos - msg->payload);
217 }
218
219 static int parse_string(struct msg_buf_t *msg, char **str)
220 {
221         parse_deb("size = %d\n", get_avail_msg_size(msg));
222         int len = strlen(msg->cur_pos) + 1;
223
224         if (get_avail_msg_size(msg) < len)
225                 return 0;
226
227         *str = strdup(msg->cur_pos);
228         parse_deb("<%s>\n",*str);
229         msg->cur_pos += len;
230         return 1;
231 }
232
233 static int parse_int32(struct msg_buf_t *msg, uint32_t *val)
234 {
235         parse_deb("size = %d\n", get_avail_msg_size(msg));
236         if (get_avail_msg_size(msg) < sizeof(*val))
237                 return 0;
238         *val = *(uint32_t *)msg->cur_pos;
239         msg->cur_pos += sizeof(uint32_t);
240
241
242         parse_deb("<%d><0x%08X>\n",*val,*val);
243         return 1;
244 }
245
246 static int parse_int64(struct msg_buf_t *msg, uint64_t *val)
247 {
248         parse_deb("size = %d\n", get_avail_msg_size(msg));
249         if (get_avail_msg_size(msg) < sizeof(*val))
250                 return 0;
251
252         *val = *(uint64_t *)msg->cur_pos;
253
254         parse_deb("<%llu><0x%016llX>\n",*val,*val);
255         msg->cur_pos += sizeof(uint64_t);
256         return 1;
257 }
258
259 static void strip_args(const char *cmd, char *path)
260 {
261         char *bin_end = strchr(cmd, ' ');
262         size_t binname_len = bin_end - cmd;
263
264         memcpy(path, cmd, binname_len);
265         path[binname_len] = '\0';
266 }
267
268 static int parse_app_info(struct msg_buf_t *msg,
269                                struct app_info_t *app_info)
270 {
271         char bin_path[MAX_FILENAME];
272
273         //Application type
274         parse_deb("parse_app_info\n");
275         if (!parse_int32(msg, &app_info->app_type) ||
276                 !check_app_type(app_info->app_type))
277         {
278                 LOGE("app type error\n");
279                 return 0;
280         }
281
282         //Application ID
283         if (!parse_string(msg, &app_info->app_id) ||
284                 !check_app_id(app_info->app_type, app_info->app_id))
285         {
286                 LOGE("app id parsing error\n");
287                 return 0;
288         }
289
290         //Applicaion exe path
291         if (!parse_string(msg, &app_info->exe_path)) {
292                 LOGE("app info parsing error\n");
293                 return 0;
294         }
295         strip_args(app_info->exe_path, bin_path);
296         if (!check_exec_path(bin_path)) {
297                 LOGE("app info parsing error\n");
298                 return 0;
299         }
300
301 //      print_app_info(app_info);
302
303         return 1;
304 }
305
306 static int parse_conf(struct msg_buf_t *msg, struct conf_t *conf)
307 {
308
309         parse_deb("parse_conf\n");
310         if (!parse_int64(msg, &conf->use_features0)) {
311                 LOGE("use features0 error\n");
312                 return 0;
313         }
314
315         if (!parse_int64(msg, &conf->use_features1)) {
316                 LOGE("use features1 parsing error\n");
317                 return 0;
318         }
319
320         //Check features value
321         if (!check_conf_features(conf->use_features0, conf->use_features1)) {
322                 LOGE("check features fail\n");
323                 return 0;
324         }
325
326         if (!parse_int32( msg, &conf->system_trace_period) ||
327                 !check_conf_systrace_period(conf->system_trace_period))
328         {
329                 LOGE("system trace period error\n");
330                 return 0;
331         }
332
333         if (!parse_int32( msg, &conf->data_message_period) ||
334                 !check_conf_datamsg_period(conf->data_message_period))
335         {
336                 LOGE("data message period error\n");
337                 return 0;
338         }
339         //print_conf(conf);
340         return 1;
341 }
342
343 static int parse_us_inst_func(struct msg_buf_t *msg , struct us_func_inst_t * dest)
344 {
345
346         if (!parse_int64(msg, &(dest->func_addr))) {
347                 LOGE("func addr parsing error\n");
348                 return 0;
349         }
350
351         if (!parse_string(msg, &dest->args) ||
352                 !check_us_inst_func_args(dest->args))
353         {
354                 LOGE("args format parsing error\n");
355                 return 0;
356         }
357         return 1;
358
359 }
360
361 static int parse_func_inst_list(struct msg_buf_t *msg,
362                             uint32_t *num,
363                             struct us_func_inst_t ** us_func_inst_list)
364 {
365         uint32_t i = 0;
366         if (!parse_int32(msg, num) ||
367                 !check_us_app_inst_func_count(*num))
368         {
369                 LOGE("func num parsing error\n");
370                 return 0;
371         }
372         //parse user space function list
373
374         parse_deb("us_func_inst_list size = %d * %d\n",(*num),
375                                 (int)sizeof(**us_func_inst_list));
376         *us_func_inst_list =
377                 (struct us_func_inst_t *)
378                 malloc((*num) * sizeof(**us_func_inst_list));
379         if (!*us_func_inst_list){
380                 LOGE("func alloc error\n");
381                 return 0;
382         };
383
384         for (i = 0; i < *num; i++){
385                 if (!parse_us_inst_func(msg, &((*us_func_inst_list)[i]))){
386                         // TODO maybe need to free allocated memory up there
387                         LOGE("parse us inst func #%d failed\n", i + 1);
388                         return 0;
389                 }
390         }
391
392         return 1;
393 }
394
395 static int parse_us_inst_lib(struct msg_buf_t *msg, struct us_lib_inst_t * dest)
396 {
397
398         if (!parse_string(msg, &(dest)->bin_path) ||
399                 !check_exec_path(dest->bin_path))
400         {
401                 LOGE("bin path parsing error\n");
402                 return 0;
403         }
404
405         if (!parse_func_inst_list(msg, &dest->func_num, &dest->us_func_inst_list)) {
406                 LOGE("funcs parsing error\n");
407                 return 0;
408         }
409         return 1;
410
411 }
412
413 static int parse_lib_inst_list(struct msg_buf_t *msg,
414                             uint32_t *num,
415                             struct us_lib_inst_t ** us_lib_inst_list)
416 {
417         uint32_t i = 0;
418         if (!parse_int32(msg, num) ||
419                 !check_lib_inst_count(*num))
420         {
421                 LOGE("lib num parsing error\n");
422                 return 0;
423         }
424
425         parse_deb("lib_list size = %d\n", (*num) * (int)sizeof(**us_lib_inst_list) );
426         *us_lib_inst_list =
427                 (struct us_lib_inst_t *)
428                 malloc( (*num) * sizeof(**us_lib_inst_list) );
429         if (!*us_lib_inst_list){
430                 LOGE("lib alloc error\n");
431                 return 0;
432         };
433         for (i = 0; i < *num; i++){
434                 if (!parse_us_inst_lib( msg, &( (*us_lib_inst_list)[i] ) )){
435                         // TODO maybe need free allocated memory up there
436                         LOGE("parse is inst lib #%d failed\n", i + 1);
437                         return 0;
438                 }
439         }
440         return 1;
441 }
442
443 static int parse_app_inst(struct msg_buf_t *msg,
444                             struct app_inst_t *app_inst)
445 {
446         if (!parse_int32(msg, &app_inst->app_type) ||
447                 !check_app_type(app_inst->app_type))
448         {
449                 LOGE("app type parsing error\n");
450                 return 0;
451         }
452         if (!parse_string(msg, &app_inst->app_id) ||
453                 !check_app_id(app_inst->app_type, app_inst->app_id))
454         {
455                 LOGE("app id parsing error\n");
456                 return 0;
457         }
458         if (!parse_string(msg, &app_inst->exec_path) ||
459                 !check_exec_path(app_inst->exec_path))
460         {
461                 LOGE("exec path parsing error\n");
462                 return 0;
463         }
464         if (!parse_func_inst_list(msg, &app_inst->func_num, &(app_inst->us_func_inst_list))) {
465                 LOGE("funcs parsing error\n");
466                 return 0;
467         }
468
469         parse_deb(">=%04X : %s, %s\n",
470              app_inst->app_type, app_inst->app_id, app_inst->exec_path);
471
472         if (!parse_lib_inst_list( msg, &app_inst->lib_num , &app_inst->us_lib_inst_list)) {
473                 LOGE("libs parsing error\n");
474                 return 0;
475         }
476
477         return 1;
478 }
479
480 int parse_user_space_inst(struct msg_buf_t *msg,
481                             struct user_space_inst_t *user_space_inst)
482 {
483         parse_deb("parse_user_space_inst\n");
484         uint32_t num = 0 , i = 0;
485         struct app_inst_t * list = 0;
486
487         if (!parse_int32 ( msg, &num ) ||
488                 !check_us_app_count(num))
489         {
490                 LOGE("app num error\n");
491                 return 0;
492         }
493
494         parse_deb("%d * %d\n",(int) sizeof(*(user_space_inst->app_inst_list)), num);
495         if ( num != 0 ) {
496                 list = (struct app_inst_t *) malloc (
497                         sizeof(*(user_space_inst->app_inst_list)) * num);
498                 if ( !list ) {
499                         LOGE("apps alloc error\n");
500                         return 0;
501                 };
502
503                 for ( i = 0; i < num; i++){
504                         if (!parse_app_inst( msg, &(list[i]) )){
505                                 LOGE("parse app inst #%d failed\n", i + 1);
506                                 free(list);
507                                 return 0;
508                         }
509                 };
510
511                 user_space_inst->app_num = num;
512                 user_space_inst->app_inst_list = list;
513         }
514         return 1;
515 }
516
517 //REPLAY EVENTS PARSE
518 static int parse_timeval(struct msg_buf_t *msg, struct timeval *tv)
519 {
520         uint32_t nsec = 0;
521
522         parse_deb("time\n");
523
524         // FIXME: is sec/usec order correct?
525         if (!parse_int32(msg, &nsec)) {
526                 LOGE("usec parsing error\n");
527                 return 0;
528         }
529         tv->tv_usec = nsec / 1000;
530
531         if (!parse_int32(msg, (uint32_t *)&tv->tv_sec)) {
532                 LOGE("sec parsing error\n");
533                 return 0;
534         }
535
536         return 1;
537 }
538
539 static int parse_replay_event(struct msg_buf_t *msg,
540                                     struct replay_event_t *re)
541 {
542
543         if (!parse_timeval(msg, &re->ev.time)) {
544                 LOGE("time parsing error\n");
545                 return 0;
546         }
547
548         if (!parse_int32(msg, &re->id)) {
549                 LOGE("id parsing error\n");
550                 return 0;
551         }
552
553         if (!parse_int32(msg, (uint32_t *)&re->ev.type)) {
554                 LOGE("type parsing error\n");
555                 return 0;
556         }
557
558         if (!parse_int32(msg, (uint32_t *)&re->ev.code)) {
559                 LOGE("code parsing error\n");
560                 return 0;
561         }
562
563         if (!parse_int32(msg, (uint32_t *)&re->ev.value)) {
564                 LOGE("value parsing error\n");
565                 return 0;
566         }
567
568         return 1;
569 }
570
571 void reset_replay_event_seq(struct replay_event_seq_t *res)
572 {
573         res->enabled = 0;
574         res->tv = (struct timeval){0, 0};
575         res->event_num = 0;
576         free(res->events);
577 }
578
579 static int parse_replay_event_seq(struct msg_buf_t *msg,
580                                     struct replay_event_seq_t *res)
581 {
582         LOGI("parse_replay_event_seq\n");
583
584         int i = 0;
585         parse_deb("REPLAY\n");
586         if (!parse_int32(msg, &res->enabled)) {
587                 LOGE("enabled parsing error\n");
588                 return 0;
589         }
590
591         if(res->enabled == 0){
592                 parse_deb("disable\n");
593                 return 1;
594         }
595
596         parse_deb("time main\n");
597         if (!parse_timeval(msg, &res->tv)) {
598                 LOGE("time parsing error\n");
599                 return 0;
600         }
601
602         parse_deb("count\n");
603         if (!parse_int32(msg, &res->event_num)) {
604                 LOGE("event num parsing error\n");
605                 return 0;
606         }
607         parse_deb("events num=%d\n", res->event_num);
608
609         res->events = (struct replay_event_t *)malloc(res->event_num *
610                                                       sizeof(*res->events));
611         if (!res->events) {
612                 LOGE("events alloc error\n");
613                 return 0;
614         }
615
616         for (i = 0; i < res->event_num; i++) {
617                 parse_deb("sub_rep\n");
618                 if (!parse_replay_event(msg, &res->events[i])) {
619                         LOGE("event #%d parsing error\n", i + 1);
620                         free(res->events);
621                         res->event_num = 0;
622                         return 0;
623                 }
624         }
625
626         return 1;
627 }
628
629 //*REPLAY EVENT PARSE
630
631 static int parse_prof_session(struct msg_buf_t *msg,
632                               struct prof_session_t *prof_session)
633 {
634         LOGI("parse_prof_session\n");
635         if (!parse_app_info(msg, &prof_session->app_info)) {
636                 LOGE("app info parsing error\n");
637                 return 1;
638         }
639         if (!parse_conf(msg, &prof_session->conf)) {
640                 LOGE("conf parsing error\n");
641                 return 1;
642         }
643
644         if (!parse_user_space_inst(msg, &prof_session->user_space_inst)) {
645                 LOGE("user space inst parsing error\n");
646                 return 1;
647         }
648
649         msg_size_with_out_replays = get_msg_cur_size(msg);
650         if (!parse_replay_event_seq(msg, &prof_session->replay_event_seq)) {
651                 LOGE("replay parsing error\n");
652                 return 1;
653         }
654
655         //print_prof_session(prof_session);
656         return 0;
657 }
658
659 int get_sys_mem_size(uint32_t *sys_mem_size){
660         struct sysinfo info;
661         sysinfo(&info);
662         *sys_mem_size = info.totalram;
663         return 0;
664 }
665
666 static int parse_msg_config(struct msg_buf_t * msg_payload,
667                               struct conf_t * conf)
668 {
669         if (!parse_conf(msg_payload, conf)) {
670                 LOGE("conf parsing error\n");
671                 return 0;
672         }
673
674         print_conf(conf);
675         return 1;
676 }
677
678 static int parse_msg_binary_info(struct msg_buf_t * msg_payload,
679                               struct app_info_t *app_info)
680 {
681         if (!parse_app_info(msg_payload, app_info)) {
682                 LOGE("app info parsing error\n");
683                 return 0;
684         }
685
686         print_app_info(app_info);
687         return 1;
688 }
689
690 static void init_parse_control(struct msg_buf_t *buf, struct msg_t *msg)
691 {
692         LOGI("init parse control\n");
693         buf->payload = msg->payload;
694         buf->len = msg->len;
695         buf->end = msg->payload + msg->len;
696         buf->cur_pos = msg->payload;
697         LOGI("init parse control done\n");
698 }
699
700 //This function concat 2 user space lists
701 // this function clean "from" pointer
702 static void concat_add_user_space_inst(struct user_space_inst_t *from,
703                                                                 struct user_space_inst_t *to)
704 {
705         struct app_inst_t *new_app_inst_list = NULL;
706         uint32_t size;
707         void *p;
708
709         if (from->app_num == 0)
710                 return;
711
712         new_app_inst_list = malloc((from->app_num + to->app_num) * sizeof(*new_app_inst_list));
713         p = new_app_inst_list;
714
715         size = from->app_num * sizeof(*new_app_inst_list);
716         memcpy(p, from->app_inst_list, size);
717         p +=size;
718
719         size = to->app_num * sizeof(*new_app_inst_list);
720         memcpy(p, to->app_inst_list, size);
721         p +=size;
722
723         free(to->app_inst_list);
724         to->app_inst_list = new_app_inst_list;
725
726         to->app_num += from->app_num;
727         return;
728 }
729
730 static void cut_replay_events(struct msg_t *msg){
731
732         LOGI("msg_size_with_out_replays = %d \n",msg_size_with_out_replays);
733         msg->len = msg_size_with_out_replays;
734
735 }
736
737 static void reset_app_info(struct app_info_t *app_info)
738 {
739         if (app_info->app_id != NULL)
740                 free(app_info->app_id);
741         if (app_info->exe_path != NULL)
742                 free(app_info->exe_path);
743         memset(app_info, 0, sizeof(*app_info));
744 }
745
746 static void reset_target_info(struct target_info_t *target_info)
747 {
748         return;
749 }
750
751 static void reset_conf(struct conf_t *conf)
752 {
753         memset(conf, 0, sizeof(*conf));
754 }
755
756 static void reset_func_inst_list(uint32_t func_num,
757                                  struct us_func_inst_t *funcs)
758 {
759         int i = 0;
760
761         for (i = 0; i < func_num; i++) {
762                 funcs[i].func_addr = 0;
763                 free(funcs[i].args);
764         }
765 }
766
767 static void reset_lib_inst_list(uint32_t lib_num, struct us_lib_inst_t *libs)
768 {
769         int i = 0;
770
771         for (i = 0; i < lib_num; i++) {
772                 free(libs[i].bin_path);
773                 reset_func_inst_list(libs[i].func_num,
774                                      libs[i].us_func_inst_list);
775         }
776 }
777
778 static void reset_app_inst(struct app_inst_t *app_inst)
779 {
780         app_inst->app_type = 0;
781         free(app_inst->app_id);
782         free(app_inst->exec_path);
783         reset_func_inst_list(app_inst->func_num,
784                              app_inst->us_func_inst_list);
785         app_inst->func_num = 0;
786         free(app_inst->us_func_inst_list);
787         reset_lib_inst_list(app_inst->lib_num, app_inst->us_lib_inst_list);
788         app_inst->lib_num = 0;
789         free(app_inst->us_lib_inst_list);
790 }
791
792 static void reset_user_space_inst(struct user_space_inst_t *us)
793 {
794         int i = 0;
795
796         for (i = 0; i < us->app_num; i++)
797                 reset_app_inst(&us->app_inst_list[i]);
798         if (us->app_inst_list != NULL){
799                 free(us->app_inst_list);
800                 us->app_inst_list = NULL;
801         }
802         us->app_num = 0;
803 }
804
805 void reset_system_info(struct system_info_t *sys_info)
806 {
807         if (sys_info->thread_load)
808                 free(sys_info->thread_load);
809         if (sys_info->process_load)
810                 free(sys_info->process_load);
811         if (sys_info->cpu_frequency)
812                 free(sys_info->cpu_frequency);
813         if (sys_info->cpu_load)
814                 free(sys_info->cpu_load);
815         memset(sys_info, 0, sizeof(*sys_info));
816 }
817
818 static void reset_prof_session(struct prof_session_t *prof_session)
819 {
820         reset_app_info(&prof_session->app_info);
821         reset_conf(&prof_session->conf);
822         reset_user_space_inst(&prof_session->user_space_inst);
823 }
824
825 static struct msg_t *gen_binary_info_reply(struct app_info_t *app_info)
826 {
827         uint32_t binary_type = get_binary_type(app_info->exe_path);
828         char binary_path[PATH_MAX];
829         struct msg_t *msg;
830         char *p = NULL;
831         uint32_t ret_id = ERR_NO;
832
833         get_build_dir(binary_path, app_info->exe_path);
834
835         if (binary_type == BINARY_TYPE_UNKNOWN) {
836                 LOGE("Binary is neither relocatable, nor executable\n");
837                 return NULL;
838         }
839
840         msg = malloc(sizeof(*msg) +
841                               sizeof(ret_id) +
842                               sizeof(binary_type) +
843                               strlen(binary_path) + 1);
844         if (!msg) {
845                 LOGE("Cannot alloc bin info msg\n");
846                 return NULL;
847         }
848
849         msg->id = NMSG_BINARY_INFO_ACK;
850         p = msg->payload;
851
852         pack_int(p, ret_id);
853         pack_int(p, binary_type);
854         pack_str(p, binary_path);
855
856         msg->len = p - msg->payload;
857
858         return msg;
859 }
860
861 static struct msg_t *gen_target_info_reply(struct target_info_t *target_info)
862 {
863         struct msg_t *msg;
864         char *p = NULL;
865         uint32_t ret_id = ERR_NO;
866
867         msg = malloc(sizeof(*msg) +
868                               sizeof(ret_id) +
869                               sizeof(*target_info) -
870                               sizeof(target_info->network_type) +
871                               strlen(target_info->network_type) + 1);
872         if (!msg) {
873                 LOGE("Cannot alloc target info msg\n");
874                 free(msg);
875                 return NULL;
876         }
877
878         msg->id = NMSG_GET_TARGET_INFO_ACK;
879         p = msg->payload;
880
881         pack_int(p, ret_id);
882         pack_int64(p, target_info->sys_mem_size);
883         pack_int64(p, target_info->storage_size);
884         pack_int(p, target_info->bluetooth_supp);
885         pack_int(p, target_info->gps_supp);
886         pack_int(p, target_info->wifi_supp);
887         pack_int(p, target_info->camera_count);
888         pack_str(p, target_info->network_type);
889         pack_int(p, target_info->max_brightness);
890         pack_int(p, target_info->cpu_core_count);
891
892         msg->len = p - msg->payload;
893
894         return msg;
895 }
896
897 static int send_reply(struct msg_t *msg)
898 {
899         printBuf(msg, msg->len + sizeof (*msg));
900         if (send(manager.host.control_socket,
901                  msg, MSG_CMD_HDR_LEN + msg->len, MSG_NOSIGNAL) == -1) {
902                 LOGE("Cannot send reply : %s\n", strerror(errno));
903                 return 1;
904         }
905
906         return 0;
907 }
908
909 int sendACKToHost(enum HostMessageT resp, enum ErrorCode err_code,
910                         char *payload, int payload_size)
911 {
912         if (manager.host.control_socket != -1)
913         {
914                 struct msg_t *msg;
915                 uint32_t err = err_code;
916                 int loglen = sizeof(*msg) - sizeof(msg->payload) +
917                                          sizeof(err) + //return ID
918                                          payload_size;
919                 msg = malloc(loglen);
920                 char *p = msg->payload;
921
922                 //get ack message ID
923                 switch (resp) {
924                         case NMSG_KEEP_ALIVE:
925                                 resp = NMSG_KEEP_ALIVE_ACK;
926                                 break;
927                         case NMSG_START:
928                                 resp = NMSG_START_ACK;
929                                 break;
930                         case NMSG_STOP:
931                                 resp = NMSG_STOP_ACK;
932                                 break;
933                         case NMSG_CONFIG:
934                                 resp = NMSG_CONFIG_ACK;
935                                 break;
936                         case NMSG_BINARY_INFO:
937                                 resp = NMSG_BINARY_INFO_ACK;
938                                 break;
939                         case NMSG_GET_TARGET_INFO:
940                                 resp = NMSG_GET_TARGET_INFO_ACK;
941                                 break;
942                         case NMSG_SWAP_INST_ADD:
943                                 resp = NMSG_SWAP_INST_ADD_ACK;
944                                 break;
945                         case NMSG_SWAP_INST_REMOVE:
946                                 resp = NMSG_SWAP_INST_REMOVE_ACK;
947                                 break;
948                         default:
949                                 //TODO report error
950                                 free(msg);
951                                 return 1;
952                 }
953
954                 //set message id
955                 msg->id = resp;
956                 //set payload lenth
957                 msg->len = payload_size + sizeof(err);
958                 //set return id
959                 //*(uint32_t *)p = err; p+=sizeof(err);
960                 pack_int(p, err);
961                 //copy payload data
962                 memcpy(p, payload, payload_size);
963
964                 LOGI("ACK (%s) errcode<%s> payload=%d; size=%d\n", msg_ID_str(resp),
965                                 msgErrStr(err_code), (int)payload, payload_size);
966                 printBuf((char *)msg, loglen);
967
968                 if (send(manager.host.control_socket, msg,
969                          loglen, MSG_NOSIGNAL) == -1) {
970                         LOGE("Cannot send reply: %s\n", strerror(errno));
971                         free(msg);
972                         return 1;
973                 }
974                 free(msg);
975                 return 0;
976         }
977         else
978                 return 1;
979 }
980
981 struct msg_t *gen_stop_msg(void){
982         struct msg_t *res = malloc(sizeof(*res));
983         memset(res, 0, sizeof(*res));
984         res->id = NMSG_STOP;
985         res->len = 0;
986         return res;
987 }
988
989 enum ErrorCode stop_all(void)
990 {
991         LOGI("entry\n");
992         enum ErrorCode error_code = ERR_NO;
993         struct msg_t *msg = gen_stop_msg();
994
995         terminate_all();
996         stop_profiling();
997
998         if (msg == NULL){
999                 LOGE("cannot generate stop message\n");
1000                 return ERR_UNKNOWN;
1001         } else {
1002                 if (ioctl_send_msg(msg) != 0){
1003                         LOGE("ioctl send filed\n");
1004                         error_code = ERR_UNKNOWN;
1005                 }
1006                 free_msg(msg);
1007         }
1008
1009         reset_prof_session(&prof_session);
1010         stop_transfer();
1011
1012         LOGI("finished\n");
1013         return error_code;
1014 }
1015
1016 int host_message_handler(struct msg_t *msg)
1017 {
1018         struct app_info_t app_info;
1019         struct target_info_t target_info;
1020         struct msg_t *msg_reply;
1021         struct msg_buf_t msg_control;
1022         struct user_space_inst_t user_space_inst;
1023         struct conf_t conf;
1024         enum ErrorCode error_code;
1025
1026         LOGI("MY HANDLE %s (%X)\n", msg_ID_str(msg->id), msg->id);
1027         init_parse_control(&msg_control, msg);
1028
1029         switch (msg->id) {
1030         case NMSG_KEEP_ALIVE:
1031                 sendACKToHost(msg->id, ERR_NO, 0, 0);
1032                 break;
1033         case NMSG_START:
1034                 if (parse_prof_session(&msg_control, &prof_session) != 0) {
1035                         LOGE("prof session parsing error\n");
1036                         sendACKToHost(msg->id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
1037                         return -1;
1038                 }
1039
1040                 if (start_transfer() != 0) {
1041                         LOGE("Cannot start transfer\n");
1042                         return -1;
1043                 }
1044
1045                 //response to control sockete
1046                 cut_replay_events(msg);
1047                 if (ioctl_send_msg(msg) != 0){
1048                         LOGE("cannot send message to device\n");
1049                         // response to control socket
1050                         sendACKToHost(msg->id, ERR_CANNOT_START_PROFILING, 0, 0);
1051                         return -1;
1052                 }
1053
1054                 if (start_profiling() < 0) {
1055                         LOGE("cannot start profiling\n");
1056                         sendACKToHost(msg->id, ERR_CANNOT_START_PROFILING, 0, 0);
1057                         return -1;
1058                 }
1059
1060                 // TODO: start app launch timer
1061
1062
1063                 // success
1064                 sendACKToHost(msg->id, ERR_NO, 0, 0);
1065                 break;
1066         case NMSG_STOP:
1067                 error_code = stop_all();
1068                 //send ack to host
1069                 sendACKToHost(msg->id, error_code, 0, 0);
1070                 break;
1071         case NMSG_CONFIG:
1072                 error_code=ERR_NO;
1073                 if (!parse_msg_config(&msg_control, &conf)) {
1074                         LOGE("config parsing error\n");
1075                         sendACKToHost(msg->id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
1076                         return -1;
1077                 }
1078                 if (reconfigure(conf) != 0) {
1079                         LOGE("Cannot change configuration\n");
1080                         return -1;
1081                 }
1082                 //write to device
1083                 if (ioctl_send_msg(msg) != 0){
1084                         sendACKToHost(msg->id, ERR_UNKNOWN, 0, 0);
1085                         return -1;
1086                 }
1087                 //send ack to host
1088                 sendACKToHost(msg->id, ERR_NO, 0, 0);
1089                 break;
1090         case NMSG_BINARY_INFO:
1091                 if (!parse_msg_binary_info(&msg_control, &app_info)) {
1092                         LOGE("binary info parsing error\n");
1093                         sendACKToHost(msg->id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
1094                         return -1;
1095                 }
1096                 msg_reply = gen_binary_info_reply(&app_info);
1097                 if (!msg_reply) {
1098                         sendACKToHost(msg->id, ERR_UNKNOWN, 0, 0);
1099                         return -1;
1100                 }
1101
1102                 if (send_reply(msg_reply) != 0) {
1103                         LOGE("Cannot send reply\n");
1104                 }
1105
1106                 reset_app_info(&app_info);
1107                 free(msg_reply);
1108                 break;
1109         case NMSG_SWAP_INST_ADD:
1110                 if (!parse_user_space_inst(&msg_control,
1111                                            &user_space_inst)) {
1112                         LOGE("user space inst parsing error\n");
1113                         sendACKToHost(msg->id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
1114                         return -1;
1115                 }
1116                 // TODO: apply_prof_session()
1117                 // warning concat_add_user_space_inst free user_space_inst
1118                 // so, data will not be availible
1119                 concat_add_user_space_inst(&user_space_inst, &prof_session.user_space_inst);
1120                 //write to device
1121                 if (ioctl_send_msg(msg) != 0){
1122                         sendACKToHost(msg->id, ERR_UNKNOWN, 0, 0);
1123                         return -1;
1124                 }
1125                 //send ack to host
1126                 sendACKToHost(msg->id, ERR_NO, 0, 0);
1127                 // TODO release user_space_inst
1128                 break;
1129         case NMSG_SWAP_INST_REMOVE:
1130                 if (!parse_user_space_inst(&msg_control,
1131                                            &prof_session.user_space_inst)){
1132                         sendACKToHost(msg->id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
1133                         LOGE("user space inst parsing error\n");
1134                         return -1;
1135                 }
1136                 if (ioctl_send_msg(msg) != 0){
1137                         sendACKToHost(msg->id, ERR_UNKNOWN, 0, 0);
1138                         return -1;
1139                 }
1140                 // TODO: apply_prof_session()
1141                 sendACKToHost(msg->id, ERR_NO, 0, 0);
1142                 break;
1143         case NMSG_GET_TARGET_INFO:
1144                 fill_target_info(&target_info);
1145                 msg_reply = gen_target_info_reply(&target_info);
1146                 if (!msg_reply) {
1147                         LOGE("cannot generate reply message\n");
1148                         sendACKToHost(msg->id, ERR_UNKNOWN, 0, 0);
1149                         return -1;
1150                 }
1151                 if (send_reply(msg_reply) != 0) {
1152                         LOGE("Cannot send reply\n");
1153                 }
1154                 free(msg_reply);
1155                 reset_target_info(&target_info);
1156                 break;
1157
1158         default:
1159                 LOGE("unknown message %d <0x%08X>\n", msg->id, msg->id);
1160         }
1161
1162         return 0;
1163 }
1164
1165 // testing
1166
1167 static void print_app_info( struct app_info_t *app_info)
1168 {
1169         LOGI("application info=\n");
1170         LOGI("\tapp_type=<%d><0x%04X>\n"
1171                  "\tapp_id=<%s>\n"
1172                  "\texe_path=<%s>\n",
1173                  app_info->app_type,
1174                  app_info->app_type,
1175                  app_info->app_id,
1176                  app_info->exe_path
1177         );
1178 }
1179
1180 static void print_conf(struct conf_t * conf)
1181 {
1182         char buf[1024];
1183         memset(&buf[0],0,1024);
1184         feature_code_str(conf->use_features0, buf);
1185         LOGI("conf = \n");
1186         LOGI("\tuse_features0 = 0x%016LX (%s)\n", conf->use_features0, buf);
1187         LOGI("\tuse_features1 = 0x%016LX (%s)\n", conf->use_features1, buf);
1188         LOGI(
1189                  "\tsystem_trace_period = %d ms\n"
1190                  "\tdata message period = %d ms\n",
1191                  conf->system_trace_period,
1192                  conf->data_message_period
1193                  );
1194 }
1195
1196 void print_replay_event( struct replay_event_t *ev, uint32_t num, char *tab)
1197 {
1198         LOGW("%s\t#%04d:time=0x%08X %08X, "
1199                 " id=0x%08X,"
1200                 " type=0x%08X,"
1201                 " code=0x%08X,"
1202                 " value=0x%08X\n",
1203                 tab,num,
1204                 (unsigned int)ev->ev.time.tv_sec,//timeval
1205                 (unsigned int)ev->ev.time.tv_usec,//timeval
1206                 ev->id,
1207                 ev->ev.type,//u16
1208                 ev->ev.code,//u16
1209                 ev->ev.value//s32
1210                 );
1211 }
1212
1213 void print_replay_event_seq( struct replay_event_seq_t *event_seq)
1214 {
1215         uint32_t i = 0;
1216         char *tab="\t";
1217
1218         LOGI( "%senabled=0x%08X; "\
1219                 "time_start=0x%08X %08X; "\
1220                 "count=0x%08X\n",
1221                 tab,event_seq->enabled,
1222                 (unsigned int)event_seq->tv.tv_sec,
1223                 (unsigned int)event_seq->tv.tv_usec,
1224                 event_seq->event_num);
1225         for (i=0;i<event_seq->event_num;i++)
1226                 print_replay_event(&event_seq->events[i], i+1, tab);
1227
1228 }