2011年08月02日
Androidのemulatorのlocalhost制限を解除する
前回の「Androidのemulator-x86でrubyを動かす」の記事でemulatorの中でWEBサーバを動かしたときに、WEBサーバのportをqemuの-redir オプションでリダイレクトしても、localhostでしか接続することができませんでした。
この件を調べました。
qemuの-redirオプションでportをリダイレクトした時に、オリジナルのqemuではlocalhostでなくても接続することができます。しかし、Androidのemulatorではこれがlocalhostからのみに制限されているようです。つまり前回の例では、http://localhost:8001/ では接続できますが、http://192.168.1.26:8001/ では接続できません。
普通はlocalhostだけアクセスできれば十分なのですが、私はビルド用マシンとUI用マシンを分けているのでこの制限は不便でした。
emulatorのソースコードを調べてみると、サーバソケットをbindしているところでアドレスをloopbackのみに制限していることがわかりました。そして、その部分を修正することで、localhost以外からでもアクセスできるようになりました。
qemuの修正
external/qemu
diff --git a/slirp-android/socket.c b/slirp-android/socket.c
index 439590a..17e6337 100644
--- a/slirp-android/socket.c
+++ b/slirp-android/socket.c
@@ -650,7 +650,11 @@ solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
so->so_laddr_ip = laddr; /* Ditto */
so->so_haddr_port = port;
+#if 0 /*koba */
s = socket_loopback_server( port, SOCKET_STREAM );
+#else
+ s = socket_inaddr_any_server(port, SOCKET_STREAM );
+#endif
if (s < 0)
return NULL;
diff --git a/sockets.c b/sockets.c
index 1063339..21a7869 100644
--- a/sockets.c
+++ b/sockets.c
@@ -1337,7 +1337,13 @@ socket_in_client( SockAddress* to, SocketType type )
return socket_connect_client( s, to );
}
-
+#if 1 /*koba*/
+int
+socket_inaddr_any_server( int port, SocketType type )
+{
+ return socket_in_server( INADDR_ANY, port, type );
+}
+#endif
int
socket_loopback_server( int port, SocketType type )
{
adb forwardの修正
adb forward でも同じようにsocketをリダイレクトしますが、やはりこれもlocalhostのみに制限されています。以下の修正でこの制限を解除できました。
system/core
diff --git a/adb/adb.c b/adb/adb.c
index f5e6e0c..1405e1c 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -481,7 +481,8 @@ int local_name_to_fd(const char *name)
if(!strncmp("tcp:", name, 4)){
int ret;
port = atoi(name + 4);
- ret = socket_loopback_server(port, SOCK_STREAM);
+ //koba ret = socket_loopback_server(port, SOCK_STREAM);
+ ret = socket_inaddr_any_server(port, SOCK_STREAM);
return ret;
}
#ifndef HAVE_WIN32_IPC /* no Unix-domain sockets on Win32 */
adbをリビルドしたら、adb kill-server としてadb serverを再起動する必要があります。