2 * socket server for emulator skin
4 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
7 * HyunJun Son <hj79.son@samsung.com>
8 * GiWoong Kim <giwoong.kim@samsung.com>
9 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
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.
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.
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.
31 #include "maru_common.h"
42 #include <sys/types.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"
51 #include "maru_err_table.h"
62 #include <arpa/inet.h>
63 #include <netinet/in.h>
64 #include <sys/socket.h>
69 MULTI_DEBUG_CHANNEL(qemu, skin_server);
72 #define MAX_REQ_ID 0x7fffffff
73 #define RECV_BUF_SIZE 32
74 #define RECV_HEADER_SIZE 12
76 #define SEND_HEADER_SIZE 10
77 #define SEND_BIG_BUF_SIZE 1024 * 1024 * 2
78 #define SEND_BUF_SIZE 512
80 #define HEART_BEAT_INTERVAL 1
81 #define HEART_BEAT_FAIL_COUNT 10
82 #define HEART_BEAT_EXPIRE_COUNT 10
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
87 #define RESTART_CLIENT_MAX_COUNT 0
90 #define PORT_RETRY_COUNT 50
92 #define TEST_HB_IGNORE "test.hb.ignore"
93 #define SKIN_CONFIG_PROP ".skinconfig.properties"
97 RECV_MOUSE_EVENT = 10,
99 RECV_HARD_KEY_EVENT = 12,
100 RECV_CHANGE_LCD_STATE = 13,
101 RECV_OPEN_SHELL = 14,
103 RECV_SCREEN_SHOT = 16,
104 RECV_DETAIL_INFO = 17,
106 RECV_GUESTMEMORY_DUMP = 19,
107 RECV_RESPONSE_HEART_BEAT = 900,
109 RECV_RESPONSE_SHUTDOWN = 999,
114 SEND_SCREEN_SHOT = 2,
115 SEND_DETAIL_INFO = 3,
116 SEND_RAMDUMP_COMPLETE = 4,
117 SEND_SENSOR_DAEMON_START = 800,
121 static int seq_req_id = 0;
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;
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;
140 static int skin_argc = 0;
141 static char** skin_argv = NULL;
142 static int qmu_argc = 0;
143 static char** qmu_argv = NULL;
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 );
154 static void* do_heart_beat( void* args );
155 static int start_heart_beat( void );
156 static void stop_heart_beat( void );
158 int start_skin_server( int argc, char** argv, int qemu_argc, char** qemu_argv ) {
163 parse_skinconfig_prop();
165 // arguments have higher priority than '.skinconfig.properties'
168 INFO( "ignore_heartbeat:%d\n", ignore_heartbeat );
170 qmu_argc = qemu_argc;
171 qmu_argv = qemu_argv;
173 QemuThread qemu_thread;
175 qemu_thread_create( &qemu_thread, run_skin_server, NULL,
176 QEMU_THREAD_JOINABLE);
182 void shutdown_skin_server( void ) {
184 INFO( "shutdown_skin_server\n" );
186 int close_server_socket = 0;
187 int success_send = 0;
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;
196 // skin sent RECV_RESPONSE_SHUTDOWN.
200 if ( success_send ) {
203 int max_sleep_count = 10;
207 if ( max_sleep_count < count ) {
208 close_server_socket = 1;
213 INFO( "skin client sent normal shutdown response.\n" );
219 usleep( 1000 ); // 1ms
227 is_force_close_client = 1;
231 closesocket( client_sock );
233 close( client_sock );
238 if ( close_server_socket ) {
239 INFO( "skin client did not send normal shutdown response.\n" );
242 closesocket( server_sock );
244 close( server_sock );
252 void notify_sensor_daemon_start( void ) {
253 INFO( "notify_sensor_daemon_start\n" );
254 is_sensord_initialized = 1;
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" );
262 void notify_ramdump_complete(void) {
263 INFO("notify_ramdump_complete\n");
266 if (0 > send_skin_header_only( client_sock, SEND_RAMDUMP_COMPLETE, 1)) {
267 ERR("fail to send SEND_RAMDUMP_COMPLETE to skin.\n");
273 int is_ready_skin_server( void ) {
277 int get_skin_server_port( void ) {
281 static void parse_skinconfig_prop( void ) {
283 int target_path_len = strlen( tizen_target_path );
284 char skin_config_path[target_path_len + 32];
286 memset( skin_config_path, 0, target_path_len + 32 );
287 strcpy( skin_config_path, tizen_target_path );
289 strcat( skin_config_path, "\\" );
291 strcat( skin_config_path, "/" );
293 strcat( skin_config_path, SKIN_CONFIG_PROP );
295 FILE* fp = fopen( skin_config_path, "r" );
298 INFO( "There is no %s. skin_config_path:%s\n", SKIN_CONFIG_PROP, skin_config_path );
302 fseek( fp, 0L, SEEK_END );
303 int buf_size = ftell( fp );
306 if ( 0 >= buf_size ) {
307 INFO( "%s contents is empty.\n", SKIN_CONFIG_PROP );
312 char* buf = g_malloc0( buf_size );
314 ERR( "Fail to malloc for %s\n", SKIN_CONFIG_PROP );
324 if ( total_cnt == buf_size ) {
328 read_cnt = fread( (void*) ( buf + read_cnt ), 1, buf_size - total_cnt, fp );
329 if ( 0 > read_cnt ) {
332 total_cnt += read_cnt;
339 INFO( "====== %s ======\n%s\n====================================\n", SKIN_CONFIG_PROP, buf );
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" );
346 char* line_str = strtok( buf, "\n" );
352 TRACE( "prop line_str:%s\n", line_str );
354 if ( 0 == strcmp( line_str, hb_ignore_prop ) ) {
355 ignore_heartbeat = 1;
356 INFO( "ignore heartbeat by %s\n", SKIN_CONFIG_PROP );
363 line_str = strtok( NULL, "\n" );
371 static void parse_skin_args( void ) {
374 for ( i = 0; i < skin_argc; i++ ) {
377 arg = strdup( skin_argv[i] );
381 char* key = strtok( arg, "=" );
382 char* value = strtok( NULL, "=" );
384 INFO( "skin params key:%s, value:%s\n", key, value );
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;
397 ERR( "fail to strdup." );
404 static void* run_skin_server( void* args ) {
406 struct sockaddr server_addr, client_addr;
407 socklen_t server_len, client_len;
408 int shutdown_qmu = 0;
410 INFO("run skin server\n");
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 : " );
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 );
424 server_len = sizeof( server_addr );
426 if ( 0 != bind( server_sock, &server_addr, server_len ) ) {
427 ERR( "skin server bind error\n" );
428 perror( "skin server bind error : " );
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 );
437 INFO( "success to bind port[127.0.0.1:%d/tcp] for skin_server in host \n", svr_port );
439 if ( 0 > listen( server_sock, 4 ) ) {
440 ERR( "skin_server listen error\n" );
441 perror( "skin_server listen error : " );
446 client_len = sizeof( client_addr );
448 char recvbuf[RECV_BUF_SIZE];
450 INFO( "skin server start...port:%d\n", svr_port );
455 INFO( "close server socket normally.\n" );
461 if( !is_started_heartbeat ) {
462 if ( !start_heart_beat() ) {
463 ERR( "Fail to start heartbeat thread.\n" );
469 INFO( "start accepting socket...\n" );
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 : " );
477 INFO( "accept client : client_sock:%d\n", client_sock );
482 INFO( "stop receiving current client socket.\n" );
487 memset( &recvbuf, 0, RECV_BUF_SIZE );
489 int read_cnt = recv_n( client_sock, recvbuf, RECV_HEADER_SIZE );
491 if ( 0 > read_cnt ) {
493 if( is_force_close_client ) {
494 INFO( "force close client socket.\n" );
495 is_force_close_client = 0;
497 ERR( "skin_server read error:%d\n", read_cnt );
498 perror( "skin_server read error : " );
504 if ( 0 == read_cnt ) {
505 ERR( "read_cnt is 0.\n" );
511 memset( log_buf, 0, 512 );
513 log_cnt = sprintf( log_buf, "== RECV read_cnt:%d ", read_cnt );
522 memcpy( &uid, p, sizeof( uid ) );
524 memcpy( &req_id, p, sizeof( req_id ) );
525 p += sizeof( req_id );
526 memcpy( &cmd, p, sizeof( cmd ) );
528 memcpy( &length, p, sizeof( length ) );
531 req_id = ntohl( req_id );
533 length = ntohs( length );
535 log_cnt += sprintf( log_buf + log_cnt, "uid:%d, req_id:%d, cmd:%d, length:%d ", uid, req_id, cmd, length );
539 if ( RECV_BUF_SIZE < length ) {
540 ERR( "length is bigger than RECV_BUF_SIZE\n" );
544 memset( &recvbuf, 0, length );
546 int recv_cnt = recv_n( client_sock, recvbuf, length );
548 log_cnt += sprintf( log_buf + log_cnt, "data read_cnt:%d ", recv_cnt );
550 if ( 0 > recv_cnt ) {
551 ERR( "skin_server read data\n" );
552 perror( "skin_server read data : " );
554 } else if ( 0 == recv_cnt ) {
555 ERR( "data read_cnt is 0.\n" );
557 } else if ( recv_cnt != length ) {
558 ERR( "read_cnt is not equal to length.\n" );
566 log_cnt += sprintf( log_buf + log_cnt, "RECV_START ==\n" );
570 ERR( "there is no data looking at 0 length." );
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;
579 double scale_ratio = 0.0;
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 ) );
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);
598 handle_id = (handle_id << 32) | low_id;
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 );
606 set_emul_win_scale( scale_ratio );
608 start_display( handle_id, lcd_size_width, lcd_size_height, scale_ratio, rotation );
612 case RECV_MOUSE_EVENT: {
613 log_cnt += sprintf( log_buf + log_cnt, "RECV_MOUSE_EVENT ==\n" );
617 ERR( "there is no data looking at 0 length." );
621 /* keep it consistent with emulator-skin definition */
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 ) );
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 );
653 do_mouse_event(button_type, event_type,
654 host_x, host_y, guest_x, guest_y, z);
657 case RECV_KEY_EVENT: {
658 log_cnt += sprintf( log_buf + log_cnt, "RECV_KEY_EVENT ==\n" );
662 ERR( "there is no data looking at 0 length." );
666 /* keep it consistent with emulator-skin definition */
670 int key_location = 0;
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 ) );
681 event_type = ntohl( event_type );
682 keycode = ntohl( keycode );
683 state_mask = ntohl( state_mask );
684 key_location = ntohl( key_location );
686 do_key_event(event_type, keycode, state_mask, key_location);
689 case RECV_HARD_KEY_EVENT: {
690 log_cnt += sprintf( log_buf + log_cnt, "RECV_HARD_KEY_EVENT ==\n" );
694 ERR( "there is no data looking at 0 length." );
698 /* keep it consistent with emulator-skin definition */
703 memcpy( &event_type, p, sizeof( event_type ) );
704 p += sizeof( event_type );
705 memcpy( &keycode, p, sizeof( keycode ) );
707 event_type = ntohl( event_type );
708 keycode = ntohl( keycode );
710 do_hardkey_event( event_type, keycode );
713 case RECV_CHANGE_LCD_STATE: {
714 log_cnt += sprintf( log_buf + log_cnt, "RECV_CHANGE_LCD_STATE ==\n" );
718 ERR( "there is no data looking at 0 length." );
722 /* keep it consistent with emulator-skin definition */
724 double scale_ratio = 0.0;
725 short rotation_type = 0;
728 memcpy( &scale, p, sizeof( scale ) );
729 p += sizeof( scale );
730 memcpy( &rotation_type, p, sizeof( rotation_type ) );
732 scale = ntohl( scale );
733 scale_ratio = ( (double) scale ) / 100;
734 rotation_type = ntohs( rotation_type );
736 if ( get_emul_win_scale() != scale_ratio ) {
737 do_scale_event( scale_ratio );
740 if ( is_sensord_initialized == 1 && get_emul_rotation() != rotation_type ) {
741 do_rotation_event( rotation_type );
745 maruskin_sdl_resize(); // send sdl event
749 case RECV_SCREEN_SHOT: {
750 log_cnt += sprintf( log_buf + log_cnt, "RECV_SCREEN_SHOT ==\n" );
753 QemuSurfaceInfo* info = get_screenshot_info();
756 send_skin_data( client_sock, SEND_SCREEN_SHOT, info->pixel_data, info->pixel_data_length, 1 );
757 free_screenshot_info( info );
759 ERR( "Fail to get screenshot data.\n" );
764 case RECV_DETAIL_INFO: {
765 log_cnt += sprintf( log_buf + log_cnt, "RECV_DETAIL_INFO ==\n" );
768 DetailInfo* detail_info = get_detail_info( qmu_argc, qmu_argv );
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 );
775 ERR( "Fail to get detail info.\n" );
780 case RECV_RAM_DUMP: {
781 log_cnt += sprintf(log_buf + log_cnt, "RECV_RAM_DUMP ==\n");
787 case RECV_GUESTMEMORY_DUMP: {
788 log_cnt += sprintf(log_buf + log_cnt, "RECV_GUESTMEMORY_DUMP ==\n");
794 case RECV_RESPONSE_HEART_BEAT: {
795 log_cnt += sprintf( log_buf + log_cnt, "RECV_RESPONSE_HEART_BEAT ==\n" );
797 TRACE( "recv HB req_id:%d\n", req_id );
799 pthread_mutex_lock( &mutex_recv_heartbeat_count );
800 recv_heartbeat_count = 0;
801 pthread_mutex_unlock( &mutex_recv_heartbeat_count );
805 case RECV_OPEN_SHELL: {
806 log_cnt += sprintf( log_buf + log_cnt, "RECV_OPEN_SHELL ==\n" );
813 log_cnt += sprintf( log_buf + log_cnt, "RECV_USB_KBD ==\n" );
817 INFO( "there is no data looking at 0 length." );
822 memcpy( &on, recvbuf, sizeof( on ) );
827 log_cnt += sprintf( log_buf + log_cnt, "RECV_CLOSE ==\n" );
833 case RECV_RESPONSE_SHUTDOWN: {
834 log_cnt += sprintf( log_buf + log_cnt, "RECV_RESPONSE_SHUTDOWN ==\n" );
841 log_cnt += sprintf( log_buf + log_cnt, "!!! unknown command : %d\n", cmd );
844 ERR( "!!! unknown command : %d\n", cmd );
860 closesocket( server_sock );
862 close( server_sock );
868 ERR( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
869 ERR( "!!! Fail to initialize for skin server operation. Shutdown QEMU !!!\n" );
870 ERR( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
871 shutdown_qemu_gracefully();
877 static int recv_n( int client_sock, char* read_buf, int recv_len ) {
884 recv_cnt = recv( client_sock, (void*) ( read_buf + recv_cnt ), ( recv_len - recv_cnt ), 0 );
886 if ( 0 > recv_cnt ) {
890 } else if ( 0 == recv_cnt ) {
892 if ( total_cnt == recv_len ) {
900 total_cnt += recv_cnt;
902 if ( total_cnt == recv_len ) {
916 static void make_header( int client_sock, short send_cmd, int data_length, char* sendbuf, int print_log ) {
918 memset( sendbuf, 0, SEND_HEADER_SIZE );
920 int request_id = ( MAX_REQ_ID == seq_req_id ) ? 0 : ++seq_req_id;
922 TRACE( "== SEND skin request_id:%d, send_cmd:%d ==\n", request_id, send_cmd );
924 request_id = htonl( request_id );
926 short cmd = send_cmd;
929 int length = data_length;
930 length = htonl( length );
933 memcpy( p, &request_id, sizeof( request_id ) );
934 p += sizeof( request_id );
935 memcpy( p, &cmd, sizeof( cmd ) );
937 memcpy( p, &length, sizeof( length ) );
941 static int send_n( int client_sock, unsigned char* data, int length, int big_data ) {
946 int buf_size = big_data ? SEND_BIG_BUF_SIZE : SEND_BUF_SIZE;
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 );
951 INFO( "send_n start. length:%d\n", length );
955 if ( total_cnt == length ) {
959 if ( buf_size < ( length - total_cnt ) ) {
962 send_cnt = ( length - total_cnt );
965 memset( databuf, 0, send_cnt );
966 memcpy( databuf, (char*) ( data + total_cnt ), send_cnt );
968 send_cnt = send( client_sock, databuf, send_cnt, 0 );
970 if ( 0 > send_cnt ) {
971 ERR( "send_n error. error code:%d\n", send_cnt );
974 total_cnt += send_cnt;
981 INFO( "send_n finished.\n" );
987 static int send_skin_header_only( int client_sock, short send_cmd, int print_log ) {
989 char headerbuf[SEND_HEADER_SIZE];
990 make_header( client_sock, send_cmd, 0, headerbuf, print_log );
992 int send_count = send( client_sock, headerbuf, SEND_HEADER_SIZE, 0 );
997 static int send_skin_data( int client_sock, short send_cmd, unsigned char* data, int length, int big_data ) {
999 char headerbuf[SEND_HEADER_SIZE];
1000 make_header( client_sock, send_cmd, length, headerbuf, 1 );
1002 int header_cnt = send( client_sock, headerbuf, SEND_HEADER_SIZE, 0 );
1004 if ( 0 > header_cnt ) {
1005 ERR( "send header for data is NULL.\n" );
1010 ERR( "send data is NULL.\n" );
1014 int send_cnt = send_n( client_sock, data, length, big_data );
1015 INFO( "send_n result:%d\n", send_cnt );
1021 static void* do_heart_beat( void* args ) {
1023 is_started_heartbeat = 1;
1025 int send_fail_count = 0;
1026 int restart_client_count = 0;
1027 int need_restart_skin_client = 0;
1030 int booting_handicap_cnt = 0;
1032 struct timeval current;
1033 struct timespec ts_heartbeat;
1036 gettimeofday( ¤t, NULL );
1038 if (booting_handicap_cnt < 5) {
1039 booting_handicap_cnt++;
1040 ts_heartbeat.tv_sec = current.tv_sec +
1041 (HEART_BEAT_INTERVAL * 10);
1043 ts_heartbeat.tv_sec = current.tv_sec + HEART_BEAT_INTERVAL;
1046 ts_heartbeat.tv_nsec = current.tv_usec * 1000;
1048 pthread_mutex_lock( &mutex_heartbeat );
1049 pthread_cond_timedwait( &cond_heartbeat, &mutex_heartbeat, &ts_heartbeat );
1050 pthread_mutex_unlock( &mutex_heartbeat );
1052 if ( stop_heartbeat ) {
1053 INFO( "[HB] stop heart beat.\n" );
1057 if ( client_sock ) {
1058 TRACE( "send HB\n" );
1059 if ( 0 > send_skin_header_only( client_sock, SEND_HEART_BEAT, 0 ) ) {
1062 send_fail_count = 0;
1065 // fail to get socket in accepting or client is not yet accepted.
1067 TRACE( "[HB] client socket is NULL yet.\n" );
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;
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 );
1080 pthread_mutex_unlock( &mutex_recv_heartbeat_count );
1082 if ( HEART_BEAT_EXPIRE_COUNT < recv_heartbeat_count ) {
1083 ERR( "received heartbeat count is expired.\n" );
1084 need_restart_skin_client = 1;
1087 if ( need_restart_skin_client ) {
1089 if ( RESTART_CLIENT_MAX_COUNT <= restart_client_count ) {
1094 if ( is_requested_shutdown_qemu_gracefully() ) {
1095 INFO( "requested shutdown_qemu_gracefully, do not retry starting skin client process.\n" );
1099 send_fail_count = 0;
1100 recv_heartbeat_count = 0;
1101 need_restart_skin_client = 0;
1102 restart_client_count++;
1104 INFO( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1105 INFO( "!!! restart skin client process !!!\n" );
1106 INFO( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1108 is_force_close_client = 1;
1109 if ( client_sock ) {
1111 closesocket( client_sock );
1113 close( client_sock );
1118 start_skin_client( skin_argc, skin_argv );
1130 INFO( "[HB] shutdown skin_server by heartbeat thread.\n" );
1132 is_force_close_client = 1;
1133 if ( client_sock ) {
1135 closesocket( client_sock );
1137 close( client_sock );
1143 if ( server_sock ) {
1145 closesocket( server_sock );
1147 close( server_sock );
1152 ERR( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1153 ERR( "!!! Fail to operate with heartbeat from skin client. Shutdown QEMU !!!\n" );
1154 ERR( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1156 maru_register_exit_msg(MARU_EXIT_HB_TIME_EXPIRED, NULL);
1157 shutdown_qemu_gracefully();
1165 static int start_heart_beat( void ) {
1167 if( is_started_heartbeat ) {
1171 if( ignore_heartbeat ) {
1174 if ( 0 != pthread_create( &thread_id_heartbeat, NULL, do_heart_beat, NULL ) ) {
1175 ERR( "[HB] fail to create heartbean pthread.\n" );
1184 static void stop_heart_beat( void ) {
1185 pthread_mutex_lock( &mutex_heartbeat );
1187 pthread_cond_signal( &cond_heartbeat );
1188 pthread_mutex_unlock( &mutex_heartbeat );