From 9b073ef78ce214eb099e8d36e8d9f67c6a6dc04a Mon Sep 17 00:00:00 2001 From: "munkyu.im" Date: Fri, 27 Jul 2012 12:16:48 +0900 Subject: [PATCH] [Title]fix multi instance problem on windows [Type] [Module] [Priority] [CQ#] N_SE-5564 [Redmine#] [Problem]when do double click twice quickly, 2 emulator instances are started. [Cause] [Solution] [TestCase] --- tizen/src/emulator.c | 1122 ++++++++++++++++++++++++-------------------------- tizen/src/sdb.c | 737 +++++++++++++++++---------------- 2 files changed, 908 insertions(+), 951 deletions(-) diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index 204a011..9104c21 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -1,582 +1,540 @@ -/* - * Emulator - * - * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * SeokYeon Hwang - * HyunJun Son - * MunKyu Im - * GiWoong Kim - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - - -#include "maru_common.h" -#include -#ifdef CONFIG_SDL -#include -#endif -#include "emulator.h" -#include "sdb.h" -#include "string.h" -#include "skin/maruskin_server.h" -#include "skin/maruskin_client.h" -#include "guest_server.h" -#include "debug_ch.h" -#include "option.h" -#include "emul_state.h" -#include "qemu_socket.h" -#include "build_info.h" -#include "maru_err_table.h" -#include -#include - -#if defined(CONFIG_WIN32) -#include -#elif defined(CONFIG_LINUX) -#include -#include -#include -#include -#include -#endif - -#include "mloop_event.h" - -MULTI_DEBUG_CHANNEL(qemu, main); - - -#define IMAGE_PATH_PREFIX "file=" -#define IMAGE_PATH_SUFFIX ",if=virtio" -#define SDB_PORT_PREFIX "sdb_port=" -#define LOGS_SUFFIX "/logs/" -#define LOGFILE "emulator.log" -#define MIDBUF 128 -int tizen_base_port = 0; - -char tizen_target_path[MAXLEN] = {0, }; -char logpath[MAXLEN] = { 0, }; - -static int skin_argc = 0; -static char** skin_argv = NULL; -static int qemu_argc = 0; -static char** qemu_argv = NULL; - -extern void maru_display_fini(void); -void exit_emulator(void) -{ - mloop_ev_stop(); - shutdown_skin_server(); - shutdown_guest_server(); - - maru_display_fini(); -} - -static int check_port_bind_listen(u_int port) -{ - struct sockaddr_in addr; - int s, opt = 1; - int ret = -1; - socklen_t addrlen = sizeof(addr); - memset(&addr, 0, addrlen); - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(port); - - if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || - (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || - (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || - (listen(s,1) < 0)) { - - /* fail */ - ret = -1; - ERR( "check port(%d) bind listen fail \n", port); - }else{ - /*fsucess*/ - ret = 1; - INFO( "check port(%d) bind listen ok \n", port); - } - -#ifdef CONFIG_WIN32 - closesocket(s); -#else - close(s); -#endif - - return ret; -} - - -void check_shdmem(void) -{ -#if defined(CONFIG_LINUX) - int shm_id; - void *shm_addr; - u_int port; - int val; - struct shmid_ds shm_info; - - for(port=26100;port < 26200; port += 10) - { - if ( -1 != ( shm_id = shmget( (key_t)port, 0, 0))) - { - if((void *)-1 == (shm_addr = shmat(shm_id, (void *)0, 0))) - { - ERR( "error occured at shmat()\n"); - break; - } - - val = shmctl(shm_id, IPC_STAT, &shm_info); - if(val != -1) - { - INFO( "count of process that use shared memory : %d\n", shm_info.shm_nattch); - if(shm_info.shm_nattch > 0 && strcmp(tizen_target_path, (char*)shm_addr) == 0) - { - if(check_port_bind_listen(port+1) > 0){ - shmdt(shm_addr); - continue; - } - shmdt(shm_addr); - maru_register_exit_msg(MARU_EXIT_UNKNOWN, (char*)"Can not execute this VM.\nThe same name is running now."); - exit(0); - } - else{ - shmdt(shm_addr); - } - } - } - } - -#elif defined(CONFIG_WIN32) - u_int port; - char* base_port = NULL; - char* pBuf; - HANDLE hMapFile; - for(port=26100;port < 26200; port += 10) - { - base_port = g_strdup_printf("%d", port); - hMapFile = OpenFileMapping( - FILE_MAP_READ, - TRUE, - base_port); - if(hMapFile == NULL) - { - INFO("port %s is not used.\n", base_port); - continue; - } - else - { - pBuf = (char*)MapViewOfFile(hMapFile, - FILE_MAP_READ, - 0, - 0, - 50); - if (pBuf == NULL) - { - ERR("Could not map view of file (%d).\n", GetLastError()); - CloseHandle(hMapFile); - return -1; - } - - if(strcmp(pBuf, tizen_target_path) == 0) - { - if(check_port_bind_listen(port+1) > 0) - { - UnmapViewOfFile(pBuf); - CloseHandle(hMapFile); - continue; - } - - maru_register_exit_msg(MARU_EXIT_UNKNOWN, "Can not execute this VM.\nThe same name is running now."); - UnmapViewOfFile(pBuf); - CloseHandle(hMapFile); - free(base_port); - exit(0); - } - else - UnmapViewOfFile(pBuf); - } - - CloseHandle(hMapFile); - free(base_port); - } -#elif defined(CONFIG_DARWIN) - //TODO: -#endif -} - -void make_shdmem(void) -{ -#if defined(CONFIG_LINUX) - int shmid; - char *shared_memory; - shmid = shmget((key_t)tizen_base_port, MAXLEN, 0666|IPC_CREAT); - if (shmid == -1) - { - ERR("shmget failed\n"); - return; - } - shared_memory = shmat(shmid, (char*)0x00, 0); - if (shared_memory == (void *)-1) - { - ERR("shmat failed\n"); - return; - } - sprintf(shared_memory, "%s", tizen_target_path); - INFO( "shared memory key: %d value: %s\n", tizen_base_port, (char*)shared_memory); -#elif defined(CONFIG_WIN32) - HANDLE hMapFile; - char* pBuf; - char* port_in_use; - char *shared_memory; - shared_memory = g_strdup_printf("%s", tizen_target_path); - port_in_use = g_strdup_printf("%d", tizen_base_port); - hMapFile = CreateFileMapping( - INVALID_HANDLE_VALUE, // use paging file - NULL, // default security - PAGE_READWRITE, // read/write access - 0, // maximum object size (high-order DWORD) - 50, // maximum object size (low-order DWORD) - port_in_use); // name of mapping object - if (hMapFile == NULL) - { - ERR("Could not create file mapping object (%d).\n", GetLastError()); - return; - } - pBuf = MapViewOfFile(hMapFile, // handle to map object - FILE_MAP_ALL_ACCESS, // read/write permission - 0, - 0, - 50); - - if (pBuf == NULL) - { - ERR("Could not map view of file (%d).\n", GetLastError()); - CloseHandle(hMapFile); - return; - } - - CopyMemory((PVOID)pBuf, shared_memory, strlen(shared_memory)); - free(port_in_use); - free(shared_memory); -#elif defined(CONFIG_DARWIN) - //TODO: -#endif - return; -} - - - -static void construct_main_window(int skin_argc, char* skin_argv[], int qemu_argc, char* qemu_argv[] ) -{ - INFO("construct main window\n"); - - start_skin_server( skin_argc, skin_argv, qemu_argc, qemu_argv ); - - if (get_emul_skin_enable() == 1) { //this line is check for debugging, etc.. - if ( 0 > start_skin_client(skin_argc, skin_argv) ) { - maru_register_exit_msg(MARU_EXIT_SKIN_SERVER_FAILED, NULL); - exit( -1 ); - } - } - - set_emul_caps_lock_state(0); - set_emul_num_lock_state(0); -} - -static void parse_options(int argc, char* argv[], int* skin_argc, char*** skin_argv, int* qemu_argc, char*** qemu_argv) -{ - int i; - int j; - -// FIXME !!! -// TODO: - - for(i = 1; i < argc; ++i) - { - if(strncmp(argv[i], "--skin-args", 11) == 0) - { - *skin_argv = &(argv[i + 1]); - break; - } - } - for(j = i; j < argc; ++j) - { - if(strncmp(argv[j], "--qemu-args", 11) == 0) - { - *skin_argc = j - i - 1; - - *qemu_argc = argc - j - i + 1; - *qemu_argv = &(argv[j]); - - argv[j] = argv[0]; - } - } -} - -static void get_bin_dir( char* exec_argv ) { - - if ( !exec_argv ) { - return; - } - - char* data = strdup( exec_argv ); - if ( !data ) { - fprintf( stderr, "Fail to strdup for paring a binary directory.\n" ); - return; - } - - char* p = NULL; -#ifdef _WIN32 - p = strrchr( data, '\\' ); - if ( !p ) { - p = strrchr( data, '/' ); - } -#else - p = strrchr( data, '/' ); -#endif - if ( !p ) { - free( data ); - return; - } - - strncpy( bin_dir, data, strlen( data ) - strlen( p ) ); - - free( data ); - -} - -void set_image_and_log_path(char* qemu_argv) -{ - int i; - int j = 0; - int name_len = 0; - int prefix_len = 0; - int suffix_len = 0; - int max = 0; - char *path = malloc(MAXLEN); - name_len = strlen(qemu_argv); - prefix_len = strlen(IMAGE_PATH_PREFIX); - suffix_len = strlen(IMAGE_PATH_SUFFIX); - max = name_len - suffix_len; - for(i = prefix_len , j = 0; i < max; i++) - { - path[j++] = qemu_argv[i]; - } - path[j] = '\0'; - if(!g_path_is_absolute(path)) - strcpy(tizen_target_path, g_get_current_dir()); - else - strcpy(tizen_target_path, g_path_get_dirname(path)); - - strcpy(logpath, tizen_target_path); - strcat(logpath, LOGS_SUFFIX); -#ifdef CONFIG_WIN32 - if(access(g_win32_locale_filename_from_utf8(logpath), R_OK) != 0) { - g_mkdir(g_win32_locale_filename_from_utf8(logpath), 0755); - } -#else - if(access(logpath, R_OK) != 0) { - g_mkdir(logpath, 0755); - } -#endif - strcat(logpath, LOGFILE); - set_log_path(logpath); -} - -void redir_output(void) -{ - FILE *fp; - - fp = freopen(logpath, "a+", stdout); - if(fp ==NULL) - fprintf(stderr, "log file open error\n"); - fp = freopen(logpath, "a+", stderr); - if(fp ==NULL) - fprintf(stderr, "log file open error\n"); - - setvbuf(stdout, NULL, _IOLBF, BUFSIZ); - setvbuf(stderr, NULL, _IOLBF, BUFSIZ); -} - -void extract_info(int qemu_argc, char** qemu_argv) -{ - int i; - - for(i = 0; i < qemu_argc; ++i) - { - if(strstr(qemu_argv[i], IMAGE_PATH_PREFIX) != NULL) { - set_image_and_log_path(qemu_argv[i]); - break; - } - } - - tizen_base_port = get_sdb_base_port(); -} - -static void system_info(void) -{ -#define DIV 1024 - - char timeinfo[64] = {0, }; - struct tm *tm_time; - struct timeval tval; - - INFO("* SDK Version : %s\n", build_version); - INFO("* Package %s\n", pkginfo_version); - INFO("* User name : %s\n", g_get_real_name()); - INFO("* Host name : %s\n", g_get_host_name()); - - /* timestamp */ - INFO("* Build date : %s\n", build_date); - gettimeofday(&tval, NULL); - tm_time = localtime(&(tval.tv_sec)); - strftime(timeinfo, sizeof(timeinfo), "%Y/%m/%d %H:%M:%S", tm_time); - INFO("* Current time : %s\n", timeinfo); - -#ifdef CONFIG_SDL - /* Gets the version of the dynamically linked SDL library */ - INFO("* Host sdl version : (%d, %d, %d)\n", - SDL_Linked_Version()->major, SDL_Linked_Version()->minor, SDL_Linked_Version()->patch); -#endif - -#if defined(CONFIG_WIN32) - /* Retrieves information about the current os */ - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - - if (GetVersionEx(&osvi)) { - INFO("* MajorVersion : %d, MinorVersion : %d, BuildNumber : %d, PlatformId : %d, CSDVersion : %s\n", - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, osvi.dwPlatformId, osvi.szCSDVersion); - } - - /* Retrieves information about the current system */ - SYSTEM_INFO sysi; - ZeroMemory(&sysi, sizeof(SYSTEM_INFO)); - - GetSystemInfo(&sysi); - INFO("* Processor type : %d, Number of processors : %d\n", sysi.dwProcessorType, sysi.dwNumberOfProcessors); - - MEMORYSTATUSEX memInfo; - memInfo.dwLength = sizeof(MEMORYSTATUSEX); - GlobalMemoryStatusEx(&memInfo); - INFO("* Total Ram : %llu kB, Free: %lld kB\n", - memInfo.ullTotalPhys / DIV, memInfo.ullAvailPhys / DIV); - -#elif defined(CONFIG_LINUX) - /* depends on building */ - INFO("* Qemu build machine linux kernel version : (%d, %d, %d)\n", - LINUX_VERSION_CODE >> 16, (LINUX_VERSION_CODE >> 8) & 0xff, LINUX_VERSION_CODE & 0xff); - - /* depends on launching */ - struct utsname host_uname_buf; - if (uname(&host_uname_buf) == 0) { - INFO("* Host machine uname : %s %s %s %s %s\n", host_uname_buf.sysname, host_uname_buf.nodename, - host_uname_buf.release, host_uname_buf.version, host_uname_buf.machine); - } - - struct sysinfo sys_info; - if (sysinfo(&sys_info) == 0) { - INFO("* Total Ram : %llu kB, Free: %llu kB\n", - sys_info.totalram * (unsigned long long)sys_info.mem_unit / DIV, - sys_info.freeram * (unsigned long long)sys_info.mem_unit / DIV); - } - - /* pci device description */ - INFO("* Pci devices :\n"); - char lscmd[MAXLEN] = "lspci >> "; - strcat(lscmd, logpath); - int i = system(lscmd); - INFO("system function command : %s, system function returned value : %d\n", lscmd, i); - -#elif defined(CONFIG_DARWIN) - //TODO: -#endif - - INFO("\n"); -} - -void prepare_maru(void) -{ - INFO("Prepare maru specified feature\n"); - - sdb_setup(); - - INFO("call construct_main_window\n"); - - construct_main_window(skin_argc, skin_argv, qemu_argc, qemu_argv); - - int guest_server_port = tizen_base_port + SDB_UDP_SENSOR_INDEX; - start_guest_server( guest_server_port ); - - mloop_ev_init(); -} - -int qemu_main(int argc, char** argv, char** envp); - -int main(int argc, char* argv[]) -{ - parse_options(argc, argv, &skin_argc, &skin_argv, &qemu_argc, &qemu_argv); - get_bin_dir( qemu_argv[0] ); - socket_init(); - extract_info(qemu_argc, qemu_argv); - - INFO("Emulator start !!!\n"); - - atexit(maru_atexit); - - check_shdmem(); - make_shdmem(); - - system_info(); - - INFO("Prepare running...\n"); - redir_output(); // Redirect stdout, stderr after debug_ch is initialized... - - int i; - - fprintf(stdout, "qemu args : ==========================================\n"); - for(i = 0; i < qemu_argc; ++i) - { - fprintf(stdout, "%s ", qemu_argv[i]); - } - fprintf(stdout, "\n"); - fprintf(stdout, "======================================================\n"); - - fprintf(stdout, "skin args : ==========================================\n"); - for(i = 0; i < skin_argc; ++i) - { - fprintf(stdout, "%s ", skin_argv[i]); - } - fprintf(stdout, "\n"); - fprintf(stdout, "======================================================\n"); - - INFO("qemu main start!\n"); - qemu_main(qemu_argc, qemu_argv, NULL); - - exit_emulator(); - - return 0; -} - +/* + * Emulator + * + * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * HyunJun Son + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + +#include +#include +#include "maru_common.h" +#include "emulator.h" +#include "sdb.h" +#include "string.h" +#include "skin/maruskin_server.h" +#include "skin/maruskin_client.h" +#include "guest_server.h" +#include "debug_ch.h" +#include "option.h" +#include "emul_state.h" +#include "qemu_socket.h" +#include "build_info.h" +#include "maru_err_table.h" +#include +#include + +#if defined( _WIN32) +#include +#elif defined(__linux__) +#include +#include +#include +#include +#include + +#endif + +#include "mloop_event.h" + +MULTI_DEBUG_CHANNEL(qemu, main); + + +#define IMAGE_PATH_PREFIX "file=" +#define IMAGE_PATH_SUFFIX ",if=virtio" +#define SDB_PORT_PREFIX "sdb_port=" +#define LOGS_SUFFIX "/logs/" +#define LOGFILE "emulator.log" +#define MIDBUF 128 +int tizen_base_port = 0; +static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER; +char tizen_target_path[MAXLEN] = {0, }; +char logpath[MAXLEN] = { 0, }; + +static int skin_argc = 0; +static char** skin_argv = NULL; +static int qemu_argc = 0; +static char** qemu_argv = NULL; + +extern void maruskin_sdl_quit(void); +void exit_emulator(void) +{ + cleanup_multi_touch_state(); + + mloop_ev_stop(); + shutdown_skin_server(); + shutdown_guest_server(); + + maruskin_sdl_quit(); +} + +void check_shdmem(void) +{ +#ifndef CONFIG_WIN32 + int shm_id; + void *shm_addr; + u_int port; + int val; + struct shmid_ds shm_info; + + for(port=26100;port < 26200; port += 10) + { + if ( -1 != ( shm_id = shmget( (key_t)port, 0, 0))) + { + if((void *)-1 == (shm_addr = shmat(shm_id, (void *)0, 0))) + { + ERR( "error occured at shmat()\n"); + break; + } + + val = shmctl(shm_id, IPC_STAT, &shm_info); + if(val != -1) + { + INFO( "count of process that use shared memory : %d\n", shm_info.shm_nattch); + if(shm_info.shm_nattch > 0 && strcmp(tizen_target_path, (char*)shm_addr) == 0) + { + if(check_port_bind_listen(port+1) > 0){ + shmdt(shm_addr); + continue; + } + shmdt(shm_addr); + maru_register_exit_msg(MARU_EXIT_UNKNOWN, (char*)"Can not execute this VM.\nThe same name is running now."); + exit(0); + } + else{ + shmdt(shm_addr); + } + } + } + } + +#else /* _WIN32*/ + u_int port; + char* base_port = NULL; + char* pBuf; + HANDLE hMapFile; + for(port=26100;port < 26200; port += 10) + { + base_port = g_strdup_printf("%d", port); + hMapFile = OpenFileMapping( + FILE_MAP_READ, + TRUE, + base_port); + if(hMapFile == NULL) + { + INFO("port %s is not used.\n", base_port); + continue; + } + else + { + pBuf = (char*)MapViewOfFile(hMapFile, + FILE_MAP_READ, + 0, + 0, + 50); + if (pBuf == NULL) + { + ERR("Could not map view of file (%d).\n", GetLastError()); + CloseHandle(hMapFile); + } + + if(strcmp(pBuf, tizen_target_path) == 0) + { + /* + if(check_port_bind_listen(port+1) > 0) + { + UnmapViewOfFile(pBuf); + CloseHandle(hMapFile); + continue; + } + */ + maru_register_exit_msg(MARU_EXIT_UNKNOWN, "Can not execute this VM.\nThe same name is running now."); + UnmapViewOfFile(pBuf); + CloseHandle(hMapFile); + free(base_port); + exit(0); + } + else + UnmapViewOfFile(pBuf); + } + + CloseHandle(hMapFile); + free(base_port); + } +#endif +} + +void make_shdmem(void) +{ +#ifndef _WIN32 + int shmid; + char *shared_memory; + shmid = shmget((key_t)tizen_base_port, MAXLEN, 0666|IPC_CREAT); + if (shmid == -1) + { + ERR("shmget failed\n"); + return; + } + shared_memory = shmat(shmid, (char*)0x00, 0); + if (shared_memory == (void *)-1) + { + ERR("shmat failed\n"); + return; + } + sprintf(shared_memory, "%s", tizen_target_path); + INFO( "shared memory key: %d value: %s\n", tizen_base_port, (char*)shared_memory); +#else + HANDLE hMapFile; + char* pBuf; + char* port_in_use; + char *shared_memory; + shared_memory = g_strdup_printf("%s", tizen_target_path); + port_in_use = g_strdup_printf("%d", tizen_base_port); + hMapFile = CreateFileMapping( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // maximum object size (high-order DWORD) + 50, // maximum object size (low-order DWORD) + port_in_use); // name of mapping object + if (hMapFile == NULL) + { + ERR("Could not create file mapping object (%d).\n", GetLastError()); + return; + } + pBuf = MapViewOfFile(hMapFile, // handle to map object + FILE_MAP_ALL_ACCESS, // read/write permission + 0, + 0, + 50); + + if (pBuf == NULL) + { + ERR("Could not map view of file (%d).\n", GetLastError()); + CloseHandle(hMapFile); + return; + } + + CopyMemory((PVOID)pBuf, shared_memory, strlen(shared_memory)); + free(port_in_use); + free(shared_memory); +#endif + return; +} + + + +static void construct_main_window(int skin_argc, char* skin_argv[], int qemu_argc, char* qemu_argv[] ) +{ + INFO("construct main window\n"); + + start_skin_server( skin_argc, skin_argv, qemu_argc, qemu_argv ); + + if (get_emul_skin_enable() == 1) { //this line is check for debugging, etc.. + if ( 0 > start_skin_client(skin_argc, skin_argv) ) { + maru_register_exit_msg(MARU_EXIT_SKIN_SERVER_FAILED, NULL); + exit( -1 ); + } + } + + set_emul_caps_lock_state(0); + set_emul_num_lock_state(0); +} + +static void parse_options(int argc, char* argv[], int* skin_argc, char*** skin_argv, int* qemu_argc, char*** qemu_argv) +{ + int i; + int j; + +// FIXME !!! +// TODO: + + for(i = 1; i < argc; ++i) + { + if(strncmp(argv[i], "--skin-args", 11) == 0) + { + *skin_argv = &(argv[i + 1]); + break; + } + } + for(j = i; j < argc; ++j) + { + if(strncmp(argv[j], "--qemu-args", 11) == 0) + { + *skin_argc = j - i - 1; + + *qemu_argc = argc - j - i + 1; + *qemu_argv = &(argv[j]); + + argv[j] = argv[0]; + } + } +} + +static void get_bin_dir( char* exec_argv ) { + + if ( !exec_argv ) { + return; + } + + char* data = strdup( exec_argv ); + if ( !data ) { + fprintf( stderr, "Fail to strdup for paring a binary directory.\n" ); + return; + } + + char* p = NULL; +#ifdef _WIN32 + p = strrchr( data, '\\' ); + if ( !p ) { + p = strrchr( data, '/' ); + } +#else + p = strrchr( data, '/' ); +#endif + if ( !p ) { + free( data ); + return; + } + + strncpy( bin_dir, data, strlen( data ) - strlen( p ) ); + + free( data ); + +} + +void set_image_and_log_path(char* qemu_argv) +{ + int i; + int j = 0; + int name_len = 0; + int prefix_len = 0; + int suffix_len = 0; + int max = 0; + char *path = malloc(MAXLEN); + name_len = strlen(qemu_argv); + prefix_len = strlen(IMAGE_PATH_PREFIX); + suffix_len = strlen(IMAGE_PATH_SUFFIX); + max = name_len - suffix_len; + for(i = prefix_len , j = 0; i < max; i++) + { + path[j++] = qemu_argv[i]; + } + path[j] = '\0'; + if(!g_path_is_absolute(path)) + strcpy(tizen_target_path, g_get_current_dir()); + else + strcpy(tizen_target_path, g_path_get_dirname(path)); + + strcpy(logpath, tizen_target_path); + strcat(logpath, LOGS_SUFFIX); +#ifdef _WIN32 + if(access(g_win32_locale_filename_from_utf8(logpath), R_OK) != 0) { + g_mkdir(g_win32_locale_filename_from_utf8(logpath), 0755); + } +#else + if(access(logpath, R_OK) != 0) { + g_mkdir(logpath, 0755); + } +#endif + strcat(logpath, LOGFILE); + set_log_path(logpath); +} + +void redir_output(void) +{ + FILE *fp; + + fp = freopen(logpath, "a+", stdout); + if(fp ==NULL) + fprintf(stderr, "log file open error\n"); + fp = freopen(logpath, "a+", stderr); + if(fp ==NULL) + fprintf(stderr, "log file open error\n"); + + setvbuf(stdout, NULL, _IOLBF, BUFSIZ); + setvbuf(stderr, NULL, _IOLBF, BUFSIZ); +} + +void extract_info(int qemu_argc, char** qemu_argv) +{ + int i; + + for(i = 0; i < qemu_argc; ++i) + { + if(strstr(qemu_argv[i], IMAGE_PATH_PREFIX) != NULL) { + set_image_and_log_path(qemu_argv[i]); + break; + } + } + + tizen_base_port = get_sdb_base_port(); +} + +static void system_info(void) +{ +#define DIV 1024 + + char timeinfo[64] = {0, }; + struct tm *tm_time; + struct timeval tval; + + INFO("* SDK Version : %s\n", build_version); + INFO("* Package %s\n", pkginfo_version); + INFO("* User name : %s\n", g_get_real_name()); + INFO("* Host name : %s\n", g_get_host_name()); + + /* timestamp */ + INFO("* Build date : %s\n", build_date); + gettimeofday(&tval, NULL); + tm_time = localtime(&(tval.tv_sec)); + strftime(timeinfo, sizeof(timeinfo), "%Y/%m/%d %H:%M:%S", tm_time); + INFO("* Current time : %s\n", timeinfo); + + /* Gets the version of the dynamically linked SDL library */ + INFO("* Host sdl version : (%d, %d, %d)\n", + SDL_Linked_Version()->major, SDL_Linked_Version()->minor, SDL_Linked_Version()->patch); + +#if defined(CONFIG_WIN32) + /* Retrieves information about the current os */ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + if (GetVersionEx(&osvi)) { + INFO("* MajorVersion : %d, MinorVersion : %d, BuildNumber : %d, PlatformId : %d, CSDVersion : %s\n", + osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, osvi.dwPlatformId, osvi.szCSDVersion); + } + + /* Retrieves information about the current system */ + SYSTEM_INFO sysi; + ZeroMemory(&sysi, sizeof(SYSTEM_INFO)); + + GetSystemInfo(&sysi); + INFO("* Processor type : %d, Number of processors : %d\n", sysi.dwProcessorType, sysi.dwNumberOfProcessors); + + MEMORYSTATUSEX memInfo; + memInfo.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&memInfo); + INFO("* Total Ram : %llu kB, Free: %lld kB\n", + memInfo.ullTotalPhys / DIV, memInfo.ullAvailPhys / DIV); + +#elif defined(CONFIG_LINUX) + /* depends on building */ + INFO("* Qemu build machine linux kernel version : (%d, %d, %d)\n", + LINUX_VERSION_CODE >> 16, (LINUX_VERSION_CODE >> 8) & 0xff, LINUX_VERSION_CODE & 0xff); + + /* depends on launching */ + struct utsname host_uname_buf; + if (uname(&host_uname_buf) == 0) { + INFO("* Host machine uname : %s %s %s %s %s\n", host_uname_buf.sysname, host_uname_buf.nodename, + host_uname_buf.release, host_uname_buf.version, host_uname_buf.machine); + } + + struct sysinfo sys_info; + if (sysinfo(&sys_info) == 0) { + INFO("* Total Ram : %llu kB, Free: %llu kB\n", + sys_info.totalram * (unsigned long long)sys_info.mem_unit / DIV, + sys_info.freeram * (unsigned long long)sys_info.mem_unit / DIV); + } + + /* pci device description */ + INFO("* Pci devices :\n"); + char lscmd[MAXLEN] = "lspci >> "; + strcat(lscmd, logpath); + int i = system(lscmd); + INFO("system function command : %s, system function returned value : %d\n", lscmd, i); + +#elif defined(CONFIG_DARWIN) + //TODO: +#endif + + INFO("\n"); +} + +void prepare_maru(void) +{ + INFO("Prepare maru specified feature\n"); + + INFO("call construct_main_window\n"); + + construct_main_window(skin_argc, skin_argv, qemu_argc, qemu_argv); + + int guest_server_port = tizen_base_port + SDB_UDP_SENSOR_INDEX; + start_guest_server( guest_server_port ); + + mloop_ev_init(); +} + +int qemu_main(int argc, char** argv, char** envp); + +int main(int argc, char* argv[]) +{ + parse_options(argc, argv, &skin_argc, &skin_argv, &qemu_argc, &qemu_argv); + get_bin_dir( qemu_argv[0] ); + socket_init(); + extract_info(qemu_argc, qemu_argv); + + INFO("Emulator start !!!\n"); + + atexit(maru_atexit); + + check_shdmem(); + make_shdmem(); + sdb_setup(); + + system_info(); + + INFO("Prepare running...\n"); + redir_output(); // Redirect stdout, stderr after debug_ch is initialized... + + int i; + + fprintf(stdout, "qemu args : ==========================================\n"); + for(i = 0; i < qemu_argc; ++i) + { + fprintf(stdout, "%s ", qemu_argv[i]); + } + fprintf(stdout, "\n"); + fprintf(stdout, "======================================================\n"); + + fprintf(stdout, "skin args : ==========================================\n"); + for(i = 0; i < skin_argc; ++i) + { + fprintf(stdout, "%s ", skin_argv[i]); + } + fprintf(stdout, "\n"); + fprintf(stdout, "======================================================\n"); + + INFO("qemu main start!\n"); + qemu_main(qemu_argc, qemu_argv, NULL); + + exit_emulator(); + + return 0; +} + diff --git a/tizen/src/sdb.c b/tizen/src/sdb.c index 4291fdd..7c040ae 100644 --- a/tizen/src/sdb.c +++ b/tizen/src/sdb.c @@ -1,369 +1,368 @@ -/* Copyright (C) 2006-2010 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -*/ - - -#ifdef _WIN32 -#include -#include -#include -#else /* !_WIN32 */ -#include -#include -#include -#include -#include -#endif /* !_WIN32 */ - -#include "net/slirp.h" -#include "qemu_socket.h" -#include "sdb.h" -#include "nbd.h" -#include "tizen/src/debug_ch.h" - -//DEFAULT_DEBUG_CHANNEL(qemu); -MULTI_DEBUG_CHANNEL(qemu, sdb); - -/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty - * easily in QEMU since we use SIGALRM to implement periodic timers - */ - -#ifdef _WIN32 -# define QSOCKET_CALL(_ret,_cmd) \ - do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR ) -#else -# define QSOCKET_CALL(_ret,_cmd) \ - do { \ - errno = 0; \ - do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \ - } while (0); -#endif - -#ifdef _WIN32 - -#include - -static int winsock_error; - -#define WINSOCK_ERRORS_LIST \ - EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \ -EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \ -EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \ -EE(WSAEINTR,EINTR,"interrupted function call") \ -EE(WSAEALREADY,EALREADY,"operation already in progress") \ -EE(WSAEBADF,EBADF,"bad file descriptor") \ -EE(WSAEACCES,EACCES,"permission denied") \ -EE(WSAEFAULT,EFAULT,"bad address") \ -EE(WSAEINVAL,EINVAL,"invalid argument") \ -EE(WSAEMFILE,EMFILE,"too many opened files") \ -EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \ -EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \ -EE(WSAEALREADY,EAGAIN,"operation already in progress") \ -EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \ -EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \ -EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \ -EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \ -EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \ -EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \ -EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \ -EE(WSAENETDOWN,ENETDOWN,"network is down") \ -EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \ -EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \ -EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \ -EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \ -EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \ -EE(WSAEISCONN,EISCONN,"socket is already connected") \ -EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \ -EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \ -EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \ -EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \ -EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \ -EE(WSAELOOP,ELOOP,"cannot translate name") \ -EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \ -EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \ -EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \ - -typedef struct { - int winsock; - int unix; - const char* string; -} WinsockError; - -static const WinsockError _winsock_errors[] = { -#define EE(w,u,s) { w, u, s }, - WINSOCK_ERRORS_LIST -#undef EE - { -1, -1, NULL } -}; - -/* this function reads the latest winsock error code and updates - * errno to a matching value. It also returns the new value of - * errno. - */ -static int _fix_errno( void ) -{ - const WinsockError* werr = _winsock_errors; - int unix = EINVAL; /* generic error code */ - - winsock_error = WSAGetLastError(); - - for ( ; werr->string != NULL; werr++ ) { - if (werr->winsock == winsock_error) { - unix = werr->unix; - break; - } - } - errno = unix; - return -1; -} - -#else -static int _fix_errno( void ) -{ - return -1; -} - -#endif - -#define SOCKET_CALL(cmd) \ - int ret; \ -QSOCKET_CALL(ret, (cmd)); \ -if (ret < 0) \ -return _fix_errno(); \ -return ret; \ - -int socket_send(int fd, const void* buf, int buflen) -{ - SOCKET_CALL(send(fd, buf, buflen, 0)) -} - -#ifdef _WIN32 - - static void -socket_close_handler( void* _fd ) -{ - int fd = (int)_fd; - int ret; - char buff[64]; - - /* we want to drain the read side of the socket before closing it */ - do { - ret = recv( fd, buff, sizeof(buff), 0 ); - } while (ret < 0 && WSAGetLastError() == WSAEINTR); - - if (ret < 0 && WSAGetLastError() == EWOULDBLOCK) - return; - - qemu_set_fd_handler( fd, NULL, NULL, NULL ); - closesocket( fd ); -} - - void -socket_close( int fd ) -{ - int old_errno = errno; - - shutdown( fd, SD_BOTH ); - /* we want to drain the socket before closing it */ - qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd ); - - errno = old_errno; -} - -#else /* !_WIN32 */ - -#include - - void -socket_close( int fd ) -{ - int old_errno = errno; - - shutdown( fd, SHUT_RDWR ); - close( fd ); - - errno = old_errno; -} - -#endif /* !_WIN32 */ - -int inet_strtoip(const char* str, uint32_t *ip) -{ - int comp[4]; - - if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4) - return -1; - - if ((unsigned)comp[0] >= 256 || - (unsigned)comp[1] >= 256 || - (unsigned)comp[2] >= 256 || - (unsigned)comp[3] >= 256) - return -1; - - *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) | - (comp[2] << 8) | comp[3]); - return 0; -} - -static int check_port_bind_listen(u_int port) -{ - struct sockaddr_in addr; - int s, opt = 1; - int ret = -1; - socklen_t addrlen = sizeof(addr); - memset(&addr, 0, addrlen); - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(port); - - if (((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0) || -#ifndef _WIN32 - (setsockopt(s, SOL_SOCKET,SO_REUSEADDR, (char *)&opt, sizeof(int)) < 0) || -#endif - (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) || - (listen(s, 1) < 0)) { - - /* fail */ - ret = -1; - ERR( "port(%d) listen fail \n", port); - }else{ - /*fsucess*/ - ret = 1; - INFO( "port(%d) listen ok \n", port); - } - -#ifdef _WIN32 - closesocket(s); -#else - close(s); -#endif - - return ret; -} - -int get_sdb_base_port(void) -{ - int tries = 10; - int success = 0; - u_int port = 26100; - - if(tizen_base_port == 0){ - - for ( ; tries > 0; tries--, port += 10 ) { - if(check_port_bind_listen(port + 1) < 0 ) - continue; - - success = 1; - break; - } - - if (!success) { - ERR( "it seems too many emulator instances are running on this machine. Aborting\n" ); - exit(1); - } - - tizen_base_port = port; - INFO( "sdb port is %d \n", tizen_base_port); - } - - return tizen_base_port; -} - -void sdb_setup(void) -{ - int tries = 10; - int success = 0; - uint32_t guest_ip; - char buf[64] = {0,}; - - inet_strtoip("10.0.2.16", &guest_ip); - - for ( ; tries > 0; tries--, tizen_base_port += 10 ) { - // redir form [tcp:26101:10.0.2.16:26101] - sprintf(buf, "tcp:%d:10.0.2.16:26101", tizen_base_port + 1); - if(net_slirp_redir((char*)buf) < 0) - continue; - - INFO( "SDBD established on port %d\n", tizen_base_port + 1); - success = 1; - break; - } - - INFO("redirect [%s] success\n", buf); - if (!success) { - ERR( "it seems too many emulator instances are running on this machine. Aborting\n" ); - exit(1); - } - - INFO( "Port(%d/tcp) listen for SDB \n", tizen_base_port + 1); - - /* for sensort */ - sprintf(buf, "tcp:%d:10.0.2.16:3577", tizen_base_port + SDB_TCP_EMULD_INDEX ); - if(net_slirp_redir((char*)buf) < 0){ - ERR( "redirect [%s] fail \n", buf); - }else{ - INFO("redirect [%s] success\n", buf); - } -} - -int sdb_loopback_client(int port, int type) -{ - struct sockaddr_in addr; - int s; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket(AF_INET, type, 0); - if(s < 0) return -1; - - if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - close(s); - return -1; - } - - return s; - -} - -void notify_sdb_daemon_start(void) { - int s; - /* - * send a simple message to the SDB host server to tell it we just started. - * it should be listening on port 26099. - */ - do { - char tmp[32] = { 0 }; - - // when connecting to loopback:26099, do not use tcp_socket_outgoing function - // tcp_socket_outgoing may occur "dns name service not known" in case of network unavaliable status. - s = sdb_loopback_client(SDB_HOST_PORT, SOCK_STREAM); - if (s < 0) { - INFO("can't create socket to talk to the SDB server \n"); - INFO("This emulator will be scaned by the SDB server \n"); - break; - } - - /* length is hex: 0x13 = 19 */ - sprintf(tmp, "0013host:emulator:%d", tizen_base_port + 1); - - if (socket_send(s, tmp, 30) < 0) { - ERR( "message sending to sdb server error!\n"); - } - - } while (0); - - if (s >= 0) - socket_close(s); -} +/* Copyright (C) 2006-2010 The Android Open Source Project +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +*/ + + +#ifdef _WIN32 +#include +#include +#include +#else /* !_WIN32 */ +#include +#include +#include +#include +#include +#endif /* !_WIN32 */ + +#include "net/slirp.h" +#include "qemu_socket.h" +#include "sdb.h" +#include "nbd.h" +#include "tizen/src/debug_ch.h" + +//DEFAULT_DEBUG_CHANNEL(qemu); +MULTI_DEBUG_CHANNEL(qemu, sdb); + +/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty + * easily in QEMU since we use SIGALRM to implement periodic timers + */ + +#ifdef _WIN32 +# define QSOCKET_CALL(_ret,_cmd) \ + do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR ) +#else +# define QSOCKET_CALL(_ret,_cmd) \ + do { \ + errno = 0; \ + do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \ + } while (0); +#endif + +#ifdef _WIN32 + +#include + +static int winsock_error; + +#define WINSOCK_ERRORS_LIST \ + EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \ +EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \ +EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \ +EE(WSAEINTR,EINTR,"interrupted function call") \ +EE(WSAEALREADY,EALREADY,"operation already in progress") \ +EE(WSAEBADF,EBADF,"bad file descriptor") \ +EE(WSAEACCES,EACCES,"permission denied") \ +EE(WSAEFAULT,EFAULT,"bad address") \ +EE(WSAEINVAL,EINVAL,"invalid argument") \ +EE(WSAEMFILE,EMFILE,"too many opened files") \ +EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \ +EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \ +EE(WSAEALREADY,EAGAIN,"operation already in progress") \ +EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \ +EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \ +EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \ +EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \ +EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \ +EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \ +EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \ +EE(WSAENETDOWN,ENETDOWN,"network is down") \ +EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \ +EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \ +EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \ +EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \ +EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \ +EE(WSAEISCONN,EISCONN,"socket is already connected") \ +EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \ +EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \ +EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \ +EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \ +EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \ +EE(WSAELOOP,ELOOP,"cannot translate name") \ +EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \ +EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \ +EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \ + +typedef struct { + int winsock; + int unix; + const char* string; +} WinsockError; + +static const WinsockError _winsock_errors[] = { +#define EE(w,u,s) { w, u, s }, + WINSOCK_ERRORS_LIST +#undef EE + { -1, -1, NULL } +}; + +/* this function reads the latest winsock error code and updates + * errno to a matching value. It also returns the new value of + * errno. + */ +static int _fix_errno( void ) +{ + const WinsockError* werr = _winsock_errors; + int unix = EINVAL; /* generic error code */ + + winsock_error = WSAGetLastError(); + + for ( ; werr->string != NULL; werr++ ) { + if (werr->winsock == winsock_error) { + unix = werr->unix; + break; + } + } + errno = unix; + return -1; +} + +#else +static int _fix_errno( void ) +{ + return -1; +} + +#endif + +#define SOCKET_CALL(cmd) \ + int ret; \ +QSOCKET_CALL(ret, (cmd)); \ +if (ret < 0) \ +return _fix_errno(); \ +return ret; \ + +int socket_send(int fd, const void* buf, int buflen) +{ + SOCKET_CALL(send(fd, buf, buflen, 0)) +} + +#ifdef _WIN32 + + static void +socket_close_handler( void* _fd ) +{ + int fd = (int)_fd; + int ret; + char buff[64]; + + /* we want to drain the read side of the socket before closing it */ + do { + ret = recv( fd, buff, sizeof(buff), 0 ); + } while (ret < 0 && WSAGetLastError() == WSAEINTR); + + if (ret < 0 && WSAGetLastError() == EWOULDBLOCK) + return; + + qemu_set_fd_handler( fd, NULL, NULL, NULL ); + closesocket( fd ); +} + + void +socket_close( int fd ) +{ + int old_errno = errno; + + shutdown( fd, SD_BOTH ); + /* we want to drain the socket before closing it */ + qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd ); + + errno = old_errno; +} + +#else /* !_WIN32 */ + +#include + + void +socket_close( int fd ) +{ + int old_errno = errno; + + shutdown( fd, SHUT_RDWR ); + close( fd ); + + errno = old_errno; +} + +#endif /* !_WIN32 */ + +int inet_strtoip(const char* str, uint32_t *ip) +{ + int comp[4]; + + if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4) + return -1; + + if ((unsigned)comp[0] >= 256 || + (unsigned)comp[1] >= 256 || + (unsigned)comp[2] >= 256 || + (unsigned)comp[3] >= 256) + return -1; + + *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) | + (comp[2] << 8) | comp[3]); + return 0; +} + +static int check_port_bind_listen(u_int port) +{ + struct sockaddr_in addr; + int s, opt = 1; + int ret = -1; + socklen_t addrlen = sizeof(addr); + memset(&addr, 0, addrlen); + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(port); + + if (((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0) || +#ifndef _WIN32 + (setsockopt(s, SOL_SOCKET,SO_REUSEADDR, (char *)&opt, sizeof(int)) < 0) || +#endif + (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) || + (listen(s, 1) < 0)) { + + /* fail */ + ret = -1; + ERR( "port(%d) listen fail \n", port); + }else{ + /*fsucess*/ + ret = 1; + INFO( "port(%d) listen ok \n", port); + } + +#ifdef _WIN32 + closesocket(s); +#else + close(s); +#endif + + return ret; +} + +int get_sdb_base_port(void) +{ + int tries = 10; + int success = 0; + u_int port = 26100; + + if(tizen_base_port == 0){ + + for ( ; tries > 0; tries--, port += 10 ) { + if(check_port_bind_listen(port + 1) < 0 ) + continue; + + success = 1; + break; + } + + if (!success) { + ERR( "it seems too many emulator instances are running on this machine. Aborting\n" ); + exit(1); + } + + tizen_base_port = port; + INFO( "sdb port is %d \n", tizen_base_port); + } + + return tizen_base_port; +} + +void sdb_setup(void) +{ + int tries = 10; + int success = 0; + uint32_t guest_ip; + char buf[64] = {0,}; + inet_strtoip("10.0.2.16", &guest_ip); + + for ( ; tries > 0; tries--, tizen_base_port += 10 ) { + // redir form [tcp:26101:10.0.2.16:26101] + sprintf(buf, "tcp:%d:10.0.2.16:26101", tizen_base_port + 1); + if(net_slirp_redir((char*)buf) < 0) + continue; + + INFO( "SDBD established on port %d\n", tizen_base_port + 1); + success = 1; + break; + } + + INFO("redirect [%s] success\n", buf); + if (!success) { + ERR( "it seems too many emulator instances are running on this machine. Aborting\n" ); + exit(1); + } + + INFO( "Port(%d/tcp) listen for SDB \n", tizen_base_port + 1); + + /* for sensort */ + sprintf(buf, "tcp:%d:10.0.2.16:3577", tizen_base_port + SDB_TCP_EMULD_INDEX ); + if(net_slirp_redir((char*)buf) < 0){ + ERR( "redirect [%s] fail \n", buf); + }else{ + INFO("redirect [%s] success\n", buf); + } +} + +int sdb_loopback_client(int port, int type) +{ + struct sockaddr_in addr; + int s; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + s = socket(AF_INET, type, 0); + if(s < 0) return -1; + + if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + close(s); + return -1; + } + + return s; + +} + +void notify_sdb_daemon_start(void) { + int s; + /* + * send a simple message to the SDB host server to tell it we just started. + * it should be listening on port 26099. + */ + do { + char tmp[32] = { 0 }; + + // when connecting to loopback:26099, do not use tcp_socket_outgoing function + // tcp_socket_outgoing may occur "dns name service not known" in case of network unavaliable status. + s = sdb_loopback_client(SDB_HOST_PORT, SOCK_STREAM); + if (s < 0) { + INFO("can't create socket to talk to the SDB server \n"); + INFO("This emulator will be scaned by the SDB server \n"); + break; + } + + /* length is hex: 0x13 = 19 */ + sprintf(tmp, "0013host:emulator:%d", tizen_base_port + 1); + + if (socket_send(s, tmp, 30) < 0) { + ERR( "message sending to sdb server error!\n"); + } + + } while (0); + + if (s >= 0) + socket_close(s); +} -- 2.7.4