web-viewer: added init and shutdown logic of nodejs and websocket 04/28204/12
authorsungmin ha <sungmin82.ha@samsung.com>
Tue, 30 Sep 2014 08:22:53 +0000 (17:22 +0900)
committersungmin ha <sungmin82.ha@samsung.com>
Mon, 6 Oct 2014 06:35:27 +0000 (15:35 +0900)
Change-Id: Ib9c9f99be49f6e40f51cb16506adc9d61bb66f1a
Signed-off-by: sungmin ha <sungmin82.ha@samsung.com>
tizen/src/emul_state.c
tizen/src/emul_state.h
tizen/src/emulator.c
tizen/src/util/osutil-linux.c
tizen/src/util/osutil.h
vl.c

index 02bdca72f6e7ccc54c34c85dc0f404c836115301..0f47b12fd67e3526d90acd0d0f2db2af2d5c4623 100644 (file)
@@ -46,12 +46,17 @@ static EmulatorConfigInfo _emul_info = {0,};
 static EmulatorConfigState _emul_state;
 
 /* misc */
+char remote_bin_path[PATH_MAX] = { 0, };
 char bin_path[PATH_MAX] = { 0, };
 #ifdef SUPPORT_LEGACY_ARGS
 // for compatibility
 char log_path[PATH_MAX] = { 0, };
 #endif
 
+const char *get_remote_bin_path(void)
+{
+    return remote_bin_path;
+}
 
 const char *get_bin_path(void)
 {
@@ -188,6 +193,12 @@ void set_emul_vm_base_port(int port)
     _emul_info.ecs_port = port + 3;
     _emul_info.serial_port = port + 4;
     _emul_info.spice_port = port + 5;
+    _emul_info.websocket_port = port + 6;
+}
+
+int get_emul_websocket_port(void)
+{
+    return _emul_info.websocket_port;
 }
 
 int get_emul_spice_port(void)
index 9e59d5bbb0718e355e36d0ca02afa26385d7f1a2..5c9d599651b9a000d92e83403873872966379fa6 100644 (file)
@@ -96,6 +96,7 @@ typedef  struct EmulatorConfigInfo {
     int device_serial_number;
     int ecs_port;
     int spice_port;
+    int websocket_port;
     char *vm_name;
     /* add here */
     int serial_port;
@@ -112,11 +113,13 @@ typedef struct EmulatorConfigState {
 } EmulatorConfigState;
 
 /* misc */
+extern char remote_bin_path[];
 extern char bin_path[];
 #ifdef SUPPORT_LEGACY_ARGS
 extern char log_path[];
 #endif
 
+char const *get_remote_bin_path(void);
 char const *get_bin_path(void);
 char const *get_log_path(void);
 
@@ -151,6 +154,7 @@ int get_device_serial_number(void);
 int get_emul_ecs_port(void);
 int get_emul_serial_port(void);
 int get_emul_spice_port(void);
+int get_emul_websocket_port(void);
 
 int get_emulator_condition(void);
 short get_emul_rotation(void);
index 73a2544a8f60dab795aa211720f8d732e092ddea..a66de955bfbf2ef9d3a1ab0958c2b804e6cdb161 100644 (file)
@@ -206,6 +206,10 @@ static void prepare_basic_features(gchar * const kernel_cmdline)
 
     set_base_port();
 
+#if defined(CONFIG_SPICE) && defined(CONFIG_LINUX)
+    clean_websocket_port(SIGKILL);
+#endif
+
     check_vm_lock();
     make_vm_lock();
 
index 53c5882276341dbeec2799acb778800cf67db5b3..a6884396e69736cf64e55a5d5ab75dc011dc164d 100644 (file)
@@ -53,6 +53,9 @@
 #include <linux/version.h>
 #include <sys/utsname.h>
 #include <sys/sysinfo.h>
+#ifdef CONFIG_SPICE
+#include <dirent.h>
+#endif
 
 MULTI_DEBUG_CHANNEL(emulator, osutil);
 
@@ -173,6 +176,11 @@ void set_bin_path_os(char const *const exec_argv)
     g_strlcpy(bin_path, link_path, strlen(link_path) - strlen(file_name) + 1);
 
     g_strlcat(bin_path, "/", PATH_MAX);
+
+#ifdef CONFIG_SPICE
+    g_strlcpy(remote_bin_path, link_path, strlen(link_path) - strlen(file_name) - 2);
+    g_strlcat(remote_bin_path, "remote/bin/", PATH_MAX);
+#endif
 }
 
 int get_number_of_processors(void)
@@ -445,3 +453,209 @@ void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, cha
     }
     pclose(output);
 }
+
+#ifdef CONFIG_SPICE
+#define PID_MAX_COUNT 256
+const char *execution_file_websocket = "websockify.py";
+const char *execution_file_node = "node";
+const char *node_proc_name = "emulator-x86-web";
+
+void get_process_id(char const *process_name, char *first_param, int *pid, int *pscount)
+{
+    char cmdline[2048], dir_name[255];
+    int total_len = 0, current_len = 0;
+    struct dirent *dir_entry_p;
+    DIR *dir_p;
+    FILE *fp;
+    char *mptr;
+
+    dir_p = opendir("/proc/");
+    while (NULL != (dir_entry_p = readdir(dir_p))) {
+        /* Checking for numbered directories */
+        if (strspn(dir_entry_p->d_name, "0123456789") == strlen(dir_entry_p->d_name)) {
+            strcpy(dir_name, "/proc/");
+            strcat(dir_name, dir_entry_p->d_name);
+            strcat(dir_name, "/cmdline");
+
+            fp = fopen(dir_name, "rb");
+            if (fp == NULL) {
+                continue;
+            }
+
+            total_len = 0;
+            memset(cmdline, 0, sizeof(cmdline));
+            while (!feof(fp)) {
+                cmdline[total_len++] = fgetc(fp);
+            }
+
+            fclose(fp);
+            current_len = strlen(cmdline);
+            mptr = cmdline;
+            do {
+                if (strstr(mptr, process_name) != NULL) {
+                    if (!first_param || strstr(&cmdline[current_len + 1], first_param) != NULL) {
+                        if (sizeof(pid) < *pscount + 1) {
+                            WARN("PID array size is not enough.\n");
+                            return;
+                        }
+                        pid[*pscount] = atoi(dir_entry_p->d_name);
+                        INFO("get_process_id(%s %s) :Found. id = %d\n", process_name, first_param, pid[*pscount]);
+                        (*pscount)++;
+                    }
+                    break;
+                }
+
+                mptr = &cmdline[current_len + 1];
+                current_len += strlen(mptr) + 1;
+            } while (current_len < total_len);
+        }
+    }
+
+    closedir(dir_p);
+    if (*pscount == 0) {
+        INFO("get_process_id(%s %s) : id = 0 (could not find process)\n", process_name, first_param);
+    }
+}
+
+void execute_websocket(int port)
+{
+    char const *remote_bin_dir = get_remote_bin_path();
+    char const *relative_path = "../websocket/";
+    char websocket_path[strlen(remote_bin_dir) + strlen(execution_file_websocket) + strlen(relative_path) + 1];
+    int ret = -1;
+    char local_port[32];
+    char websocket_port[16];
+
+    memset(websocket_port, 0, sizeof(websocket_port));
+    sprintf(websocket_port, "%d", port);
+
+    memset(local_port, 0, sizeof(local_port));
+    sprintf(local_port, "localhost:%d", get_emul_spice_port());
+
+    memset(websocket_path, 0, sizeof(websocket_path));
+    sprintf(websocket_path, "%s%s%s", remote_bin_dir, relative_path, execution_file_websocket);
+
+    INFO("Exec [%s %s %s]\n", websocket_path, websocket_port, local_port);
+
+    ret = execl(websocket_path, execution_file_websocket, websocket_port, local_port, (char *)0);
+    if (ret == 127) {
+        WARN("Can't execute websocket.\n");
+    } else if (ret == -1) {
+        WARN("Fork error!\n");
+    }
+}
+
+void execute_nodejs(void)
+{
+    char const *remote_bin_dir = get_remote_bin_path();
+    char const *relative_path = "../web-viewer/bin/emul";
+    char webviewer_script[strlen(remote_bin_dir) + strlen(relative_path) + 1];
+    char nodejs_path[strlen(remote_bin_dir) + strlen(execution_file_node) + 1];
+    int ret = -1;
+
+    memset(webviewer_script, 0, sizeof(webviewer_script));
+    sprintf(webviewer_script, "%s%s", remote_bin_dir, relative_path);
+
+    memset(nodejs_path, 0, sizeof(nodejs_path));
+    sprintf(nodejs_path, "%s%s", remote_bin_dir, execution_file_node);
+
+    INFO("Exec [%s %s]\n", nodejs_path, webviewer_script);
+
+    ret = execl(nodejs_path, execution_file_node, webviewer_script, (char *)0);
+    if (ret == 127) {
+        WARN("Can't execute node server.\n");
+    } else if (ret == -1) {
+        WARN("Fork error!\n");
+    }
+}
+
+void clean_websocket_port(int signal)
+{
+    char websocket_port[16];
+    memset(websocket_port, 0, sizeof(websocket_port));
+    sprintf(websocket_port, "%d", get_emul_websocket_port());
+
+    int pscount = 0, i = 0;
+    int pid[PID_MAX_COUNT];
+
+    memset(pid, 0, PID_MAX_COUNT);
+    get_process_id(execution_file_websocket, websocket_port, pid, &pscount);
+    if (pscount > 0) {
+        for (i = 0; i < pscount; i++) {
+            INFO("Will be killed PID: %d\n", pid[i]);
+            kill(pid[i], signal);
+        }
+    }
+}
+
+static void websocket_notify_exit(Notifier *notifier, void *data)
+{
+    clean_websocket_port(SIGTERM);
+}
+
+static void nodejs_notify_exit(Notifier *notifier, void *data)
+{
+    int pscount = 0, i = 0;
+    int pid[PID_MAX_COUNT];
+
+    memset(pid, 0, sizeof(pid));
+    get_process_id("spicevmc", NULL, pid, &pscount);
+    if (pscount == 1) {
+        INFO("Detected the last spice emulator.\n");
+        pid[0] = 0;
+        pscount = 0;
+        get_process_id(node_proc_name, NULL, pid, &pscount);
+        for (i = 0; i < pscount; i++) {
+            INFO("Will be killed %s, PID: %d\n", node_proc_name, pid[i]);
+            kill(pid[i], SIGTERM);
+        }
+    }
+}
+
+static Notifier websocket_exit = { .notify = websocket_notify_exit };
+static Notifier nodejs_exit = { .notify = nodejs_notify_exit };
+
+void websocket_init(void)
+{
+    int pscount = 0;
+    char websocket_port[16];
+    int pid[PID_MAX_COUNT];
+
+    memset(websocket_port, 0, sizeof(websocket_port));
+    sprintf(websocket_port, "%d", get_emul_websocket_port());
+
+    memset(pid, 0, sizeof(pid));
+    get_process_id(execution_file_websocket, websocket_port, pid, &pscount);
+    emulator_add_exit_notifier(&websocket_exit);
+
+    if (pscount == 0) {
+        int pid = fork();
+        if (pid == 0) {
+            setsid();
+            execute_websocket(get_emul_websocket_port());
+        }
+    } else {
+       INFO("Aleady running websokify %s localhost:%d\n", websocket_port, get_emul_spice_port());
+    }
+}
+
+void nodejs_init(void)
+{
+    int pscount = 0;
+    int pid[PID_MAX_COUNT];
+
+    memset(pid, 0, sizeof(pid));
+    get_process_id(node_proc_name, NULL, pid, &pscount);
+    emulator_add_exit_notifier(&nodejs_exit);
+
+    if (pscount == 0) {
+        int pid = fork();
+        if (pid == 0) {
+            setsid();
+            execute_nodejs();
+        }
+    } else {
+       INFO("Aleady running node server.\n");
+    }
+}
+#endif
index f8858237a2b865a6c22844b71fd9d30b9200b10f..64835742284a247a641c8e56bdde7bd9c2c75ec2 100644 (file)
@@ -74,6 +74,15 @@ void download_url(char *);
 size_t write_data(void *, size_t, size_t, FILE *);
 void remove_string(char *, char *, const char *);
 
+#if defined(CONFIG_SPICE) && defined(CONFIG_LINUX)
+void get_process_id(char const *process_name, char *first_param, int *pid, int *pscount);
+void execute_websocket(int port);
+void execute_nodejs(void);
+void clean_websocket_port(int signal);
+void nodejs_init(void);
+void websocket_init(void);
+#endif
+
 static inline int get_timeofday(char *buf, size_t size)
 {
     qemu_timeval tv;
diff --git a/vl.c b/vl.c
index 228b817bb62f2d1818a6857f395da40cdba86c8c..99b6614780bde2042d2067aabbf69d280f86857e 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -150,6 +150,10 @@ extern int enable_spice;
 static const char *yagl_backend = NULL;
 static int enable_vigs = 0;
 static char *vigs_backend = NULL;
+#if defined(CONFIG_SPICE) && defined(CONFIG_LINUX)
+extern void websocket_init(void);
+extern void nodejs_init(void);
+#endif
 #endif
 
 static const char *data_dir[16];
@@ -4370,6 +4374,10 @@ int main(int argc, char **argv, char **envp)
     qemu_mutex_lock_iothread();
 
 #ifdef CONFIG_SPICE
+#if defined(CONFIG_MARU) && defined(CONFIG_LINUX)
+    nodejs_init();
+#endif
+
     /* spice needs the timers to be initialized by this point */
     qemu_spice_init();
 #endif
@@ -4636,6 +4644,9 @@ int main(int argc, char **argv, char **envp)
 #ifdef CONFIG_SPICE
     if (using_spice) {
         qemu_spice_display_init();
+#if defined(CONFIG_MARU) && defined(CONFIG_LINUX)
+        websocket_init();
+#endif
     }
 #endif