From: SeokYeon Hwang Date: Mon, 4 Jan 2016 10:28:26 +0000 (+0900) Subject: emulator: clean-up emulator network initialization X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.2~108 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=346ee8b1ee5cccd871ba7bc2c0a78c4e98d88748;p=sdk%2Femulator%2Fqemu.git emulator: clean-up emulator network initialization Do port forwarding and base port initialization at once. Some emul_state getters/setters are refined. "sdb.c" is "net_helper.c" now and it use new_debug_channel. Change-Id: I0659b35e231a8f60bd3707a2d04b09213a9cb830 Signed-off-by: SeokYeon Hwang Signed-off-by: Jinhyung Choi --- diff --git a/include/net/slirp.h b/include/net/slirp.h index 64b795cda9..89f871a604 100644 --- a/include/net/slirp.h +++ b/include/net/slirp.h @@ -42,6 +42,12 @@ int net_slirp_smb(const char *exported_dir); void hmp_info_usernet(Monitor *mon, const QDict *qdict); +#ifdef CONFIG_MARU +bool hostfwd_try_add(int is_udp, const char *host_addr_str, + int host_port, const char *guest_addr_str, int guest_port); +bool hostfwd_try_remove(int is_udp, const char *host_addr_str, int host_port); +#endif + #endif #endif /* QEMU_NET_SLIRP_H */ diff --git a/net/slirp.c b/net/slirp.c index f505570adb..7cf1eeb764 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -275,6 +275,56 @@ error: return -1; } +#ifdef CONFIG_MARU +bool hostfwd_try_add(int is_udp, const char *host_addr_str, + int host_port, const char *guest_addr_str, int guest_port) +{ + if (QTAILQ_EMPTY(&slirp_stacks)) { + return false; + } + + SlirpState *s = QTAILQ_FIRST(&slirp_stacks); + struct in_addr host_addr = { .s_addr = INADDR_ANY }; + struct in_addr guest_addr = { .s_addr = 0 }; + + if ((host_addr_str && !inet_aton(host_addr_str, &host_addr)) || + (guest_addr_str && !inet_aton(guest_addr_str, &guest_addr))) { + error_report("invalid host forwarding rule '%s' '%s", + host_addr_str, guest_addr_str); + return false; + } + + if (slirp_add_hostfwd(s->slirp, is_udp, host_addr, host_port, guest_addr, + guest_port) < 0) { + return false; + } + + return true; +} + +bool hostfwd_try_remove(int is_udp, const char *host_addr_str, int host_port) +{ + if (QTAILQ_EMPTY(&slirp_stacks)) { + return false; + } + + SlirpState *s = QTAILQ_FIRST(&slirp_stacks); + struct in_addr host_addr = { .s_addr = INADDR_ANY }; + + if (host_addr_str && !inet_aton(host_addr_str, &host_addr)) { + error_report("invalid host forwarding rule '%s", + host_addr_str); + return false; + } + + if (slirp_remove_hostfwd(s->slirp, is_udp, host_addr, host_port) < 0) { + return false; + } + + return true; +} +#endif + static SlirpState *slirp_lookup(Monitor *mon, const char *vlan, const char *stack) { diff --git a/tizen/src/ecs/ecs.c b/tizen/src/ecs/ecs.c index 05e27661d8..663d7f89ed 100644 --- a/tizen/src/ecs/ecs.c +++ b/tizen/src/ecs/ecs.c @@ -46,7 +46,7 @@ #include "qapi/qmp/qint.h" #include "emulator.h" -#include "util/sdb.h" +#include "util/net_helper.h" #include "ecs.h" #include "emul_state.h" @@ -635,6 +635,7 @@ static int ecs_loop(ECS_State *cs) static int socket_initialize(ECS_State *cs) { LOG_INFO("Listen fd is %d\n", emul_vm_base_socket); + g_assert(emul_vm_base_socket >= 0); cs->listen_fd = emul_vm_base_socket; diff --git a/tizen/src/ecs/ecs_msg_injector.c b/tizen/src/ecs/ecs_msg_injector.c index 199781c23c..84a27971cd 100644 --- a/tizen/src/ecs/ecs_msg_injector.c +++ b/tizen/src/ecs/ecs_msg_injector.c @@ -317,7 +317,7 @@ static bool push_package(const char* data) #else ret = sprintf(cmd, "cmd /S /C \"\"%s%s\" -s emulator-%d push \"%s%s%s%s%s\" /opt/usr/apps/tmp/sdk_tools/%s 2>&1\"", #endif - bin_dir, sdb_path, get_device_serial_number(), + bin_dir, sdb_path, get_vm_device_serial_number(), bin_dir, platform_path, get_profile_name(), addon_path, addon, addon); if (ret < 0) { diff --git a/tizen/src/emul_state.c b/tizen/src/emul_state.c index 6772eeb876..3962298767 100644 --- a/tizen/src/emul_state.c +++ b/tizen/src/emul_state.c @@ -57,12 +57,14 @@ extern bool hax_allowed; #include "emulator_options.h" #include "hw/virtio/maru_virtio_touchscreen.h" #include "hw/virtio/maru_virtio_evdi.h" -#include "util/new_debug_ch.h" +#include "util/net_helper.h" #ifdef CONFIG_JAVA_UI #include "skin/maruskin_server.h" #endif +#include "util/new_debug_ch.h" + DECLARE_DEBUG_CHANNEL(emul_state); #define MAXLEN 512 @@ -134,50 +136,6 @@ int get_max_touch_point(void) } } -/* base port for emualtor vm */ -void set_emul_vm_base_port(int port) -{ - _emul_info.vm_base_port = port; - if (is_netclient_tap_attached()) { - _emul_info.device_serial_number = 26101; - } else { - _emul_info.device_serial_number = port + 1; - } - _emul_info.ecs_port = port + 3; - _emul_info.serial_port = port + 4; - _emul_info.spice_port = port + 5; -} - -int get_emul_spice_port(void) -{ - return _emul_info.spice_port; -} - -void set_emul_ecs_port(int port) -{ - _emul_info.ecs_port = port; -} - -int get_emul_vm_base_port(void) -{ - return _emul_info.vm_base_port; -} - -int get_device_serial_number(void) -{ - return _emul_info.device_serial_number; -} - -int get_emul_ecs_port(void) -{ - return _emul_info.ecs_port; -} - -int get_emul_serial_port(void) -{ - return _emul_info.serial_port; -} - /* current emulator condition */ int get_emulator_condition(void) { @@ -661,6 +619,42 @@ uint64_t get_ram_size(void) return ram_size; } +// VM base port +static int vm_base_port = 0; + +void set_vm_base_port(int port) +{ + vm_base_port = port; +} + +int get_vm_base_port(void) +{ + // should not be called before base port is prepared + g_assert(vm_base_port != 0); + + return vm_base_port; +} + +int get_vm_spice_port(void) +{ + // should not be called before base port is prepared + g_assert(vm_base_port != 0); + + return vm_base_port + SPICE_TCP_INDEX; +} + +int get_vm_device_serial_number(void) +{ + // should not be called before base port is prepared + g_assert(vm_base_port != 0); + + if (is_netclient_tap_attached()) { + return (START_VM_BASE_PORT + SDB_TCP_INDEX); + } + + return vm_base_port + SDB_TCP_INDEX; +} + // look-up PCI devices bool is_pci_device_enabled(int device_id) { diff --git a/tizen/src/emul_state.h b/tizen/src/emul_state.h index 00223b9649..bcdc04e8d9 100644 --- a/tizen/src/emul_state.h +++ b/tizen/src/emul_state.h @@ -93,17 +93,12 @@ enum { typedef struct EmulatorConfigInfo { int sdl_bpp; - int vm_base_port; - int device_serial_number; - int ecs_port; char guest_ip[16]; char host_ip[16]; - int spice_port; const char *skin_path; const char *file_sharing_path; - int serial_port; /* add here */ } EmulatorConfigInfo; @@ -124,8 +119,6 @@ typedef struct EmulatorConfigState { /* setter */ void set_emul_win_scale(double scale); void set_emul_sdl_bpp(int bpp); -void set_emul_vm_base_port(int port); -void set_emul_ecs_port(int port); void set_emul_guest_ip(char *ip); void set_emul_host_ip(char *ip); @@ -140,11 +133,6 @@ void set_sdb_connection(bool connected); /* getter */ double get_emul_win_scale(void); int get_emul_sdl_bpp(void); -int get_emul_vm_base_port(void); -int get_device_serial_number(void); -int get_emul_ecs_port(void); -int get_emul_serial_port(void); -int get_emul_spice_port(void); const char* get_emul_skin_path(void); bool get_emul_cpu_accel(void); @@ -194,6 +182,11 @@ bool is_netclient_tap_attached(void); uint64_t get_ram_size(void); +void set_vm_base_port(int port); +int get_vm_base_port(void); +int get_vm_device_serial_number(void); +int get_vm_spice_port(void); + void set_initial_display_resolution(int width, int height); int get_display_resolution_width(void); int get_display_resolution_height(void); diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index e5d7ab9263..0e1277989b 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -42,8 +42,7 @@ #include "emulator_options.h" #include "util/error_handler.h" #include "util/osutil.h" -#include "util/sdb.h" -#include "util/new_debug_ch.h" +#include "util/net_helper.h" #include "ecs/ecs.h" #include "util/device_hotplug.h" #include "util/exported_strings.h" @@ -66,6 +65,7 @@ int thread_running = 1; /* Check if we need exit main */ #endif +#include "util/new_debug_ch.h" DECLARE_DEBUG_CHANNEL(main); #define ARGS_LIMIT 128 @@ -274,15 +274,11 @@ const char *prepare_maru(const char * const kernel_cmdline) init_emul_state(); - // We should call socket_init() here since this function called - // before calling socket_init() in "vl.c". - // It is safe to call socket_init() multiple times. - socket_init(); - init_vm_base_port(); + init_sdb_and_vm_base_port(); // Assemble new kernel cmdline maru_kernel_cmdline = g_strdup_printf("%s sdb_port=%d, " - "vm_resolution=%dx%d", kernel_cmdline, get_emul_vm_base_port(), + "vm_resolution=%dx%d", kernel_cmdline, get_vm_base_port(), get_display_resolution_width(), get_display_resolution_height()); set_emul_host_ip(maru_kernel_cmdline); LOG_INFO("kernel commandline : %s\n", maru_kernel_cmdline); @@ -295,7 +291,6 @@ void prepare_maru_after_device_init(void) make_vm_lock_os(); init_device_hotplug(); start_ecs(); - init_sdb(get_emul_vm_base_port()); // Only for intent logging of essential information get_vm_name(); diff --git a/tizen/src/hw/maru_pm.c b/tizen/src/hw/maru_pm.c index 2fcf610ce6..179d70544a 100644 --- a/tizen/src/hw/maru_pm.c +++ b/tizen/src/hw/maru_pm.c @@ -31,7 +31,7 @@ #include "sysemu/sysemu.h" #include "debug_ch.h" -#include "util/sdb.h" +#include "util/net_helper.h" /* define debug channel */ MULTI_DEBUG_CHANNEL(tizen, power_mgr); diff --git a/tizen/src/ui/menu/contextmenu.cpp b/tizen/src/ui/menu/contextmenu.cpp index 307b600bf7..5f8a5ae4e4 100644 --- a/tizen/src/ui/menu/contextmenu.cpp +++ b/tizen/src/ui/menu/contextmenu.cpp @@ -45,6 +45,7 @@ void qemu_system_reset_request(void); #define MENU_ACTION_REBOOT 1 void send_shutdown_request(int action); +#include "util/net_helper.h" #include "util/osutil.h" #include "util/device_hotplug.h" #include "util/ui_operations.h" @@ -76,7 +77,7 @@ ContextMenu::ContextMenu(QWidget *parent) : QMenu(parent) this->controllerMapper = NULL; vmName = this->parent->getUiInfo()->getVmName() + " : " - + QString::number(get_device_serial_number()); + + QString::number(get_vm_device_serial_number()); /* for SDB shell */ shellOpener = new ShellOpener(); diff --git a/tizen/src/ui/menu/contextmenu.h b/tizen/src/ui/menu/contextmenu.h index 3c2181eda7..bae1553eb7 100644 --- a/tizen/src/ui/menu/contextmenu.h +++ b/tizen/src/ui/menu/contextmenu.h @@ -46,7 +46,6 @@ class MainWindow; extern "C" { #include "emul_state.h" -#include "util/sdb.h" } #define CLOSE_POWER_KEY_INTERVAL 1200 /* milli-seconds */ diff --git a/tizen/src/ui/menu/screenshotdialog.cpp b/tizen/src/ui/menu/screenshotdialog.cpp index 36f393b17a..b41798c905 100644 --- a/tizen/src/ui/menu/screenshotdialog.cpp +++ b/tizen/src/ui/menu/screenshotdialog.cpp @@ -53,7 +53,7 @@ ScreenShotDialog::ScreenShotDialog(QWidget *parent) : setWindowTitle(QString(SCREENSHOT_TITLE) + " - " + win->getUiInfo()->getVmName() + " : " + - QString::number(get_device_serial_number())); + QString::number(get_vm_device_serial_number())); setWindowIcon(QIcon(":/icons/screen_shot.png")); dialogLayout = new QGridLayout(this); diff --git a/tizen/src/ui/menu/shellopener.cpp b/tizen/src/ui/menu/shellopener.cpp index 76ebb50e4b..c4f52492f6 100644 --- a/tizen/src/ui/menu/shellopener.cpp +++ b/tizen/src/ui/menu/shellopener.cpp @@ -57,7 +57,7 @@ void ShellOpener::openShell(QString title) QString command; QStringList arguments; - QString sdbPort = QString::number(get_device_serial_number()); + QString sdbPort = QString::number(get_vm_device_serial_number()); QString sdbSerialName; if (is_netclient_tap_attached()) { sdbSerialName = QString(get_emul_guest_ip()); diff --git a/tizen/src/ui/qt5_supplement.cpp b/tizen/src/ui/qt5_supplement.cpp index cb681950e7..4de20ab393 100644 --- a/tizen/src/ui/qt5_supplement.cpp +++ b/tizen/src/ui/qt5_supplement.cpp @@ -117,7 +117,7 @@ static void qt5_gui_init(void) uiInfo->setResolution(QSize( get_display_resolution_width(), get_display_resolution_height())); - uiInfo->setBasePort(get_emul_vm_base_port()); + uiInfo->setBasePort(get_vm_base_port()); qDebug() << "VM base port:" << uiInfo->getBasePort(); uiInfo->setVmDataPath(QDir( diff --git a/tizen/src/util/Makefile.objs b/tizen/src/util/Makefile.objs index 6c2564f2f1..a4a2969fcc 100644 --- a/tizen/src/util/Makefile.objs +++ b/tizen/src/util/Makefile.objs @@ -19,8 +19,8 @@ obj-$(CONFIG_DARWIN) += osutil-darwin.o # tap helper obj-$(CONFIG_LINUX) += tap_helper.o -#sdb -obj-y += sdb.o +# net helper +obj-y += net_helper.o # hotplug obj-y += device_hotplug.o diff --git a/tizen/src/util/net_helper.c b/tizen/src/util/net_helper.c new file mode 100644 index 0000000000..4a0454b111 --- /dev/null +++ b/tizen/src/util/net_helper.c @@ -0,0 +1,633 @@ +/* + * Net helper + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * MunKyu Im + * Jinhyung Choi + * SeokYeon Hwnag + * Sangho Park + * + * 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 "net_helper.h" + +#include "qemu/sockets.h" +#include "net/slirp.h" +#include "block/nbd.h" +#include "qemu/error-report.h" + +#include "emulator.h" +#include "emulator_common.h" +#include "emul_state.h" + +#include "hw/virtio/maru_virtio_hwkey.h" +#include "hw/maru_pm.h" +#include "ecs/ecs.h" +#include "new_debug_ch.h" + +DECLARE_DEBUG_CHANNEL(sdb); + +#ifdef CONFIG_JAVA_UI +#include "skin/maruskin_server.h" +#endif + +#define BUF_SIZE 64 + +int emul_vm_base_socket; +static bool sdb_daemon_is_initialized = false; +#ifdef _WIN32 +#include "qemu/main-loop.h" + +static void socket_close_handler( void* _fd ) +{ + int fd = (int)(uintptr_t)_fd; + int ret; + char buff[BUF_SIZE]; + + /* 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*)(uintptr_t)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; +} + +int check_port_bind_listen(uint32_t port) +{ + struct sockaddr_in addr; + int ret = -1; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + if (inet_aton(HOST_LISTEN_ADDR, &addr.sin_addr) == 0) { + LOG_SEVERE("inet_aton failure\n"); + return -1; + } + + ret = qemu_socket(PF_INET, SOCK_STREAM, 0); + if (ret < 0) { + LOG_SEVERE("socket creation failed.\n"); + return -1; + } + + qemu_set_nonblock(ret); + + if (socket_set_fast_reuse(ret) != 0) { + LOG_SEVERE("It cannot be reach here.\n"); + closesocket(ret); + return -1; + } + + if (bind(ret, (struct sockaddr *)&addr, sizeof(addr)) != 0) { + LOG_INFO("bind failed for port: %d, errno: %d\n", port, errno); + closesocket(ret); + return -1; + } + + if (listen(ret, 1) != 0) { + LOG_SEVERE("listen failed :%s-%d\n", strerror(errno), errno); + closesocket(ret); + return -1; + } + + return ret; +} + +static int prepare_network_port(uint32_t base_port) +{ + int ret = -1; + + /* no need to redir if network is tap */ + if (!is_netclient_tap_attached()) { + if (!hostfwd_try_add(0, NULL, base_port + SDB_TCP_INDEX, + NULL, SDB_GUEST_PORT)) { + LOG_INFO("TCP port %"PRIu32" is aleady occupied", + base_port + SDB_TCP_INDEX); + + return -1; + } + + if (!hostfwd_try_add(0, NULL, base_port + GDB_TCP_INDEX, + NULL, GDB_GUEST_PORT)) { + LOG_INFO("TCP port %"PRIu32" is aleady occupied", + base_port + GDB_TCP_INDEX); + hostfwd_try_remove(0, NULL, base_port + SDB_TCP_INDEX); + + return -1; + } + } + + if ((ret = check_port_bind_listen(base_port + ECS_TCP_INDEX)) < 0) { + LOG_INFO("TCP port %"PRIu32" is aleady occupied", + base_port + ECS_TCP_INDEX); + + if (!is_netclient_tap_attached()) { + hostfwd_try_remove(0, NULL, base_port + SDB_TCP_INDEX); + hostfwd_try_remove(0, NULL, base_port + GDB_TCP_INDEX); + } + + return -1; + } + + g_assert(ret >= 0); + + // save ecs socket fd as global variable + // FIXME: should not use global variable. + emul_vm_base_socket = ret; + + return ret; +} + +static void start_sdb_noti_server(int server_port); + +void init_sdb_and_vm_base_port(void) +{ + uint32_t port = 0; + + for (port = START_VM_BASE_PORT ; port < END_VM_BASE_PORT; port += 10) { + if (prepare_network_port(port) < 0) { + continue; + } + + break; + } + + if (port >= END_VM_BASE_PORT) { + error_report("It seems too many emulator instances are " + "running on this machine. Aborting."); + exit(1); + } + + LOG_INFO("Emulator base port is %"PRIu32".\n", port); + + start_sdb_noti_server(port + SDB_UDP_NOTI_PORT_INDEX); + + set_vm_base_port(port); +} + +/* + * SDB Notification server + */ + +#define RECV_BUF_SIZE 32 +typedef struct SDB_Noti_Server { + int server_fd; + GIOChannel *server_chan; + guint server_tag; +} SDB_Noti_Server; + +typedef struct SDB_Client { + int port; + struct sockaddr_in addr; + char serial[RECV_BUF_SIZE]; + + QTAILQ_ENTRY(SDB_Client) next; +} SDB_Client; + +static QTAILQ_HEAD(SDB_ClientHead, SDB_Client) +clients = QTAILQ_HEAD_INITIALIZER(clients); + +static SDB_Noti_Server *current_server; +static QemuMutex mutex_clients; + +static void remove_sdb_client(SDB_Client* client) +{ + if (client == NULL) { + return; + } + + qemu_mutex_lock(&mutex_clients); + + QTAILQ_REMOVE(&clients, client, next); + + qemu_mutex_unlock(&mutex_clients); + + g_free(client); +} + +static void send_to_sdb_client(SDB_Client* client, int state) +{ + struct sockaddr_in sock_addr; + int s, slen = sizeof(sock_addr); + int serial_len = 0; + char buf[BUF_SIZE]; + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1){ + LOG_INFO("socket creation error! %d\n", errno); + return; + } + + memset(&sock_addr, 0, sizeof(sock_addr)); + + sock_addr.sin_family = AF_INET; + sock_addr.sin_port = htons(client->port); + sock_addr.sin_addr = (client->addr).sin_addr; + + if (connect(s, (struct sockaddr*)&sock_addr, slen) == -1) { + LOG_INFO("connect error! remove this client.\n"); + remove_sdb_client(client); + close(s); + return; + } + + memset(buf, 0, sizeof(buf)); + + serial_len = strlen(client->serial); + + // send message "[4 digit message length]host:sync:emulator-26101:[0|1]" + sprintf(buf, "%04xhost:sync:%s:%01d", (serial_len + 12), client->serial, state); + + LOG_INFO("send %s to client %s\n", buf, inet_ntoa(client->addr.sin_addr)); + + if (send(s, buf, sizeof(buf), 0) == -1) + { + LOG_INFO("send error! remove this client.\n"); + remove_sdb_client(client); + } + + close(s); +} + +void notify_all_sdb_clients(int state) +{ + qemu_mutex_lock(&mutex_clients); + SDB_Client *client, *next; + + QTAILQ_FOREACH_SAFE(client, &clients, next, next) + { + send_to_sdb_client(client, state); + } + qemu_mutex_unlock(&mutex_clients); + +} + +static void add_sdb_client(struct sockaddr_in* addr, int port, const char* serial) +{ + SDB_Client *cli = NULL; + SDB_Client *client = NULL, *next; + + if (addr == NULL) { + LOG_INFO("SDB_Client client's address is EMPTY.\n"); + return; + } else if (serial == NULL || strlen(serial) <= 0) { + LOG_INFO("SDB_Client client's serial is EMPTY.\n"); + return; + } else if (strlen(serial) > RECV_BUF_SIZE) { + LOG_INFO("SDB_Client client's serial is too long. %s\n", serial); + return; + } + + qemu_mutex_lock(&mutex_clients); + QTAILQ_FOREACH_SAFE(cli, &clients, next, next) + { + if (!strcmp(serial, cli->serial) && !strcmp(inet_ntoa(addr->sin_addr), inet_ntoa((cli->addr).sin_addr))) { + LOG_INFO("Client cannot be duplicated.\n"); + qemu_mutex_unlock(&mutex_clients); + return; + } + } + qemu_mutex_unlock(&mutex_clients); + + client = g_malloc0(sizeof(SDB_Client)); + if (NULL == client) { + LOG_INFO("SDB_Client allocation failed.\n"); + return; + } + + memcpy(&client->addr, addr, sizeof(struct sockaddr_in)); + client->port = port; + strcpy(client->serial, serial); + + qemu_mutex_lock(&mutex_clients); + + QTAILQ_INSERT_TAIL(&clients, client, next); + + qemu_mutex_unlock(&mutex_clients); + + LOG_INFO("Added new sdb client. ip: %s, port: %d, serial: %s\n", inet_ntoa((client->addr).sin_addr), client->port, client->serial); + + send_to_sdb_client(client, runstate_check(RUN_STATE_SUSPENDED)); +} + +static int parse_val(char* buff, unsigned char data, char* parsbuf) +{ + int count = 0; + + while (1) { + if (count > 12) { + return -1; + } + + if (buff[count] == data) { + count++; + strncpy(parsbuf, buff, count); + return count; + } + + count++; + } + + return 0; +} + +#define SDB_SERVER_PORT 26097 +static void register_sdb_server(char* readbuf, struct sockaddr_in* client_addr) +{ + int port = 0; + char token[] = "\n"; + char* ret = NULL; + char* serial = NULL; + + ret = strtok(readbuf, token); + if (ret == NULL) { + LOG_INFO("command is not found."); + return; + } + + serial = strtok(NULL, token); + if (serial == NULL) { + LOG_INFO("serial is not found."); + return; + } + + port = SDB_SERVER_PORT; + + add_sdb_client(client_addr, port, serial); +} + +#define PRESS 1 +#define RELEASE 2 +#define POWER_KEY 116 +static void wakeup_guest(void) +{ + // FIXME: Temporarily working model. + // It must be fixed as the way it works. + maru_hwkey_event(PRESS, POWER_KEY); + maru_hwkey_event(RELEASE, POWER_KEY); +} + +static void suspend_lock_state(int state) +{ + ecs_suspend_lock_state(state); +} + +static void command_handler(char* readbuf, struct sockaddr_in* client_addr) +{ + char command[RECV_BUF_SIZE]; + memset(command, '\0', sizeof(command)); + + parse_val(readbuf, 0x0a, command); + + LOG_TRACE("----------------------------------------\n"); + LOG_TRACE("command:%s\n", command); + if (strcmp(command, "2\n" ) == 0) { +#ifdef CONFIG_JAVA_UI + notify_sdb_daemon_start(); +#endif + sdb_daemon_is_initialized = true; + } else if (strcmp(command, "5\n") == 0) { + register_sdb_server(readbuf, client_addr); + set_sdb_connection(true); + } else if (strcmp(command, "6\n") == 0) { + wakeup_guest(); + } else if (strcmp(command, "7\n") == 0) { + suspend_lock_state(SUSPEND_LOCK); + } else if (strcmp(command, "8\n") == 0) { + suspend_lock_state(SUSPEND_UNLOCK); + } else { + LOG_INFO("!!! unknown command : %s\n", command); + } + LOG_TRACE("========================================\n"); +} + +static void close_clients(void) +{ + qemu_mutex_lock(&mutex_clients); + SDB_Client * client, *next; + + QTAILQ_FOREACH_SAFE(client, &clients, next, next) + { + QTAILQ_REMOVE(&clients, client, next); + + if (NULL != client) + { + g_free(client); + } + } + + qemu_mutex_unlock(&mutex_clients); +} + +static void close_server(void) +{ + if (current_server == NULL) { + return; + } + + close_clients(); + + if (current_server->server_fd > 0) { + if (current_server->server_tag) { + g_source_remove(current_server->server_tag); + current_server->server_tag = 0; + } + if (current_server->server_chan) { + g_io_channel_unref(current_server->server_chan); + } + closesocket(current_server->server_fd); + } + + g_free(current_server); + + qemu_mutex_destroy(&mutex_clients); +} + +static gboolean sdb_noti_read(GIOChannel *channel, GIOCondition cond, void *opaque) +{ + int recv_cnt = 0; + struct sockaddr_in client_addr; + socklen_t client_len = sizeof(client_addr); + char readbuf[RECV_BUF_SIZE + 1]; + SDB_Noti_Server *server = opaque; + + memset(&readbuf, 0, sizeof(readbuf)); + + recv_cnt = recvfrom(server->server_fd, readbuf, RECV_BUF_SIZE, 0, + (struct sockaddr*) &client_addr, &client_len); + + if (recv_cnt > 0) { + command_handler((char*)readbuf, &client_addr); + } else if (recv_cnt == 0) { + LOG_INFO("noti server recvfrom returned 0.\n"); + } else { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + LOG_TRACE("recvfrom error case (it can be from non-blocking socket): %d", errno); + } + + return TRUE; +} + +static int create_UDP_server(SDB_Noti_Server *server, int port) +{ + struct sockaddr_in server_addr; + int opt = 1; + + if ((server->server_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { + LOG_INFO("create listen socket error:%d\n", errno); + return -1; + } + + memset(&server_addr, '\0', sizeof(server_addr)); + server_addr.sin_family = PF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(port); + + qemu_set_nonblock(server->server_fd); + + if (qemu_setsockopt(server->server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) { + LOG_INFO("setsockopt SO_REUSEADDR is failed.: %d\n", errno); + return -1; + } + + if (bind(server->server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) { + LOG_INFO("sdb noti server bind error: %d", errno); + return -1; + } + + return 0; +} + +static GIOChannel *io_channel_from_socket(int fd) +{ + GIOChannel *chan; + + if (fd == -1) { + return NULL; + } + +#ifdef _WIN32 + chan = g_io_channel_win32_new_socket(fd); +#else + chan = g_io_channel_unix_new(fd); +#endif + + g_io_channel_set_encoding(chan, NULL, NULL); + g_io_channel_set_buffered(chan, FALSE); + + return chan; +} + +static void sdb_noti_server_notify_exit(Notifier *notifier, void *data) +{ + LOG_INFO("shutdown sdb notification server.\n"); + close_server(); +} + +static Notifier sdb_noti_server_exit = { .notify = sdb_noti_server_notify_exit }; + +static void start_sdb_noti_server(int server_port) +{ + SDB_Noti_Server *server; + int ret; + + LOG_INFO("start sdb noti server thread.\n"); + + server = g_malloc0(sizeof(SDB_Noti_Server)); + if (server == NULL) { + LOG_INFO("SDB Notification server allocation is failed.\n"); + return; + } + + ret = create_UDP_server(server, server_port); + if (ret < 0) { + LOG_INFO("failed to create UDP server\n"); + close_server(); + return; + } + + server->server_chan = io_channel_from_socket(server->server_fd); + server->server_tag = g_io_add_watch(server->server_chan, G_IO_IN, sdb_noti_read, server); + + current_server = server; + + qemu_mutex_init(&mutex_clients); + + LOG_INFO("success to bind port[127.0.0.1:%d/udp] for sdb noti server in host \n", server_port); + + emulator_add_exit_notifier(&sdb_noti_server_exit); +} + +bool is_sdb_daemon_initialized(void) +{ + return sdb_daemon_is_initialized; +} diff --git a/tizen/src/util/net_helper.h b/tizen/src/util/net_helper.h new file mode 100644 index 0000000000..be0651f7ef --- /dev/null +++ b/tizen/src/util/net_helper.h @@ -0,0 +1,79 @@ +/* + * Net helper + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * MunKyu Im + * Jinhyung Choi + * SeokYeon Hwnag + * Sangho Park + * + * 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 + * + */ + +#ifndef SDB_SERVER_H_ +#define SDB_SERVER_H_ + +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#else /* !_WIN32 */ +#include +#include +#include +#include +#include +#endif /* !_WIN32 */ + + +#define SDB_HOST_PORT 26099 + +#define START_VM_BASE_PORT 26100 +#define END_VM_BASE_PORT 26200 + +#define SDB_TCP_INDEX 1 +#define GDB_TCP_INDEX 2 +#define ECS_TCP_INDEX 3 +#define SPICE_TCP_INDEX 3 +#define SDB_UDP_NOTI_PORT_INDEX 3 + +#define SDB_GUEST_PORT (START_VM_BASE_PORT + SDB_TCP_INDEX) +#define GDB_GUEST_PORT (START_VM_BASE_PORT + GDB_TCP_INDEX) + +void init_sdb_and_vm_base_port(void); +int inet_strtoip(const char* str, uint32_t *ip); +int socket_send(int fd, const void* buf, int buflen); +void socket_close(int fd); +int check_port_bind_listen(uint32_t port); +bool is_sdb_daemon_initialized(void); + +extern int emul_vm_base_socket; + +#define STATE_RUNNING 0 +#define STATE_SUSPEND 1 +void notify_all_sdb_clients(int state); + +#endif + diff --git a/tizen/src/util/osutil-darwin.c b/tizen/src/util/osutil-darwin.c index 3945580537..62ae4a30d6 100644 --- a/tizen/src/util/osutil-darwin.c +++ b/tizen/src/util/osutil-darwin.c @@ -39,7 +39,6 @@ #include "emulator.h" #include "emul_state.h" #include "debug_ch.h" -#include "sdb.h" #include "emulator_options.h" #ifndef CONFIG_DARWIN @@ -79,7 +78,7 @@ void make_vm_lock_os(void) { char *shared_memory; int base_port; - base_port = get_emul_vm_base_port(); + base_port = get_vm_base_port(); g_shmid = shmget((key_t)base_port, getpagesize(), 0666|IPC_CREAT); if (g_shmid == -1) { ERR("shmget failed\n"); diff --git a/tizen/src/util/osutil-linux.c b/tizen/src/util/osutil-linux.c index 5ea0d6580f..d0cd9cedfb 100644 --- a/tizen/src/util/osutil-linux.c +++ b/tizen/src/util/osutil-linux.c @@ -49,7 +49,7 @@ #include "osutil.h" #include "emulator.h" #include "emul_state.h" -#include "sdb.h" +#include "net_helper.h" #include "emulator_options.h" #ifndef CONFIG_LINUX @@ -92,9 +92,12 @@ void check_vm_lock_os(void) continue; } shmdt(shm_addr); + // FIXME: VM lock logic should be refactored ASAP. +#if 0 error_report("Can not execute this VM. " "The same name is running now."); exit(1); +#endif } else { shmdt(shm_addr); } @@ -124,7 +127,7 @@ void make_vm_lock_os(void) check_vm_lock_os(); - base_port = get_emul_vm_base_port(); + base_port = get_vm_base_port(); g_shmid = shmget((key_t)base_port, getpagesize(), 0666|IPC_CREAT); if (g_shmid == -1) { diff --git a/tizen/src/util/osutil-win32.c b/tizen/src/util/osutil-win32.c index a904ea5a0a..70ce715d61 100644 --- a/tizen/src/util/osutil-win32.c +++ b/tizen/src/util/osutil-win32.c @@ -39,7 +39,6 @@ #include "osutil.h" #include "emulator.h" #include "emul_state.h" -#include "sdb.h" #include "emulator_options.h" #ifndef CONFIG_WIN32 @@ -120,7 +119,7 @@ void make_vm_lock_os(void) check_vm_lock_os(); - base_port = get_emul_vm_base_port(); + base_port = get_vm_base_port(); shared_memory = g_strdup_printf("%s", get_drive_image_file()); port_in_use = g_strdup_printf("%d", base_port); g_hMapFile = CreateFileMapping( diff --git a/tizen/src/util/sdb.c b/tizen/src/util/sdb.c deleted file mode 100644 index ccdd13c303..0000000000 --- a/tizen/src/util/sdb.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * Emulator SDB Notification Server - * - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * Jinhyung choi - * MunKyu Im - * Sangho Park - * 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 "net/slirp.h" -#include "qemu/sockets.h" -#include "sdb.h" -#include "block/nbd.h" - -#include "emulator.h" -#include "emulator_common.h" -#include "emul_state.h" - -#include "hw/virtio/maru_virtio_hwkey.h" -#include "hw/maru_pm.h" -#include "ecs/ecs.h" -#include "debug_ch.h" - -MULTI_DEBUG_CHANNEL(qemu, sdb); - -#ifdef CONFIG_JAVA_UI -#include "skin/maruskin_server.h" -#endif - -#define SDB_INDEX 1 -#define GDB_INDEX 2 -#define ECS_INDEX 3 -#define SDB_NOTI_PORT_INDEX 3 -#define START_BASE_PORT 26100 -#define SDB_GUEST_PORT (START_BASE_PORT + SDB_INDEX) -#define GDB_GUEST_PORT (START_BASE_PORT + GDB_INDEX) - -int emul_vm_base_socket; -static bool sdb_daemon_is_initialized = false; -#ifdef _WIN32 -#include "qemu/main-loop.h" - -static void socket_close_handler( void* _fd ) -{ - int fd = (int)(uintptr_t)_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*)(uintptr_t)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; -} - -int check_port_bind_listen(uint32_t port) -{ - struct sockaddr_in addr; - int ret = -1; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - - if (inet_aton(HOST_LISTEN_ADDR, &addr.sin_addr) == 0) { - LOG_SEVERE("inet_aton failure\n"); - return -1; - } - - ret = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (ret < 0) { - LOG_SEVERE("socket creation failed.\n"); - return -1; - } - - qemu_set_nonblock(ret); - - if (socket_set_fast_reuse(ret) != 0) { - LOG_SEVERE("It cannot be reach here.\n"); - closesocket(ret); - return -1; - } - - if (bind(ret, (struct sockaddr *)&addr, sizeof(addr)) != 0) { - LOG_INFO("bind failed for port: %d, errno: %d\n", port, errno); - closesocket(ret); - return -1; - } - - if (listen(ret, 1) != 0) { - LOG_SEVERE("listen failed :%s-%d\n", strerror(errno), errno); - closesocket(ret); - return -1; - } - - return ret; -} - -int find_available_port(uint32_t base_port) -{ - int ret = 0; - int i = 0; - for (i = SDB_INDEX; i <= ECS_INDEX; i++) { - ret = check_port_bind_listen(base_port + i); - if (ret >= 0 && i != ECS_INDEX) { - //TODO: Because of checking and closing socket, - // not guaranteed fully that sdb/gdb port is available, - // when the time call net_slirp_redir() - closesocket(ret); - } else if (ret < 0) { - LOG_INFO("port(%"PRIu32") is reserved.\n", base_port + i); - return -1; - } - } - // save ecs socket fd as global variable - emul_vm_base_socket = ret; - LOG_INFO("find available port: %"PRIu32"\n", base_port); - return ret; -} - -void init_vm_base_port(void) -{ - int tries = 10; - int success = 0; - uint32_t port = START_BASE_PORT; - int base_port; - - base_port = get_emul_vm_base_port(); - - if (base_port == 0) { - - for ( ; tries > 0; tries--, port += 10 ) { - if (find_available_port(port) < 0) { - LOG_INFO("port(%d) is not available. It can be reserved.\n", port); - continue; - } - - success = 1; - break; - } - - if (!success) { - INFO( "it seems too many emulator instances are running on this machine. Aborting\n" ); - exit(1); - } - - base_port = port; - INFO( "emulator base port is %d\n", base_port); - } - - set_emul_vm_base_port(base_port); -} - -static void start_sdb_noti_server(int server_port); -void init_sdb(int server_port) -{ - start_sdb_noti_server(server_port + SDB_NOTI_PORT_INDEX); - - /* no need to redir if network is tap */ - if (is_netclient_tap_attached()) { - return; - } - - char buf_sdb[64] = {0,}; - char buf_gdb[64] = {0,}; - - sprintf(buf_sdb, "tcp:%d::%d", server_port + SDB_INDEX, SDB_GUEST_PORT); - if (net_slirp_redir((char*)buf_sdb) < 0) { - LOG_WARNING("failed to redirect sdb port [%s]\n", buf_sdb); - } else { - INFO("redirect port for sdb [%s]\n", buf_sdb); - } - - sprintf(buf_gdb, "tcp:%d::%d", server_port + GDB_INDEX, GDB_GUEST_PORT); - if (net_slirp_redir((char*)buf_gdb) < 0) { - LOG_WARNING("failed to redirect gdb port [%s]\n", buf_gdb); - } else { - INFO("redirect port for gdb [%s]\n", buf_gdb); - } -} - -/* - * SDB Notification server - */ - -#define RECV_BUF_SIZE 32 -typedef struct SDB_Noti_Server { - int server_fd; - GIOChannel *server_chan; - guint server_tag; -} SDB_Noti_Server; - -typedef struct SDB_Client { - int port; - struct sockaddr_in addr; - char serial[RECV_BUF_SIZE]; - - QTAILQ_ENTRY(SDB_Client) next; -} SDB_Client; - -static QTAILQ_HEAD(SDB_ClientHead, SDB_Client) -clients = QTAILQ_HEAD_INITIALIZER(clients); - -static SDB_Noti_Server *current_server; -static QemuMutex mutex_clients; - -static void remove_sdb_client(SDB_Client* client) -{ - if (client == NULL) { - return; - } - - qemu_mutex_lock(&mutex_clients); - - QTAILQ_REMOVE(&clients, client, next); - - qemu_mutex_unlock(&mutex_clients); - - g_free(client); -} - -static void send_to_sdb_client(SDB_Client* client, int state) -{ - struct sockaddr_in sock_addr; - int s, slen = sizeof(sock_addr); - int serial_len = 0; - char buf [64]; - - if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1){ - INFO("socket creation error! %d\n", errno); - return; - } - - memset(&sock_addr, 0, sizeof(sock_addr)); - - sock_addr.sin_family = AF_INET; - sock_addr.sin_port = htons(client->port); - sock_addr.sin_addr = (client->addr).sin_addr; - - if (connect(s, (struct sockaddr*)&sock_addr, slen) == -1) { - INFO("connect error! remove this client.\n"); - remove_sdb_client(client); - close(s); - return; - } - - memset(buf, 0, sizeof(buf)); - - serial_len = strlen(client->serial); - - // send message "[4 digit message length]host:sync:emulator-26101:[0|1]" - sprintf(buf, "%04xhost:sync:%s:%01d", (serial_len + 12), client->serial, state); - - INFO("send %s to client %s\n", buf, inet_ntoa(client->addr.sin_addr)); - - if (send(s, buf, sizeof(buf), 0) == -1) - { - INFO("send error! remove this client.\n"); - remove_sdb_client(client); - } - - close(s); -} - -void notify_all_sdb_clients(int state) -{ - qemu_mutex_lock(&mutex_clients); - SDB_Client *client, *next; - - QTAILQ_FOREACH_SAFE(client, &clients, next, next) - { - send_to_sdb_client(client, state); - } - qemu_mutex_unlock(&mutex_clients); - -} - -static void add_sdb_client(struct sockaddr_in* addr, int port, const char* serial) -{ - SDB_Client *cli = NULL; - SDB_Client *client = NULL, *next; - - if (addr == NULL) { - INFO("SDB_Client client's address is EMPTY.\n"); - return; - } else if (serial == NULL || strlen(serial) <= 0) { - INFO("SDB_Client client's serial is EMPTY.\n"); - return; - } else if (strlen(serial) > RECV_BUF_SIZE) { - INFO("SDB_Client client's serial is too long. %s\n", serial); - return; - } - - qemu_mutex_lock(&mutex_clients); - QTAILQ_FOREACH_SAFE(cli, &clients, next, next) - { - if (!strcmp(serial, cli->serial) && !strcmp(inet_ntoa(addr->sin_addr), inet_ntoa((cli->addr).sin_addr))) { - INFO("Client cannot be duplicated.\n"); - qemu_mutex_unlock(&mutex_clients); - return; - } - } - qemu_mutex_unlock(&mutex_clients); - - client = g_malloc0(sizeof(SDB_Client)); - if (NULL == client) { - INFO("SDB_Client allocation failed.\n"); - return; - } - - memcpy(&client->addr, addr, sizeof(struct sockaddr_in)); - client->port = port; - strcpy(client->serial, serial); - - qemu_mutex_lock(&mutex_clients); - - QTAILQ_INSERT_TAIL(&clients, client, next); - - qemu_mutex_unlock(&mutex_clients); - - INFO("Added new sdb client. ip: %s, port: %d, serial: %s\n", inet_ntoa((client->addr).sin_addr), client->port, client->serial); - - send_to_sdb_client(client, runstate_check(RUN_STATE_SUSPENDED)); -} - -static int parse_val(char* buff, unsigned char data, char* parsbuf) -{ - int count = 0; - - while (1) { - if (count > 12) { - return -1; - } - - if (buff[count] == data) { - count++; - strncpy(parsbuf, buff, count); - return count; - } - - count++; - } - - return 0; -} - -#define SDB_SERVER_PORT 26097 -static void register_sdb_server(char* readbuf, struct sockaddr_in* client_addr) -{ - int port = 0; - char token[] = "\n"; - char* ret = NULL; - char* serial = NULL; - - ret = strtok(readbuf, token); - if (ret == NULL) { - INFO("command is not found."); - return; - } - - serial = strtok(NULL, token); - if (serial == NULL) { - INFO("serial is not found."); - return; - } - - port = SDB_SERVER_PORT; - - add_sdb_client(client_addr, port, serial); -} - -#define PRESS 1 -#define RELEASE 2 -#define POWER_KEY 116 -static void wakeup_guest(void) -{ - // FIXME: Temporarily working model. - // It must be fixed as the way it works. - maru_hwkey_event(PRESS, POWER_KEY); - maru_hwkey_event(RELEASE, POWER_KEY); -} - -static void suspend_lock_state(int state) -{ - ecs_suspend_lock_state(state); -} - -static void command_handler(char* readbuf, struct sockaddr_in* client_addr) -{ - char command[RECV_BUF_SIZE]; - memset(command, '\0', sizeof(command)); - - parse_val(readbuf, 0x0a, command); - - TRACE("----------------------------------------\n"); - TRACE("command:%s\n", command); - if (strcmp(command, "2\n" ) == 0) { -#ifdef CONFIG_JAVA_UI - notify_sdb_daemon_start(); -#endif - sdb_daemon_is_initialized = true; - } else if (strcmp(command, "5\n") == 0) { - register_sdb_server(readbuf, client_addr); - set_sdb_connection(true); - } else if (strcmp(command, "6\n") == 0) { - wakeup_guest(); - } else if (strcmp(command, "7\n") == 0) { - suspend_lock_state(SUSPEND_LOCK); - } else if (strcmp(command, "8\n") == 0) { - suspend_lock_state(SUSPEND_UNLOCK); - } else { - INFO("!!! unknown command : %s\n", command); - } - TRACE("========================================\n"); -} - -static void close_clients(void) -{ - qemu_mutex_lock(&mutex_clients); - SDB_Client * client, *next; - - QTAILQ_FOREACH_SAFE(client, &clients, next, next) - { - QTAILQ_REMOVE(&clients, client, next); - - if (NULL != client) - { - g_free(client); - } - } - - qemu_mutex_unlock(&mutex_clients); -} - -static void close_server(void) -{ - if (current_server == NULL) { - return; - } - - close_clients(); - - if (current_server->server_fd > 0) { - if (current_server->server_tag) { - g_source_remove(current_server->server_tag); - current_server->server_tag = 0; - } - if (current_server->server_chan) { - g_io_channel_unref(current_server->server_chan); - } - closesocket(current_server->server_fd); - } - - g_free(current_server); - - qemu_mutex_destroy(&mutex_clients); -} - -static gboolean sdb_noti_read(GIOChannel *channel, GIOCondition cond, void *opaque) -{ - int recv_cnt = 0; - struct sockaddr_in client_addr; - socklen_t client_len = sizeof(client_addr); - char readbuf[RECV_BUF_SIZE + 1]; - SDB_Noti_Server *server = opaque; - - memset(&readbuf, 0, sizeof(readbuf)); - - recv_cnt = recvfrom(server->server_fd, readbuf, RECV_BUF_SIZE, 0, - (struct sockaddr*) &client_addr, &client_len); - - if (recv_cnt > 0) { - command_handler((char*)readbuf, &client_addr); - } else if (recv_cnt == 0) { - INFO("noti server recvfrom returned 0.\n"); - } else { -#ifdef _WIN32 - errno = WSAGetLastError(); -#endif - TRACE("recvfrom error case (it can be from non-blocking socket): %d", errno); - } - - return TRUE; -} - -static int create_UDP_server(SDB_Noti_Server *server, int port) -{ - struct sockaddr_in server_addr; - int opt = 1; - - if ((server->server_fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - INFO("create listen socket error:%d\n", errno); - return -1; - } - - memset(&server_addr, '\0', sizeof(server_addr)); - server_addr.sin_family = PF_INET; - server_addr.sin_addr.s_addr = INADDR_ANY; - server_addr.sin_port = htons(port); - - qemu_set_nonblock(server->server_fd); - - if (qemu_setsockopt(server->server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) { - INFO("setsockopt SO_REUSEADDR is failed.: %d\n", errno); - return -1; - } - - if (bind(server->server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) { - INFO("sdb noti server bind error: %d", errno); - return -1; - } - - return 0; -} - -static GIOChannel *io_channel_from_socket(int fd) -{ - GIOChannel *chan; - - if (fd == -1) { - return NULL; - } - -#ifdef _WIN32 - chan = g_io_channel_win32_new_socket(fd); -#else - chan = g_io_channel_unix_new(fd); -#endif - - g_io_channel_set_encoding(chan, NULL, NULL); - g_io_channel_set_buffered(chan, FALSE); - - return chan; -} - -static void sdb_noti_server_notify_exit(Notifier *notifier, void *data) -{ - INFO("shutdown sdb notification server.\n"); - close_server(); -} - -static Notifier sdb_noti_server_exit = { .notify = sdb_noti_server_notify_exit }; - -static void start_sdb_noti_server(int server_port) -{ - SDB_Noti_Server *server; - int ret; - - INFO("start sdb noti server thread.\n"); - - server = g_malloc0(sizeof(SDB_Noti_Server)); - if (server == NULL) { - INFO("SDB Notification server allocation is failed.\n"); - return; - } - - ret = create_UDP_server(server, server_port); - if (ret < 0) { - INFO("failed to create UDP server\n"); - close_server(); - return; - } - - server->server_chan = io_channel_from_socket(server->server_fd); - server->server_tag = g_io_add_watch(server->server_chan, G_IO_IN, sdb_noti_read, server); - - current_server = server; - - qemu_mutex_init(&mutex_clients); - - INFO("success to bind port[127.0.0.1:%d/udp] for sdb noti server in host \n", server_port); - - emulator_add_exit_notifier(&sdb_noti_server_exit); -} - -bool is_sdb_daemon_initialized(void) -{ - return sdb_daemon_is_initialized; -} diff --git a/tizen/src/util/sdb.h b/tizen/src/util/sdb.h deleted file mode 100644 index 2dd0cc0c07..0000000000 --- a/tizen/src/util/sdb.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Emulator SDB Notification Server - * - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * Jinhyung choi - * MunKyu Im - * Sangho Park - * 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 - * - */ - -#ifndef SDB_SERVER_H_ -#define SDB_SERVER_H_ - -#include - -#ifdef _WIN32 -#include -#include -#include -#else /* !_WIN32 */ -#include -#include -#include -#include -#include -#endif /* !_WIN32 */ - - -#define SDB_HOST_PORT 26099 - -#define SDB_TCP_EMULD_INDEX 2 /* emulator daemon port */ -#define SDB_TCP_OPENGL_INDEX 3 /* opengl server port */ -#define SDB_UDP_SENSOR_INDEX 3 /* sensor server port */ - -void init_sdb(int server_port); -void init_vm_base_port(void); -int inet_strtoip(const char* str, uint32_t *ip); -int socket_send(int fd, const void* buf, int buflen); -void socket_close(int fd); -int check_port_bind_listen(uint32_t port); -int find_available_port(uint32_t base_port); -bool is_sdb_daemon_initialized(void); - -extern int emul_vm_base_socket; -#define STATE_RUNNING 0 -#define STATE_SUSPEND 1 -void notify_all_sdb_clients(int state); - -#endif - diff --git a/vl.c b/vl.c index c4af1d3b40..ed7f8a312f 100644 --- a/vl.c +++ b/vl.c @@ -4194,6 +4194,15 @@ int main(int argc, char **argv, char **envp) exit(1); } +#if defined(CONFIG_MARU) + if (is_maru_machine(machine_class)) { + preallocated_ram_ptr = qemu_anon_ram_alloc(ram_size, NULL); + if (preallocated_ram_ptr) { + preallocated_ram_size = ram_size; + } + } +#endif + set_memory_options(&ram_slots, &maxram_size, machine_class); loc_set_none(); @@ -4252,21 +4261,6 @@ int main(int argc, char **argv, char **envp) exit(0); } -#if defined(CONFIG_MARU) - if (is_maru_machine(machine_class)) { - preallocated_ram_ptr = qemu_anon_ram_alloc(ram_size, NULL); - if (preallocated_ram_ptr) { - preallocated_ram_size = ram_size; - } - - kernel_cmdline = qemu_opt_get(qemu_get_machine_opts(), "append"); - // Returned variable points different address from input variable. - kernel_cmdline = prepare_maru(kernel_cmdline); - qemu_opt_set(qemu_get_machine_opts(), "append", - kernel_cmdline, &error_abort); - } -#endif - /* Open the logfile at this point and set the log mask if necessary. */ if (log_file) { @@ -4711,6 +4705,18 @@ int main(int argc, char **argv, char **envp) configure_accelerator(current_machine); +#if defined(CONFIG_MARU) + if (is_maru_machine(machine_class)) { + kernel_cmdline = qemu_opt_get(machine_opts, "append"); + // Returned variable points different address from input variable. + kernel_cmdline = prepare_maru(kernel_cmdline); + qemu_opt_set(qemu_get_machine_opts(), "append", + kernel_cmdline, &error_abort); + + current_machine->kernel_cmdline = (char *)kernel_cmdline; + } +#endif + machine_class->init(current_machine); realtime_init();