diff options
Diffstat (limited to 'java/jni/com_zerotierone_sdk_Node.cpp')
-rw-r--r-- | java/jni/com_zerotierone_sdk_Node.cpp | 177 |
1 files changed, 109 insertions, 68 deletions
diff --git a/java/jni/com_zerotierone_sdk_Node.cpp b/java/jni/com_zerotierone_sdk_Node.cpp index f0405813..e98342e7 100644 --- a/java/jni/com_zerotierone_sdk_Node.cpp +++ b/java/jni/com_zerotierone_sdk_Node.cpp @@ -27,17 +27,18 @@ #include "com_zerotierone_sdk_Node.h" #include "ZT1_jniutils.h" -#include "ZT1_jnicache.h" +#include "ZT1_jnilookup.h" #include <ZeroTierOne.h> +#include "Mutex.hpp" #include <map> #include <string> #include <assert.h> #include <string.h> -// global static JNI Cache Object -JniCache cache; +// global static JNI Lookup Object +JniLookup lookup; #ifdef __cplusplus extern "C" { @@ -92,7 +93,7 @@ namespace { enum ZT1_VirtualNetworkConfigOperation operation, const ZT1_VirtualNetworkConfig *config) { - LOGD("VritualNetworkConfigFunctionCallback"); + LOGV("VritualNetworkConfigFunctionCallback"); JniRef *ref = (JniRef*)userData; JNIEnv *env = NULL; ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); @@ -104,7 +105,7 @@ namespace { return -1; } - jmethodID configListenerCallbackMethod = cache.findMethod(configListenerClass, + jmethodID configListenerCallbackMethod = lookup.findMethod(configListenerClass, "onNetworkConfigurationUpdated", "(JLcom/zerotier/sdk/VirtualNetworkConfigOperation;Lcom/zerotier/sdk/VirtualNetworkConfig;)I"); if(configListenerCallbackMethod == NULL) @@ -142,7 +143,9 @@ namespace { const void *frameData, unsigned int frameLength) { - LOGD("VirtualNetworkFrameFunctionCallback"); + LOGV("VirtualNetworkFrameFunctionCallback"); + unsigned char* local = (unsigned char*)frameData; + LOGV("Type Bytes: 0x%02x%02x", local[12], local[13]); JniRef *ref = (JniRef*)userData; assert(ref->node == node); JNIEnv *env = NULL; @@ -156,7 +159,7 @@ namespace { return; } - jmethodID frameListenerCallbackMethod = cache.findMethod( + jmethodID frameListenerCallbackMethod = lookup.findMethod( frameListenerClass, "onVirtualNetworkFrame", "(JJJJJ[B)V"); if(env->ExceptionCheck() || frameListenerCallbackMethod == NULL) @@ -172,9 +175,9 @@ namespace { return; } - jbyte *data = env->GetByteArrayElements(dataArray, NULL); + void *data = env->GetPrimitiveArrayCritical(dataArray, NULL); memcpy(data, frameData, frameLength); - env->ReleaseByteArrayElements(dataArray, data, 0); + env->ReleasePrimitiveArrayCritical(dataArray, data, 0); if(env->ExceptionCheck()) { @@ -188,9 +191,13 @@ namespace { void EventCallback(ZT1_Node *node,void *userData,enum ZT1_Event event, const void *data) { - LOGD("EventCallback"); + LOGV("EventCallback"); JniRef *ref = (JniRef*)userData; - assert(ref->node == node); + if(ref->node != node && event != ZT1_EVENT_UP) + { + LOGE("Nodes not equal. ref->node %p, node %p. Event: %d", ref->node, node, event); + return; + } JNIEnv *env = NULL; ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); @@ -202,7 +209,7 @@ namespace { return; } - jmethodID onEventMethod = cache.findMethod(eventListenerClass, + jmethodID onEventMethod = lookup.findMethod(eventListenerClass, "onEvent", "(Lcom/zerotier/sdk/Event;)V"); if(onEventMethod == NULL) { @@ -211,7 +218,7 @@ namespace { } - jmethodID onOutOfDateMethod = cache.findMethod(eventListenerClass, + jmethodID onOutOfDateMethod = lookup.findMethod(eventListenerClass, "onOutOfDate", "(Lcom/zerotier/sdk/Version;)V"); if(onOutOfDateMethod == NULL) { @@ -220,7 +227,7 @@ namespace { } - jmethodID onNetworkErrorMethod = cache.findMethod(eventListenerClass, + jmethodID onNetworkErrorMethod = lookup.findMethod(eventListenerClass, "onNetworkError", "(Lcom/zerotier/sdk/Event;Ljava/net/InetSocketAddress;)V"); if(onNetworkErrorMethod == NULL) { @@ -229,7 +236,7 @@ namespace { } - jmethodID onTraceMethod = cache.findMethod(eventListenerClass, + jmethodID onTraceMethod = lookup.findMethod(eventListenerClass, "onTrace", "(Ljava/lang/String;)V"); if(onTraceMethod == NULL) { @@ -314,7 +321,7 @@ namespace { return -2; } - jmethodID dataStoreGetCallbackMethod = cache.findMethod( + jmethodID dataStoreGetCallbackMethod = lookup.findMethod( dataStoreGetClass, "onDataStoreGet", "(Ljava/lang/String;[BJ[J)J"); @@ -354,16 +361,16 @@ namespace { if(retval > 0) { - jbyte *data = env->GetByteArrayElements(bufferObj, NULL); + void *data = env->GetPrimitiveArrayCritical(bufferObj, NULL); memcpy(buffer, data, retval); - env->ReleaseByteArrayElements(bufferObj, data, JNI_ABORT); + env->ReleasePrimitiveArrayCritical(bufferObj, data, 0); - jlong *objSize = env->GetLongArrayElements(objectSizeObj, NULL); + jlong *objSize = (jlong*)env->GetPrimitiveArrayCritical(objectSizeObj, NULL); *out_objectSize = (unsigned long)objSize[0]; - env->ReleaseLongArrayElements(objectSizeObj, objSize, JNI_ABORT); + env->ReleasePrimitiveArrayCritical(objectSizeObj, objSize, 0); } - LOGI("Out Object Size: %lu", *out_objectSize); + LOGV("Out Object Size: %lu", *out_objectSize); return retval; } @@ -386,7 +393,7 @@ namespace { return -1; } - jmethodID dataStorePutCallbackMethod = cache.findMethod( + jmethodID dataStorePutCallbackMethod = lookup.findMethod( dataStorePutClass, "onDataStorePut", "(Ljava/lang/String;[BZ)I"); @@ -396,7 +403,7 @@ namespace { return -2; } - jmethodID deleteMethod = cache.findMethod(dataStorePutClass, + jmethodID deleteMethod = lookup.findMethod(dataStorePutClass, "onDelete", "(Ljava/lang/String;)I"); if(deleteMethod == NULL) { @@ -408,18 +415,25 @@ namespace { if(buffer == NULL) { + LOGD("JNI: Delete file: %s", objectName); // delete operation return env->CallIntMethod( ref->dataStorePutListener, deleteMethod, nameStr); } else { + LOGD("JNI: Write file: %s", objectName); // set operation jbyteArray bufferObj = env->NewByteArray(bufferSize); + if(env->ExceptionCheck() || bufferObj == NULL) + { + LOGE("Error creating byte array buffer!"); + return -4; + } + env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer); bool bsecure = secure != 0; - return env->CallIntMethod(ref->dataStorePutListener, dataStorePutCallbackMethod, nameStr, bufferObj, bsecure); @@ -431,7 +445,7 @@ namespace { const void *buffer, unsigned int bufferSize) { - LOGD("WirePacketSendFunction(%p, %p, %d)", address, buffer, bufferSize); + LOGV("WirePacketSendFunction(%p, %p, %d)", address, buffer, bufferSize); JniRef *ref = (JniRef*)userData; assert(ref->node == node); @@ -446,7 +460,7 @@ namespace { return -1; } - jmethodID packetSenderCallbackMethod = cache.findMethod(packetSenderClass, + jmethodID packetSenderCallbackMethod = lookup.findMethod(packetSenderClass, "onSendPacketRequested", "(Ljava/net/InetSocketAddress;[B)I"); if(packetSenderCallbackMethod == NULL) { @@ -459,15 +473,17 @@ namespace { env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer); int retval = env->CallIntMethod(ref->packetSender, packetSenderCallbackMethod, addressObj, bufferObj); - LOGD("JNI Packet Sender returned: %d", retval); + LOGV("JNI Packet Sender returned: %d", retval); return retval; } typedef std::map<uint64_t, JniRef*> NodeMap; static NodeMap nodeMap; + ZeroTier::Mutex nodeMapMutex; ZT1_Node* findNode(uint64_t nodeId) { + ZeroTier::Mutex::Lock lock(nodeMapMutex); NodeMap::iterator found = nodeMap.find(nodeId); if(found != nodeMap.end()) { @@ -480,13 +496,13 @@ namespace { JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { - cache.setJavaVM(vm); + lookup.setJavaVM(vm); return JNI_VERSION_1_6; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { - cache.clearCache(); + } @@ -507,7 +523,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( env->GetJavaVM(&ref->jvm); jclass cls = env->GetObjectClass(obj); - jfieldID fid = cache.findField( + jfieldID fid = lookup.findField( cls, "getListener", "Lcom/zerotier/sdk/DataStoreGetListener;"); if(fid == NULL) @@ -522,7 +538,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( } ref->dataStoreGetListener = env->NewGlobalRef(tmp); - fid = cache.findField( + fid = lookup.findField( cls, "putListener", "Lcom/zerotier/sdk/DataStorePutListener;"); if(fid == NULL) @@ -537,7 +553,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( } ref->dataStorePutListener = env->NewGlobalRef(tmp); - fid = cache.findField( + fid = lookup.findField( cls, "sender", "Lcom/zerotier/sdk/PacketSender;"); if(fid == NULL) { @@ -551,7 +567,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( } ref->packetSender = env->NewGlobalRef(tmp); - fid = cache.findField( + fid = lookup.findField( cls, "frameListener", "Lcom/zerotier/sdk/VirtualNetworkFrameListener;"); if(fid == NULL) { @@ -565,7 +581,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( } ref->frameListener = env->NewGlobalRef(tmp); - fid = cache.findField( + fid = lookup.findField( cls, "configListener", "Lcom/zerotier/sdk/VirtualNetworkConfigListener;"); if(fid == NULL) { @@ -579,7 +595,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( } ref->configListener = env->NewGlobalRef(tmp); - fid = cache.findField( + fid = lookup.findField( cls, "eventListener", "Lcom/zerotier/sdk/EventListener;"); if(fid == NULL) { @@ -604,6 +620,8 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( &VirtualNetworkConfigFunctionCallback, &EventCallback); + LOGI("Node Created."); + if(rc != ZT1_RESULT_OK) { LOGE("Error creating Node: %d", rc); @@ -618,8 +636,10 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( return resultObject; } + ZeroTier::Mutex::Lock lock(nodeMapMutex); ref->node = node; nodeMap.insert(std::make_pair(ref->id, ref)); + return resultObject; } @@ -635,7 +655,12 @@ JNIEXPORT void JNICALL Java_com_zerotier_sdk_Node_node_1delete( LOGV("Destroying ZT1_Node struct"); uint64_t nodeId = (uint64_t)id; - NodeMap::iterator found = nodeMap.find(nodeId); + NodeMap::iterator found; + { + ZeroTier::Mutex::Lock lock(nodeMapMutex); + found = nodeMap.find(nodeId); + } + if(found != nodeMap.end()) { JniRef *ref = found->second; @@ -693,7 +718,10 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame( unsigned int vlanId = (unsigned int)in_vlanId; unsigned int frameLength = env->GetArrayLength(in_frameData); - jbyte *frameData =env->GetByteArrayElements(in_frameData, NULL); + void *frameData = env->GetPrimitiveArrayCritical(in_frameData, NULL); + void *localData = malloc(frameLength); + memcpy(localData, frameData, frameLength); + env->ReleasePrimitiveArrayCritical(in_frameData, frameData, 0); uint64_t nextBackgroundTaskDeadline = 0; @@ -705,15 +733,13 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame( destMac, etherType, vlanId, - (const void*)frameData, + (const void*)localData, frameLength, &nextBackgroundTaskDeadline); - jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL); + jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL); outDeadline[0] = (jlong)nextBackgroundTaskDeadline; - env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0); - - env->ReleaseByteArrayElements(in_frameData, frameData, 0); + env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0); return createResultObject(env, rc); } @@ -736,26 +762,29 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( if(node == NULL) { // cannot find valid node. We should never get here. + LOGE("Couldn't find a valid node!"); return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); } unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline); if(nbtd_len < 1) { + LOGE("nbtd_len < 1"); return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); } uint64_t now = (uint64_t)in_now; // get the java.net.InetSocketAddress class and getAddress() method - jclass inetAddressClass = cache.findClass("java/net/InetAddress"); + jclass inetAddressClass = lookup.findClass("java/net/InetAddress"); if(inetAddressClass == NULL) { + LOGE("Can't find InetAddress class"); // can't find java.net.InetAddress return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); } - jmethodID getAddressMethod = cache.findMethod( + jmethodID getAddressMethod = lookup.findMethod( inetAddressClass, "getAddress", "()[B"); if(getAddressMethod == NULL) { @@ -763,13 +792,13 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); } - jclass InetSocketAddressClass = cache.findClass("java/net/InetSocketAddress"); + jclass InetSocketAddressClass = lookup.findClass("java/net/InetSocketAddress"); if(InetSocketAddressClass == NULL) { return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); } - jmethodID inetSockGetAddressMethod = cache.findMethod( + jmethodID inetSockGetAddressMethod = lookup.findMethod( InetSocketAddressClass, "getAddress", "()Ljava/net/InetAddress;"); jobject addrObject = env->CallObjectMethod(in_remoteAddress, inetSockGetAddressMethod); @@ -779,7 +808,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); } - jmethodID inetSock_getPort = cache.findMethod( + jmethodID inetSock_getPort = lookup.findMethod( InetSocketAddressClass, "getPort", "()I"); if(env->ExceptionCheck() || inetSock_getPort == NULL) @@ -800,14 +829,14 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( jbyteArray addressArray = (jbyteArray)env->CallObjectMethod(addrObject, getAddressMethod); if(addressArray == NULL) { + LOGE("Unable to call getAddress()"); // unable to call getAddress() return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); } unsigned int addrSize = env->GetArrayLength(addressArray); // get the address bytes - jbyte *addr = env->GetByteArrayElements(addressArray, NULL); - + jbyte *addr = (jbyte*)env->GetPrimitiveArrayCritical(addressArray, NULL); sockaddr_storage remoteAddress = {}; @@ -831,14 +860,23 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( } else { + LOGE("Unknown IP version"); // unknown address type - env->ReleaseByteArrayElements(addressArray, addr, 0); + env->ReleasePrimitiveArrayCritical(addressArray, addr, 0); return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); } - + env->ReleasePrimitiveArrayCritical(addressArray, addr, 0); unsigned int packetLength = env->GetArrayLength(in_packetData); - jbyte *packetData = env->GetByteArrayElements(in_packetData, NULL); + if(packetLength == 0) + { + LOGE("Empty packet?!?"); + return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); + } + void *packetData = env->GetPrimitiveArrayCritical(in_packetData, NULL); + void *localData = malloc(packetLength); + memcpy(localData, packetData, packetLength); + env->ReleasePrimitiveArrayCritical(in_packetData, packetData, 0); uint64_t nextBackgroundTaskDeadline = 0; @@ -846,16 +884,19 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( node, now, &remoteAddress, - packetData, + localData, packetLength, &nextBackgroundTaskDeadline); + if(rc != ZT1_RESULT_OK) + { + LOGE("ZT1_Node_processWirePacket returned: %d", rc); + } - jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL); - outDeadline[0] = (jlong)nextBackgroundTaskDeadline; - env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0); + free(localData); - env->ReleaseByteArrayElements(addressArray, addr, 0); - env->ReleaseByteArrayElements(in_packetData, packetData, 0); + jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL); + outDeadline[0] = (jlong)nextBackgroundTaskDeadline; + env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0); return createResultObject(env, rc); } @@ -890,9 +931,9 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processBackgroundTasks( ZT1_ResultCode rc = ZT1_Node_processBackgroundTasks(node, now, &nextBackgroundTaskDeadline); - jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL); + jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL); outDeadline[0] = (jlong)nextBackgroundTaskDeadline; - env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0); + env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0); return createResultObject(env, rc); } @@ -1043,13 +1084,13 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_status jmethodID nodeStatusConstructor = NULL; // create a com.zerotier.sdk.NodeStatus object - nodeStatusClass = cache.findClass("com/zerotier/sdk/NodeStatus"); + nodeStatusClass = lookup.findClass("com/zerotier/sdk/NodeStatus"); if(nodeStatusClass == NULL) { return NULL; } - nodeStatusConstructor = cache.findMethod( + nodeStatusConstructor = lookup.findMethod( nodeStatusClass, "<init>", "()V"); if(nodeStatusConstructor == NULL) { @@ -1070,25 +1111,25 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_status jfieldID secretIdentityField = NULL; jfieldID onlineField = NULL; - addressField = cache.findField(nodeStatusClass, "address", "J"); + addressField = lookup.findField(nodeStatusClass, "address", "J"); if(addressField == NULL) { return NULL; } - publicIdentityField = cache.findField(nodeStatusClass, "publicIdentity", "Ljava/lang/String;"); + publicIdentityField = lookup.findField(nodeStatusClass, "publicIdentity", "Ljava/lang/String;"); if(publicIdentityField == NULL) { return NULL; } - secretIdentityField = cache.findField(nodeStatusClass, "secretIdentity", "Ljava/lang/String;"); + secretIdentityField = lookup.findField(nodeStatusClass, "secretIdentity", "Ljava/lang/String;"); if(secretIdentityField == NULL) { return NULL; } - onlineField = cache.findField(nodeStatusClass, "online", "Z"); + onlineField = lookup.findField(nodeStatusClass, "online", "Z"); if(onlineField == NULL) { return NULL; @@ -1191,7 +1232,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers( return NULL; } - jclass peerClass = cache.findClass("com/zerotier/sdk/Peer"); + jclass peerClass = lookup.findClass("com/zerotier/sdk/Peer"); if(env->ExceptionCheck() || peerClass == NULL) { LOGE("Error finding Peer class"); @@ -1249,7 +1290,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_networks( return NULL; } - jclass vnetConfigClass = cache.findClass("com/zerotier/sdk/VirtualNetworkConfig"); + jclass vnetConfigClass = lookup.findClass("com/zerotier/sdk/VirtualNetworkConfig"); if(env->ExceptionCheck() || vnetConfigClass == NULL) { LOGE("Error finding VirtualNetworkConfig class"); |