From 72ed50d1e9048b79efdb5b9e4ffb07c99a302d84 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 16 Jan 2015 15:12:40 +0900 Subject: Use the IPv6 instead of the IPv4 wildcard address in sockets. A few places in libcore consider the local address of an unbound socket to be Inet4Address.ANY. For example, calling getLocalAddress on an uncreated Socket will return 0.0.0.0, and when creating a DatagramSocket, libcore attempts to bind it to 0.0.0.0 unless the caller specifies another address. On Android, this is incorrect. All native socket filedescriptors that underpin Java socket objects are created by IoBridge.socket, and are dual-stack AF_INET6 sockets, not AF_INET sockets. When such a socket is created, its local address is ::, not 0.0.0.0. Thus, for example, calling getLocalAddress on a just-created ServerSocket object will return ::. Binding to 0.0.0.0 is not even allowed by os.bind, which silently converts it to :: instead (in inetAddresstoSockaddr). Therefore, accept reality and use :: instead of 0.0.0.0 in the Java layer as well. Specifically: 1. Change DatagramSocket's constructors to bind to :: instead of 0.0.0.0. This is a complete no-op, because os.bind() silently converts 0.0.0.0 into ::. Add a test for the other of the two codepaths. 2. Change InetSocketAddress so that an uninitialized object has an IP address of :: and not 0.0.0.0, and update its test. This is unlikely to break anything short of an app that explicitly depends on this behaviour, because os.bind() converts 0.0.0.0 to ::, and because any SocketAddress returned by any real socket will never contain 0.0.0.0 anyway. 3. Change Socket so that calling getLocalAddress() when there is no underlying socket file descriptor is will return :: instead of 0.0.0.0. This is more correct, because it's consistent with sockets that have been created, which will never have a local address of 0.0.0.0. Tested: vogar $(find libcore/*Socket*Test*) all passes on device. Bug: 18094870 Change-Id: I9d60710fe945a99d6a5e65430248a889008ef4b1 --- .../apache/harmony/tests/java/net/DatagramSocketTest.java | 13 +++++++------ luni/src/main/java/java/net/DatagramSocket.java | 8 ++++---- luni/src/main/java/java/net/InetSocketAddress.java | 2 +- luni/src/main/java/java/net/ServerSocket.java | 8 ++++---- luni/src/main/java/java/net/Socket.java | 12 ++++++------ .../test/java/libcore/java/net/InetSocketAddressTest.java | 4 ++-- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java index e585b14..d9f3d91 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketTest.java @@ -745,12 +745,13 @@ public class DatagramSocketTest extends junit.framework.TestCase { public void test_getLocalSocketAddress_ANY() throws Exception { DatagramSocket s = new DatagramSocket(0); - try { - assertTrue("ANY address not IPv6: " + s.getLocalSocketAddress(), - ((InetSocketAddress) s.getLocalSocketAddress()).getAddress() instanceof Inet6Address); - } finally { - s.close(); - } + assertEquals("ANY address not IPv6: " + s.getLocalSocketAddress(), + Inet6Address.ANY, s.getLocalAddress()); + s.close(); + s = new DatagramSocket(0, null); + assertEquals(Inet6Address.ANY, s.getLocalAddress()); + assertFalse(0 == s.getLocalPort()); + s.close(); } public void test_setReuseAddressZ() throws Exception { diff --git a/luni/src/main/java/java/net/DatagramSocket.java b/luni/src/main/java/java/net/DatagramSocket.java index 01d3bed..3195240 100644 --- a/luni/src/main/java/java/net/DatagramSocket.java +++ b/luni/src/main/java/java/net/DatagramSocket.java @@ -77,7 +77,7 @@ public class DatagramSocket implements Closeable { */ public DatagramSocket(int aPort) throws SocketException { checkPort(aPort); - createSocket(aPort, Inet4Address.ANY); + createSocket(aPort, Inet6Address.ANY); } /** @@ -94,7 +94,7 @@ public class DatagramSocket implements Closeable { */ public DatagramSocket(int aPort, InetAddress addr) throws SocketException { checkPort(aPort); - createSocket(aPort, (addr == null) ? Inet4Address.ANY : addr); + createSocket(aPort, (addr == null) ? Inet6Address.ANY : addr); } private void checkPort(int aPort) { @@ -443,7 +443,7 @@ public class DatagramSocket implements Closeable { private void ensureBound() throws SocketException { if (!isBound()) { - impl.bind(0, Inet4Address.ANY); + impl.bind(0, Inet6Address.ANY); isBound = true; } } @@ -467,7 +467,7 @@ public class DatagramSocket implements Closeable { InetAddress addr; if (localAddr == null) { localPort = 0; - addr = Inet4Address.ANY; + addr = Inet6Address.ANY; } else { if (!(localAddr instanceof InetSocketAddress)) { throw new IllegalArgumentException("Local address not an InetSocketAddress: " + diff --git a/luni/src/main/java/java/net/InetSocketAddress.java b/luni/src/main/java/java/net/InetSocketAddress.java index f12c399..1b3eabe 100644 --- a/luni/src/main/java/java/net/InetSocketAddress.java +++ b/luni/src/main/java/java/net/InetSocketAddress.java @@ -67,7 +67,7 @@ public class InetSocketAddress extends SocketAddress { if (port < 0 || port > 65535) { throw new IllegalArgumentException("port=" + port); } - this.addr = (address == null) ? Inet4Address.ANY : address; + this.addr = (address == null) ? Inet6Address.ANY : address; this.hostname = null; this.port = port; } diff --git a/luni/src/main/java/java/net/ServerSocket.java b/luni/src/main/java/java/net/ServerSocket.java index b1d59d5..a2cd9c6 100644 --- a/luni/src/main/java/java/net/ServerSocket.java +++ b/luni/src/main/java/java/net/ServerSocket.java @@ -72,7 +72,7 @@ public class ServerSocket implements Closeable { * @throws IOException if an error occurs while creating the socket. */ public ServerSocket(int port) throws IOException { - this(port, DEFAULT_BACKLOG, Inet4Address.ANY); + this(port, DEFAULT_BACKLOG, Inet6Address.ANY); } /** @@ -83,7 +83,7 @@ public class ServerSocket implements Closeable { * @throws IOException if an error occurs while creating the socket. */ public ServerSocket(int port, int backlog) throws IOException { - this(port, backlog, Inet4Address.ANY); + this(port, backlog, Inet6Address.ANY); } /** @@ -98,7 +98,7 @@ public class ServerSocket implements Closeable { checkListen(port); this.impl = factory != null ? factory.createSocketImpl() : new PlainServerSocketImpl(); - InetAddress addr = (localAddress == null) ? Inet4Address.ANY : localAddress; + InetAddress addr = (localAddress == null) ? Inet6Address.ANY : localAddress; synchronized (this) { impl.create(true); @@ -317,7 +317,7 @@ public class ServerSocket implements Closeable { InetAddress addr; int port; if (localAddr == null) { - addr = Inet4Address.ANY; + addr = Inet6Address.ANY; port = 0; } else { if (!(localAddr instanceof InetSocketAddress)) { diff --git a/luni/src/main/java/java/net/Socket.java b/luni/src/main/java/java/net/Socket.java index 737b01b..7ee6b05 100644 --- a/luni/src/main/java/java/net/Socket.java +++ b/luni/src/main/java/java/net/Socket.java @@ -41,7 +41,7 @@ public class Socket implements Closeable { private boolean isInputShutdown = false; private boolean isOutputShutdown = false; - private InetAddress localAddress = Inet4Address.ANY; + private InetAddress localAddress = Inet6Address.ANY; private final Object connectLock = new Object(); @@ -317,7 +317,7 @@ public class Socket implements Closeable { isConnected = false; // RI compatibility: the RI returns the any address (but the original local port) after // close. - localAddress = Inet4Address.ANY; + localAddress = Inet6Address.ANY; impl.close(); } @@ -332,7 +332,7 @@ public class Socket implements Closeable { isConnected = false; // RI compatibility: the RI returns the any address (but the original local port) after // close. - localAddress = Inet4Address.ANY; + localAddress = Inet6Address.ANY; impl.onClose(); } @@ -579,7 +579,7 @@ public class Socket implements Closeable { throw new IllegalArgumentException("Local port out of range: " + localPort); } - InetAddress addr = localAddress == null ? Inet4Address.ANY : localAddress; + InetAddress addr = localAddress == null ? Inet6Address.ANY : localAddress; synchronized (this) { impl.create(streaming); isCreated = true; @@ -774,7 +774,7 @@ public class Socket implements Closeable { InetAddress addr; if (localAddr == null) { port = 0; - addr = Inet4Address.ANY; + addr = Inet6Address.ANY; } else { if (!(localAddr instanceof InetSocketAddress)) { throw new IllegalArgumentException("Local address not an InetSocketAddress: " + @@ -877,7 +877,7 @@ public class Socket implements Closeable { // options on create // impl.create(true); if (!usingSocks()) { - impl.bind(Inet4Address.ANY, 0); + impl.bind(Inet6Address.ANY, 0); } isBound = true; } diff --git a/luni/src/test/java/libcore/java/net/InetSocketAddressTest.java b/luni/src/test/java/libcore/java/net/InetSocketAddressTest.java index ccd8b72..d97c48a 100644 --- a/luni/src/test/java/libcore/java/net/InetSocketAddressTest.java +++ b/luni/src/test/java/libcore/java/net/InetSocketAddressTest.java @@ -63,7 +63,7 @@ public class InetSocketAddressTest extends TestCase { } InetSocketAddress isa = new InetSocketAddress((InetAddress)null, 80); - assertEquals("0.0.0.0", isa.getHostName()); + assertEquals("::", isa.getHostName()); try { new InetSocketAddress(InetAddress.getByName("localhost"), 65536); @@ -80,7 +80,7 @@ public class InetSocketAddressTest extends TestCase { public void test_ConstructorI() { InetSocketAddress isa = new InetSocketAddress(65535); - assertEquals("0.0.0.0", isa.getHostName()); + assertEquals("::", isa.getHostName()); assertEquals(65535, isa.getPort()); try { -- cgit v1.1