Browse Source

add fromSocketAddressObject

Brenton Bostick 2 years ago
parent
commit
4ee73fa272
3 changed files with 75 additions and 91 deletions
  1. 67 1
      java/jni/ZT_jniutils.cpp
  2. 3 0
      java/jni/ZT_jniutils.h
  3. 5 90
      java/jni/com_zerotierone_sdk_Node.cpp

+ 67 - 1
java/jni/ZT_jniutils.cpp

@@ -26,7 +26,6 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 
 #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<jbyteArray>(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<sockaddr_in *>(&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<sockaddr_in6 *>(&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;
+}

+ 3 - 0
java/jni/ZT_jniutils.h

@@ -23,6 +23,7 @@
 #include <ZeroTierOne.h>
 
 #include <limits> // for numeric_limits
+#include <sys/socket.h> // 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_

+ 5 - 90
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,63 +831,10 @@ 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;
-    }
-
-    // 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;
+    sockaddr_storage remoteAddress = fromSocketAddressObject(env, in_remoteAddress);
+    if (env->ExceptionCheck() || isSocketAddressEmpty(remoteAddress)) {
+        return NULL;
     }
-    env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0);
 
     unsigned int packetLength = (unsigned int)env->GetArrayLength(in_packetData);
     if(packetLength == 0)