Manual merge of eclair change I26548922 into master.
diff --git a/libcore/luni/src/main/java/java/net/Inet4Address.java b/libcore/luni/src/main/java/java/net/Inet4Address.java
index 5e1a420..b467b64 100644
--- a/libcore/luni/src/main/java/java/net/Inet4Address.java
+++ b/libcore/luni/src/main/java/java/net/Inet4Address.java
@@ -217,22 +217,10 @@
return prefix >= 0xEFC0 && prefix <= 0xEFC3;
}
- /**
- * Returns a textual representation of this IP address.
- *
- * @return the textual representation of this host address.
- */
- @Override
- public String getHostAddress() {
- String hostAddress = ""; //$NON-NLS-1$
- for (int i = 0; i < 4; i++) {
- hostAddress += ipaddress[i] & 255;
- if (i != 3) {
- hostAddress += "."; //$NON-NLS-1$
- }
- }
- return hostAddress;
- }
+ // BEGIN android-removed
+ // public String getHostAddress() {
+ // }
+ // END android-removed
// BEGIN android-removed
// public int hashCode() {
diff --git a/libcore/luni/src/main/java/java/net/Inet6Address.java b/libcore/luni/src/main/java/java/net/Inet6Address.java
index 91ec48e..f333770 100644
--- a/libcore/luni/src/main/java/java/net/Inet6Address.java
+++ b/libcore/luni/src/main/java/java/net/Inet6Address.java
@@ -362,15 +362,10 @@
return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 8;
}
- /**
- * Gets the textual representation of this IP address.
- *
- * @return the as a dotted string formatted IP address.
- */
- @Override
- public String getHostAddress() {
- return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
- }
+ // BEGIN android-removed
+ // public String getHostAddress() {
+ // }
+ // END android-removed
/**
* Gets the scope id as a number if this address is linked to an interface.
diff --git a/libcore/luni/src/main/java/java/net/InetAddress.java b/libcore/luni/src/main/java/java/net/InetAddress.java
index a7ea3f6..0fa4796 100644
--- a/libcore/luni/src/main/java/java/net/InetAddress.java
+++ b/libcore/luni/src/main/java/java/net/InetAddress.java
@@ -301,14 +301,31 @@
return getAllByNameImpl(host, false)[0];
}
+ /*
+ * Convenience method to convert a byte array to a string, converting
+ * exceptions to runtime exceptions. This is used when passing in byte
+ * arrays that have been verified to be correct and is necessary because
+ * some methods, such as getHostName(), are not allowed to throw exceptions
+ * but are implemented using byteArrayToIpString(), which throws
+ * UnknownHostException. Exceptions should never occur when the address is
+ * valid, but they cannot be simply ignored because they could be due to
+ * runtime errors such as out-of-memory conditions.
+ */
+ private static String ipAddressToString(byte[] ipaddress) {
+ try {
+ return NETIMPL.byteArrayToIpString(ipaddress);
+ } catch(UnknownHostException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
/**
* Gets the textual representation of this IP address.
*
- * @return the textual representation of this host address in form of a
- * dotted string.
+ * @return the textual representation of host's IP address.
*/
public String getHostAddress() {
- return inetNtoaImpl(bytesToInt(ipaddress, 0));
+ return ipAddressToString(ipaddress);
}
/**
@@ -325,18 +342,17 @@
if (ipaddress.length == 4) {
address = bytesToInt(ipaddress, 0);
if (address == 0) {
- return hostName = inetNtoaImpl(address);
+ return hostName = ipAddressToString(ipaddress);
}
}
hostName = getHostByAddrImpl(ipaddress).hostName;
if (hostName.equals("localhost") && ipaddress.length == 4 //$NON-NLS-1$
&& address != 0x7f000001) {
- return hostName = inetNtoaImpl(address);
+ return hostName = ipAddressToString(ipaddress);
}
}
} catch (UnknownHostException e) {
- return hostName = Inet6Util
- .createIPAddrStringFromByteArray(ipaddress);
+ return hostName = ipAddressToString(ipaddress);
}
SecurityManager security = System.getSecurityManager();
try {
@@ -345,7 +361,7 @@
security.checkConnect(hostName, -1);
}
} catch (SecurityException e) {
- return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
+ return ipAddressToString(ipaddress);
}
return hostName;
}
@@ -365,12 +381,12 @@
if (ipaddress.length == 4) {
address = bytesToInt(ipaddress, 0);
if (address == 0) {
- return inetNtoaImpl(address);
+ return ipAddressToString(ipaddress);
}
}
canonicalName = getHostByAddrImpl(ipaddress).hostName;
} catch (UnknownHostException e) {
- return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
+ return ipAddressToString(ipaddress);
}
SecurityManager security = System.getSecurityManager();
try {
@@ -379,7 +395,7 @@
security.checkConnect(canonicalName, -1);
}
} catch (SecurityException e) {
- return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
+ return ipAddressToString(ipaddress);
}
return canonicalName;
}
@@ -550,10 +566,9 @@
private static native String gethostbyaddr(byte[] addr);
// END android-changed
- static int inetAddr(String host) throws UnknownHostException {
- return (host.equals("255.255.255.255")) ? 0xFFFFFFFF //$NON-NLS-1$
- : inetAddrImpl(host);
- }
+ // BEGIN android-removed
+ // static int inetAddr(String host) throws UnknownHostException
+ // END android-removed
/**
* Convert a string containing an IPv4 Internet Protocol dotted address into
@@ -561,41 +576,17 @@
* exception, so this value should not be used as an argument. See also
* inetAddr(String).
*/
- // BEGIN android-changed
+ // BEGIN android-removed
// static native int inetAddrImpl(String host) throws UnknownHostException;
- static int inetAddrImpl(String host) throws UnknownHostException {
- // TODO Probably not exactly what we want, and also inefficient. Provide native later.
- try {
- String[] args = host.split("\\.");
-
- int a = Integer.parseInt(args[0]) << 24;
- int b = Integer.parseInt(args[1]) << 16;
- int c = Integer.parseInt(args[2]) << 8;
- int d = Integer.parseInt(args[3]) ;
-
- return a | b | c | d;
- } catch (Exception ex) {
- throw new UnknownHostException(host);
- }
- }
- // END android-changed
+ // END android-removed
/**
* Convert a binary address into a string containing an Ipv4 Internet
* Protocol dotted address.
*/
- // BEGIN android-changed
+ // BEGIN android-removed
// static native String inetNtoaImpl(int hipAddr);
- static String inetNtoaImpl(int hipAddr) {
- // TODO Inefficient and probably wrong. Provide proper (native?) implementation later.
- int a = (hipAddr >> 24) & 0xFF;
- int b = (hipAddr >> 16) & 0xFF;
- int c = (hipAddr >> 8) & 0xFF;
- int d = (hipAddr ) & 0xFF;
-
- return "" + a + "." + b + "." + c + "." + d;
- }
- // END android-changed
+ // END android-removed
// BEGIN android-removed
/**
@@ -1223,7 +1214,11 @@
static InetAddress getByAddressInternal(String hostName, byte[] ipAddress,
int scope_id) throws UnknownHostException {
if (ipAddress == null) {
- throw new NullPointerException();
+ // We don't throw NullPointerException here for RI compatibility,
+ // but we do say "address is null" (K0331), instead of "addr is of
+ // illegal length".
+ throw new UnknownHostException(
+ Msg.getString("K0331", hostName)); //$NON-NLS-1$
}
switch (ipAddress.length) {
case 4:
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
index eae5261..1345341 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
@@ -217,7 +217,10 @@
throws UnknownHostException;
public void setInetAddress(InetAddress sender, byte[] address);
-
+
+ public String byteArrayToIpString(byte[] address)
+ throws UnknownHostException;
+
// BEGIN android-removed
// public boolean isReachableByICMP(InetAddress dest,InetAddress source,int ttl,int timeout);
// END android-removed
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
index 70432a6..0fa25ea 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
@@ -239,6 +239,9 @@
return getSocketFlagsImpl();
}
+ public native String byteArrayToIpString(byte[] address)
+ throws UnknownHostException;
+
static native int getSocketFlagsImpl();
public InetAddress getSocketLocalAddress(FileDescriptor fd,
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
index d8b261d..4dae1c3 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
@@ -144,55 +144,6 @@
}
- // BEGIN android-changed
- static char[] hexCharacters = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
- '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- // END android-changed
-
- public static String createIPAddrStringFromByteArray(byte ipByteArray[]) {
- if (ipByteArray.length == 4) {
- return addressToString(bytesToInt(ipByteArray, 0));
- }
-
- if (ipByteArray.length == 16) {
- if (isIPv4MappedAddress(ipByteArray)) {
- byte ipv4ByteArray[] = new byte[4];
- for (int i = 0; i < 4; i++) {
- ipv4ByteArray[i] = ipByteArray[i + 12];
- }
- return addressToString(bytesToInt(ipv4ByteArray, 0));
- }
- StringBuilder buffer = new StringBuilder();
- // BEGIN android-changed
- for (int i = 0; i < 8; i++) { // ipByteArray.length / 2
-
- int num = (ipByteArray[2 * i] & 0xff) << 8;
- num ^= ipByteArray[2 * i + 1] & 0xff;
-
- // count the digits to display without leading 0
- int count = 1, j = num;
- while ((j >>>= 4) != 0) {
- count++;
- }
-
- char[] buf = new char[count];
- do {
- int t = num & 0x0f;
- buf[--count] = hexCharacters[t];
- num >>>= 4;
- } while (count > 0);
-
- buffer.append(buf);
- if ((i + 1) < 8) { // ipByteArray.length / 2
- buffer.append(":");
- }
- }
- // END android-changed
- return buffer.toString();
- }
- return null;
- }
-
/** Converts a 4 character hex word into a 2 byte word equivalent */
public static void convertToBytes(String hexWord, byte ipByteArray[],
int byteIndex) {
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index afa0dfc..6d258e0 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -295,8 +295,7 @@
/**
* Converts a native address structure to an InetAddress object.
* Throws a NullPointerException or an IOException in case of
- * error. This is signaled by a return value of -1. The normal
- * return value is 0.
+ * error.
*
* @param sockaddress the sockaddr_storage structure to convert
*
@@ -323,39 +322,30 @@
* @param port the port number
* @param sockaddress the sockaddr_storage structure to write to
*
- * @return 0 on success, -1 on failure
+ * @return 0 on success, a system error code on failure
*
* @exception SocketError if the address family is unknown
*/
-static int inetAddressToSocketAddress(JNIEnv *env, jobject inetaddress,
- int port, struct sockaddr_storage *sockaddress) {
- // Get the byte array that stores the IP address bytes in the InetAddress.
- if (inetaddress == NULL) {
- throwNullPointerException(env);
- return -1;
- }
- jbyteArray addressBytes =
- reinterpret_cast<jbyteArray>(env->GetObjectField(inetaddress,
- gCachedFields.iaddr_ipaddress));
+static int byteArrayToSocketAddress(JNIEnv *env,
+ jbyteArray addressBytes, int port, sockaddr_storage *sockaddress) {
if (addressBytes == NULL) {
throwNullPointerException(env);
- return -1;
+ return EFAULT;
}
-
// Convert the IP address bytes to the proper IP address type.
size_t addressLength = env->GetArrayLength(addressBytes);
if (addressLength == 4) {
// IPv4 address.
- struct sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sockaddress);
- memset(sin, 0, sizeof(struct sockaddr_in));
+ sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sockaddress);
+ memset(sin, 0, sizeof(sockaddr_in));
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
jbyte* dst = reinterpret_cast<jbyte*>(&sin->sin_addr.s_addr);
env->GetByteArrayRegion(addressBytes, 0, 4, dst);
} else if (addressLength == 16) {
// IPv6 address.
- struct sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6*>(sockaddress);
- memset(sin6, 0, sizeof(struct sockaddr_in6));
+ sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6*>(sockaddress);
+ memset(sin6, 0, sizeof(sockaddr_in6));
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
jbyte* dst = reinterpret_cast<jbyte*>(&sin6->sin6_addr.s6_addr);
@@ -363,12 +353,126 @@
} else {
// Unknown address family.
throwSocketException(env, SOCKERR_BADAF);
- return -1;
+ return EAFNOSUPPORT;
}
return 0;
}
/**
+ * Converts an InetAddress object and port number to a native address structure.
+ * Throws a NullPointerException or a SocketException in case of
+ * error. This is signaled by a return value of -1. The normal
+ * return value is 0.
+ *
+ * @param inetaddress the InetAddress object to convert
+ * @param port the port number
+ * @param sockaddress the sockaddr_storage structure to write to
+ *
+ * @return 0 on success, a system error code on failure
+ * @throw UnknownHostException if any error occurs
+ *
+ * @exception SocketError if the address family is unknown
+ */
+static int inetAddressToSocketAddress(JNIEnv *env, jobject inetaddress,
+ int port, sockaddr_storage *sockaddress) {
+ // Get the byte array that stores the IP address bytes in the InetAddress.
+ if (inetaddress == NULL) {
+ throwNullPointerException(env);
+ return EFAULT;
+ }
+ jbyteArray addressBytes =
+ reinterpret_cast<jbyteArray>(env->GetObjectField(inetaddress,
+ gCachedFields.iaddr_ipaddress));
+
+ return byteArrayToSocketAddress(env, addressBytes, port, sockaddress);
+}
+
+/**
+ * Convert a sockaddr_storage structure to a Java string.
+ *
+ * @param address pointer to sockaddr_storage structure to convert.
+ * @param withPort whether to include the port number in the output as well.
+ *
+ * @return 0 on success, a getnameinfo return code on failure.
+ *
+ * @throws SocketException the address family was unknown.
+ */
+static int socketAddressToString(sockaddr_storage *address, char *ipString,
+ int len, bool withPort) {
+ // TODO: getnameinfo seems to want its length parameter to be exactly
+ // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
+ // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
+ // then remove this hack.
+ int size;
+ if (address->ss_family == AF_INET) {
+ size = sizeof(sockaddr_in);
+ } else if (address->ss_family == AF_INET6) {
+ size = sizeof(sockaddr_in6);
+ } else {
+ errno = EAFNOSUPPORT;
+ return EAI_SYSTEM;
+ }
+
+ char tmp[INET6_ADDRSTRLEN];
+ int result = getnameinfo((sockaddr *)address, size, tmp, sizeof(tmp), NULL,
+ 0, NI_NUMERICHOST);
+ if (result != 0) {
+ return result;
+ }
+
+ int port;
+ if (withPort) {
+ if (address->ss_family == AF_INET6) {
+ sockaddr_in6 *sin6 = (sockaddr_in6 *) address;
+ port = ntohs(sin6->sin6_port);
+ snprintf(ipString, len, "[%s]:%d", tmp, port);
+ } else {
+ sockaddr_in *sin = (sockaddr_in *) address;
+ port = ntohs(sin->sin_port);
+ snprintf(ipString, len, "%s:%d", tmp, port);
+ }
+ } else {
+ strncpy(ipString, tmp, len);
+ }
+ return 0;
+}
+
+/**
+ * Convert a Java byte array representing an IP address to a Java string.
+ *
+ * @param addressByteArray the byte array to convert.
+ *
+ * @return a string with the textual representation of the address.
+ *
+ * @throws SocketException the address family was unknown.
+ */
+static jstring osNetworkSystem_byteArrayToIpString(JNIEnv *env, jclass clazz,
+ jbyteArray byteArray) {
+ // For compatibility, ensure that an UnknownHostException is thrown if the
+ // address is null.
+ if (byteArray == NULL) {
+ jniThrowException(env, "java/net/UnknownHostException",
+ strerror(EFAULT));
+ return NULL;
+ }
+ struct sockaddr_storage ss;
+ int ret = byteArrayToSocketAddress(env, byteArray, 0, &ss);
+ if (ret) {
+ jniThrowException(env, "java/net/UnknownHostException", strerror(ret));
+ return NULL;
+ }
+ char ipString[INET6_ADDRSTRLEN];
+ ret = socketAddressToString(&ss, ipString, sizeof(ipString), false);
+ if (ret) {
+ env->ExceptionClear();
+ jniThrowException(env, "java/net/UnknownHostException",
+ gai_strerror(ret));
+ return NULL;
+ }
+ return env->NewStringUTF(ipString);
+}
+
+/**
* Answer a new java.lang.Boolean object.
*
* @param env pointer to the JNI library
@@ -487,49 +591,6 @@
}
/**
- * Convert a sockaddr_storage structure to a string for logging purposes.
- *
- * @param address pointer to sockaddr_storage structure to print
- *
- * @return a string with the textual representation of the address.
- *
- * @note Returns a statically allocated buffer, so is not thread-safe.
- */
-static char *socketAddressToString(struct sockaddr_storage *address) {
- static char invalidString[] = "<invalid>";
- static char ipString[INET6_ADDRSTRLEN + sizeof("[]:65535")];
-
- char tmp[INET6_ADDRSTRLEN];
- int port;
- // TODO: getnameinfo seems to want its length parameter to be exactly
- // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
- // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
- // then remove this hack.
- int size = (address->ss_family == AF_INET) ?
- sizeof(sockaddr_in) : sizeof(sockaddr_in6);
- int result = getnameinfo((struct sockaddr *)address,
- size, tmp, sizeof(tmp), NULL, 0,
- NI_NUMERICHOST);
-
- if (result != 0)
- return invalidString;
-
- if (address->ss_family == AF_INET6) {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
- port = ntohs(sin6->sin6_port);
- sprintf(ipString, "[%s]:%d", tmp, port);
- return ipString;
- } else if (address->ss_family == AF_INET) {
- struct sockaddr_in *sin = (struct sockaddr_in *) address;
- port = ntohs(sin->sin_port);
- sprintf(ipString, "%s:%d", tmp, port);
- return ipString;
- } else {
- return invalidString;
- }
-}
-
-/**
* Answer the errorString corresponding to the errorNumber, if available.
* This function will answer a default error string, if the errorNumber is not
* recognized.
@@ -863,6 +924,23 @@
}
/**
+ * Converts an IPv4-mapped IPv6 address to an IPv4 address. Performs no error
+ * checking.
+ *
+ * @param address the address to convert. Must contain an IPv4-mapped address.
+ * @param outputAddress the converted address. Will contain an IPv4 address.
+ */
+static void convertMappedToIpv4(sockaddr_storage *address,
+ sockaddr_storage *outputAddress) {
+ memset(outputAddress, 0, sizeof(sockaddr_in));
+ const sockaddr_in6 *sin6 = ((sockaddr_in6 *) address);
+ sockaddr_in *sin = ((sockaddr_in *) outputAddress);
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
+ sin->sin_port = sin6->sin6_port;
+}
+
+/**
* Converts an IPv4 address to an IPv4-mapped IPv6 address. Performs no error
* checking.
*
@@ -870,9 +948,9 @@
* @param outputAddress the converted address. Will contain an IPv6 address.
* @param mapUnspecified if true, convert 0.0.0.0 to ::ffff:0:0; if false, to ::
*/
-static void ipv4ToMappedAddress(struct sockaddr_storage *address,
+static void convertIpv4ToMapped(struct sockaddr_storage *address,
struct sockaddr_storage *outputAddress, bool mapUnspecified) {
- memset(outputAddress, 0, sizeof(struct sockaddr_storage));
+ memset(outputAddress, 0, sizeof(struct sockaddr_in6));
const struct sockaddr_in *sin = ((struct sockaddr_in *) address);
struct sockaddr_in6 *sin6 = ((struct sockaddr_in6 *) outputAddress);
sin6->sin6_family = AF_INET6;
@@ -895,7 +973,7 @@
struct sockaddr_storage *realAddress;
if (socketAddress->ss_family == AF_INET &&
getSocketAddressFamily(socket) == AF_INET6) {
- ipv4ToMappedAddress(socketAddress, &mappedAddress, true);
+ convertIpv4ToMapped(socketAddress, &mappedAddress, true);
realAddress = &mappedAddress;
} else {
realAddress = socketAddress;
@@ -920,7 +998,7 @@
struct sockaddr_storage *realAddress;
if (socketAddress->ss_family == AF_INET &&
getSocketAddressFamily(socket) == AF_INET6) {
- ipv4ToMappedAddress(socketAddress, &mappedAddress, false);
+ convertIpv4ToMapped(socketAddress, &mappedAddress, false);
realAddress = &mappedAddress;
} else {
realAddress = socketAddress;
@@ -3510,6 +3588,7 @@
{ "socketCloseImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_socketCloseImpl },
{ "setInetAddressImpl", "(Ljava/net/InetAddress;[B)V", (void*) osNetworkSystem_setInetAddressImpl },
{ "inheritedChannelImpl", "()Ljava/nio/channels/Channel;", (void*) osNetworkSystem_inheritedChannelImpl },
+ { "byteArrayToIpString", "([B)Ljava/lang/String;", (void*) osNetworkSystem_byteArrayToIpString },
};
int register_org_apache_harmony_luni_platform_OSNetworkSystem(JNIEnv* env) {