Browse Source

add array functions

Brenton Bostick 2 years ago
parent
commit
f51ce077a3
3 changed files with 160 additions and 134 deletions
  1. 83 68
      java/jni/ZT_jniutils.cpp
  2. 62 0
      java/jni/ZT_jniutils.h
  3. 15 66
      java/jni/com_zerotierone_sdk_Node.cpp

+ 83 - 68
java/jni/ZT_jniutils.cpp

@@ -107,14 +107,14 @@ jobject newInetAddress(JNIEnv *env, const sockaddr_storage &addr)
         case AF_INET6:
         case AF_INET6:
         {
         {
             sockaddr_in6 *ipv6 = (sockaddr_in6*)&addr;
             sockaddr_in6 *ipv6 = (sockaddr_in6*)&addr;
-            jbyteArray buff = env->NewByteArray(16);
-            if(buff == NULL)
+            const unsigned char *bytes = reinterpret_cast<const unsigned char *>(&ipv6->sin6_addr.s6_addr);
+
+            jbyteArray buff = newByteArray(env, bytes, 16);
+            if(env->ExceptionCheck() || buff == NULL)
             {
             {
-                LOGE("Error creating IPV6 byte array");
                 return NULL;
                 return NULL;
             }
             }
 
 
-            env->SetByteArrayRegion(buff, 0, 16, (jbyte*)ipv6->sin6_addr.s6_addr);
             inetAddressObj = env->CallStaticObjectMethod(
             inetAddressObj = env->CallStaticObjectMethod(
                 InetAddress_class, InetAddress_getByAddress_method, buff);
                 InetAddress_class, InetAddress_getByAddress_method, buff);
         }
         }
@@ -122,14 +122,13 @@ jobject newInetAddress(JNIEnv *env, const sockaddr_storage &addr)
         case AF_INET:
         case AF_INET:
         {
         {
             sockaddr_in *ipv4 = (sockaddr_in*)&addr;
             sockaddr_in *ipv4 = (sockaddr_in*)&addr;
-            jbyteArray buff = env->NewByteArray(4);
-            if(buff == NULL)
+            const unsigned char *bytes = reinterpret_cast<const unsigned char *>(&ipv4->sin_addr.s_addr);
+            jbyteArray buff = newByteArray(env, bytes, 4);
+            if(env->ExceptionCheck() || buff == NULL)
             {
             {
-                LOGE("Error creating IPV4 byte array");
                 return NULL;
                 return NULL;
             }
             }
 
 
-            env->SetByteArrayRegion(buff, 0, 4, (jbyte*)&ipv4->sin_addr);
             inetAddressObj = env->CallStaticObjectMethod(
             inetAddressObj = env->CallStaticObjectMethod(
                 InetAddress_class, InetAddress_getByAddress_method, buff);
                 InetAddress_class, InetAddress_getByAddress_method, buff);
         }
         }
@@ -241,26 +240,7 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer)
     env->SetIntField(peerObject, Peer_latency_field, peer.latency);
     env->SetIntField(peerObject, Peer_latency_field, peer.latency);
     env->SetObjectField(peerObject, Peer_role_field, createPeerRole(env, peer.role));
     env->SetObjectField(peerObject, Peer_role_field, createPeerRole(env, peer.role));
 
 
-    jobjectArray arrayObject = env->NewObjectArray(
-        peer.pathCount, PeerPhysicalPath_class, NULL);
-    if(env->ExceptionCheck() || arrayObject == NULL)
-    {
-        LOGE("Error creating PeerPhysicalPath[] array");
-        return NULL;
-    }
-
-    for(unsigned int i = 0; i < peer.pathCount; ++i)
-    {
-        jobject path = newPeerPhysicalPath(env, peer.paths[i]);
-
-        env->SetObjectArrayElement(arrayObject, i, path);
-        if(env->ExceptionCheck()) {
-            LOGE("exception assigning PeerPhysicalPath to array");
-            break;
-        }
-
-        env->DeleteLocalRef(path);
-    }
+    jobjectArray arrayObject = newPeerPhysicalPathArray(env, peer.paths, peer.pathCount);
 
 
     env->SetObjectField(peerObject, Peer_paths_field, arrayObject);
     env->SetObjectField(peerObject, Peer_paths_field, arrayObject);
 
 
@@ -305,49 +285,11 @@ jobject newNetworkConfig(JNIEnv *env, const ZT_VirtualNetworkConfig &vnetConfig)
     env->SetBooleanField(vnetConfigObj, VirtualNetworkConfig_broadcastEnabled_field, vnetConfig.broadcastEnabled);
     env->SetBooleanField(vnetConfigObj, VirtualNetworkConfig_broadcastEnabled_field, vnetConfig.broadcastEnabled);
     env->SetIntField(vnetConfigObj, VirtualNetworkConfig_portError_field, vnetConfig.portError);
     env->SetIntField(vnetConfigObj, VirtualNetworkConfig_portError_field, vnetConfig.portError);
 
 
-    jobjectArray assignedAddrArrayObj = env->NewObjectArray(
-        vnetConfig.assignedAddressCount, InetSocketAddress_class, NULL);
-    if(env->ExceptionCheck() || assignedAddrArrayObj == NULL)
-    {
-        LOGE("Error creating InetSocketAddress[] array");
-        return NULL;
-    }
-
-    for(unsigned int i = 0; i < vnetConfig.assignedAddressCount; ++i)
-    {
-        jobject inetAddrObj = newInetSocketAddress(env, vnetConfig.assignedAddresses[i]);
-        env->SetObjectArrayElement(assignedAddrArrayObj, i, inetAddrObj);
-        if(env->ExceptionCheck())
-        {
-            LOGE("Error assigning InetSocketAddress to array");
-            return NULL;
-        }
-
-        env->DeleteLocalRef(inetAddrObj);
-    }
+    jobjectArray assignedAddrArrayObj = newInetSocketAddressArray(env, vnetConfig.assignedAddresses, vnetConfig.assignedAddressCount);
 
 
     env->SetObjectField(vnetConfigObj, VirtualNetworkConfig_assignedAddresses_field, assignedAddrArrayObj);
     env->SetObjectField(vnetConfigObj, VirtualNetworkConfig_assignedAddresses_field, assignedAddrArrayObj);
 
 
-    jobjectArray routesArrayObj = env->NewObjectArray(
-        vnetConfig.routeCount, VirtualNetworkRoute_class, NULL);
-    if(env->ExceptionCheck() || routesArrayObj == NULL)
-    {
-        LOGE("Error creating VirtualNetworkRoute[] array");
-        return NULL;
-    }
-
-    for(unsigned int i = 0; i < vnetConfig.routeCount; ++i)
-    {
-        jobject routeObj = newVirtualNetworkRoute(env, vnetConfig.routes[i]);
-        env->SetObjectArrayElement(routesArrayObj, i, routeObj);
-        if(env->ExceptionCheck())
-        {
-            LOGE("Error assigning VirtualNetworkRoute to array");
-            return NULL;
-        }
-
-        env->DeleteLocalRef(routeObj);
-    }
+    jobjectArray routesArrayObj = newVirtualNetworkRouteArray(env, vnetConfig.routes, vnetConfig.routeCount);
 
 
     env->SetObjectField(vnetConfigObj, VirtualNetworkConfig_routes_field, routesArrayObj);
     env->SetObjectField(vnetConfigObj, VirtualNetworkConfig_routes_field, routesArrayObj);
 
 
@@ -456,3 +398,76 @@ jobject newNodeStatus(JNIEnv *env, const ZT_NodeStatus &status) {
 
 
     return nodeStatusObj;
     return nodeStatusObj;
 }
 }
+
+jobjectArray newPeerArray(JNIEnv *env, const ZT_Peer *peers, size_t count) {
+    return newArrayObject<ZT_Peer, newPeer>(env, peers, count, Peer_class);
+}
+
+jobjectArray newVirtualNetworkConfigArray(JNIEnv *env, const ZT_VirtualNetworkConfig *networks, size_t count) {
+    return newArrayObject<ZT_VirtualNetworkConfig, newNetworkConfig>(env, networks, count, VirtualNetworkConfig_class);
+}
+
+jobjectArray newPeerPhysicalPathArray(JNIEnv *env, const ZT_PeerPhysicalPath *paths, size_t count) {
+    return newArrayObject<ZT_PeerPhysicalPath, newPeerPhysicalPath>(env, paths, count, PeerPhysicalPath_class);
+}
+
+jobjectArray newInetSocketAddressArray(JNIEnv *env, const sockaddr_storage *addresses, size_t count) {
+    return newArrayObject<sockaddr_storage, newInetSocketAddress>(env, addresses, count, InetSocketAddress_class);
+}
+
+jobjectArray newVirtualNetworkRouteArray(JNIEnv *env, const ZT_VirtualNetworkRoute *routes, size_t count) {
+    return newArrayObject<ZT_VirtualNetworkRoute, newVirtualNetworkRoute>(env, routes, count, VirtualNetworkRoute_class);
+}
+
+void newArrayObject_logCount(size_t count) {
+    LOGE("count > JSIZE_MAX: %zu", count);
+}
+
+void newArrayObject_log(const char *msg) {
+    LOGE("%s", msg);
+}
+
+jbyteArray newByteArray(JNIEnv *env, const unsigned char *bytes, size_t count) {
+
+    if (count > JSIZE_MAX) {
+        LOGE("count > JSIZE_MAX: %zu", count);
+        return NULL;
+    }
+
+    jsize jCount = static_cast<jsize>(count);
+    const jbyte *jBytes = reinterpret_cast<const jbyte *>(bytes);
+
+    jbyteArray byteArrayObj = env->NewByteArray(jCount);
+    if(byteArrayObj == NULL)
+    {
+        LOGE("NewByteArray returned NULL");
+        return NULL;
+    }
+
+    env->SetByteArrayRegion(byteArrayObj, 0, jCount, jBytes);
+    if (env->ExceptionCheck()) {
+        LOGE("Exception when calling SetByteArrayRegion");
+        return NULL;
+    }
+
+    return byteArrayObj;
+}
+
+jbyteArray newByteArray(JNIEnv *env, size_t count) {
+
+    if (count > JSIZE_MAX) {
+        LOGE("count > JSIZE_MAX: %zu", count);
+        return NULL;
+    }
+
+    jsize jCount = static_cast<jsize>(count);
+
+    jbyteArray byteArrayObj = env->NewByteArray(jCount);
+    if(byteArrayObj == NULL)
+    {
+        LOGE("NewByteArray returned NULL");
+        return NULL;
+    }
+
+    return byteArrayObj;
+}

+ 62 - 0
java/jni/ZT_jniutils.h

@@ -22,6 +22,8 @@
 #include <jni.h>
 #include <jni.h>
 #include <ZeroTierOne.h>
 #include <ZeroTierOne.h>
 
 
+#include <limits> // for numeric_limits
+
 #if defined(__ANDROID__)
 #if defined(__ANDROID__)
 
 
 #include <android/log.h>
 #include <android/log.h>
@@ -75,6 +77,8 @@
     } while (false)
     } while (false)
 
 
 
 
+const jsize JSIZE_MAX = std::numeric_limits<jsize>::max();
+
 jobject createResultObject(JNIEnv *env, ZT_ResultCode code);
 jobject createResultObject(JNIEnv *env, ZT_ResultCode code);
 jobject createVirtualNetworkStatus(JNIEnv *env, ZT_VirtualNetworkStatus status);
 jobject createVirtualNetworkStatus(JNIEnv *env, ZT_VirtualNetworkStatus status);
 jobject createVirtualNetworkType(JNIEnv *env, ZT_VirtualNetworkType type);
 jobject createVirtualNetworkType(JNIEnv *env, ZT_VirtualNetworkType type);
@@ -98,4 +102,62 @@ jobject newVirtualNetworkDNS(JNIEnv *env, const ZT_VirtualNetworkDNS &dns);
 
 
 jobject newNodeStatus(JNIEnv *env, const ZT_NodeStatus &status);
 jobject newNodeStatus(JNIEnv *env, const ZT_NodeStatus &status);
 
 
+jobjectArray newPeerArray(JNIEnv *env, const ZT_Peer *peers, size_t count);
+
+jobjectArray newVirtualNetworkConfigArray(JNIEnv *env, const ZT_VirtualNetworkConfig *networks, size_t count);
+
+jobjectArray newPeerPhysicalPathArray(JNIEnv *env, const ZT_PeerPhysicalPath *paths, size_t count);
+
+jobjectArray newInetSocketAddressArray(JNIEnv *env, const sockaddr_storage *addresses, size_t count);
+
+jobjectArray newVirtualNetworkRouteArray(JNIEnv *env, const ZT_VirtualNetworkRoute *routes, size_t count);
+
+//
+// log functions only for newArrayObject below
+//
+void newArrayObject_logCount(size_t count);
+void newArrayObject_log(const char *msg);
+
+//
+// function template for creating array objects
+//
+template <typename T, jobject (*F)(JNIEnv *, const T &)>
+jobjectArray newArrayObject(JNIEnv *env, const T *buffer, size_t count, jclass clazz) {
+
+    if (count > JSIZE_MAX) {
+        newArrayObject_logCount(count);
+        return NULL;
+    }
+
+    jsize jCount = static_cast<jsize>(count);
+
+    jobjectArray arrayObj = env->NewObjectArray(jCount, clazz, NULL);
+    if (env->ExceptionCheck() || arrayObj == NULL) {
+        newArrayObject_log("Error creating array object");
+        return NULL;
+    }
+
+    for (jsize i = 0; i < jCount; i++) {
+
+        jobject obj = F(env, buffer[i]);
+        if(env->ExceptionCheck() || obj == NULL) {
+            return NULL;
+        }
+
+        env->SetObjectArrayElement(arrayObj, i, obj);
+        if(env->ExceptionCheck()) {
+            newArrayObject_log("Error assigning object to array");
+            return NULL;
+        }
+
+        env->DeleteLocalRef(obj);
+    }
+
+    return arrayObj;
+}
+
+jbyteArray newByteArray(JNIEnv *env, const unsigned char *bytes, size_t count);
+
+jbyteArray newByteArray(JNIEnv *env, size_t count);
+
 #endif // ZT_jniutils_h_
 #endif // ZT_jniutils_h_

+ 15 - 66
java/jni/com_zerotierone_sdk_Node.cpp

@@ -164,20 +164,10 @@ namespace {
             return;
             return;
         }
         }
 
 
-        jbyteArray dataArray = env->NewByteArray(frameLength);
+        const unsigned char *bytes = static_cast<const unsigned char*>(frameData);
+        jbyteArray dataArray = newByteArray(env, bytes, frameLength);
         if(env->ExceptionCheck() || dataArray == NULL)
         if(env->ExceptionCheck() || dataArray == NULL)
         {
         {
-            LOGE("Couldn't create frame data array");
-            return;
-        }
-
-        void *data = env->GetPrimitiveArrayCritical(dataArray, NULL);
-        memcpy(data, frameData, frameLength);
-        env->ReleasePrimitiveArrayCritical(dataArray, data, 0);
-
-        if(env->ExceptionCheck())
-        {
-            LOGE("Error setting frame data to array");
             return;
             return;
         }
         }
 
 
@@ -304,16 +294,13 @@ namespace {
 
 
         if (bufferLength >= 0) {
         if (bufferLength >= 0) {
             LOGD("JNI: Write file: %s", p);
             LOGD("JNI: Write file: %s", p);
-            // set operation
-            jbyteArray bufferObj = env->NewByteArray(bufferLength);
+            const unsigned char *bytes = static_cast<const unsigned char *>(buffer);
+            jbyteArray bufferObj = newByteArray(env, bytes, bufferLength);
             if(env->ExceptionCheck() || bufferObj == NULL)
             if(env->ExceptionCheck() || bufferObj == NULL)
             {
             {
-                LOGE("Error creating byte array buffer!");
                 return;
                 return;
             }
             }
 
 
-            env->SetByteArrayRegion(bufferObj, 0, bufferLength, (jbyte*)buffer);
-
             env->CallIntMethod(ref->dataStorePutListener,
             env->CallIntMethod(ref->dataStorePutListener,
                                DataStorePutListener_onDataStorePut_method,
                                DataStorePutListener_onDataStorePut_method,
                                nameStr, bufferObj, secure);
                                nameStr, bufferObj, secure);
@@ -375,10 +362,9 @@ namespace {
             return -103; // out of memory
             return -103; // out of memory
         }
         }
 
 
-        jbyteArray bufferObj = env->NewByteArray(bufferLength);
-        if(bufferObj == NULL)
+        jbyteArray bufferObj = newByteArray(env, bufferLength);
+        if(env->ExceptionCheck() || bufferObj == NULL)
         {
         {
-            LOGE("Error creating byte[] buffer of size: %u", bufferLength);
             return -104;
             return -104;
         }
         }
 
 
@@ -424,8 +410,13 @@ namespace {
         }
         }
 
 
         jobject remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
         jobject remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
-        jbyteArray bufferObj = env->NewByteArray(bufferSize);
-        env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer);
+        const unsigned char *bytes = static_cast<const unsigned char *>(buffer);
+        jbyteArray bufferObj = newByteArray(env, bytes, bufferSize);
+        if (env->ExceptionCheck() || bufferObj == NULL)
+        {
+            return -101;
+        }
+        
         int retval = env->CallIntMethod(ref->packetSender, PacketSender_onSendPacketRequested_method, localSocket, remoteAddressObj, bufferObj);
         int retval = env->CallIntMethod(ref->packetSender, PacketSender_onSendPacketRequested_method, localSocket, remoteAddressObj, bufferObj);
 
 
         LOGV("JNI Packet Sender returned: %d", retval);
         LOGV("JNI Packet Sender returned: %d", retval);
@@ -1207,29 +1198,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers(
         return NULL;
         return NULL;
     }
     }
 
 
-    jobjectArray peerArrayObj = env->NewObjectArray(
-        peerList->peerCount, Peer_class, NULL);
-
-    if(env->ExceptionCheck() || peerArrayObj == NULL)
-    {
-        LOGE("Error creating Peer[] array");
-        ZT_Node_freeQueryResult(node, peerList);
-        return NULL;
-    }
-
-
-    for(unsigned int i = 0; i < peerList->peerCount; ++i)
-    {
-        jobject peerObj = newPeer(env, peerList->peers[i]);
-        env->SetObjectArrayElement(peerArrayObj, i, peerObj);
-        if(env->ExceptionCheck())
-        {
-            LOGE("Error assigning Peer object to array");
-            break;
-        }
-
-        env->DeleteLocalRef(peerObj);
-    }
+    jobjectArray peerArrayObj = newPeerArray(env, peerList->peers, peerList->peerCount);
 
 
     ZT_Node_freeQueryResult(node, peerList);
     ZT_Node_freeQueryResult(node, peerList);
     peerList = NULL;
     peerList = NULL;
@@ -1254,27 +1223,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_networks(
         return NULL;
         return NULL;
     }
     }
 
 
-    jobjectArray networkListObject = env->NewObjectArray(
-        networkList->networkCount, VirtualNetworkConfig_class, NULL);
-    if(env->ExceptionCheck() || networkListObject == NULL)
-    {
-        LOGE("Error creating VirtualNetworkConfig[] array");
-        ZT_Node_freeQueryResult(node, networkList);
-        return NULL;
-    }
-
-    for(unsigned int i = 0; i < networkList->networkCount; ++i)
-    {
-        jobject networkObject = newNetworkConfig(env, networkList->networks[i]);
-        env->SetObjectArrayElement(networkListObject, i, networkObject);
-        if(env->ExceptionCheck())
-        {
-            LOGE("Error assigning VirtualNetworkConfig object to array");
-            break;
-        }
-
-        env->DeleteLocalRef(networkObject);
-    }
+    jobjectArray networkListObject = newVirtualNetworkConfigArray(env, networkList->networks, networkList->networkCount);
 
 
     ZT_Node_freeQueryResult(node, networkList);
     ZT_Node_freeQueryResult(node, networkList);