2 * socket server for emulator skin
4 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
7 * GiWoong Kim <giwoong.kim@samsung.com>
8 * 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"
37 #include <sys/types.h>
40 #include "maruskin_server.h"
41 #include "maruskin_operation.h"
42 #include "qemu-thread.h"
43 #include "emul_state.h"
44 #include "maruskin_client.h"
46 #include "maru_err_table.h"
48 #ifndef CONFIG_USE_SHM
57 #define socket_error() WSAGetLastError()
60 #include <arpa/inet.h>
61 #include <netinet/in.h>
62 #include <sys/socket.h>
64 #define socket_error() errno
70 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"
95 extern char tizen_target_path[];
98 /* This values must match the Java definitions
102 RECV_MOUSE_EVENT = 10,
104 RECV_HARD_KEY_EVENT = 12,
105 RECV_CHANGE_LCD_STATE = 13,
106 RECV_OPEN_SHELL = 14,
108 RECV_SCREEN_SHOT = 16,
109 RECV_DETAIL_INFO = 17,
111 RECV_GUESTMEMORY_DUMP = 19,
112 RECV_RESPONSE_HEART_BEAT = 900,
114 RECV_RESPONSE_SHUTDOWN = 999,
118 /* This values must match the Java definitions
122 SEND_SCREEN_SHOT = 2,
123 SEND_DETAIL_INFO = 3,
124 SEND_RAMDUMP_COMPLETE = 4,
125 SEND_BOOTING_PROGRESS = 5,
126 SEND_BRIGHTNESS_VALUE = 6,
127 SEND_SENSOR_DAEMON_START = 800,
131 static int seq_req_id = 0;
133 static uint16_t svr_port = 0;
134 static int server_sock = 0;
135 static int client_sock = 0;
136 static int stop_server = 0;
137 static int is_sensord_initialized = 0;
138 static int ready_server = 0;
139 static int ignore_heartbeat = 0;
140 static int is_force_close_client = 0;
142 static int is_started_heartbeat = 0;
143 static int stop_heartbeat = 0;
144 static int recv_heartbeat_count = 0;
145 static pthread_t thread_id_heartbeat;
147 static pthread_mutex_t mutex_send_data = PTHREAD_MUTEX_INITIALIZER;
148 static pthread_mutex_t mutex_recv_heartbeat_count = PTHREAD_MUTEX_INITIALIZER;
149 pthread_mutex_t mutex_screenshot = PTHREAD_MUTEX_INITIALIZER;
150 pthread_cond_t cond_screenshot = PTHREAD_COND_INITIALIZER;
152 static int skin_argc = 0;
153 static char** skin_argv = NULL;
154 static int qmu_argc = 0;
155 static char** qmu_argv = NULL;
157 static void parse_skin_args(void);
158 static void parse_skinconfig_prop(void);
159 static void* run_skin_server(void* args);
161 static int recv_n(int client_sock, char* read_buf, int recv_len);
162 static int send_n(int client_sock, unsigned char* data, int length, int big_data);
164 static void make_header(int client_sock,
165 short send_cmd, int data_length, char* sendbuf, int print_log);
166 static int send_skin_header_only(int client_sock,
167 short send_cmd, int print_log);
168 static int send_skin_data(int client_sock,
169 short send_cmd, unsigned char* data, int length, int big_data);
172 static void* do_heart_beat(void* args);
173 static int start_heart_beat(void);
174 static void stop_heart_beat(void);
176 int start_skin_server(int argc, char** argv,
177 int qemu_argc, char** qemu_argv)
182 parse_skinconfig_prop();
184 // arguments have higher priority than '.skinconfig.properties'
187 INFO("ignore_heartbeat:%d\n", ignore_heartbeat);
189 qmu_argc = qemu_argc;
190 qmu_argv = qemu_argv;
192 QemuThread qemu_thread;
194 qemu_thread_create( &qemu_thread, run_skin_server, NULL,
195 QEMU_THREAD_JOINABLE);
201 void shutdown_skin_server(void)
203 INFO("shutdown_skin_server\n");
205 int close_server_socket = 0;
206 int success_send = 0;
209 INFO("send shutdown to skin.\n");
210 if (0 > send_skin_header_only(client_sock, SEND_SHUTDOWN, 1)) {
211 ERR("fail to send SEND_SHUTDOWN to skin.\n");
212 close_server_socket = 1;
215 /* skin sent RECV_RESPONSE_SHUTDOWN */
222 int max_sleep_count = 10;
226 if (max_sleep_count < count) {
227 close_server_socket = 1;
232 INFO("skin client sent normal shutdown response.\n");
245 pthread_cond_destroy(&cond_screenshot);
246 pthread_mutex_destroy(&mutex_screenshot);
249 is_force_close_client = 1;
253 closesocket(client_sock);
260 if (close_server_socket) {
261 INFO("skin client did not send normal shutdown response.\n");
264 closesocket(server_sock);
272 pthread_mutex_destroy(&mutex_send_data);
273 pthread_mutex_destroy(&mutex_recv_heartbeat_count);
276 void notify_sensor_daemon_start(void)
278 INFO("notify_sensor_daemon_start\n");
280 is_sensord_initialized = 1;
282 if (0 > send_skin_header_only(
283 client_sock, SEND_SENSOR_DAEMON_START, 1)) {
285 ERR("fail to send SEND_SENSOR_DAEMON_START to skin.\n");
290 void notify_ramdump_completed(void)
292 INFO("ramdump completed!\n");
295 if (0 > send_skin_header_only(
296 client_sock, SEND_RAMDUMP_COMPLETE, 1)) {
298 ERR("fail to send SEND_RAMDUMP_COMPLETE to skin.\n");
303 void notify_booting_progress(int progress_value)
305 #define PROGRESS_DATA_LENGTH 4
307 char progress_data[PROGRESS_DATA_LENGTH] = { 0, };
310 TRACE("notify_booting_progress\n");
313 if (progress_value < 0) {
316 } else if (progress_value < 10) {
318 } else if (progress_value < 100) {
321 progress_value = 100;
325 snprintf(progress_data, len + 1, "%d", progress_value);
326 TRACE("booting...%s\%\n", progress_data);
329 if (0 > send_skin_data(client_sock,
330 SEND_BOOTING_PROGRESS, (unsigned char *)progress_data, len + 1, 0)) {
332 ERR("fail to send SEND_BOOTING_PROGRESS to skin.\n");
343 void notify_brightness(bool on)
345 char brightness_data[2] = { 0, };
346 int brightness_value = 1;
349 brightness_value = 0;
352 snprintf(brightness_data, 2, "%d", brightness_value);
353 TRACE("brightness value = %s\n", brightness_data);
356 if (0 > send_skin_data(client_sock,
357 SEND_BRIGHTNESS_VALUE, (unsigned char *)brightness_data, 2, 0)) {
359 ERR("fail to send SEND_BRIGHTNESS_VALUE to skin.\n");
364 int is_ready_skin_server(void)
369 int get_skin_server_port(void)
374 static void parse_skinconfig_prop(void)
376 int target_path_len = strlen( tizen_target_path );
377 char skin_config_path[target_path_len + 32];
379 memset( skin_config_path, 0, target_path_len + 32 );
380 strcpy( skin_config_path, tizen_target_path );
382 strcat( skin_config_path, "\\" );
384 strcat( skin_config_path, "/" );
386 strcat( skin_config_path, SKIN_CONFIG_PROP );
388 FILE* fp = fopen( skin_config_path, "r" );
391 INFO( "There is no %s. skin_config_path:%s\n", SKIN_CONFIG_PROP, skin_config_path );
395 fseek( fp, 0L, SEEK_END );
396 int buf_size = ftell( fp );
399 if ( 0 >= buf_size ) {
400 INFO( "%s contents is empty.\n", SKIN_CONFIG_PROP );
405 char* buf = g_malloc0( buf_size );
407 ERR( "Fail to malloc for %s\n", SKIN_CONFIG_PROP );
417 if ( total_cnt == buf_size ) {
421 read_cnt = fread( (void*) ( buf + read_cnt ), 1, buf_size - total_cnt, fp );
422 if ( 0 > read_cnt ) {
425 total_cnt += read_cnt;
432 INFO( "====== %s ======\n%s\n====================================\n", SKIN_CONFIG_PROP, buf );
434 char hb_ignore_prop[32];
435 memset( hb_ignore_prop, 0, 32 );
436 strcat( hb_ignore_prop, TEST_HB_IGNORE );
437 strcat( hb_ignore_prop, "=true" );
439 char* line_str = strtok( buf, "\n" );
445 TRACE( "prop line_str:%s\n", line_str );
447 if ( 0 == strcmp( line_str, hb_ignore_prop ) ) {
448 ignore_heartbeat = 1;
449 INFO( "ignore heartbeat by %s\n", SKIN_CONFIG_PROP );
456 line_str = strtok( NULL, "\n" );
464 static void parse_skin_args(void)
468 for (i = 0; i < skin_argc; i++) {
471 arg = strdup(skin_argv[i]);
475 char* key = strtok(arg, "=");
476 char* value = strtok(NULL, "=");
478 INFO("skin params key:%s, value:%s\n", key, value);
480 if (0 == strcmp(TEST_HB_IGNORE, key)) {
481 if (0 == strcmp("true", value)) {
482 ignore_heartbeat = 1;
483 } else if (0 == strcmp("false", value)) {
484 ignore_heartbeat = 0;
491 ERR("fail to strdup.");
498 static void print_fail_log(void)
500 ERR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
501 ERR("! Fail to initialize for skin server operation. Shutdown QEMU !\n");
502 ERR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
505 static void* run_skin_server(void* args)
507 struct sockaddr server_addr, client_addr;
508 socklen_t server_len, client_len;
509 int shutdown_qemu = 0;
511 INFO("run skin server\n");
513 if (0 > (server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
514 ERR("create listen socket error\n");
515 perror("create listen socket error : ");
518 shutdown_qemu_gracefully();
523 memset( &server_addr, '\0', sizeof( server_addr ) );
524 ( (struct sockaddr_in *) &server_addr )->sin_family = AF_INET;
525 memcpy( &( (struct sockaddr_in *) &server_addr )->sin_addr, "\177\000\000\001", 4 ); // 127.0.0.1
526 ( (struct sockaddr_in *) &server_addr )->sin_port = htons( 0 );
528 server_len = sizeof( server_addr );
530 if (0 != bind(server_sock, &server_addr, server_len)) {
531 ERR("skin server bind error\n");
532 perror("skin server bind error : ");
536 closesocket(server_sock);
544 shutdown_qemu_gracefully();
549 memset( &server_addr, '\0', sizeof( server_addr ) );
550 getsockname( server_sock, (struct sockaddr *) &server_addr, &server_len );
551 svr_port = ntohs( ( (struct sockaddr_in *) &server_addr )->sin_port );
553 INFO("success to bind port[127.0.0.1:%d/tcp] for skin_server in host \n", svr_port);
555 if (0 > listen( server_sock, 4)) {
556 ERR("skin_server listen error\n");
557 perror("skin_server listen error : ");
561 closesocket(server_sock);
569 shutdown_qemu_gracefully();
574 client_len = sizeof(client_addr);
576 char recvbuf[RECV_BUF_SIZE];
578 INFO("skin server start...port:%d\n", svr_port);
583 INFO("close server socket normally.\n");
589 if( !is_started_heartbeat ) {
590 if ( !start_heart_beat() ) {
591 ERR( "Fail to start heartbeat thread.\n" );
597 INFO( "start accepting socket...\n" );
599 if ( 0 > ( client_sock = accept( server_sock, (struct sockaddr *) &client_addr, &client_len ) ) ) {
600 ERR("skin_server accept error\n");
601 perror("skin_server accept error : ");
606 INFO( "accept client : client_sock:%d\n", client_sock );
611 INFO( "stop receiving current client socket.\n" );
616 memset( &recvbuf, 0, RECV_BUF_SIZE );
618 int read_cnt = recv_n( client_sock, recvbuf, RECV_HEADER_SIZE );
621 if (is_force_close_client) {
622 INFO( "force close client socket.\n" );
623 is_force_close_client = 0;
625 ERR("skin_server read error (%d): %d\n",
626 socket_error(), read_cnt);
627 perror("skin_server read error : ");
635 ERR("read_cnt is 0.\n");
641 memset(log_buf, 0, 512);
643 log_cnt = sprintf(log_buf, "== RECV read_cnt:%d ", read_cnt);
650 char* packet = recvbuf;
652 memcpy(&uid, packet, sizeof(uid));
653 packet += sizeof(uid);
654 memcpy(&req_id, packet, sizeof(req_id));
655 packet += sizeof(req_id);
656 memcpy(&cmd, packet, sizeof(cmd));
657 packet += sizeof(cmd);
658 memcpy(&length, packet, sizeof(length));
661 req_id = ntohl(req_id);
663 length = ntohs(length);
665 log_cnt += sprintf(log_buf + log_cnt,
666 "uid:%d, req_id:%d, cmd:%d, length:%d ", uid, req_id, cmd, length);
670 if ( RECV_BUF_SIZE < length ) {
671 ERR( "length is bigger than RECV_BUF_SIZE\n" );
675 memset( &recvbuf, 0, length );
677 int recv_cnt = recv_n( client_sock, recvbuf, length );
679 log_cnt += sprintf( log_buf + log_cnt, "data read_cnt:%d ", recv_cnt );
681 if ( 0 > recv_cnt ) {
682 ERR( "skin_server read data\n" );
683 perror( "skin_server read data : " );
685 } else if ( 0 == recv_cnt ) {
686 ERR( "data read_cnt is 0.\n" );
688 } else if ( recv_cnt != length ) {
689 ERR( "read_cnt is not equal to length.\n" );
697 log_cnt += sprintf( log_buf + log_cnt, "RECV_START ==\n" );
701 ERR( "there is no data looking at 0 length." );
705 /* keep it consistent with emulator-skin definition */
706 uint64 handle_id = 0;
707 int lcd_size_width = 0;
708 int lcd_size_height = 0;
710 double scale_ratio = 0.0;
714 memcpy( &handle_id, p, sizeof( handle_id ) );
715 p += sizeof( handle_id );
716 memcpy( &lcd_size_width, p, sizeof( lcd_size_width ) );
717 p += sizeof( lcd_size_width );
718 memcpy( &lcd_size_height, p, sizeof( lcd_size_height ) );
719 p += sizeof( lcd_size_height );
720 memcpy( &scale, p, sizeof( scale ) );
721 p += sizeof( scale );
722 memcpy( &rotation, p, sizeof( rotation ) );
724 int low_id = (int)handle_id;
725 int high_id = (int)(handle_id >> 32);
726 low_id = ntohl(high_id);
727 high_id = ntohl(low_id);
729 handle_id = (handle_id << 32) | low_id;
731 lcd_size_width = ntohl( lcd_size_width );
732 lcd_size_height = ntohl( lcd_size_height );
733 scale = ntohl( scale );
734 scale_ratio = ( (double) scale ) / 100;
735 rotation = ntohs( rotation );
737 set_emul_win_scale( scale_ratio );
739 start_display( handle_id, lcd_size_width, lcd_size_height, scale_ratio, rotation );
743 case RECV_MOUSE_EVENT: {
744 log_cnt += sprintf( log_buf + log_cnt, "RECV_MOUSE_EVENT ==\n" );
748 ERR( "there is no data looking at 0 length." );
752 /* keep it consistent with emulator-skin definition */
762 memcpy( &button_type, p, sizeof( button_type ) );
763 p += sizeof( button_type );
764 memcpy( &event_type, p, sizeof( event_type ) );
765 p += sizeof( event_type );
766 memcpy( &host_x, p, sizeof( host_x ) );
767 p += sizeof( host_x );
768 memcpy( &host_y, p, sizeof( host_y ) );
769 p += sizeof( host_y );
770 memcpy( &guest_x, p, sizeof( guest_x ) );
771 p += sizeof( guest_x );
772 memcpy( &guest_y, p, sizeof( guest_y ) );
773 p += sizeof( guest_y );
774 memcpy( &z, p, sizeof( z ) );
776 button_type = ntohl( button_type );
777 event_type = ntohl( event_type );
778 host_x = ntohl( host_x );
779 host_y = ntohl( host_y );
780 guest_x = ntohl( guest_x );
781 guest_y = ntohl( guest_y );
784 do_mouse_event(button_type, event_type,
785 host_x, host_y, guest_x, guest_y, z);
788 case RECV_KEY_EVENT: {
789 log_cnt += sprintf( log_buf + log_cnt, "RECV_KEY_EVENT ==\n" );
793 ERR( "there is no data looking at 0 length." );
797 /* keep it consistent with emulator-skin definition */
801 int key_location = 0;
804 memcpy( &event_type, p, sizeof( event_type ) );
805 p += sizeof( event_type );
806 memcpy( &keycode, p, sizeof( keycode ) );
807 p += sizeof( keycode );
808 memcpy( &state_mask, p, sizeof( state_mask ) );
809 p += sizeof( state_mask );
810 memcpy( &key_location, p, sizeof( key_location ) );
812 event_type = ntohl( event_type );
813 keycode = ntohl( keycode );
814 state_mask = ntohl( state_mask );
815 key_location = ntohl( key_location );
817 do_key_event(event_type, keycode, state_mask, key_location);
820 case RECV_HARD_KEY_EVENT: {
821 log_cnt += sprintf( log_buf + log_cnt, "RECV_HARD_KEY_EVENT ==\n" );
825 ERR( "there is no data looking at 0 length." );
829 /* keep it consistent with emulator-skin definition */
834 memcpy( &event_type, p, sizeof( event_type ) );
835 p += sizeof( event_type );
836 memcpy( &keycode, p, sizeof( keycode ) );
838 event_type = ntohl( event_type );
839 keycode = ntohl( keycode );
841 do_hardkey_event( event_type, keycode );
844 case RECV_CHANGE_LCD_STATE: {
845 log_cnt += sprintf( log_buf + log_cnt, "RECV_CHANGE_LCD_STATE ==\n" );
849 ERR( "there is no data looking at 0 length." );
853 /* keep it consistent with emulator-skin definition */
855 double scale_ratio = 0.0;
856 short rotation_type = 0;
859 memcpy( &scale, p, sizeof( scale ) );
860 p += sizeof( scale );
861 memcpy( &rotation_type, p, sizeof( rotation_type ) );
863 scale = ntohl( scale );
864 scale_ratio = ( (double) scale ) / 100;
865 rotation_type = ntohs( rotation_type );
867 if ( get_emul_win_scale() != scale_ratio ) {
868 do_scale_event( scale_ratio );
871 if ( is_sensord_initialized == 1 && get_emul_rotation() != rotation_type ) {
872 do_rotation_event( rotation_type );
875 #ifndef CONFIG_USE_SHM
876 maruskin_sdl_resize(); // send sdl event
880 case RECV_SCREEN_SHOT: {
881 log_cnt += sprintf( log_buf + log_cnt, "RECV_SCREEN_SHOT ==\n" );
884 QemuSurfaceInfo* info = get_screenshot_info();
887 send_skin_data( client_sock, SEND_SCREEN_SHOT, info->pixel_data, info->pixel_data_length, 1 );
888 free_screenshot_info( info );
890 ERR( "Fail to get screenshot data.\n" );
895 case RECV_DETAIL_INFO: {
896 log_cnt += sprintf( log_buf + log_cnt, "RECV_DETAIL_INFO ==\n" );
899 DetailInfo* detail_info = get_detail_info( qmu_argc, qmu_argv );
902 send_skin_data( client_sock, SEND_DETAIL_INFO, (unsigned char*) detail_info->data,
903 detail_info->data_length, 0 );
904 free_detail_info( detail_info );
906 ERR( "Fail to get detail info.\n" );
911 case RECV_RAM_DUMP: {
912 log_cnt += sprintf(log_buf + log_cnt, "RECV_RAM_DUMP ==\n");
918 case RECV_GUESTMEMORY_DUMP: {
919 log_cnt += sprintf(log_buf + log_cnt, "RECV_GUESTMEMORY_DUMP ==\n");
922 do_guestmemory_dump();
925 case RECV_RESPONSE_HEART_BEAT: {
926 log_cnt += sprintf(log_buf + log_cnt, "RECV_RESPONSE_HEART_BEAT ==\n");
930 TRACE("recv HB req_id:%d\n", req_id);
932 pthread_mutex_lock(&mutex_recv_heartbeat_count);
933 recv_heartbeat_count = 0;
934 pthread_mutex_unlock(&mutex_recv_heartbeat_count);
938 case RECV_OPEN_SHELL: {
939 log_cnt += sprintf(log_buf + log_cnt, "RECV_OPEN_SHELL ==\n");
945 case RECV_HOST_KBD: {
948 log_cnt += sprintf(log_buf + log_cnt, "RECV_HOST_KBD ==\n");
952 INFO("there is no data looking at 0 length.\n");
956 memcpy(&on, recvbuf, sizeof(on));
962 log_cnt += sprintf(log_buf + log_cnt, "RECV_CLOSE ==\n");
968 case RECV_RESPONSE_SHUTDOWN: {
969 log_cnt += sprintf( log_buf + log_cnt, "RECV_RESPONSE_SHUTDOWN ==\n" );
976 log_cnt += sprintf( log_buf + log_cnt, "!!! unknown command : %d\n", cmd );
979 ERR( "!!! unknown command : %d\n", cmd );
995 closesocket(server_sock);
1002 if (shutdown_qemu) {
1004 shutdown_qemu_gracefully();
1010 static int recv_n(int sockfd, char* read_buf, int recv_len)
1016 recv_cnt = recv(sockfd,
1017 (void*)(read_buf + recv_cnt), (recv_len - recv_cnt), 0);
1021 } else if (0 == recv_cnt) {
1022 if (total_cnt == recv_len) {
1028 total_cnt += recv_cnt;
1030 if (total_cnt == recv_len) {
1041 static void make_header(int sockfd,
1042 short send_cmd, int data_length, char* sendbuf, int print_log)
1044 memset(sendbuf, 0, SEND_HEADER_SIZE);
1046 int request_id = (MAX_REQ_ID == seq_req_id) ? 0 : ++seq_req_id;
1048 TRACE("== SEND skin request_id:%d, send_cmd:%d ==\n", request_id, send_cmd);
1050 request_id = htonl(request_id);
1052 short cmd = send_cmd;
1055 int length = data_length;
1056 length = htonl(length);
1059 memcpy(p, &request_id, sizeof(request_id));
1060 p += sizeof(request_id);
1061 memcpy(p, &cmd, sizeof(cmd));
1063 memcpy(p, &length, sizeof(length));
1066 static int send_n(int sockfd,
1067 unsigned char* data, int length, int big_data)
1072 int buf_size = (big_data != 0) ?
1073 SEND_BIG_BUF_SIZE : SEND_BUF_SIZE;
1075 /* use malloc instead of general array definition
1076 to avoid seg fault in 'alloca' in MinGW env, only using big buf size */
1077 char* databuf = (char*)g_malloc0(buf_size);
1079 if (big_data != 0) {
1080 TRACE("big_data send_n start. length:%d\n", length);
1082 TRACE("send_n start. length:%d\n", length);
1086 if (total_cnt == length) {
1090 if (buf_size < (length - total_cnt)) {
1091 send_cnt = buf_size;
1093 send_cnt = (length - total_cnt);
1096 memset(databuf, 0, send_cnt);
1097 memcpy(databuf, (char*) (data + total_cnt), send_cnt);
1099 send_cnt = send(sockfd, databuf, send_cnt, 0);
1102 ERR("send_n error. error code:%d\n", send_cnt);
1105 total_cnt += send_cnt;
1111 TRACE("send_n finished.\n");
1116 static int send_skin_header_only(int sockfd, short send_cmd, int print_log)
1118 char headerbuf[SEND_HEADER_SIZE] = { 0, };
1120 make_header(sockfd, send_cmd, 0, headerbuf, print_log);
1123 pthread_mutex_lock(&mutex_send_data);
1125 int send_count = send(sockfd, headerbuf, SEND_HEADER_SIZE, 0);
1127 pthread_mutex_unlock(&mutex_send_data);
1132 static int send_skin_data(int sockfd,
1133 short send_cmd, unsigned char* data, int length, int big_data)
1136 char headerbuf[SEND_HEADER_SIZE] = { 0, };
1139 ERR("send data is NULL.\n");
1143 make_header(sockfd, send_cmd, length, headerbuf, 1);
1146 pthread_mutex_lock(&mutex_send_data);
1148 int header_cnt = send(sockfd, headerbuf, SEND_HEADER_SIZE, 0);
1149 if (0 > header_cnt) {
1150 ERR("send header for data is NULL.\n");
1151 pthread_mutex_unlock(&mutex_send_data);
1156 int send_cnt = send_n(sockfd, data, length, big_data);
1158 pthread_mutex_unlock(&mutex_send_data);
1160 TRACE("send_n result:%d\n", send_cnt);
1165 static void* do_heart_beat(void* args)
1167 is_started_heartbeat = 1;
1169 int send_fail_count = 0;
1170 int restart_client_count = 0;
1171 int need_restart_skin_client = 0;
1174 unsigned int booting_handicap_cnt = 0;
1175 unsigned int hb_interval = HEART_BEAT_INTERVAL * 1000;
1178 if (booting_handicap_cnt < 5) {
1179 booting_handicap_cnt++;
1182 Sleep(hb_interval * 10); /* 10sec */
1184 usleep(hb_interval * 1000 * 10);
1188 Sleep(hb_interval); /* 1sec */
1190 usleep(hb_interval * 1000);
1194 if (stop_heartbeat) {
1195 INFO("[HB] stop heart beat.\n");
1199 if ( client_sock ) {
1200 TRACE( "send HB\n" );
1201 if ( 0 > send_skin_header_only( client_sock, SEND_HEART_BEAT, 0 ) ) {
1204 send_fail_count = 0;
1207 /* fail to get socket in accepting or client is not yet accepted */
1209 TRACE( "[HB] client socket is NULL yet.\n" );
1212 if ( HEART_BEAT_FAIL_COUNT < send_fail_count ) {
1213 ERR( "[HB] fail to send heart beat to skin. fail count:%d\n", HEART_BEAT_FAIL_COUNT );
1214 need_restart_skin_client = 1;
1217 pthread_mutex_lock( &mutex_recv_heartbeat_count );
1218 recv_heartbeat_count++;
1219 if ( 1 < recv_heartbeat_count ) {
1220 TRACE( "[HB] recv_heartbeat_count:%d\n", recv_heartbeat_count );
1222 pthread_mutex_unlock( &mutex_recv_heartbeat_count );
1224 if ( HEART_BEAT_EXPIRE_COUNT < recv_heartbeat_count ) {
1225 ERR( "received heartbeat count is expired.\n" );
1226 need_restart_skin_client = 1;
1229 if ( need_restart_skin_client ) {
1231 if ( RESTART_CLIENT_MAX_COUNT <= restart_client_count ) {
1236 if ( is_requested_shutdown_qemu_gracefully() ) {
1237 INFO( "requested shutdown_qemu_gracefully, do not retry starting skin client process.\n" );
1241 send_fail_count = 0;
1242 recv_heartbeat_count = 0;
1243 need_restart_skin_client = 0;
1244 restart_client_count++;
1246 INFO( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1247 INFO( "!!! restart skin client process !!!\n" );
1248 INFO( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
1250 is_force_close_client = 1;
1251 if ( client_sock ) {
1253 closesocket( client_sock );
1255 close( client_sock );
1260 start_skin_client( skin_argc, skin_argv );
1272 INFO( "[HB] shutdown skin_server by heartbeat thread.\n" );
1274 is_force_close_client = 1;
1275 if ( client_sock ) {
1277 closesocket( client_sock );
1279 close( client_sock );
1285 if ( server_sock ) {
1287 closesocket( server_sock );
1289 close( server_sock );
1294 ERR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
1295 ERR("!!! Fail to operate with heartbeat from skin client. Shutdown QEMU !!!\n");
1296 ERR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
1298 maru_register_exit_msg(MARU_EXIT_HB_TIME_EXPIRED, NULL);
1299 shutdown_qemu_gracefully();
1307 static int start_heart_beat(void)
1309 if (is_started_heartbeat) {
1313 if (ignore_heartbeat) {
1316 if (0 != pthread_create(&thread_id_heartbeat, NULL, do_heart_beat, NULL)) {
1317 ERR("[HB] fail to create heartbean pthread.\n");
1325 static void stop_heart_beat(void)