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を再起動する必要があります。