diff options
-rw-r--r-- | luni/src/main/java/java/net/InetAddress.java | 22 | ||||
-rw-r--r-- | luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp | 262 |
2 files changed, 105 insertions, 179 deletions
diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java index c844d54..e88d8b3 100644 --- a/luni/src/main/java/java/net/InetAddress.java +++ b/luni/src/main/java/java/net/InetAddress.java @@ -303,22 +303,18 @@ public class InetAddress extends Object implements Serializable { // BEGIN android-added /** - * 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. + * Returns the numeric string form of the given IP address. * - * @param ipaddress the byte array to convert + * @param ipAddress + * the byte array to convert; length 4 for IPv4, 16 for IPv6. + * @throws IllegalArgumentException + * if ipAddress is of length other than 4 or 16. */ - private static String ipAddressToString(byte[] ipaddress) { + private static String ipAddressToString(byte[] ipAddress) { try { - return NETIMPL.byteArrayToIpString(ipaddress); - } catch(UnknownHostException e) { - throw new RuntimeException(e); + return NETIMPL.byteArrayToIpString(ipAddress); + } catch (IOException ex) { + throw new IllegalArgumentException("byte[] neither 4 nor 16 bytes", ex); } } // END android-added diff --git a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp index 3dc4e21..b7724e5 100644 --- a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp +++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp @@ -23,23 +23,23 @@ #define LOG_TAG "OSNetworkSystem" +#include "AndroidSystemNatives.h" #include "JNIHelp.h" #include "jni.h" -#include "errno.h" -#include <unistd.h> -#include <stdio.h> -#include <sys/socket.h> +#include <arpa/inet.h> +#include <assert.h> +#include <errno.h> +#include <netdb.h> #include <netinet/in.h> #include <netinet/tcp.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <sys/time.h> +#include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/time.h> #include <sys/un.h> - -#include "AndroidSystemNatives.h" +#include <unistd.h> // Temporary hack to build on systems that don't have up-to-date libc headers. #ifndef IPV6_TCLASS @@ -204,22 +204,25 @@ static void throwSocketException(JNIEnv *env, int errorCode) { netLookupErrorString(errorCode)); } -/** - * Throws a NullPointerException. - */ +// TODO: move to JNIHelp.h static void throwNullPointerException(JNIEnv *env) { jniThrowException(env, "java/lang/NullPointerException", NULL); } +// TODO: move to JNIHelp.h +static void jniThrowAssertionError(JNIEnv* env, const char* message) { + jniThrowException(env, "java/lang/AssertionError", message); +} + +// Used by functions that shouldn't throw SocketException. (These functions +// aren't meant to see bad addresses, so seeing one really does imply an +// internal error.) +static void jniThrowBadAddressFamily(JNIEnv* env) { + jniThrowAssertionError(env, "Bad address family"); +} + /** - * Converts a native address structure to a Java byte array. 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. - * - * @param address the sockaddr_storage structure to convert - * - * @exception SocketException the address family is unknown, or out of memory - * + * Converts a native address structure to a Java byte array. */ static jbyteArray socketAddressToByteArray(JNIEnv *env, struct sockaddr_storage *address) { @@ -235,13 +238,12 @@ static jbyteArray socketAddressToByteArray(JNIEnv *env, rawAddress = &sin6->sin6_addr.s6_addr; addressLength = 16; } else { - throwSocketException(env, SOCKERR_BADAF); + jniThrowBadAddressFamily(env); return NULL; } jbyteArray byteArray = env->NewByteArray(addressLength); if (byteArray == NULL) { - throwSocketException(env, SOCKERR_NOBUFFERS); return NULL; } env->SetByteArrayRegion(byteArray, 0, addressLength, (jbyte *) rawAddress); @@ -337,26 +339,17 @@ static void convertIpv4ToMapped(struct sockaddr_in *sin, /** * 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 - * - * @exception SocketError if the address family is unknown + * error. */ -static int byteArrayToSocketAddress(JNIEnv *env, +static bool byteArrayToSocketAddress(JNIEnv *env, jbyteArray addressBytes, int port, sockaddr_storage *sockaddress) { if (addressBytes == NULL) { throwNullPointerException(env); - return EFAULT; + return false; } - size_t addressLength = env->GetArrayLength(addressBytes); // Convert the IP address bytes to the proper IP address type. + size_t addressLength = env->GetArrayLength(addressBytes); if (addressLength == 4) { // IPv4 address. sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sockaddress); @@ -374,34 +367,21 @@ static int byteArrayToSocketAddress(JNIEnv *env, jbyte* dst = reinterpret_cast<jbyte*>(&sin6->sin6_addr.s6_addr); env->GetByteArrayRegion(addressBytes, 0, 16, dst); } else { - // Unknown address family. - throwSocketException(env, SOCKERR_BADAF); - return EAFNOSUPPORT; + jniThrowBadAddressFamily(env); + return false; } - return 0; + return true; } /** * 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, +static bool 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; + return false; } jbyteArray addressBytes = reinterpret_cast<jbyteArray>(env->GetObjectField(inetaddress, @@ -415,13 +395,9 @@ static int inetAddressToSocketAddress(JNIEnv *env, jobject inetaddress, * * @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) { +static bool socketAddressToString(JNIEnv* env, + sockaddr_storage* address, char* ipString, size_t len) { // 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 @@ -432,32 +408,17 @@ static int socketAddressToString(sockaddr_storage *address, char *ipString, } else if (address->ss_family == AF_INET6) { size = sizeof(sockaddr_in6); } else { - errno = EAFNOSUPPORT; - return EAI_SYSTEM; + jniThrowBadAddressFamily(env); + return false; } - char tmp[INET6_ADDRSTRLEN]; - int result = getnameinfo((sockaddr *)address, size, tmp, sizeof(tmp), NULL, + int rc = getnameinfo((sockaddr*) address, size, ipString, len, 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); + if (rc != 0) { + jniThrowException(env, "java/net/UnknownHostException", gai_strerror(rc)); + return false; } - return 0; + return true; } /** @@ -466,30 +427,19 @@ static int socketAddressToString(sockaddr_storage *address, char *ipString, * @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, +static jstring osNetworkSystem_byteArrayToIpString(JNIEnv* env, jclass, 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)); + throwNullPointerException(env); return NULL; } struct sockaddr_storage ss; - int ret = byteArrayToSocketAddress(env, byteArray, 0, &ss); - if (ret) { - jniThrowException(env, "java/net/UnknownHostException", strerror(ret)); + if (!byteArrayToSocketAddress(env, byteArray, 0, &ss)) { 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)); + if (!socketAddressToString(env, &ss, ipString, sizeof(ipString))) { return NULL; } return env->NewStringUTF(ipString); @@ -516,7 +466,7 @@ static jstring osNetworkSystem_byteArrayToIpString(JNIEnv *env, jclass clazz, * * @throws UnknownHostException the IP address was invalid. */ -static jbyteArray osNetworkSystem_ipStringToByteArray(JNIEnv *env, jclass clazz, +static jbyteArray osNetworkSystem_ipStringToByteArray(JNIEnv* env, jclass, jstring javaString) { if (javaString == NULL) { throwNullPointerException(env); @@ -1364,9 +1314,9 @@ static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal, } // Convert the inetAddress to an IPv4 address structure. - result = inetAddressToSocketAddress(env, optVal, 0, &sockaddrP); - if (result < 0) // Exception has already been thrown. + if (!inetAddressToSocketAddress(env, optVal, 0, &sockaddrP)) { return; + } if (sockaddrP.ss_family != AF_INET) { throwSocketException(env, SOCKERR_BADAF); return; @@ -1402,9 +1352,9 @@ static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal, interfaceIndex = env->GetIntField(optVal, interfaceIdxID); } - result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP); - if (result < 0) // Exception has already been thrown. + if (!inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP)) { return; + } int family = getSocketAddressFamily(handle); @@ -1784,9 +1734,8 @@ static jint osNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env, // LOGD("ENTER connectWithTimeoutSocketImpl"); sockaddr_storage address; - int result = inetAddressToSocketAddress(env, inetAddr, port, &address); - if (result < 0) { - return result; + if (!inetAddressToSocketAddress(env, inetAddr, port, &address)) { + return -1; } int handle = jniGetFDFromFileDescriptor(env, fileDescriptor); @@ -1796,15 +1745,18 @@ static jint osNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env, } jbyte* context = env->GetByteArrayElements(passContext, NULL); + int result = 0; switch (step) { - case SOCKET_CONNECT_STEP_START: - result = sockConnectWithTimeout(handle, address, 0, - SOCKET_STEP_START, context); - break; - case SOCKET_CONNECT_STEP_CHECK: - result = sockConnectWithTimeout(handle, address, timeout, - SOCKET_STEP_CHECK, context); - break; + case SOCKET_CONNECT_STEP_START: + result = sockConnectWithTimeout(handle, address, 0, + SOCKET_STEP_START, context); + break; + case SOCKET_CONNECT_STEP_CHECK: + result = sockConnectWithTimeout(handle, address, timeout, + SOCKET_STEP_CHECK, context); + break; + default: + assert(false); } env->ReleaseByteArrayElements(passContext, context, 0); @@ -1852,9 +1804,9 @@ static void osNetworkSystem_connectStreamWithTimeoutSocketImpl(JNIEnv* env, return; } - result = inetAddressToSocketAddress(env, inetAddr, remotePort, &address); - if (result < 0) // Exception has already been thrown. + if (!inetAddressToSocketAddress(env, inetAddr, remotePort, &address)) { return; + } /* * we will be looping checking for when we are connected so allocate @@ -1964,20 +1916,18 @@ bail: } } +// TODO: should return void! static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz, jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port) { //LOGD("ENTER direct-call connectSocketImpl\n"); struct sockaddr_storage address; - int ret; - int handle; - - ret = inetAddressToSocketAddress(env, inetAddr, port, &address); - if (ret < 0) - return ret; + if (!inetAddressToSocketAddress(env, inetAddr, port, &address)) { + return -1; + } - handle = jniGetFDFromFileDescriptor(env, fileDescriptor); - if (handle == 0 || handle == -1) { + int handle = jniGetFDFromFileDescriptor(env, fileDescriptor); + if (handle == -1) { throwSocketException(env, SOCKERR_BADDESC); return -1; } @@ -1985,21 +1935,7 @@ static jint osNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz, // call this method with a timeout of zero osNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz, fileDescriptor, port, 0, trafficClass, inetAddr); - if (env->ExceptionOccurred() != 0) { - return -1; - } else { - return 0; - } - - // TODO: unreachable code! - - if (ret < 0) { - jniThrowException(env, "java/net/ConnectException", - netLookupErrorString(convertError(errno))); - return ret; - } - - return ret; + return 0; } static void osNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz, @@ -2007,20 +1943,17 @@ static void osNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz, // LOGD("ENTER socketBindImpl"); struct sockaddr_storage sockaddress; - int ret; - int handle; - - ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress); - if (ret < 0) + if (!inetAddressToSocketAddress(env, inetAddress, port, &sockaddress)) { return; + } - handle = jniGetFDFromFileDescriptor(env, fileDescriptor); - if (handle == 0 || handle == -1) { + int handle = jniGetFDFromFileDescriptor(env, fileDescriptor); + if (handle == -1) { throwSocketException(env, SOCKERR_BADDESC); return; } - ret = doBind(handle, &sockaddress); + int ret = doBind(handle, &sockaddress); if (ret < 0) { jniThrowException(env, "java/net/BindException", netLookupErrorString(convertError(errno))); @@ -2140,7 +2073,7 @@ static void osNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass clazz, jobject inetAddress = socketAddressToInetAddress(env, &sa); if (ret == -1) { close(retFD); - newSocket = NULL; // Exception has already been thrown. + newSocket = NULL; return; } @@ -2192,16 +2125,13 @@ static void osNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass clazz, jobject fd, jint port, jint trafficClass, jobject inetAddress) { // LOGD("ENTER connectDatagramImpl2"); - int handle = jniGetFDFromFileDescriptor(env, fd); - struct sockaddr_storage sockAddr; - int ret; - - ret = inetAddressToSocketAddress(env, inetAddress, port, &sockAddr); - if (ret < 0) // Exception has already been thrown. + if (!inetAddressToSocketAddress(env, inetAddress, port, &sockAddr)) { return; + } - ret = doConnect(handle, &sockAddr); + int handle = jniGetFDFromFileDescriptor(env, fd); + int ret = doConnect(handle, &sockAddr); if (ret < 0) { int err = convertError(errno); throwSocketException(env, err); @@ -2256,8 +2186,9 @@ static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz, } sender = socketAddressToInetAddress(env, &sockAddr); - if (sender == NULL) // Exception has already been thrown. + if (sender == NULL) { return -1; + } port = getSocketAddressPort(&sockAddr); return port; @@ -2297,8 +2228,9 @@ static jint osNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz, if (packet != NULL) { jbyteArray addr = socketAddressToByteArray(env, &sockAddr); - if (addr == NULL) // Exception has already been thrown. + if (addr == NULL) { return 0; + } int port = getSocketAddressPort(&sockAddr); jobject sender = env->CallStaticObjectMethod( gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress, @@ -2407,9 +2339,8 @@ static jint osNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz, } struct sockaddr_storage receiver; - if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) { - // Exception has already been thrown. - return 0; + if (!inetAddressToSocketAddress(env, inetAddress, port, &receiver)) { + return -1; } ssize_t result = 0; @@ -2488,8 +2419,9 @@ static void osNetworkSystem_createServerStreamSocketImpl(JNIEnv* env, // LOGD("ENTER createServerStreamSocketImpl"); int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM); - if (handle < 0) + if (handle < 0) { return; + } int value = 1; setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int)); @@ -2645,16 +2577,15 @@ static jint osNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz, jobject inetAddress) { // LOGD("ENTER sendDatagramImpl2"); - jbyte *message; unsigned short nPort; int ret = 0, sent = 0; int handle = 0; struct sockaddr_storage sockaddrP; if (inetAddress != NULL) { - ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddrP); - if (ret < 0) // Exception has already been thrown. - return 0; + if (!inetAddressToSocketAddress(env, inetAddress, port, &sockaddrP)) { + return -1; + } handle = jniGetFDFromFileDescriptor(env, fd); if (handle == 0 || handle == -1) { @@ -2663,7 +2594,7 @@ static jint osNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz, } } - message = (jbyte*) malloc(length * sizeof(jbyte)); + jbyte* message = (jbyte*) malloc(length * sizeof(jbyte)); if (message == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", "couldn't allocate enough memory for readSocket"); @@ -3044,8 +2975,7 @@ static void osNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz, } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) { byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value); } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) { - if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) { - // Exception has already been thrown. + if (!inetAddressToSocketAddress(env, optVal, 0, &sockVal)) { return; } } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) { |