guest server: changed as sdb notification server 39/23639/5
authorJinhyung Choi <jinhyung2.choi@samsung.com>
Tue, 1 Jul 2014 01:52:19 +0000 (10:52 +0900)
committerJinhyung Choi <jinhyung2.choi@samsung.com>
Tue, 1 Jul 2014 08:33:36 +0000 (17:33 +0900)
Current guest server supports 3 operations.
1. enabling sdb shell from emulator
2. registering sdb server w/ address, port, and serial
3. sending notification to registered sdb server suspend/resume message

Because guest server's functionalities are changed,
its name is also changed to "SDB Notification Server"
It moved into sdb_noti_server.c and sdb_noti_server.h

It does not require to create a new thread and blocking socket.
Now, it is using g_io_add_watch to receive and handle messages from
others.

Change-Id: I034122842e6cc59e753b859eb057b012f43213aa
Signed-off-by: Jinhyung Choi <jinhyung2.choi@samsung.com>
tizen/src/Makefile.objs
tizen/src/ecs/ecs.c
tizen/src/emulator.c
tizen/src/emulator_legacy.c
tizen/src/guest_server.c [deleted file]
tizen/src/hw/maru_pm.c
tizen/src/sdb_noti_server.c [new file with mode: 0644]
tizen/src/sdb_noti_server.h [moved from tizen/src/guest_server.h with 68% similarity]

index d502f85..2a6d433 100644 (file)
@@ -23,8 +23,8 @@ obj-y += tethering/
 # maru skin
 obj-y += skin/
 
-# guest server
-obj-y += guest_server.o
+# sdb noti server
+obj-y += sdb_noti_server.o
 
 # debug channel
 obj-y += debug_ch.o
index ee7c3ba..c9af676 100644 (file)
@@ -48,7 +48,6 @@
 #include "emulator.h"
 #include "util/sdb.h"
 #include "ecs.h"
-#include "guest_server.h"
 #include "emul_state.h"
 
 #include "genmsg/ecs.pb-c.h"
index 8538bcd..7bc6d19 100644 (file)
@@ -37,7 +37,7 @@
 #include "build_info.h"
 #include "emulator.h"
 #include "emul_state.h"
-#include "guest_server.h"
+#include "sdb_noti_server.h"
 #include "emulator_options.h"
 #include "util/check_gl.h"
 #include "maru_err_table.h"
@@ -253,7 +253,7 @@ static void prepare_basic_features(gchar * const kernel_cmdline)
     qemu_add_opts(&qemu_ecs_opts);
     start_ecs();
 
-    start_guest_server(get_device_serial_number() + SDB_UDP_SENSOR_INDEX);
+    start_sdb_noti_server(get_device_serial_number() + SDB_UDP_SENSOR_INDEX);
 
     sdb_setup();
 
index 096114c..721c8c8 100644 (file)
@@ -39,7 +39,6 @@
 #include "emulator.h"
 #include "emul_state.h"
 #include "guest_debug.h"
-#include "guest_server.h"
 #include "hw/maru_virtio_touchscreen.h"
 #include "util/check_gl.h"
 #include "maru_err_table.h"
diff --git a/tizen/src/guest_server.c b/tizen/src/guest_server.c
deleted file mode 100644 (file)
index 51365f3..0000000
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- *
- *
- * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * JiHye Kim <jihye1128.kim@samsung.com>
- * GiWoong Kim <giwoong.kim@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- * HyunJun Son
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <assert.h>
-#include <glib.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#else
-#include <arpa/inet.h>
-#endif
-
-#include "qemu/sockets.h"
-#include "emulator.h"
-#include "guest_server.h"
-#include "skin/maruskin_server.h"
-#include "debug_ch.h"
-#include "util/sdb.h"
-#include "maru_common.h"
-#include "hw/maru_virtio_hwkey.h"
-#include "hw/maru_pm.h"
-#include "ecs/ecs.h"
-
-MULTI_DEBUG_CHANNEL(qemu, guest_server);
-
-#define RECV_BUF_SIZE 32
-
-static int svr_port = 0;
-static int server_sock = 0;
-
-/*
- * SDB server data
- */
-typedef struct GS_Client {
-    int port;
-    struct sockaddr_in addr;
-    char serial[RECV_BUF_SIZE];
-
-    QTAILQ_ENTRY(GS_Client) next;
-} GS_Client;
-
-static QTAILQ_HEAD(GS_ClientHead, GS_Client)
-clients = QTAILQ_HEAD_INITIALIZER(clients);
-
-static QemuThread guest_thread_id;
-static QemuMutex mutex_clients;
-static int running = 0;
-
-static void remove_sdb_client(GS_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(GS_Client* client, int state)
-{
-    struct sockaddr_in sock_addr;
-    int s, slen = sizeof(sock_addr);
-    int serial_len = 0;
-    char buf [32];
-
-    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);
-    GS_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)
-{
-    GS_Client *cli = NULL;
-    GS_Client *client = NULL, *next;
-
-    if (addr == NULL) {
-        INFO("GS_Client client's address is EMPTY.\n");
-        return;
-    } else if (serial == NULL || strlen(serial) <= 0) {
-        INFO("GS_Client client's serial is EMPTY.\n");
-        return;
-    } else if (strlen(serial) > RECV_BUF_SIZE) {
-        INFO("GS_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(GS_Client));
-    if (NULL == client) {
-        INFO("GS_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;
-}
-#if 0
-/*
- *  In case that SDK does not refer to sdk.info to get tizen-sdk-data path.
- *  When SDK is not installed by the latest SDK installer,
- *  SDK installed path is fixed and there is no sdk.info file.
- */
-static gchar *get_old_tizen_sdk_data_path(void)
-{
-    gchar *tizen_sdk_data_path = NULL;
-
-    INFO("try to search tizen-sdk-data path in another way.\n");
-
-#ifndef CONFIG_WIN32
-    gchar tizen_sdk_data[] = "/tizen-sdk-data";
-    gint tizen_sdk_data_len = 0;
-    gchar *home_dir;
-
-    home_dir = (gchar *)g_getenv("HOME");
-    if (!home_dir) {
-        home_dir = (gchar *)g_get_home_dir();
-    }
-
-    tizen_sdk_data_len = strlen(home_dir) + sizeof(tizen_sdk_data) + 1;
-    tizen_sdk_data_path = g_malloc(tizen_sdk_data_len);
-    if (!tizen_sdk_data_path) {
-        INFO("failed to allocate memory.\n");
-        return NULL;
-    }
-    g_strlcpy(tizen_sdk_data_path, home_dir, tizen_sdk_data_len);
-    g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len);
-
-#else
-    gchar tizen_sdk_data[] = "\\tizen-sdk-data\\";
-    gint tizen_sdk_data_len = 0;
-    HKEY hKey;
-    char strLocalAppDataPath[1024] = { 0 };
-    DWORD dwBufLen = 1024;
-
-    RegOpenKeyEx(HKEY_CURRENT_USER,
-        "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
-        0, KEY_QUERY_VALUE, &hKey);
-
-    RegQueryValueEx(hKey, "Local AppData", NULL,
-                    NULL, (LPBYTE)strLocalAppDataPath, &dwBufLen);
-    RegCloseKey(hKey);
-
-    tizen_sdk_data_len = strlen(strLocalAppDataPath) + sizeof(tizen_sdk_data) + 1;
-    tizen_sdk_data_path = g_malloc(tizen_sdk_data_len);
-    if (!tizen_sdk_data_path) {
-        INFO("failed to allocate memory.\n");
-        return NULL;
-    }
-
-    g_strlcpy(tizen_sdk_data_path, strLocalAppDataPath, tizen_sdk_data_len);
-    g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len);
-#endif
-
-    INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path);
-    return tizen_sdk_data_path;
-}
-
-
-
-/*
- *  get tizen-sdk-data path from sdk.info.
- */
-gchar *get_tizen_sdk_data_path(void)
-{
-    gchar *emul_bin_path = NULL;
-    gchar *sdk_info_file_path = NULL;
-    gchar *tizen_sdk_data_path = NULL;
-#ifndef CONFIG_WIN32
-    const char *sdk_info = "../../../sdk.info";
-#else
-    const char *sdk_info = "..\\..\\..\\sdk.info";
-#endif
-    const char sdk_data_var[] = "TIZEN_SDK_DATA_PATH";
-
-    FILE *sdk_info_fp = NULL;
-    int sdk_info_path_len = 0;
-
-    TRACE("%s\n", __func__);
-
-    emul_bin_path = get_bin_path();
-    if (!emul_bin_path) {
-        INFO("failed to get emulator path.\n");
-        return NULL;
-    }
-
-    sdk_info_path_len = strlen(emul_bin_path) + strlen(sdk_info) + 1;
-    sdk_info_file_path = g_malloc(sdk_info_path_len);
-    if (!sdk_info_file_path) {
-        INFO("failed to allocate sdk-data buffer.\n");
-        return NULL;
-    }
-
-    g_snprintf(sdk_info_file_path, sdk_info_path_len, "%s%s",
-                emul_bin_path, sdk_info);
-    INFO("sdk.info path: %s\n", sdk_info_file_path);
-
-    sdk_info_fp = fopen(sdk_info_file_path, "r");
-    g_free(sdk_info_file_path);
-
-    if (sdk_info_fp) {
-        INFO("Succeeded to open [sdk.info].\n");
-
-        char tmp[256] = { '\0', };
-        char *tmpline = NULL;
-        while (fgets(tmp, sizeof(tmp), sdk_info_fp) != NULL) {
-            if ((tmpline = g_strstr_len(tmp, sizeof(tmp), sdk_data_var))) {
-                tmpline += strlen(sdk_data_var) + 1; // 1 for '='
-                break;
-            }
-        }
-
-        if (tmpline) {
-            if (tmpline[strlen(tmpline) - 1] == '\n') {
-                tmpline[strlen(tmpline) - 1] = '\0';
-            }
-            if (tmpline[strlen(tmpline) - 1] == '\r') {
-                tmpline[strlen(tmpline) - 1] = '\0';
-            }
-
-            tizen_sdk_data_path = g_malloc(strlen(tmpline) + 1);
-            g_strlcpy(tizen_sdk_data_path, tmpline, strlen(tmpline) + 1);
-
-            INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path);
-
-            fclose(sdk_info_fp);
-            return tizen_sdk_data_path;
-        }
-
-        fclose(sdk_info_fp);
-    }
-
-    // legacy mode
-    INFO("Failed to open [sdk.info].\n");
-
-    return get_old_tizen_sdk_data_path();
-}
-
-static char* get_emulator_sdcard_path(void)
-{
-    gchar *emulator_sdcard_path = NULL;
-    gchar *tizen_sdk_data = NULL;
-#ifndef CONFIG_WIN32
-    char emulator_sdcard[] = "/emulator/sdcard/";
-#else
-    char emulator_sdcard[] = "\\emulator\\sdcard\\";
-#endif
-
-    TRACE("emulator_sdcard: %s, %d\n", emulator_sdcard, sizeof(emulator_sdcard));
-
-    tizen_sdk_data = get_tizen_sdk_data_path();
-    if (!tizen_sdk_data) {
-        INFO("failed to get tizen-sdk-data path.\n");
-        return NULL;
-    }
-
-    emulator_sdcard_path =
-        g_malloc(strlen(tizen_sdk_data) + sizeof(emulator_sdcard) + 1);
-    if (!emulator_sdcard_path) {
-        INFO("failed to allocate memory.\n");
-        return NULL;
-    }
-
-    g_snprintf(emulator_sdcard_path, strlen(tizen_sdk_data) + sizeof(emulator_sdcard),
-             "%s%s", tizen_sdk_data, emulator_sdcard);
-
-    g_free(tizen_sdk_data);
-
-    TRACE("sdcard path: %s\n", emulator_sdcard_path);
-    return emulator_sdcard_path;
-}
-
-static void handle_sdcard(char* readbuf)
-{
-    char token[] = "\n";
-    char* ret = NULL;
-    ret = strtok(readbuf, token);
-    ret = strtok(NULL, token);
-
-    if (atoi(ret) == 0) {
-        /* umount sdcard */
-        //mloop_evcmd_usbdisk(NULL);
-        mloop_evcmd_sdcard(NULL);
-    } else if (atoi(ret) == 1) {
-        /* mount sdcard */
-        char sdcard_img_path[256];
-        char* sdcard_path = NULL;
-
-        sdcard_path = get_emulator_sdcard_path();
-        if (sdcard_path) {
-            g_strlcpy(sdcard_img_path, sdcard_path, sizeof(sdcard_img_path));
-
-            /* emulator_sdcard_img_path + sdcard img name */
-            ret = strtok(NULL, token);
-
-            g_strlcat(sdcard_img_path, ret, sizeof(sdcard_img_path));
-            TRACE("sdcard path: %s\n", sdcard_img_path);
-
-            //mloop_evcmd_usbdisk(sdcard_img_path);
-            mloop_evcmd_sdcard(sdcard_img_path);
-
-            g_free(sdcard_path);
-        } else {
-            INFO("failed to get sdcard path!!\n");
-        }
-    } else {
-        INFO("!!! unknown command : %s\n", ret);
-    }
-}
-#endif
-
-#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) {
-        notify_sdb_daemon_start();
-    } else if (strcmp(command, "5\n") == 0) {
-        register_sdb_server(readbuf, client_addr);
-    } 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 server_process(void)
-{
-    int read_cnt = 0;
-    struct sockaddr_in client_addr;
-    socklen_t client_len;
-    char readbuf[RECV_BUF_SIZE + 1];
-
-    client_len = sizeof(client_addr);
-
-    running = 1;
-
-    while (running) {
-        memset(&readbuf, 0, sizeof(readbuf));
-
-        if (server_sock == 0) {
-            INFO("server_sock is closed\n");
-            return;
-        }
-        read_cnt = recvfrom(server_sock, readbuf, RECV_BUF_SIZE, 0,
-                            (struct sockaddr*) &client_addr, &client_len);
-
-        if (read_cnt < 0) {
-            if (errno == EAGAIN || errno == EWOULDBLOCK) {
-#ifdef _WIN32
-                Sleep(2);
-#else
-                usleep(2000);
-#endif
-                continue;
-            }
-            INFO("fail to recvfrom in guest_server:%d\n", errno);
-            break;
-        } else if (read_cnt == 0) {
-            INFO("read_cnt is 0.\n");
-            break;
-        }
-
-        TRACE("================= recv =================\n");
-        TRACE("read_cnt:%d\n", read_cnt);
-        TRACE("readbuf:%s\n", readbuf);
-
-        command_handler(readbuf, &client_addr);
-
-    }
-}
-
-static void close_clients(void)
-{
-    qemu_mutex_lock(&mutex_clients);
-    GS_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)
-{
-    close_clients();
-#ifdef _WIN32
-    if (server_sock) {
-        closesocket(server_sock);
-    }
-#else
-    if (server_sock) {
-        close(server_sock);
-    }
-#endif
-    server_sock = 0;
-
-    qemu_mutex_destroy(&mutex_clients);
-}
-
-static void* run_guest_server(void* args)
-{
-    uint16_t port = svr_port;
-    int opt = 1;
-    int ret = 0;
-    struct sockaddr_in server_addr;
-
-    INFO("start guest server thread.\n");
-
-    if ((server_sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
-        INFO("create listen socket error:%d\n", errno);
-
-        close_server();
-
-        return NULL;
-    }
-
-    memset(&server_addr, '\0', sizeof(server_addr));
-    server_addr.sin_family = PF_INET;
-    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
-    server_addr.sin_port = htons(port);
-
-    qemu_set_nonblock(server_sock);
-
-    ret = qemu_setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
-    if (ret == -1) {
-        INFO("setsockopt SO_REUSEADDR is failed.: %d\n", errno);
-        close_server();
-        return NULL;
-    }
-
-    if (bind(server_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
-        INFO("guest server bind error: %d", errno);
-
-        close_server();
-
-        return NULL;
-    } else {
-        INFO("success to bind port[127.0.0.1:%d/udp] for guest_server in host\n", port);
-    }
-
-    INFO("guest server start...port:%d\n", port);
-
-    qemu_mutex_init(&mutex_clients);
-
-    server_process();
-
-    close_server();
-
-    return NULL;
-}
-
-static void shutdown_guest_server(void)
-{
-    void *ret = NULL;
-    INFO("shutdown_guest_server.\n");
-
-    running = 0;
-
-    ret = qemu_thread_join(&guest_thread_id);
-    if (ret)
-        INFO("guest_thread_id join failed.\n");
-}
-
-static void guest_server_notify_exit(Notifier *notifier, void *data) {
-    shutdown_guest_server();
-}
-static Notifier guest_server_exit = { .notify = guest_server_notify_exit };
-
-void start_guest_server(int server_port)
-{
-    svr_port = server_port;
-    qemu_thread_create(&guest_thread_id, "guest_server", run_guest_server, NULL, QEMU_THREAD_JOINABLE);
-    INFO("created guest server thread\n");
-
-    emulator_add_exit_notifier(&guest_server_exit);
-}
index 9bb2b68..abaf96c 100644 (file)
@@ -31,7 +31,7 @@
 #include "sysemu/sysemu.h"
 
 #include "debug_ch.h"
-#include "guest_server.h"
+#include "sdb_noti_server.h"
 
 /* define debug channel */
 MULTI_DEBUG_CHANNEL(tizen, maru_pm);
diff --git a/tizen/src/sdb_noti_server.c b/tizen/src/sdb_noti_server.c
new file mode 100644 (file)
index 0000000..252b770
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * Emulator SDB Notification Server
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ *  Jinhyung choi   <jinhyung2.choi@samsung.com>
+ *  MunKyu Im       <munkyu.im@samsung.com>
+ *  Sangho Park     <sangho1206.park@samsung.com>
+ *  YeongKyoon Lee  <yeongkyoon.lee@samsung.com>
+ *
+ * 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 "qemu/sockets.h"
+
+#include "hw/maru_virtio_hwkey.h"
+#include "hw/maru_pm.h"
+#include "skin/maruskin_server.h"
+#include "ecs/ecs.h"
+
+#include "emulator.h"
+#include "debug_ch.h"
+#include "sdb_noti_server.h"
+
+MULTI_DEBUG_CHANNEL(qemu, sdb_noti);
+
+#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 [32];
+
+    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) {
+        notify_sdb_daemon_start();
+    } else if (strcmp(command, "5\n") == 0) {
+        register_sdb_server(readbuf, client_addr);
+    } 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;
+    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 = inet_addr("127.0.0.1");
+    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 };
+
+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);
+}
+
similarity index 68%
rename from tizen/src/guest_server.h
rename to tizen/src/sdb_noti_server.h
index 2f0404d..9aaf7b3 100644 (file)
@@ -1,13 +1,13 @@
 /*
+ * Emulator SDB Notification Server
  *
- *
- * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Contact:
- * JiHye Kim <jihye1128.kim@samsung.com>
- * GiWoong Kim <giwoong.kim@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- * Hyunjun Son
+ *  Jinhyung choi   <jinhyung2.choi@samsung.com>
+ *  MunKyu Im       <munkyu.im@samsung.com>
+ *  Sangho Park     <sangho1206.park@samsung.com>
+ *  YeongKyoon Lee  <yeongkyoon.lee@samsung.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  *
  */
 
+#ifndef SDB_NOTI_SERVER_H_
+#define SDB_NOTI_SERVER_H_
 
-#ifndef GUEST_SERVER_H_
-#define GUEST_SERVER_H_
-
-#include <pthread.h>
-
-void start_guest_server( int server_port );
+void start_sdb_noti_server(int server_port);
 
 #define STATE_RUNNING 0
 #define STATE_SUSPEND 1
 void notify_all_sdb_clients(int state);
 
-#endif /* GUEST_SERVER_H_ */
+#endif