Merge remote-tracking branch 'score/develop' into tizen-arm
[sdk/emulator/qemu.git] / tizen / src / skin / maruskin_server.c
1 /*
2  * socket server for emulator skin
3  *
4  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * HyunJun Son <hj79.son@samsung.com>
8  * GiWoong Kim <giwoong.kim@samsung.com>
9  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30
31 #include "maru_common.h"
32
33 #ifdef CONFIG_DARWIN
34 //shared memory
35 #define USE_SHM
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <string.h>
42 #include <sys/types.h>
43 #include <sys/time.h>
44 #include <pthread.h>
45 #include "maruskin_server.h"
46 #include "maruskin_operation.h"
47 #include "qemu-thread.h"
48 #include "emul_state.h"
49 #include "maruskin_client.h"
50 #include "emulator.h"
51 #include "maru_err_table.h"
52
53 #ifndef USE_SHM
54 #include "maru_sdl.h"
55 #endif
56
57 #ifdef CONFIG_WIN32
58 #include <windows.h>
59 #include <winsock2.h>
60 #include <ws2tcpip.h>
61 #else
62 #include <arpa/inet.h>
63 #include <netinet/in.h>
64 #include <sys/socket.h>
65 #endif
66
67 #include "debug_ch.h"
68
69 MULTI_DEBUG_CHANNEL(qemu, skin_server);
70
71
72 #define MAX_REQ_ID 0x7fffffff
73 #define RECV_BUF_SIZE 32
74 #define RECV_HEADER_SIZE 12
75
76 #define SEND_HEADER_SIZE 10
77 #define SEND_BIG_BUF_SIZE 1024 * 1024 * 2
78 #define SEND_BUF_SIZE 512
79
80 #define HEART_BEAT_INTERVAL 1
81 #define HEART_BEAT_FAIL_COUNT 10
82 #define HEART_BEAT_EXPIRE_COUNT 10
83
84 #if 0 // do not restarting skin process ( prevent from abnormal behavior killing a skin process in Windows )
85 #define RESTART_CLIENT_MAX_COUNT 1
86 #else
87 #define RESTART_CLIENT_MAX_COUNT 0
88 #endif
89
90 #define PORT_RETRY_COUNT 50
91
92 #define TEST_HB_IGNORE "test.hb.ignore"
93 #define SKIN_CONFIG_PROP ".skinconfig.properties"
94
95 enum {
96     RECV_START = 1,
97     RECV_MOUSE_EVENT = 10,
98     RECV_KEY_EVENT = 11,
99     RECV_HARD_KEY_EVENT = 12,
100     RECV_CHANGE_LCD_STATE = 13,
101     RECV_OPEN_SHELL = 14,
102     RECV_USB_KBD = 15,
103     RECV_SCREEN_SHOT = 16,
104     RECV_DETAIL_INFO = 17,
105     RECV_RAM_DUMP = 18,
106     RECV_GUESTMEMORY_DUMP = 19,
107     RECV_RESPONSE_HEART_BEAT = 900,
108     RECV_CLOSE = 998,
109     RECV_RESPONSE_SHUTDOWN = 999,
110 };
111
112 enum {
113     SEND_HEART_BEAT = 1,
114     SEND_SCREEN_SHOT = 2,
115     SEND_DETAIL_INFO = 3,
116     SEND_RAMDUMP_COMPLETE = 4,
117     SEND_SENSOR_DAEMON_START = 800,
118     SEND_SHUTDOWN = 999,
119 };
120
121 static int seq_req_id = 0;
122
123 static uint16_t svr_port = 0;
124 static int server_sock = 0;
125 static int client_sock = 0;
126 static int stop_server = 0;
127 static int is_sensord_initialized = 0;
128 static int ready_server = 0;
129 static int ignore_heartbeat = 0;
130 static int is_force_close_client = 0;
131
132 static int is_started_heartbeat = 0;
133 static int stop_heartbeat = 0;
134 static int recv_heartbeat_count = 0;
135 static pthread_t thread_id_heartbeat;
136 static pthread_mutex_t mutex_heartbeat = PTHREAD_MUTEX_INITIALIZER;
137 static pthread_cond_t cond_heartbeat = PTHREAD_COND_INITIALIZER;
138 static pthread_mutex_t mutex_recv_heartbeat_count = PTHREAD_MUTEX_INITIALIZER;
139
140 static int skin_argc = 0;
141 static char** skin_argv = NULL;
142 static int qmu_argc = 0;
143 static char** qmu_argv = NULL;
144
145 static void parse_skin_args( void );
146 static void parse_skinconfig_prop( void );
147 static void* run_skin_server( void* args );
148 static int recv_n( int client_sock, char* read_buf, int recv_len );
149 static void make_header( int client_sock, short send_cmd, int data_length, char* sendbuf, int print_log );
150 static int send_skin_header_only( int client_sock, short send_cmd, int print_log );
151 static int send_skin_data( int client_sock, short send_cmd, unsigned char* data, int length, int big_data );
152 static int send_n( int client_sock, unsigned char* data, int length, int big_data );
153
154 static void* do_heart_beat( void* args );
155 static int start_heart_beat( void );
156 static void stop_heart_beat( void );
157
158 int start_skin_server( int argc, char** argv, int qemu_argc, char** qemu_argv ) {
159
160     skin_argc = argc;
161     skin_argv = argv;
162
163     parse_skinconfig_prop();
164
165     // arguments have higher priority than '.skinconfig.properties'
166     parse_skin_args();
167
168     INFO( "ignore_heartbeat:%d\n", ignore_heartbeat );
169
170     qmu_argc = qemu_argc;
171     qmu_argv = qemu_argv;
172
173     QemuThread qemu_thread;
174
175     qemu_thread_create( &qemu_thread, run_skin_server, NULL,
176             QEMU_THREAD_JOINABLE);
177
178     return 1;
179
180 }
181
182 void shutdown_skin_server( void ) {
183
184     INFO( "shutdown_skin_server\n" );
185
186     int close_server_socket = 0;
187     int success_send = 0;
188
189     if ( client_sock ) {
190         INFO( "send shutdown to skin.\n" );
191         if ( 0 > send_skin_header_only( client_sock, SEND_SHUTDOWN, 1 ) ) {
192             ERR( "fail to send SEND_SHUTDOWN to skin.\n" );
193             close_server_socket = 1;
194         } else {
195             success_send = 1;
196             // skin sent RECV_RESPONSE_SHUTDOWN.
197         }
198     }
199
200     if ( success_send ) {
201
202         int count = 0;
203         int max_sleep_count = 10;
204
205         while ( 1 ) {
206
207             if ( max_sleep_count < count ) {
208                 close_server_socket = 1;
209                 break;
210             }
211
212             if ( stop_server ) {
213                 INFO( "skin client sent normal shutdown response.\n" );
214                 break;
215             } else {
216 #ifdef CONFIG_WIN32
217                 Sleep( 1 ); // 1ms
218 #else
219                 usleep( 1000 ); // 1ms
220 #endif
221                 count++;
222             }
223         }
224     }
225
226     stop_server = 1;
227     is_force_close_client = 1;
228
229     if ( client_sock ) {
230 #ifdef CONFIG_WIN32
231         closesocket( client_sock );
232 #else
233         close( client_sock );
234 #endif
235         client_sock = 0;
236     }
237
238     if ( close_server_socket ) {
239         INFO( "skin client did not send normal shutdown response.\n" );
240         if ( server_sock ) {
241 #ifdef CONFIG_WIN32
242             closesocket( server_sock );
243 #else
244             close( server_sock );
245 #endif
246             server_sock = 0;
247         }
248     }
249
250 }
251
252 void notify_sensor_daemon_start( void ) {
253     INFO( "notify_sensor_daemon_start\n" );
254     is_sensord_initialized = 1;
255     if ( client_sock ) {
256         if ( 0 > send_skin_header_only( client_sock, SEND_SENSOR_DAEMON_START, 1 ) ) {
257             ERR( "fail to send SEND_SENSOR_DAEMON_START to skin.\n" );
258         }
259     }
260 }
261
262 void notify_ramdump_complete(void) {
263     INFO("notify_ramdump_complete\n");
264
265     if (client_sock) {
266         if (0 > send_skin_header_only( client_sock, SEND_RAMDUMP_COMPLETE, 1)) {
267             ERR("fail to send SEND_RAMDUMP_COMPLETE to skin.\n");
268         }
269     }
270 }
271
272
273 int is_ready_skin_server( void ) {
274     return ready_server;
275 }
276
277 int get_skin_server_port( void ) {
278     return svr_port;
279 }
280
281 static void parse_skinconfig_prop( void ) {
282
283     int target_path_len = strlen( tizen_target_path );
284     char skin_config_path[target_path_len + 32];
285
286     memset( skin_config_path, 0, target_path_len + 32 );
287     strcpy( skin_config_path, tizen_target_path );
288 #ifdef CONFIG_WIN32
289     strcat( skin_config_path, "\\" );
290 #else
291     strcat( skin_config_path, "/" );
292 #endif
293     strcat( skin_config_path, SKIN_CONFIG_PROP );
294
295     FILE* fp = fopen( skin_config_path, "r" );
296
297     if ( !fp ) {
298         INFO( "There is no %s. skin_config_path:%s\n", SKIN_CONFIG_PROP, skin_config_path );
299         return;
300     }
301
302     fseek( fp, 0L, SEEK_END );
303     int buf_size = ftell( fp );
304     rewind( fp );
305
306     if ( 0 >= buf_size ) {
307         INFO( "%s contents is empty.\n", SKIN_CONFIG_PROP );
308         fclose( fp );
309         return;
310     }
311
312     char* buf = g_malloc0( buf_size );
313     if ( !buf ) {
314         ERR( "Fail to malloc for %s\n", SKIN_CONFIG_PROP );
315         fclose( fp );
316         return;
317     }
318
319     int read_cnt = 0;
320     int total_cnt = 0;
321
322     while ( 1 ) {
323
324         if ( total_cnt == buf_size ) {
325             break;
326         }
327
328         read_cnt = fread( (void*) ( buf + read_cnt ), 1, buf_size - total_cnt, fp );
329         if ( 0 > read_cnt ) {
330             break;
331         } else {
332             total_cnt += read_cnt;
333         }
334
335     }
336
337     fclose( fp );
338
339     INFO( "====== %s ======\n%s\n====================================\n", SKIN_CONFIG_PROP, buf );
340
341     char hb_ignore_prop[32];
342     memset( hb_ignore_prop, 0, 32 );
343     strcat( hb_ignore_prop, TEST_HB_IGNORE );
344     strcat( hb_ignore_prop, "=true" );
345
346     char* line_str = strtok( buf, "\n" );
347
348     while ( 1 ) {
349
350         if ( line_str ) {
351
352             TRACE( "prop line_str:%s\n", line_str );
353
354             if ( 0 == strcmp( line_str, hb_ignore_prop ) ) {
355                 ignore_heartbeat = 1;
356                 INFO( "ignore heartbeat by %s\n", SKIN_CONFIG_PROP );
357             }
358
359         } else {
360             break;
361         }
362
363         line_str = strtok( NULL, "\n" );
364
365     }
366
367     g_free( buf );
368
369 }
370
371 static void parse_skin_args( void ) {
372
373     int i;
374     for ( i = 0; i < skin_argc; i++ ) {
375
376         char* arg = NULL;
377         arg = strdup( skin_argv[i] );
378
379         if ( arg ) {
380
381             char* key = strtok( arg, "=" );
382             char* value = strtok( NULL, "=" );
383
384             INFO( "skin params key:%s, value:%s\n", key, value );
385
386             if( 0 == strcmp( TEST_HB_IGNORE, key ) ) {
387                 if( 0 == strcmp( "true", value ) ) {
388                     ignore_heartbeat = 1;
389                 }else if( 0 == strcmp( "false", value ) ) {
390                     ignore_heartbeat = 0;
391                 }
392             }
393
394             free( arg );
395
396         } else {
397             ERR( "fail to strdup." );
398         }
399
400     }
401
402 }
403
404 static void* run_skin_server( void* args ) {
405
406     struct sockaddr server_addr, client_addr;
407     socklen_t server_len, client_len;
408     int shutdown_qmu = 0;
409
410     INFO("run skin server\n");
411
412     if ( 0 > ( server_sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) ) {
413         ERR( "create listen socket error\n" );
414         perror( "create listen socket error : " );
415         shutdown_qmu = 1;
416         goto cleanup;
417     }
418
419     memset( &server_addr, '\0', sizeof( server_addr ) );
420     ( (struct sockaddr_in *) &server_addr )->sin_family = AF_INET;
421     memcpy( &( (struct sockaddr_in *) &server_addr )->sin_addr, "\177\000\000\001", 4 ); // 127.0.0.1
422     ( (struct sockaddr_in *) &server_addr )->sin_port = htons( 0 );
423
424     server_len = sizeof( server_addr );
425
426     if ( 0 != bind( server_sock, &server_addr, server_len ) ) {
427         ERR( "skin server bind error\n" );
428         perror( "skin server bind error : " );
429         shutdown_qmu = 1;
430         goto cleanup;
431     }
432
433     memset( &server_addr, '\0', sizeof( server_addr ) );
434     getsockname( server_sock, (struct sockaddr *) &server_addr, &server_len );
435     svr_port = ntohs( ( (struct sockaddr_in *) &server_addr )->sin_port );
436
437     INFO( "success to bind port[127.0.0.1:%d/tcp] for skin_server in host \n", svr_port );
438
439     if ( 0 > listen( server_sock, 4 ) ) {
440         ERR( "skin_server listen error\n" );
441         perror( "skin_server listen error : " );
442         shutdown_qmu = 1;
443         goto cleanup;
444     }
445
446     client_len = sizeof( client_addr );
447
448     char recvbuf[RECV_BUF_SIZE];
449
450     INFO( "skin server start...port:%d\n", svr_port );
451
452     while ( 1 ) {
453
454         if ( stop_server ) {
455             INFO( "close server socket normally.\n" );
456             break;
457         }
458
459         ready_server = 1;
460
461         if( !is_started_heartbeat ) {
462             if ( !start_heart_beat() ) {
463                 ERR( "Fail to start heartbeat thread.\n" );
464                 shutdown_qmu = 1;
465                 break;
466             }
467         }
468
469         INFO( "start accepting socket...\n" );
470
471         if ( 0 > ( client_sock = accept( server_sock, (struct sockaddr *) &client_addr, &client_len ) ) ) {
472             ERR( "skin_servier accept error\n" );
473             perror( "skin_servier accept error : " );
474             continue;
475         }
476
477         INFO( "accept client : client_sock:%d\n", client_sock );
478
479         while ( 1 ) {
480
481             if ( stop_server ) {
482                 INFO( "stop receiving current client socket.\n" );
483                 break;
484             }
485
486             stop_heartbeat = 0;
487             memset( &recvbuf, 0, RECV_BUF_SIZE );
488
489             int read_cnt = recv_n( client_sock, recvbuf, RECV_HEADER_SIZE );
490
491             if ( 0 > read_cnt ) {
492
493                 if( is_force_close_client ) {
494                     INFO( "force close client socket.\n" );
495                     is_force_close_client = 0;
496                 }else {
497                     ERR( "skin_server read error:%d\n", read_cnt );
498                     perror( "skin_server read error : " );
499                 }
500                 break;
501
502             } else {
503
504                 if ( 0 == read_cnt ) {
505                     ERR( "read_cnt is 0.\n" );
506                     break;
507                 }
508
509                 int log_cnt;
510                 char log_buf[512];
511                 memset( log_buf, 0, 512 );
512
513                 log_cnt = sprintf( log_buf, "== RECV read_cnt:%d ", read_cnt );
514
515                 int uid = 0;
516                 int req_id = 0;
517                 short cmd = 0;
518                 short length = 0;
519
520                 char* p = recvbuf;
521
522                 memcpy( &uid, p, sizeof( uid ) );
523                 p += sizeof( uid );
524                 memcpy( &req_id, p, sizeof( req_id ) );
525                 p += sizeof( req_id );
526                 memcpy( &cmd, p, sizeof( cmd ) );
527                 p += sizeof( cmd );
528                 memcpy( &length, p, sizeof( length ) );
529
530                 uid = ntohl( uid );
531                 req_id = ntohl( req_id );
532                 cmd = ntohs( cmd );
533                 length = ntohs( length );
534
535                 log_cnt += sprintf( log_buf + log_cnt, "uid:%d, req_id:%d, cmd:%d, length:%d ", uid, req_id, cmd, length );
536
537                 if ( 0 < length ) {
538
539                     if ( RECV_BUF_SIZE < length ) {
540                         ERR( "length is bigger than RECV_BUF_SIZE\n" );
541                         continue;
542                     }
543
544                     memset( &recvbuf, 0, length );
545
546                     int recv_cnt = recv_n( client_sock, recvbuf, length );
547
548                     log_cnt += sprintf( log_buf + log_cnt, "data read_cnt:%d ", recv_cnt );
549
550                     if ( 0 > recv_cnt ) {
551                         ERR( "skin_server read data\n" );
552                         perror( "skin_server read data : " );
553                         break;
554                     } else if ( 0 == recv_cnt ) {
555                         ERR( "data read_cnt is 0.\n" );
556                         break;
557                     } else if ( recv_cnt != length ) {
558                         ERR( "read_cnt is not equal to length.\n" );
559                         break;
560                     }
561
562                 }
563
564                 switch ( cmd ) {
565                 case RECV_START: {
566                     log_cnt += sprintf( log_buf + log_cnt, "RECV_START ==\n" );
567                     INFO( log_buf );
568
569                     if ( 0 >= length ) {
570                         ERR( "there is no data looking at 0 length." );
571                         continue;
572                     }
573
574                     /* keep it consistent with emulator-skin definition */
575                     uint64 handle_id = 0;
576                     int lcd_size_width = 0;
577                     int lcd_size_height = 0;
578                     int scale = 0;
579                     double scale_ratio = 0.0;
580                     short rotation = 0;
581
582                     char* p = recvbuf;
583                     memcpy( &handle_id, p, sizeof( handle_id ) );
584                     p += sizeof( handle_id );
585                     memcpy( &lcd_size_width, p, sizeof( lcd_size_width ) );
586                     p += sizeof( lcd_size_width );
587                     memcpy( &lcd_size_height, p, sizeof( lcd_size_height ) );
588                     p += sizeof( lcd_size_height );
589                     memcpy( &scale, p, sizeof( scale ) );
590                     p += sizeof( scale );
591                     memcpy( &rotation, p, sizeof( rotation ) );
592
593                     int low_id = (int)handle_id;
594                     int high_id = (int)(handle_id >> 32);
595                     low_id = ntohl(high_id);
596                     high_id = ntohl(low_id);
597                     handle_id = high_id;
598                     handle_id = (handle_id << 32) | low_id;
599
600                     lcd_size_width = ntohl( lcd_size_width );
601                     lcd_size_height = ntohl( lcd_size_height );
602                     scale = ntohl( scale );
603                     scale_ratio = ( (double) scale ) / 100;
604                     rotation = ntohs( rotation );
605
606                     set_emul_win_scale( scale_ratio );
607
608                     start_display( handle_id, lcd_size_width, lcd_size_height, scale_ratio, rotation );
609
610                     break;
611                 }
612                 case RECV_MOUSE_EVENT: {
613                     log_cnt += sprintf( log_buf + log_cnt, "RECV_MOUSE_EVENT ==\n" );
614                     TRACE( log_buf );
615
616                     if ( 0 >= length ) {
617                         ERR( "there is no data looking at 0 length." );
618                         continue;
619                     }
620
621                     /* keep it consistent with emulator-skin definition */
622                     int button_type = 0;
623                     int event_type = 0;
624                     int host_x = 0;
625                     int host_y = 0;
626                     int guest_x = 0;
627                     int guest_y = 0;
628                     int z = 0;
629
630                     char* p = recvbuf;
631                     memcpy( &button_type, p, sizeof( button_type ) );
632                     p += sizeof( button_type );
633                     memcpy( &event_type, p, sizeof( event_type ) );
634                     p += sizeof( event_type );
635                     memcpy( &host_x, p, sizeof( host_x ) );
636                     p += sizeof( host_x );
637                     memcpy( &host_y, p, sizeof( host_y ) );
638                     p += sizeof( host_y );
639                     memcpy( &guest_x, p, sizeof( guest_x ) );
640                     p += sizeof( guest_x );
641                     memcpy( &guest_y, p, sizeof( guest_y ) );
642                     p += sizeof( guest_y );
643                     memcpy( &z, p, sizeof( z ) );
644
645                     button_type = ntohl( button_type );
646                     event_type = ntohl( event_type );
647                     host_x = ntohl( host_x );
648                     host_y = ntohl( host_y );
649                     guest_x = ntohl( guest_x );
650                     guest_y = ntohl( guest_y );
651                     z = ntohl( z );
652
653                     do_mouse_event(button_type, event_type,
654                         host_x, host_y, guest_x, guest_y, z);
655                     break;
656                 }
657                 case RECV_KEY_EVENT: {
658                     log_cnt += sprintf( log_buf + log_cnt, "RECV_KEY_EVENT ==\n" );
659                     TRACE( log_buf );
660
661                     if ( 0 >= length ) {
662                         ERR( "there is no data looking at 0 length." );
663                         continue;
664                     }
665
666                     /* keep it consistent with emulator-skin definition */
667                     int event_type = 0;
668                     int keycode = 0;
669                     int state_mask = 0;
670                     int key_location = 0;
671
672                     char* p = recvbuf;
673                     memcpy( &event_type, p, sizeof( event_type ) );
674                     p += sizeof( event_type );
675                     memcpy( &keycode, p, sizeof( keycode ) );
676                     p += sizeof( keycode );
677                     memcpy( &state_mask, p, sizeof( state_mask ) );
678                     p += sizeof( state_mask );
679                     memcpy( &key_location, p, sizeof( key_location ) );
680
681                     event_type = ntohl( event_type );
682                     keycode = ntohl( keycode );
683                     state_mask = ntohl( state_mask );
684                     key_location = ntohl( key_location );
685
686                     do_key_event(event_type, keycode, state_mask, key_location);
687                     break;
688                 }
689                 case RECV_HARD_KEY_EVENT: {
690                     log_cnt += sprintf( log_buf + log_cnt, "RECV_HARD_KEY_EVENT ==\n" );
691                     TRACE( log_buf );
692
693                     if ( 0 >= length ) {
694                         ERR( "there is no data looking at 0 length." );
695                         continue;
696                     }
697
698                     /* keep it consistent with emulator-skin definition */
699                     int event_type = 0;
700                     int keycode = 0;
701
702                     char* p = recvbuf;
703                     memcpy( &event_type, p, sizeof( event_type ) );
704                     p += sizeof( event_type );
705                     memcpy( &keycode, p, sizeof( keycode ) );
706
707                     event_type = ntohl( event_type );
708                     keycode = ntohl( keycode );
709
710                     do_hardkey_event( event_type, keycode );
711                     break;
712                 }
713                 case RECV_CHANGE_LCD_STATE: {
714                     log_cnt += sprintf( log_buf + log_cnt, "RECV_CHANGE_LCD_STATE ==\n" );
715                     TRACE( log_buf );
716
717                     if ( 0 >= length ) {
718                         ERR( "there is no data looking at 0 length." );
719                         continue;
720                     }
721
722                     /* keep it consistent with emulator-skin definition */
723                     int scale = 0;
724                     double scale_ratio = 0.0;
725                     short rotation_type = 0;
726
727                     char* p = recvbuf;
728                     memcpy( &scale, p, sizeof( scale ) );
729                     p += sizeof( scale );
730                     memcpy( &rotation_type, p, sizeof( rotation_type ) );
731
732                     scale = ntohl( scale );
733                     scale_ratio = ( (double) scale ) / 100;
734                     rotation_type = ntohs( rotation_type );
735
736                     if ( get_emul_win_scale() != scale_ratio ) {
737                         do_scale_event( scale_ratio );
738                     }
739
740                     if ( is_sensord_initialized == 1 && get_emul_rotation() != rotation_type ) {
741                         do_rotation_event( rotation_type );
742                     }
743
744 #ifndef USE_SHM
745                     maruskin_sdl_resize(); // send sdl event
746 #endif
747                     break;
748                 }
749                 case RECV_SCREEN_SHOT: {
750                     log_cnt += sprintf( log_buf + log_cnt, "RECV_SCREEN_SHOT ==\n" );
751                     TRACE( log_buf );
752
753                     QemuSurfaceInfo* info = get_screenshot_info();
754
755                     if ( info ) {
756                         send_skin_data( client_sock, SEND_SCREEN_SHOT, info->pixel_data, info->pixel_data_length, 1 );
757                         free_screenshot_info( info );
758                     } else {
759                         ERR( "Fail to get screenshot data.\n" );
760                     }
761
762                     break;
763                 }
764                 case RECV_DETAIL_INFO: {
765                     log_cnt += sprintf( log_buf + log_cnt, "RECV_DETAIL_INFO ==\n" );
766                     TRACE( log_buf );
767
768                     DetailInfo* detail_info = get_detail_info( qmu_argc, qmu_argv );
769
770                     if ( detail_info ) {
771                         send_skin_data( client_sock, SEND_DETAIL_INFO, (unsigned char*) detail_info->data,
772                             detail_info->data_length, 0 );
773                         free_detail_info( detail_info );
774                     } else {
775                         ERR( "Fail to get detail info.\n" );
776                     }
777
778                     break;
779                 }
780                 case RECV_RAM_DUMP: {
781                     log_cnt += sprintf(log_buf + log_cnt, "RECV_RAM_DUMP ==\n");
782                     TRACE(log_buf);
783
784                     ram_dump();
785                     break;
786                 }
787                 case RECV_GUESTMEMORY_DUMP: {
788                     log_cnt += sprintf(log_buf + log_cnt, "RECV_GUESTMEMORY_DUMP ==\n");
789                     TRACE(log_buf);
790
791                     guestmemory_dump();
792                     break;
793                 }
794                 case RECV_RESPONSE_HEART_BEAT: {
795                     log_cnt += sprintf( log_buf + log_cnt, "RECV_RESPONSE_HEART_BEAT ==\n" );
796 //                    TRACE( log_buf );
797                     TRACE( "recv HB req_id:%d\n", req_id );
798
799                     pthread_mutex_lock( &mutex_recv_heartbeat_count );
800                     recv_heartbeat_count = 0;
801                     pthread_mutex_unlock( &mutex_recv_heartbeat_count );
802
803                     break;
804                 }
805                 case RECV_OPEN_SHELL: {
806                     log_cnt += sprintf( log_buf + log_cnt, "RECV_OPEN_SHELL ==\n" );
807                     TRACE( log_buf );
808
809                     open_shell();
810                     break;
811                 }
812                 case RECV_USB_KBD: {
813                     log_cnt += sprintf( log_buf + log_cnt, "RECV_USB_KBD ==\n" );
814                     TRACE( log_buf );
815
816                     if ( 0 >= length ) {
817                         INFO( "there is no data looking at 0 length." );
818                         continue;
819                     }
820
821                     char on = 0;
822                     memcpy( &on, recvbuf, sizeof( on ) );
823                     onoff_usb_kbd( on );
824                     break;
825                 }
826                 case RECV_CLOSE: {
827                     log_cnt += sprintf( log_buf + log_cnt, "RECV_CLOSE ==\n" );
828                     TRACE( log_buf );
829
830                     request_close();
831                     break;
832                 }
833                 case RECV_RESPONSE_SHUTDOWN: {
834                     log_cnt += sprintf( log_buf + log_cnt, "RECV_RESPONSE_SHUTDOWN ==\n" );
835                     INFO( log_buf );
836
837                     stop_server = 1;
838                     break;
839                 }
840                 default: {
841                     log_cnt += sprintf( log_buf + log_cnt, "!!! unknown command : %d\n", cmd );
842                     TRACE( log_buf );
843
844                     ERR( "!!! unknown command : %d\n", cmd );
845                     break;
846                 }
847                 }
848
849             }
850
851         }
852
853     }
854
855     stop_heart_beat();
856
857 cleanup:
858     if ( server_sock ) {
859 #ifdef CONFIG_WIN32
860         closesocket( server_sock );
861 #else
862         close( server_sock );
863 #endif
864         server_sock = 0;
865     }
866
867     if( shutdown_qmu ) {
868         ERR( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
869         ERR( "!!! Fail to initialize for skin server operation. Shutdown QEMU !!!\n" );
870         ERR( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
871         shutdown_qemu_gracefully();
872     }
873
874     return NULL;
875 }
876
877 static int recv_n( int client_sock, char* read_buf, int recv_len ) {
878
879     int total_cnt = 0;
880     int recv_cnt = 0;
881
882     while ( 1 ) {
883
884         recv_cnt = recv( client_sock, (void*) ( read_buf + recv_cnt ), ( recv_len - recv_cnt ), 0 );
885
886         if ( 0 > recv_cnt ) {
887
888             return recv_cnt;
889
890         } else if ( 0 == recv_cnt ) {
891
892             if ( total_cnt == recv_len ) {
893                 return total_cnt;
894             } else {
895                 continue;
896             }
897
898         } else {
899
900             total_cnt += recv_cnt;
901
902             if ( total_cnt == recv_len ) {
903                 return total_cnt;
904             } else {
905                 continue;
906             }
907
908         }
909
910     }
911
912     return 0;
913
914 }
915
916 static void make_header( int client_sock, short send_cmd, int data_length, char* sendbuf, int print_log ) {
917
918     memset( sendbuf, 0, SEND_HEADER_SIZE );
919
920     int request_id = ( MAX_REQ_ID == seq_req_id ) ? 0 : ++seq_req_id;
921     if( print_log ) {
922         TRACE( "== SEND skin request_id:%d, send_cmd:%d ==\n", request_id, send_cmd );
923     }
924     request_id = htonl( request_id );
925
926     short cmd = send_cmd;
927     cmd = htons( cmd );
928
929     int length = data_length;
930     length = htonl( length );
931
932     char* p = sendbuf;
933     memcpy( p, &request_id, sizeof( request_id ) );
934     p += sizeof( request_id );
935     memcpy( p, &cmd, sizeof( cmd ) );
936     p += sizeof( cmd );
937     memcpy( p, &length, sizeof( length ) );
938
939 }
940
941 static int send_n( int client_sock, unsigned char* data, int length, int big_data ) {
942
943     int send_cnt = 0;
944     int total_cnt = 0;
945
946     int buf_size = big_data ? SEND_BIG_BUF_SIZE : SEND_BUF_SIZE;
947
948     // use malloc instead of general array definition to avoid seg fault in 'alloca' in MinGW env, only using big buf size.
949     char* databuf = (char*)g_malloc0( buf_size );
950
951     INFO( "send_n start. length:%d\n", length );
952
953     while ( 1 ) {
954
955         if ( total_cnt == length ) {
956             break;
957         }
958
959         if ( buf_size < ( length - total_cnt ) ) {
960             send_cnt = buf_size;
961         } else {
962             send_cnt = ( length - total_cnt );
963         }
964
965         memset( databuf, 0, send_cnt );
966         memcpy( databuf, (char*) ( data + total_cnt ), send_cnt );
967
968         send_cnt = send( client_sock, databuf, send_cnt, 0 );
969
970         if ( 0 > send_cnt ) {
971             ERR( "send_n error. error code:%d\n", send_cnt );
972             return send_cnt;
973         } else {
974             total_cnt += send_cnt;
975         }
976
977     }
978
979     g_free( databuf );
980
981     INFO( "send_n finished.\n" );
982
983     return total_cnt;
984
985 }
986
987 static int send_skin_header_only( int client_sock, short send_cmd, int print_log ) {
988
989     char headerbuf[SEND_HEADER_SIZE];
990     make_header( client_sock, send_cmd, 0, headerbuf, print_log );
991
992     int send_count = send( client_sock, headerbuf, SEND_HEADER_SIZE, 0 );
993     return send_count;
994
995 }
996
997 static int send_skin_data( int client_sock, short send_cmd, unsigned char* data, int length, int big_data ) {
998
999     char headerbuf[SEND_HEADER_SIZE];
1000     make_header( client_sock, send_cmd, length, headerbuf, 1 );
1001
1002     int header_cnt = send( client_sock, headerbuf, SEND_HEADER_SIZE, 0 );
1003
1004     if ( 0 > header_cnt ) {
1005         ERR( "send header for data is NULL.\n" );
1006         return header_cnt;
1007     }
1008
1009     if ( !data ) {
1010         ERR( "send data is NULL.\n" );
1011         return -1;
1012     }
1013
1014     int send_cnt = send_n( client_sock, data, length, big_data );
1015     INFO( "send_n result:%d\n", send_cnt );
1016
1017     return send_cnt;
1018
1019 }
1020
1021 static void* do_heart_beat( void* args ) {
1022
1023     is_started_heartbeat = 1;
1024
1025     int send_fail_count = 0;
1026     int restart_client_count = 0;
1027     int need_restart_skin_client = 0;
1028     int shutdown = 0;
1029
1030     int booting_handicap_cnt = 0;
1031
1032     struct timeval current;
1033     struct timespec ts_heartbeat;
1034
1035     while ( 1 ) {
1036         gettimeofday( &current, NULL );
1037
1038         if (booting_handicap_cnt < 5) {
1039             booting_handicap_cnt++;
1040             ts_heartbeat.tv_sec = current.tv_sec +
1041                 (HEART_BEAT_INTERVAL * 10);
1042         } else {
1043             ts_heartbeat.tv_sec = current.tv_sec + HEART_BEAT_INTERVAL;
1044         }
1045
1046         ts_heartbeat.tv_nsec = current.tv_usec * 1000;
1047
1048         pthread_mutex_lock( &mutex_heartbeat );
1049         pthread_cond_timedwait( &cond_heartbeat, &mutex_heartbeat, &ts_heartbeat );
1050         pthread_mutex_unlock( &mutex_heartbeat );
1051
1052         if ( stop_heartbeat ) {
1053             INFO( "[HB] stop heart beat.\n" );
1054             break;
1055         }
1056
1057         if ( client_sock ) {
1058             TRACE( "send HB\n" );
1059             if ( 0 > send_skin_header_only( client_sock, SEND_HEART_BEAT, 0 ) ) {
1060                 send_fail_count++;
1061             } else {
1062                 send_fail_count = 0;
1063             }
1064         } else {
1065             // fail to get socket in accepting or client is not yet accepted.
1066             send_fail_count++;
1067             TRACE( "[HB] client socket is NULL yet.\n" );
1068         }
1069
1070         if ( HEART_BEAT_FAIL_COUNT < send_fail_count ) {
1071             ERR( "[HB] fail to send heart beat to skin. fail count:%d\n", HEART_BEAT_FAIL_COUNT );
1072             need_restart_skin_client = 1;
1073         }
1074
1075         pthread_mutex_lock( &mutex_recv_heartbeat_count );
1076         recv_heartbeat_count++;
1077         if ( 1 < recv_heartbeat_count ) {
1078             TRACE( "[HB] recv_heartbeat_count:%d\n", recv_heartbeat_count );
1079         }
1080         pthread_mutex_unlock( &mutex_recv_heartbeat_count );
1081
1082         if ( HEART_BEAT_EXPIRE_COUNT < recv_heartbeat_count ) {
1083             ERR( "received heartbeat count is expired.\n" );
1084             need_restart_skin_client = 1;
1085         }
1086
1087         if ( need_restart_skin_client ) {
1088
1089             if ( RESTART_CLIENT_MAX_COUNT <= restart_client_count ) {
1090                 shutdown = 1;
1091                 break;
1092             } else {
1093
1094                 if ( is_requested_shutdown_qemu_gracefully() ) {
1095                     INFO( "requested shutdown_qemu_gracefully, do not retry starting skin client process.\n" );
1096                     break;
1097                 } else {
1098
1099                     send_fail_count = 0;
1100                     recv_heartbeat_count = 0;
1101                     need_restart_skin_client = 0;
1102                     restart_client_count++;
1103
1104                     INFO( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1105                     INFO( "!!! restart skin client process !!!\n" );
1106                     INFO( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1107
1108                     is_force_close_client = 1;
1109                     if ( client_sock ) {
1110 #ifdef CONFIG_WIN32
1111                         closesocket( client_sock );
1112 #else
1113                         close( client_sock );
1114 #endif
1115                         client_sock = 0;
1116                     }
1117
1118                     start_skin_client( skin_argc, skin_argv );
1119
1120                 }
1121
1122             }
1123
1124         }
1125
1126     }
1127
1128     if ( shutdown ) {
1129
1130         INFO( "[HB] shutdown skin_server by heartbeat thread.\n" );
1131
1132         is_force_close_client = 1;
1133         if ( client_sock ) {
1134 #ifdef CONFIG_WIN32
1135             closesocket( client_sock );
1136 #else
1137             close( client_sock );
1138 #endif
1139             client_sock = 0;
1140         }
1141
1142         stop_server = 1;
1143         if ( server_sock ) {
1144 #ifdef CONFIG_WIN32
1145             closesocket( server_sock );
1146 #else
1147             close( server_sock );
1148 #endif
1149             server_sock = 0;
1150         }
1151
1152         ERR( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1153         ERR( "!!! Fail to operate with heartbeat from skin client. Shutdown QEMU !!!\n" );
1154         ERR( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1155
1156         maru_register_exit_msg(MARU_EXIT_HB_TIME_EXPIRED, NULL);
1157         shutdown_qemu_gracefully();
1158
1159     }
1160
1161     return NULL;
1162
1163 }
1164
1165 static int start_heart_beat( void ) {
1166
1167     if( is_started_heartbeat ) {
1168         return 1;
1169     }
1170
1171     if( ignore_heartbeat ) {
1172         return 1;
1173     }else {
1174         if ( 0 != pthread_create( &thread_id_heartbeat, NULL, do_heart_beat, NULL ) ) {
1175             ERR( "[HB] fail to create heartbean pthread.\n" );
1176             return 0;
1177         } else {
1178             return 1;
1179         }
1180     }
1181
1182 }
1183
1184 static void stop_heart_beat( void ) {
1185     pthread_mutex_lock( &mutex_heartbeat );
1186     stop_heartbeat = 1;
1187     pthread_cond_signal( &cond_heartbeat );
1188     pthread_mutex_unlock( &mutex_heartbeat );
1189 }