diff --git a/java/jni/ZT_jniutils.cpp b/java/jni/ZT_jniutils.cpp index 8d4469366..86e4fdcb8 100644 --- a/java/jni/ZT_jniutils.cpp +++ b/java/jni/ZT_jniutils.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #define LOG_TAG "Utils" @@ -586,3 +585,70 @@ bool isSocketAddressEmpty(const sockaddr_storage addr) { return (memcmp(&addr, &emptyAddress, sizeof(sockaddr_storage)) == 0); //NOLINT } + +// +// returns empty sockaddr_storage on error +// +sockaddr_storage fromSocketAddressObject(JNIEnv *env, jobject sockAddressObject) { + + sockaddr_storage emptyAddress; //NOLINT + + memset(&emptyAddress, 0, sizeof(sockaddr_storage)); + + jint port = env->CallIntMethod(sockAddressObject, InetSocketAddress_getPort_method); + if(env->ExceptionCheck()) + { + LOGE("Exception calling getPort"); + return emptyAddress; + } + + jobject addressObject = env->CallObjectMethod(sockAddressObject, InetSocketAddress_getAddress_method); + if(env->ExceptionCheck() || addressObject == NULL) + { + LOGE("Exception calling getAddress"); + return emptyAddress; + } + + jbyteArray addressArrayObj = reinterpret_cast(env->CallObjectMethod(addressObject, InetAddress_getAddress_method)); + if(env->ExceptionCheck() || addressArrayObj == NULL) + { + LOGE("Exception calling getAddress"); + return emptyAddress; + } + + sockaddr_storage addr = {}; + + if (env->IsInstanceOf(addressObject, Inet4Address_class)) { + + // IPV4 + + assert(env->GetArrayLength(addressArrayObj) == 4); + + sockaddr_in *addr_4 = reinterpret_cast(&addr); + addr_4->sin_family = AF_INET; + addr_4->sin_port = htons(port); + + void *data = env->GetPrimitiveArrayCritical(addressArrayObj, NULL); + memcpy(&addr_4->sin_addr.s_addr, data, 4); + env->ReleasePrimitiveArrayCritical(addressArrayObj, data, 0); + + } else if (env->IsInstanceOf(addressObject, Inet6Address_class)) { + + // IPV6 + + assert(env->GetArrayLength(addressArrayObj) == 16); + + sockaddr_in6 *addr_6 = reinterpret_cast(&addr); + addr_6->sin6_family = AF_INET6; + addr_6->sin6_port = htons(port); + + void *data = env->GetPrimitiveArrayCritical(addressArrayObj, NULL); + memcpy(&addr_6->sin6_addr.s6_addr, data, 16); + env->ReleasePrimitiveArrayCritical(addressArrayObj, data, 0); + + } else { + assert(false && "addressObject is neither Inet4Address nor Inet6Address"); + } + + return addr; +} diff --git a/java/jni/ZT_jniutils.h b/java/jni/ZT_jniutils.h index 2c57bfdb7..23664a732 100644 --- a/java/jni/ZT_jniutils.h +++ b/java/jni/ZT_jniutils.h @@ -23,6 +23,7 @@ #include #include // for numeric_limits +#include // for sockaddr_storage #if defined(__ANDROID__) @@ -163,4 +164,6 @@ jbyteArray newByteArray(JNIEnv *env, size_t count); bool isSocketAddressEmpty(const sockaddr_storage addr); +sockaddr_storage fromSocketAddressObject(JNIEnv *env, jobject sockAddressObject); + #endif // ZT_jniutils_h_ diff --git a/java/jni/com_zerotierone_sdk_Node.cpp b/java/jni/com_zerotierone_sdk_Node.cpp index a143d9210..28a5ed5b9 100644 --- a/java/jni/com_zerotierone_sdk_Node.cpp +++ b/java/jni/com_zerotierone_sdk_Node.cpp @@ -498,40 +498,8 @@ namespace { return false; } - jint port = env->CallIntMethod(sockAddressObject, InetSocketAddress_getPort_method); - jobject addressObject = env->CallObjectMethod(sockAddressObject, InetSocketAddress_getAddress_method); - - jbyteArray addressBytes = (jbyteArray)env->CallObjectMethod(addressObject, InetAddress_getAddress_method); - if(addressBytes == NULL) - { - LOGE("Unable to call InetAddress.getBytes()"); - return false; - } - - int addressSize = env->GetArrayLength(addressBytes); - if(addressSize == 4) - { - // IPV4 - sockaddr_in *addr = (sockaddr_in*)result; - addr->sin_family = AF_INET; - addr->sin_port = htons(port); - - void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL); - memcpy(&addr->sin_addr, data, 4); - env->ReleasePrimitiveArrayCritical(addressBytes, data, 0); - } - else if (addressSize == 16) - { - // IPV6 - sockaddr_in6 *addr = (sockaddr_in6*)result; - addr->sin6_family = AF_INET6; - addr->sin6_port = htons(port); - void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL); - memcpy(&addr->sin6_addr, data, 16); - env->ReleasePrimitiveArrayCritical(addressBytes, data, 0); - } - else - { + *result = fromSocketAddressObject(env, sockAddressObject); + if (env->ExceptionCheck() || isSocketAddressEmpty(*result)) { return false; } @@ -863,64 +831,11 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( int64_t now = (int64_t)in_now; - jobject remoteAddrObject = env->CallObjectMethod(in_remoteAddress, InetSocketAddress_getAddress_method); - - if(remoteAddrObject == NULL) - { - return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum; + sockaddr_storage remoteAddress = fromSocketAddressObject(env, in_remoteAddress); + if (env->ExceptionCheck() || isSocketAddressEmpty(remoteAddress)) { + return NULL; } - // call InetSocketAddress.getPort() - int remotePort = env->CallIntMethod(in_remoteAddress, InetSocketAddress_getPort_method); - if(env->ExceptionCheck()) - { - LOGE("Exception calling InetSocketAddress.getPort()"); - return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum; - } - - // Call InetAddress.getAddress() - jbyteArray remoteAddressArray = (jbyteArray)env->CallObjectMethod(remoteAddrObject, InetAddress_getAddress_method); - if(remoteAddressArray == NULL) - { - LOGE("Unable to call getAddress()"); - // unable to call getAddress() - return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum; - } - - unsigned int addrSize = env->GetArrayLength(remoteAddressArray); - - - // get the address bytes - jbyte *addr = (jbyte*)env->GetPrimitiveArrayCritical(remoteAddressArray, NULL); - sockaddr_storage remoteAddress = {}; - - if(addrSize == 16) - { - // IPV6 address - sockaddr_in6 ipv6 = {}; - ipv6.sin6_family = AF_INET6; - ipv6.sin6_port = htons(remotePort); - memcpy(ipv6.sin6_addr.s6_addr, addr, 16); - memcpy(&remoteAddress, &ipv6, sizeof(sockaddr_in6)); - } - else if(addrSize == 4) - { - // IPV4 address - sockaddr_in ipv4 = {}; - ipv4.sin_family = AF_INET; - ipv4.sin_port = htons(remotePort); - memcpy(&ipv4.sin_addr, addr, 4); - memcpy(&remoteAddress, &ipv4, sizeof(sockaddr_in)); - } - else - { - LOGE("Unknown IP version"); - // unknown address type - env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0); - return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum; - } - env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0); - unsigned int packetLength = (unsigned int)env->GetArrayLength(in_packetData); if(packetLength == 0) {