add array functions

This commit is contained in:
Brenton Bostick 2023-01-31 18:32:19 -05:00
parent 2de4c95446
commit f51ce077a3
3 changed files with 160 additions and 134 deletions

View file

@ -107,14 +107,14 @@ jobject newInetAddress(JNIEnv *env, const sockaddr_storage &addr)
case AF_INET6:
{
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;
}
env->SetByteArrayRegion(buff, 0, 16, (jbyte*)ipv6->sin6_addr.s6_addr);
inetAddressObj = env->CallStaticObjectMethod(
InetAddress_class, InetAddress_getByAddress_method, buff);
}
@ -122,14 +122,13 @@ jobject newInetAddress(JNIEnv *env, const sockaddr_storage &addr)
case AF_INET:
{
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;
}
env->SetByteArrayRegion(buff, 0, 4, (jbyte*)&ipv4->sin_addr);
inetAddressObj = env->CallStaticObjectMethod(
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->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);
@ -305,49 +285,11 @@ jobject newNetworkConfig(JNIEnv *env, const ZT_VirtualNetworkConfig &vnetConfig)
env->SetBooleanField(vnetConfigObj, VirtualNetworkConfig_broadcastEnabled_field, vnetConfig.broadcastEnabled);
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);
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);
@ -456,3 +398,76 @@ jobject newNodeStatus(JNIEnv *env, const ZT_NodeStatus &status) {
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;
}

View file

@ -22,6 +22,8 @@
#include <jni.h>
#include <ZeroTierOne.h>
#include <limits> // for numeric_limits
#if defined(__ANDROID__)
#include <android/log.h>
@ -75,6 +77,8 @@
} while (false)
const jsize JSIZE_MAX = std::numeric_limits<jsize>::max();
jobject createResultObject(JNIEnv *env, ZT_ResultCode code);
jobject createVirtualNetworkStatus(JNIEnv *env, ZT_VirtualNetworkStatus status);
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);
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_

View file

@ -164,20 +164,10 @@ namespace {
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)
{
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;
}
@ -304,16 +294,13 @@ namespace {
if (bufferLength >= 0) {
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)
{
LOGE("Error creating byte array buffer!");
return;
}
env->SetByteArrayRegion(bufferObj, 0, bufferLength, (jbyte*)buffer);
env->CallIntMethod(ref->dataStorePutListener,
DataStorePutListener_onDataStorePut_method,
nameStr, bufferObj, secure);
@ -375,10 +362,9 @@ namespace {
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;
}
@ -424,8 +410,13 @@ namespace {
}
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);
LOGV("JNI Packet Sender returned: %d", retval);
@ -1207,29 +1198,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers(
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);
peerList = NULL;
@ -1254,27 +1223,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_networks(
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);