net: support bridged network
authorMunkyu Im <munkyu.im@samsung.com>
Fri, 8 May 2015 13:23:33 +0000 (22:23 +0900)
committerMunkyu Im <munkyu.im@samsung.com>
Fri, 8 May 2015 13:23:33 +0000 (22:23 +0900)
Change-Id: Ia38c660d8ddf8b19325bf1817b96ad809f65714a
Signed-off-by: Munkyu Im <munkyu.im@samsung.com>
12 files changed:
include/net/tap.h
net/tap-linux.c
tizen/src/emul_state.c
tizen/src/emul_state.h
tizen/src/emulator.c
tizen/src/emulator_common.h
tizen/src/scripts/emulator-ifup-darwin.sh [new file with mode: 0755]
tizen/src/scripts/emulator-ifup-linux.sh [new file with mode: 0755]
tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java
tizen/src/skin/client/src/org/tizen/emulator/skin/config/EmulatorConfig.java
tizen/src/skin/maruskin_client.c
tizen/src/ui/menu/contextmenu.cpp

index 6daeb42..cf7021a 100644 (file)
@@ -28,6 +28,9 @@
 
 #include "qemu-common.h"
 #include "qapi-types.h"
+#if defined(CONFIG_MARU)
+#include "tizen/src/emul_state.h"
+#endif
 
 int tap_enable(NetClientState *nc);
 int tap_disable(NetClientState *nc);
index 812bf2d..f960781 100644 (file)
 
 #define PATH_NET_TUN "/dev/net/tun"
 
+#if defined(CONFIG_MARU)
+static int launch_openvpn(bool ismake, const char *ifname)
+{
+    int pid, status;
+    const char* args[] = {
+        "/usr/bin/sudo",
+        "/usr/sbin/openvpn",
+        "--mktun",
+        "--dev",
+        ifname,
+        NULL
+    };
+    if (ismake) {
+        fprintf(stdout, "launch_openvpn make tap: %s\n", ifname);
+    } else {
+        fprintf(stdout, "launch_openvpn remove tap: %s\n", ifname);
+        args[2] = "--rmtun";
+    }
+    /* try to launch network script */
+    pid = fork();
+    if (pid == 0) {
+        execv(args[0], (char**)args);
+        _exit(1);
+    } else if (pid > 0) {
+        while (waitpid(pid, &status, 0) != pid) {
+            /* loop */
+        }
+
+        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+            return 0;
+        }
+    }
+    fprintf(stderr, "Could not launch openvpn\n");
+    return -1;
+}
+
+static int tap_cleanup(void)
+{
+    int fd, ret;
+    struct ifreq ifr;
+    char dname[100];
+    int port = get_emul_vm_base_port() + 10;
+
+    TFR(fd = open(PATH_NET_TUN, O_RDWR));
+    if (fd < 0) {
+        error_report("could not open %s: %m", PATH_NET_TUN);
+        return -1;
+    }
+    memset(&ifr, 0, sizeof(ifr));
+    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+
+    for ( ; port < 26200; port += 10) {
+        snprintf(dname, sizeof(dname), "tap%d", port);
+        pstrcpy(ifr.ifr_name, IFNAMSIZ, dname);
+        ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
+        if (ret == 0) {
+            close(fd);
+            if (launch_openvpn(false, dname)) {
+                fprintf(stderr, "Failed to remove %s device. It can be used on the other emulator\n", dname);
+            }
+            TFR(fd = open(PATH_NET_TUN, O_RDWR));
+            if (fd < 0) {
+                error_report("could not open %s: %m", PATH_NET_TUN);
+                return -1;
+            }
+        } else {
+            close(fd);
+        }
+    }
+    return 0;
+}
+
+#endif
+
 int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
              int vnet_hdr_required, int mq_required)
 {
@@ -43,7 +117,11 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     int fd, ret;
     int len = sizeof(struct virtio_net_hdr);
     unsigned int features;
-
+#if defined(CONFIG_MARU)
+    if (tap_cleanup() < 0) {
+        return -1;
+    }
+#endif
     TFR(fd = open(PATH_NET_TUN, O_RDWR));
     if (fd < 0) {
         error_report("could not open %s: %m", PATH_NET_TUN);
@@ -97,8 +175,20 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
 
     if (ifname[0] != '\0')
         pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname);
-    else
+    else {
+#if defined(CONFIG_MARU)
+        /* Create tap */
+        char dname[100];
+        snprintf(dname, sizeof dname, "tap%d", get_emul_vm_base_port());
+        if (launch_openvpn(true, dname)) {
+            close(fd);
+            return -1;
+        }
+        pstrcpy(ifr.ifr_name, IFNAMSIZ, dname);
+#else
         pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d");
+#endif
+    }
     ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
     if (ret != 0) {
         if (ifname[0] != '\0') {
index d56a519..b39efe9 100644 (file)
@@ -189,6 +189,36 @@ char* get_emul_guest_ip(void)
     return _emul_info.guest_ip;
 }
 
+void set_emul_host_ip(char *kernel_cmdline)
+{
+#ifdef SUPPORT_LEGACY_ARGS
+    char *buf = strstr(kernel_cmdline, HOST_IP_PREFIX);
+#else
+    char *buf = get_variable("host_ip");
+#endif
+    if (buf) {
+        char buf_host_ip[MAXLEN] = {0,};
+        int len = strlen(HOST_IP_PREFIX);
+        int i, j;
+        int max_len = strlen(buf);
+        for(i = len, j = 0; i < max_len; i++) {
+            if (buf[i] == ' ' || buf[i] == '\0')
+                break;
+            buf_host_ip[j++] = buf[i];
+        }
+
+        buf_host_ip[j] = '\0';
+        LOG_INFO("host_ip information=%s\n", buf_host_ip);
+        strncpy(_emul_info.host_ip, buf_host_ip, sizeof(_emul_info.host_ip));
+    }
+}
+
+char* get_emul_host_ip(void)
+{
+    LOG_INFO("host ip: %s\n", _emul_info.guest_ip);
+    return _emul_info.host_ip;
+}
+
 /* maximum number of touch point */
 void set_emul_max_touch_point(int cnt)
 {
@@ -387,6 +417,35 @@ char* get_emul_vm_name(void)
     return _emul_info.vm_name;
 }
 
+/* emualtor http proxy */
+void set_emul_http_proxy_addr(char *addr)
+{
+    strncpy(_emul_info.http_proxy_addr, addr, sizeof(_emul_info.http_proxy_addr));
+}
+
+char* get_emul_http_proxy_addr(void)
+{
+    if (strlen(_emul_info.http_proxy_addr) > 0) {
+        return _emul_info.http_proxy_addr;
+    } else {
+        return NULL;
+    }
+}
+
+void set_emul_http_proxy_port(char *port)
+{
+    strncpy(_emul_info.http_proxy_port, port, sizeof(_emul_info.http_proxy_port));
+}
+
+char* get_emul_http_proxy_port(void)
+{
+    if (strlen(_emul_info.http_proxy_port) > 0) {
+        return _emul_info.http_proxy_port;
+    } else {
+        return NULL;
+    }
+}
+
 void set_emul_hds_attached(bool attached)
 {
     _emul_state.hds_attached = attached;
index b2146bc..56534ce 100644 (file)
@@ -37,6 +37,8 @@
 #include "display/maru_finger.h"
 
 #define SUPPORT_LEGACY_ARGS
+#define MAX_ADDR_LEN    256
+#define MAX_PORT_LEN    256
 
 #define MAX_HDS_PATH    256
 #define MAX_PROFILE     256
@@ -97,8 +99,12 @@ typedef  struct EmulatorConfigInfo {
     int vm_base_port;
     int device_serial_number;
     int ecs_port;
+    char http_proxy_addr[MAX_ADDR_LEN];
+    char http_proxy_port[MAX_PORT_LEN];
+
     bool tap_enable;
     char guest_ip[16];
+    char host_ip[16];
 
     int spice_port;
     char *vm_name;
@@ -147,6 +153,7 @@ void set_emul_max_touch_point(int cnt);
 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);
 void set_emul_vm_name(char *vm_name);
 void set_emul_skin_path(char *path);
 void set_emul_gpu_accel(bool enable);
@@ -159,6 +166,8 @@ void set_emul_rotation(short rotation_type);
 void set_emul_caps_lock_state(int state);
 void set_emul_num_lock_state(int state);
 void set_emul_tap_enable(bool enable);
+void set_emul_http_proxy_addr(char *addr);
+void set_emul_http_proxy_port(char *port);
 void set_emul_hds_attached(bool attached);
 void set_emul_hds_path(const char *path);
 void set_emul_hds_guest_path(const char *path);
@@ -195,7 +204,10 @@ int get_host_lock_key_state_darwin(int key);
 int get_emul_caps_lock_state(void);
 int get_emul_num_lock_state(void);
 char* get_emul_guest_ip(void);
+char* get_emul_host_ip(void);
 bool is_emul_tap_enable(void);
+char* get_emul_http_proxy_addr(void);
+char* get_emul_http_proxy_port(void);
 
 bool get_emul_hds_attached(void);
 char* get_emul_hds_path(void);
index bd4ef2e..ad1b7d9 100644 (file)
@@ -172,6 +172,43 @@ static void print_options_info(void)
     fprintf(stdout, "\n====================================================\n");
 }
 
+static void http_proxy_setup(gchar * const kernel_cmdline)
+{
+#ifdef SUPPORT_LEGACY_ARGS
+    char *buf = strstr(kernel_cmdline, HTTP_PROXY_PREFIX);
+#else
+    char *buf = get_variable("network_proxy");
+#endif
+    gchar** proxy;
+    if (buf) {
+        char http_proxy[MAXLEN] = {0,};
+        int len = strlen(HTTP_PROXY_PREFIX);
+        int i, j;
+        int max_len = strlen(buf);
+        for(i = len, j = 0; i < max_len; i++) {
+            if (buf[i] == ' ')
+                break;
+            http_proxy[j++] = buf[i];
+        }
+
+        http_proxy[j] = '\0';
+        proxy = g_strsplit(http_proxy, ":", -1);
+        if (g_strv_length(proxy) > 1) {
+            if (proxy[0] != NULL && proxy[1] != NULL) {
+                LOG_INFO("http_proxy information= addr: %s, port: %s\n", proxy[0], proxy[1]);
+                set_emul_http_proxy_addr(proxy[0]);
+                set_emul_http_proxy_port(proxy[1]);
+            }
+        } else {
+            LOG_INFO("http proxy is NULL\n");
+        }
+
+        if (proxy != NULL) {
+            g_strfreev(proxy);
+        }
+    }
+}
+
 #define PROXY_BUFFER_LEN  128
 static void prepare_basic_features(gchar * const kernel_cmdline)
 {
@@ -193,6 +230,8 @@ static void prepare_basic_features(gchar * const kernel_cmdline)
             " vm_resolution=%dx%d", get_emul_vm_base_port(),
             get_emul_resolution_width(), get_emul_resolution_height());
 
+    http_proxy_setup(kernel_cmdline);
+
     g_strlcat(kernel_cmdline, tmp_str, LEN_MARU_KERNEL_CMDLINE);
 
     g_free(tmp_str);
index 99821be..34142b2 100644 (file)
 #endif
 
 #define JAVA_MAX_COMMAND_LENGTH 1024
+#define MAXLEN  512
+#define HTTP_PROXY_PREFIX "http_proxy="
+#define HOST_IP_PREFIX "host_ip="
+
 
 #define JAR_SKINFILE "emulator-skin.jar"
 #define JAVA_LIBRARY_PATH "-Djava.library.path"
diff --git a/tizen/src/scripts/emulator-ifup-darwin.sh b/tizen/src/scripts/emulator-ifup-darwin.sh
new file mode 100755 (executable)
index 0000000..2a0ed71
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh -x
+BRIDGE=bridge1
+TAP=$1
+BASE=en0
+
+#get base network information
+IP=`ipconfig getifaddr $BASE`
+NETMASK=`ifconfig $BASE | grep "inet " | awk '{print $4}'`
+GW=`netstat -rn | grep ^default | awk '{print $2}'`
+
+#create bridge interface
+CHECK_BR=`ifconfig | grep ^bridge1:`
+if [ "$CHECK_BR" = "" ]
+then
+    ifconfig $BRIDGE create
+fi
+
+#add base network and tap device to bridge
+ifconfig $BRIDGE addm $BASE
+ifconfig $BRIDGE addm $TAP
+ifconfig $BRIDGE up
+
+#set IP of base network to bridge
+ifconfig $BASE delete $IP
+ifconfig $BRIDGE $IP netmask $NETMASK
+
+#change network interface of default gateway
+NET=`netstat -rn | grep ^default | awk '{print $6}'`
+if [ $NET != $BRIDGE ];then
+route change default $GW
+fi
diff --git a/tizen/src/scripts/emulator-ifup-linux.sh b/tizen/src/scripts/emulator-ifup-linux.sh
new file mode 100755 (executable)
index 0000000..3e059ff
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/sh +x
+
+BASEIF=eth0
+NETMASK=`ifconfig $BASE | grep "inet " | awk '{print $4}' | cut -d : -f2`
+GW=`netstat -rn | grep ^0.0.0.0 | awk '{print $2}'`
+BR=br-tizen-vm-1
+
+# Check if bridge interface exists.
+CHECK_BR=`ifconfig $BR`
+if [ "$CHECK_BR" = "" ]
+then
+    BASEIPADDR=`ip addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1`
+    brctl addbr $BR
+else
+    BASEIPADDR=`ip addr show $BR | awk '/inet / {print $2}' | cut -d/ -f1`
+fi
+
+# ifconfig up tap device.
+ifconfig $1 0.0.0.0 promisc up
+
+# Take interface down.
+ifdown $BASEIF
+ifconfig $BASEIF 0.0.0.0 promisc up
+
+# Add tap device and interface to bridge.
+brctl addif $BR $BASEIF
+brctl addif $BR $1
+
+# Add the default route.
+ifconfig $BR $BASEIPADDR netmask $NETMASK
+
+NET=`netstat -rn | grep ^0.0.0.0 | awk '{print $8}'`
+if [ "$NET" != "$BR" ]
+then
+    route add default gw $GW
+fi
+exit 0
index 31982a5..bc7c714 100644 (file)
@@ -1934,21 +1934,46 @@ public class EmulatorSkin {
                 }
 
                 String emulName = SkinUtil.getVmName(config);
-                int portSdb = config.getArgInt(ArgsConstants.VM_BASE_PORT);
+                               int basePort = config.getArgInt(ArgsConstants.VM_BASE_PORT);
+                               String proxyAddr = config.getArg(ArgsConstants.PROXY_ADDR);
+                               String proxyPort = config.getArg(ArgsConstants.PROXY_PORT);
 
                                ProcessBuilder procEcp = new ProcessBuilder();
 
                                // FIXME: appropriate running binary setting is necessary.
                                if (SwtUtil.isWindowsPlatform()) {
-                                       procEcp.command("java.exe", "-jar", ecpPath, "vmname="
-                                                       + emulName, "base.port=" + portSdb);
+                                       if (proxyAddr != null && proxyPort != null) {
+                                               procEcp.command("java.exe", "-Dhttp.proxyHost="
+                                                               + proxyAddr, "-Dhttp.proxyPort=" + proxyPort,
+                                                               "-jar", ecpPath, "vmname=" + emulName,
+                                                               "base.port=" + basePort);
+                                       } else {
+                                               procEcp.command("java.exe", "-jar", ecpPath, "vmname="
+                                                               + emulName, "base.port=" + basePort);
+                                       }
                                } else if (SwtUtil.isMacPlatform()) {
-                                       procEcp.command("java", "-jar", "-XstartOnFirstThread",
-                                                       ecpPath, "vmname=" + emulName, "base.port="
-                                                                       + portSdb);
+                                       if (proxyAddr != null && proxyPort != null) {
+                                               procEcp.command("java",
+                                                               "-Dhttp.proxyHost=" + proxyAddr,
+                                                               "-Dhttp.proxyPort=" + proxyPort, "-jar",
+                                                               "-XstartOnFirstThread", ecpPath, "vmname="
+                                                                               + emulName, "base.port=" + basePort);
+                                       } else {
+                                               procEcp.command("java", "-jar", "-XstartOnFirstThread",
+                                                               ecpPath, "vmname=" + emulName, "base.port="
+                                                                               + basePort);
+                                       }
                                } else { /* Linux */
-                                       procEcp.command("java", "-jar", ecpPath, "vmname="
-                                                       + emulName, "base.port=" + portSdb);
+                                       if (proxyAddr != null && proxyPort != null) {
+                                               procEcp.command("java",
+                                                               "-Dhttp.proxyHost=" + proxyAddr,
+                                                               "-Dhttp.proxyPort=" + proxyPort, "-jar",
+                                                               ecpPath, "vmname=" + emulName, "base.port="
+                                                                               + basePort);
+                                       } else {
+                                               procEcp.command("java", "-jar", ecpPath, "vmname="
+                                                               + emulName, "base.port=" + basePort);
+                                       }
                                }
 
                                logger.info(procEcp.command().toString());
index 7e30c44..ddd2848 100644 (file)
@@ -82,6 +82,8 @@ public class EmulatorConfig {
                public static final String INPUT_MOUSE = "input.mouse";
                public static final String INPUT_TOUCHSCREEN = "input.touch";
                public static final String INPUT_TOUCH_MAXPOINT = "input.touch.maxpoint";
+               public static final String PROXY_ADDR = "proxy.addr";
+               public static final String PROXY_PORT = "proxy.port";
        }
 
        public interface SkinPropertiesConstants {
index 589a287..953019a 100644 (file)
@@ -66,6 +66,8 @@ MULTI_DEBUG_CHANNEL(qemu, skinclient);
 #define OPT_INPUT_MOUSE "input.mouse"
 #define OPT_INPUT_TOUCH "input.touch"
 #define OPT_MAX_TOUCHPOINT "input.touch.maxpoint"
+#define OPT_PROXY_ADDR "proxy.addr"
+#define OPT_PROXY_PORT "proxy.port"
 
 #define OPT_BOOLEAN_TRUE "true"
 #define OPT_BOOLEAN_FALSE "false"
@@ -103,9 +105,9 @@ static void *run_skin_client(void *arg)
     int skin_server_port = get_skin_server_port();
     int vm_base_port = get_emul_vm_base_port();
 
-    char buf_skin_server_port[16];
-    char buf_uid[16];
-    char buf_vm_base_port[16];
+    char buf_skin_server_port[16] = { 0, };
+    char buf_uid[16] = { 0, };
+    char buf_vm_base_port[16] = { 0, };
     sprintf(buf_skin_server_port, "%d", skin_server_port);
     sprintf(buf_uid, "%d", uid);
     sprintf(buf_vm_base_port, "%d", vm_base_port);
@@ -126,10 +128,26 @@ static void *run_skin_client(void *arg)
 
     /* input */
     char buf_input[12] = { 0, };
-    if (is_emul_input_mouse_enable() == true)
+    if (is_emul_input_mouse_enable() == true) {
         strcpy(buf_input, OPT_INPUT_MOUSE);
-    else
+    } else {
         strcpy(buf_input, OPT_INPUT_TOUCH);
+    }
+
+    /* network */
+    gchar const* proxy_addr;
+    int proxy_addr_len = 0;
+
+    if (get_emul_http_proxy_addr() == NULL) {
+        proxy_addr = g_strdup_printf("%s= %s=",
+                OPT_PROXY_ADDR, OPT_PROXY_PORT);
+        proxy_addr_len = (int)strlen(proxy_addr);
+    } else {
+        proxy_addr = g_strdup_printf("%s=%s %s=%s",
+                OPT_PROXY_ADDR, get_emul_http_proxy_addr(),
+                OPT_PROXY_PORT, get_emul_http_proxy_port());
+        proxy_addr_len = (int)strlen(proxy_addr);
+    }
 
 #ifdef CONFIG_WIN32
     /* find java path in 64bit windows */
@@ -187,7 +205,8 @@ static void *run_skin_client(void *arg)
         strlen(buf_input) + EQUAL_LEN +
             strlen(OPT_BOOLEAN_TRUE) + SPACE_LEN +
         strlen(OPT_MAX_TOUCHPOINT) + EQUAL_LEN +
-            len_maxtouchpoint + SPACE_LEN + 1 +
+            len_maxtouchpoint + SPACE_LEN +
+        proxy_addr_len + SPACE_LEN + 1 +
         strlen(argv);
 
     INFO("skin command length : %d\n", cmd_len);
@@ -207,6 +226,7 @@ static void *run_skin_client(void *arg)
 %s=%s \
 %s=%s \
 %s=%d \
+%s \
 %s",
         JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAVA_LIBRARY_PATH,
 #ifdef CONFIG_WIN32
@@ -221,6 +241,7 @@ static void *run_skin_client(void *arg)
         OPT_DISPLAY_SHM, buf_display_shm,
         buf_input, OPT_BOOLEAN_TRUE,
         OPT_MAX_TOUCHPOINT, maxtouchpoint,
+        proxy_addr,
         argv);
 
     INFO("command for swt : %s\n", cmd);
index 1dc5f7e..efc25da 100644 (file)
@@ -673,6 +673,17 @@ void ContextMenu::slotControlPanel()
     /* SWT Display must be created on main thread due to Cocoa restrictions */
     arguments << "-XstartOnFirstThread";
 #endif
+    QString httpProxyAddr;
+    QString httpProxyPort;
+    if (get_emul_http_proxy_addr()) {
+        httpProxyAddr = "-Dhttp.proxyHost=" + QString(get_emul_http_proxy_addr());
+        httpProxyPort = "-Dhttp.proxyPort=" + QString(get_emul_http_proxy_port());
+    }
+
+    if (httpProxyAddr != NULL && httpProxyPort != NULL) {
+        arguments << httpProxyAddr << httpProxyPort;
+    }
+
     arguments << "-jar" << ecpPath << vmNameOpt << basePortOpt;
     qDebug() << command << arguments;