diff options
author | Adam Ierymenko <adam.ierymenko@zerotier.com> | 2018-04-25 06:39:02 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-25 06:39:02 -0700 |
commit | 42ec780a6f6eedef4d8b1d8218bd72fc6ed75cc0 (patch) | |
tree | 7bf86c4d92d6a0f77eced79bfc33313c62c7b6dd /java/jni | |
parent | 18c9dc8a0649c866eff9f299f20fa5b19c502e52 (diff) | |
parent | 4608880fb06700822d01e9e5d6729fcdeb82b64b (diff) | |
download | infinitytier-42ec780a6f6eedef4d8b1d8218bd72fc6ed75cc0.tar.gz infinitytier-42ec780a6f6eedef4d8b1d8218bd72fc6ed75cc0.zip |
Merge branch 'dev' into netbsd-support
Diffstat (limited to 'java/jni')
-rw-r--r-- | java/jni/Android.mk | 47 | ||||
-rw-r--r-- | java/jni/Application.mk | 4 | ||||
-rw-r--r-- | java/jni/ZT_jniutils.cpp | 194 | ||||
-rw-r--r-- | java/jni/ZT_jniutils.h | 52 | ||||
-rw-r--r-- | java/jni/com_zerotierone_sdk_Node.cpp | 779 | ||||
-rw-r--r-- | java/jni/com_zerotierone_sdk_Node.h | 2 |
6 files changed, 754 insertions, 324 deletions
diff --git a/java/jni/Android.mk b/java/jni/Android.mk index c563879c..8cda2474 100644 --- a/java/jni/Android.mk +++ b/java/jni/Android.mk @@ -3,22 +3,28 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := ZeroTierOneJNI -LOCAL_C_INCLUDES := $(ZT1)/include -LOCAL_C_INCLUDES += $(ZT1)/node -LOCAL_LDLIBS := -llog +LOCAL_C_INCLUDES := \ + $(ZT1)/include \ + $(ZT1)/node \ + $(ZT1)/osdep \ + $(ZT1)/ext/miniupnpc \ + $(ZT1)/ext/libnatpmp + +LOCAL_LDLIBS := -llog -latomic # LOCAL_CFLAGS := -g +LOCAL_CFLAGS := -DZT_USE_MINIUPNPC + # ZeroTierOne SDK source files LOCAL_SRC_FILES := \ - $(ZT1)/ext/lz4/lz4.c \ - $(ZT1)/ext/json-parser/json.c \ - $(ZT1)/ext/http-parser/http_parser.c \ - $(ZT1)/node/C25519.cpp \ + $(ZT1)/node/C25519.cpp \ + $(ZT1)/node/Capability.cpp \ $(ZT1)/node/CertificateOfMembership.cpp \ - $(ZT1)/node/DeferredPackets.cpp \ + $(ZT1)/node/CertificateOfOwnership.cpp \ $(ZT1)/node/Identity.cpp \ $(ZT1)/node/IncomingPacket.cpp \ $(ZT1)/node/InetAddress.cpp \ + $(ZT1)/node/Membership.cpp \ $(ZT1)/node/Multicaster.cpp \ $(ZT1)/node/Network.cpp \ $(ZT1)/node/NetworkConfig.cpp \ @@ -28,14 +34,35 @@ LOCAL_SRC_FILES := \ $(ZT1)/node/Path.cpp \ $(ZT1)/node/Peer.cpp \ $(ZT1)/node/Poly1305.cpp \ + $(ZT1)/node/Revocation.cpp \ $(ZT1)/node/Salsa20.cpp \ $(ZT1)/node/SelfAwareness.cpp \ $(ZT1)/node/SHA512.cpp \ $(ZT1)/node/Switch.cpp \ + $(ZT1)/node/Tag.cpp \ $(ZT1)/node/Topology.cpp \ + $(ZT1)/node/Trace.cpp \ $(ZT1)/node/Utils.cpp \ - $(ZT1)/osdep/Http.cpp \ - $(ZT1)/osdep/OSUtils.cpp + $(ZT1)/osdep/OSUtils.cpp \ + $(ZT1)/osdep/PortMapper.cpp + +# libminiupnpc and libnatpmp files +LOCAL_SRC_FILES += \ + $(ZT1)/ext/miniupnpc/connecthostport.c \ + $(ZT1)/ext/miniupnpc/igd_desc_parse.c \ + $(ZT1)/ext/miniupnpc/minisoap.c \ + $(ZT1)/ext/miniupnpc/minissdpc.c \ + $(ZT1)/ext/miniupnpc/miniupnpc.c \ + $(ZT1)/ext/miniupnpc/miniwget.c \ + $(ZT1)/ext/miniupnpc/minixml.c \ + $(ZT1)/ext/miniupnpc/portlistingparse.c \ + $(ZT1)/ext/miniupnpc/receivedata.c \ + $(ZT1)/ext/miniupnpc/upnpcommands.c \ + $(ZT1)/ext/miniupnpc/upnpdev.c \ + $(ZT1)/ext/miniupnpc/upnperrors.c \ + $(ZT1)/ext/miniupnpc/upnpreplyparse.c \ + $(ZT1)/ext/libnatpmp/natpmp.c \ + $(ZT1)/ext/libnatpmp/getgateway.c # JNI Files LOCAL_SRC_FILES += \ diff --git a/java/jni/Application.mk b/java/jni/Application.mk index 6950c0e6..f5a87ac7 100644 --- a/java/jni/Application.mk +++ b/java/jni/Application.mk @@ -1,5 +1,5 @@ # NDK_TOOLCHAIN_VERSION := clang3.5 -APP_STL := gnustl_static -APP_CPPFLAGS := -O3 -fPIC -fPIE -Wall -fstack-protector -fexceptions -fno-strict-aliasing -Wno-deprecated-register -DZT_NO_TYPE_PUNNING=1 +APP_STL := c++_static +APP_CPPFLAGS := -Wall -fstack-protector -fexceptions -fno-strict-aliasing -Wno-deprecated-register -DZT_NO_TYPE_PUNNING=1 APP_PLATFORM := android-14 APP_ABI := all diff --git a/java/jni/ZT_jniutils.cpp b/java/jni/ZT_jniutils.cpp index 512bf839..c52a2066 100644 --- a/java/jni/ZT_jniutils.cpp +++ b/java/jni/ZT_jniutils.cpp @@ -1,3 +1,21 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "ZT_jniutils.h" #include "ZT_jnilookup.h" #include <string> @@ -12,7 +30,7 @@ extern "C" { jobject createResultObject(JNIEnv *env, ZT_ResultCode code) { jclass resultClass = NULL; - + jobject resultObject = NULL; resultClass = lookup.findClass("com/zerotier/sdk/ResultCode"); @@ -49,14 +67,14 @@ jobject createResultObject(JNIEnv *env, ZT_ResultCode code) } jfieldID enumField = lookup.findStaticField(resultClass, fieldName.c_str(), "Lcom/zerotier/sdk/ResultCode;"); - if(env->ExceptionCheck() || enumField == NULL) + if(env->ExceptionCheck() || enumField == NULL) { LOGE("Error on FindStaticField"); return NULL; } resultObject = env->GetStaticObjectField(resultClass, enumField); - if(env->ExceptionCheck() || resultObject == NULL) + if(env->ExceptionCheck() || resultObject == NULL) { LOGE("Error on GetStaticObjectField"); } @@ -136,6 +154,11 @@ jobject createEvent(JNIEnv *env, ZT_Event event) case ZT_EVENT_TRACE: fieldName = "EVENT_TRACE"; break; + case ZT_EVENT_USER_MESSAGE: + break; + case ZT_EVENT_REMOTE_TRACE: + default: + break; } jfieldID enumField = lookup.findStaticField(eventClass, fieldName.c_str(), "Lcom/zerotier/sdk/Event;"); @@ -162,11 +185,11 @@ jobject createPeerRole(JNIEnv *env, ZT_PeerRole role) case ZT_PEER_ROLE_LEAF: fieldName = "PEER_ROLE_LEAF"; break; - case ZT_PEER_ROLE_RELAY: - fieldName = "PEER_ROLE_RELAY"; + case ZT_PEER_ROLE_MOON: + fieldName = "PEER_ROLE_MOON"; break; - case ZT_PEER_ROLE_ROOT: - fieldName = "PEER_ROLE_ROOTS"; + case ZT_PEER_ROLE_PLANET: + fieldName = "PEER_ROLE_PLANET"; break; } @@ -313,11 +336,20 @@ jobject newInetSocketAddress(JNIEnv *env, const sockaddr_storage &addr) return NULL; } - jobject inetAddressObject = newInetAddress(env, addr); + jobject inetAddressObject = NULL; - if(env->ExceptionCheck() || inetAddressObject == NULL) + if(addr.ss_family != 0) + { + inetAddressObject = newInetAddress(env, addr); + + if(env->ExceptionCheck() || inetAddressObject == NULL) + { + LOGE("Error creating new inet address"); + return NULL; + } + } + else { - LOGE("Error creating new inet address"); return NULL; } @@ -350,10 +382,9 @@ jobject newInetSocketAddress(JNIEnv *env, const sockaddr_storage &addr) break; default: { - LOGE("ERROR: addr.ss_family is not set or unknown"); break; } - }; + } jobject inetSocketAddressObject = env->NewObject(inetSocketAddressClass, inetSocketAddress_constructor, inetAddressObject, port); @@ -371,7 +402,6 @@ jobject newPeerPhysicalPath(JNIEnv *env, const ZT_PeerPhysicalPath &ppp) jfieldID addressField = NULL; jfieldID lastSendField = NULL; jfieldID lastReceiveField = NULL; - jfieldID activeField = NULL; jfieldID preferredField = NULL; jmethodID ppp_constructor = NULL; @@ -404,13 +434,6 @@ jobject newPeerPhysicalPath(JNIEnv *env, const ZT_PeerPhysicalPath &ppp) return NULL; } - activeField = lookup.findField(pppClass, "active", "Z"); - if(env->ExceptionCheck() || activeField == NULL) - { - LOGE("Error finding active field"); - return NULL; - } - preferredField = lookup.findField(pppClass, "preferred", "Z"); if(env->ExceptionCheck() || preferredField == NULL) { @@ -441,7 +464,6 @@ jobject newPeerPhysicalPath(JNIEnv *env, const ZT_PeerPhysicalPath &ppp) env->SetObjectField(pppObject, addressField, addressObject); env->SetLongField(pppObject, lastSendField, ppp.lastSend); env->SetLongField(pppObject, lastReceiveField, ppp.lastReceive); - env->SetBooleanField(pppObject, activeField, ppp.active); env->SetBooleanField(pppObject, preferredField, ppp.preferred); if(env->ExceptionCheck()) { @@ -451,15 +473,13 @@ jobject newPeerPhysicalPath(JNIEnv *env, const ZT_PeerPhysicalPath &ppp) return pppObject; } -jobject newPeer(JNIEnv *env, const ZT_Peer &peer) +jobject newPeer(JNIEnv *env, const ZT_Peer &peer) { LOGV("newPeer called"); jclass peerClass = NULL; jfieldID addressField = NULL; - jfieldID lastUnicastFrameField = NULL; - jfieldID lastMulticastFrameField = NULL; jfieldID versionMajorField = NULL; jfieldID versionMinorField = NULL; jfieldID versionRevField = NULL; @@ -483,20 +503,6 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer) return NULL; } - lastUnicastFrameField = lookup.findField(peerClass, "lastUnicastFrame", "J"); - if(env->ExceptionCheck() || lastUnicastFrameField == NULL) - { - LOGE("Error finding lastUnicastFrame field of Peer object"); - return NULL; - } - - lastMulticastFrameField = lookup.findField(peerClass, "lastMulticastFrame", "J"); - if(env->ExceptionCheck() || lastMulticastFrameField == NULL) - { - LOGE("Error finding lastMulticastFrame field of Peer object"); - return NULL; - } - versionMajorField = lookup.findField(peerClass, "versionMajor", "I"); if(env->ExceptionCheck() || versionMajorField == NULL) { @@ -554,8 +560,6 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer) } env->SetLongField(peerObject, addressField, (jlong)peer.address); - env->SetLongField(peerObject, lastUnicastFrameField, (jlong)peer.lastUnicastFrame); - env->SetLongField(peerObject, lastMulticastFrameField, (jlong)peer.lastMulticastFrame); env->SetIntField(peerObject, versionMajorField, peer.versionMajor); env->SetIntField(peerObject, versionMinorField, peer.versionMinor); env->SetIntField(peerObject, versionRevField, peer.versionRev); @@ -571,7 +575,7 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer) jobjectArray arrayObject = env->NewObjectArray( peer.pathCount, peerPhysicalPathClass, NULL); - if(env->ExceptionCheck() || arrayObject == NULL) + if(env->ExceptionCheck() || arrayObject == NULL) { LOGE("Error creating PeerPhysicalPath[] array"); return NULL; @@ -609,6 +613,7 @@ jobject newNetworkConfig(JNIEnv *env, const ZT_VirtualNetworkConfig &vnetConfig) jfieldID portErrorField = NULL; jfieldID netconfRevisionField = NULL; jfieldID assignedAddressesField = NULL; + jfieldID routesField = NULL; vnetConfigClass = lookup.findClass("com/zerotier/sdk/VirtualNetworkConfig"); if(vnetConfigClass == NULL) @@ -709,13 +714,22 @@ jobject newNetworkConfig(JNIEnv *env, const ZT_VirtualNetworkConfig &vnetConfig) return NULL; } - assignedAddressesField = lookup.findField(vnetConfigClass, "assignedAddresses", "[Ljava/net/InetSocketAddress;"); + assignedAddressesField = lookup.findField(vnetConfigClass, "assignedAddresses", + "[Ljava/net/InetSocketAddress;"); if(env->ExceptionCheck() || assignedAddressesField == NULL) { LOGE("Error getting assignedAddresses field"); return NULL; } + routesField = lookup.findField(vnetConfigClass, "routes", + "[Lcom/zerotier/sdk/VirtualNetworkRoute;"); + if(env->ExceptionCheck() || routesField == NULL) + { + LOGE("Error getting routes field"); + return NULL; + } + env->SetLongField(vnetConfigObj, nwidField, vnetConfig.nwid); env->SetLongField(vnetConfigObj, macField, vnetConfig.mac); jstring nameStr = env->NewStringUTF(vnetConfig.name); @@ -773,6 +787,34 @@ jobject newNetworkConfig(JNIEnv *env, const ZT_VirtualNetworkConfig &vnetConfig) env->SetObjectField(vnetConfigObj, assignedAddressesField, assignedAddrArrayObj); + jclass virtualNetworkRouteClass = lookup.findClass("com/zerotier/sdk/VirtualNetworkRoute"); + if(env->ExceptionCheck() || virtualNetworkRouteClass == NULL) + { + LOGE("Error finding VirtualNetworkRoute class"); + return NULL; + } + + jobjectArray routesArrayObj = env->NewObjectArray( + vnetConfig.routeCount, virtualNetworkRouteClass, 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->SetObjectField(vnetConfigObj, routesField, routesArrayObj); + return vnetConfigObj; } @@ -831,6 +873,72 @@ jobject newVersion(JNIEnv *env, int major, int minor, int rev) return versionObj; } +jobject newVirtualNetworkRoute(JNIEnv *env, const ZT_VirtualNetworkRoute &route) +{ + jclass virtualNetworkRouteClass = NULL; + jmethodID routeConstructor = NULL; + + virtualNetworkRouteClass = lookup.findClass("com/zerotier/sdk/VirtualNetworkRoute"); + if(env->ExceptionCheck() || virtualNetworkRouteClass == NULL) + { + return NULL; + } + + routeConstructor = lookup.findMethod(virtualNetworkRouteClass, "<init>", "()V"); + if(env->ExceptionCheck() || routeConstructor == NULL) + { + return NULL; + } + + jobject routeObj = env->NewObject(virtualNetworkRouteClass, routeConstructor); + if(env->ExceptionCheck() || routeObj == NULL) + { + return NULL; + } + + jfieldID targetField = NULL; + jfieldID viaField = NULL; + jfieldID flagsField = NULL; + jfieldID metricField = NULL; + + targetField = lookup.findField(virtualNetworkRouteClass, "target", + "Ljava/net/InetSocketAddress;"); + if(env->ExceptionCheck() || targetField == NULL) + { + return NULL; + } + + viaField = lookup.findField(virtualNetworkRouteClass, "via", + "Ljava/net/InetSocketAddress;"); + if(env->ExceptionCheck() || targetField == NULL) + { + return NULL; + } + + flagsField = lookup.findField(virtualNetworkRouteClass, "flags", "I"); + if(env->ExceptionCheck() || flagsField == NULL) + { + return NULL; + } + + metricField = lookup.findField(virtualNetworkRouteClass, "metric", "I"); + if(env->ExceptionCheck() || metricField == NULL) + { + return NULL; + } + + jobject targetObj = newInetSocketAddress(env, route.target); + jobject viaObj = newInetSocketAddress(env, route.via); + + env->SetObjectField(routeObj, targetField, targetObj); + env->SetObjectField(routeObj, viaField, viaObj); + env->SetIntField(routeObj, flagsField, (jint)route.flags); + env->SetIntField(routeObj, metricField, (jint)route.metric); + + return routeObj; +} + #ifdef __cplusplus } -#endif
\ No newline at end of file +#endif + diff --git a/java/jni/ZT_jniutils.h b/java/jni/ZT_jniutils.h index 34dfc471..56b63179 100644 --- a/java/jni/ZT_jniutils.h +++ b/java/jni/ZT_jniutils.h @@ -1,3 +1,21 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef ZT_jniutils_h_ #define ZT_jniutils_h_ #include <stdio.h> @@ -10,17 +28,31 @@ extern "C" { #define LOG_TAG "ZeroTierOneJNI" -#if __ANDROID__ +#if defined(__ANDROID__) + #include <android/log.h> -#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) -#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) -#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) + + #if !defined(NDEBUG) + #define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) + #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) + #else + #define LOGV(...) + #define LOGD(...) + #endif + + #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) + #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) #else -#define LOGV(...) fprintf(stdout, __VA_ARGS__) -#define LOGI(...) fprintf(stdout, __VA_ARGS__) -#define LOGD(...) fprintf(stdout, __VA_ARGS__) -#define LOGE(...) fprintf(stdout, __VA_ARGS__) + #if !defined(NDEBUG) + #define LOGV(...) fprintf(stdout, __VA_ARGS__) + #define LOGD(...) fprintf(stdout, __VA_ARGS__) + #else + #define LOGV(...) + #define LOGD(...) + #endif + + #define LOGI(...) fprintf(stdout, __VA_ARGS__) + #define LOGE(...) fprintf(stdout, __VA_ARGS__) #endif jobject createResultObject(JNIEnv *env, ZT_ResultCode code); @@ -42,6 +74,8 @@ jobject newNetworkConfig(JNIEnv *env, const ZT_VirtualNetworkConfig &config); jobject newVersion(JNIEnv *env, int major, int minor, int rev); +jobject newVirtualNetworkRoute(JNIEnv *env, const ZT_VirtualNetworkRoute &route); + #ifdef __cplusplus } #endif diff --git a/java/jni/com_zerotierone_sdk_Node.cpp b/java/jni/com_zerotierone_sdk_Node.cpp index 4d9a2102..9a36e99b 100644 --- a/java/jni/com_zerotierone_sdk_Node.cpp +++ b/java/jni/com_zerotierone_sdk_Node.cpp @@ -32,6 +32,8 @@ #include <ZeroTierOne.h> #include "Mutex.hpp" +#include "PortMapper.hpp" + #include <map> #include <string> #include <assert.h> @@ -56,7 +58,13 @@ namespace { , eventListener(NULL) , frameListener(NULL) , configListener(NULL) - {} + , pathChecker(NULL) + , callbacks(NULL) + , portMapper(NULL) + { + callbacks = (ZT_Node_Callbacks*)malloc(sizeof(ZT_Node_Callbacks)); + memset(callbacks, 0, sizeof(ZT_Node_Callbacks)); + } ~JniRef() { @@ -69,9 +77,16 @@ namespace { env->DeleteGlobalRef(eventListener); env->DeleteGlobalRef(frameListener); env->DeleteGlobalRef(configListener); + env->DeleteGlobalRef(pathChecker); + + free(callbacks); + callbacks = NULL; + + delete portMapper; + portMapper = NULL; } - uint64_t id; + int64_t id; JavaVM *jvm; @@ -83,12 +98,18 @@ namespace { jobject eventListener; jobject frameListener; jobject configListener; + jobject pathChecker; + + ZT_Node_Callbacks *callbacks; + + ZeroTier::PortMapper *portMapper; }; int VirtualNetworkConfigFunctionCallback( ZT_Node *node, void *userData, + void *threadData, uint64_t nwid, void **, enum ZT_VirtualNetworkConfigOperation operation, @@ -99,6 +120,11 @@ namespace { JNIEnv *env = NULL; ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); + if (ref->configListener == NULL) { + LOGE("configListener is NULL"); + return -1; + } + jclass configListenerClass = env->GetObjectClass(ref->configListener); if(configListenerClass == NULL) { @@ -130,13 +156,14 @@ namespace { } return env->CallIntMethod( - ref->configListener, - configListenerCallbackMethod, + ref->configListener, + configListenerCallbackMethod, (jlong)nwid, operationObject, networkConfigObject); } void VirtualNetworkFrameFunctionCallback(ZT_Node *node, void *userData, + void *threadData, uint64_t nwid, void**, uint64_t sourceMac, @@ -147,13 +174,19 @@ namespace { unsigned int frameLength) { LOGV("VirtualNetworkFrameFunctionCallback"); +#ifndef NDEBUG unsigned char* local = (unsigned char*)frameData; LOGV("Type Bytes: 0x%02x%02x", local[12], local[13]); +#endif JniRef *ref = (JniRef*)userData; assert(ref->node == node); JNIEnv *env = NULL; ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); + if (ref->frameListener == NULL) { + LOGE("frameListener is NULL"); + return; + } jclass frameListenerClass = env->GetObjectClass(ref->frameListener); if(env->ExceptionCheck() || frameListenerClass == NULL) @@ -194,109 +227,232 @@ namespace { void EventCallback(ZT_Node *node, void *userData, - enum ZT_Event event, - const void *data) - { + void *threadData, + enum ZT_Event event, + const void *data) { LOGV("EventCallback"); - JniRef *ref = (JniRef*)userData; - if(ref->node != node && event != ZT_EVENT_UP) - { + JniRef *ref = (JniRef *) userData; + if (ref->node != node && event != ZT_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); + ref->jvm->GetEnv((void **) &env, JNI_VERSION_1_6); + if (ref->eventListener == NULL) { + LOGE("eventListener is NULL"); + return; + } jclass eventListenerClass = env->GetObjectClass(ref->eventListener); - if(eventListenerClass == NULL) - { + if (eventListenerClass == NULL) { LOGE("Couldn't class for EventListener instance"); return; } jmethodID onEventMethod = lookup.findMethod(eventListenerClass, - "onEvent", "(Lcom/zerotier/sdk/Event;)V"); - if(onEventMethod == NULL) - { + "onEvent", "(Lcom/zerotier/sdk/Event;)V"); + if (onEventMethod == NULL) { LOGE("Couldn't find onEvent method"); return; } jmethodID onTraceMethod = lookup.findMethod(eventListenerClass, - "onTrace", "(Ljava/lang/String;)V"); - if(onTraceMethod == NULL) - { + "onTrace", "(Ljava/lang/String;)V"); + if (onTraceMethod == NULL) { LOGE("Couldn't find onTrace method"); return; } jobject eventObject = createEvent(env, event); - if(eventObject == NULL) - { + if (eventObject == NULL) { return; } - switch(event) - { - case ZT_EVENT_UP: - { - LOGD("Event Up"); - env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); - break; + switch (event) { + case ZT_EVENT_UP: { + LOGD("Event Up"); + env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); + break; + } + case ZT_EVENT_OFFLINE: { + LOGD("Event Offline"); + env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); + break; + } + case ZT_EVENT_ONLINE: { + LOGD("Event Online"); + env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); + break; + } + case ZT_EVENT_DOWN: { + LOGD("Event Down"); + env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); + break; + } + case ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION: { + LOGV("Identity Collision"); + // call onEvent() + env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); + } + break; + case ZT_EVENT_TRACE: { + LOGV("Trace Event"); + // call onTrace() + if (data != NULL) { + const char *message = (const char *) data; + jstring messageStr = env->NewStringUTF(message); + env->CallVoidMethod(ref->eventListener, onTraceMethod, messageStr); + } + } + break; + case ZT_EVENT_USER_MESSAGE: + case ZT_EVENT_REMOTE_TRACE: + default: + break; } - case ZT_EVENT_OFFLINE: - { - LOGD("Event Offline"); - env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); - break; + } + + void StatePutFunction( + ZT_Node *node, + void *userData, + void *threadData, + enum ZT_StateObjectType type, + const uint64_t id[2], + const void *buffer, + int bufferLength) { + char p[4096] = {0}; + bool secure = false; + switch (type) { + case ZT_STATE_OBJECT_IDENTITY_PUBLIC: + snprintf(p, sizeof(p), "identity.public"); + break; + case ZT_STATE_OBJECT_IDENTITY_SECRET: + snprintf(p, sizeof(p), "identity.secret"); + secure = true; + break; + case ZT_STATE_OBJECT_PLANET: + snprintf(p, sizeof(p), "planet"); + break; + case ZT_STATE_OBJECT_MOON: + snprintf(p, sizeof(p), "moons.d/%.16llx.moon", (unsigned long long)id[0]); + break; + case ZT_STATE_OBJECT_NETWORK_CONFIG: + snprintf(p, sizeof(p), "networks.d/%.16llx.conf", (unsigned long long)id[0]); + break; + case ZT_STATE_OBJECT_PEER: + snprintf(p, sizeof(p), "peers.d/%.10llx", (unsigned long long)id[0]); + break; + default: + return; } - case ZT_EVENT_ONLINE: - { - LOGD("Event Online"); - env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); - break; + + if (strlen(p) < 1) { + return; } - case ZT_EVENT_DOWN: + + JniRef *ref = (JniRef*)userData; + JNIEnv *env = NULL; + ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); + + if (ref->dataStorePutListener == NULL) { + LOGE("dataStorePutListener is NULL"); + return; + } + + jclass dataStorePutClass = env->GetObjectClass(ref->dataStorePutListener); + if (dataStorePutClass == NULL) { - LOGD("Event Down"); - env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); - break; + LOGE("Couldn't find class for DataStorePutListener instance"); + return; } - case ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION: + + jmethodID dataStorePutCallbackMethod = lookup.findMethod( + dataStorePutClass, + "onDataStorePut", + "(Ljava/lang/String;[BZ)I"); + if(dataStorePutCallbackMethod == NULL) { - LOGV("Identity Collision"); - // call onEvent() - env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject); + LOGE("Couldn't find onDataStorePut method"); + return; } - break; - case ZT_EVENT_TRACE: + + jmethodID deleteMethod = lookup.findMethod(dataStorePutClass, + "onDelete", "(Ljava/lang/String;)I"); + if(deleteMethod == NULL) { - LOGV("Trace Event"); - // call onTrace() - if(data != NULL) + LOGE("Couldn't find onDelete method"); + return; + } + + jstring nameStr = env->NewStringUTF(p); + + if (bufferLength >= 0) { + LOGD("JNI: Write file: %s", p); + // set operation + jbyteArray bufferObj = env->NewByteArray(bufferLength); + if(env->ExceptionCheck() || bufferObj == NULL) { - const char* message = (const char*)data; - jstring messageStr = env->NewStringUTF(message); - env->CallVoidMethod(ref->eventListener, onTraceMethod, messageStr); + LOGE("Error creating byte array buffer!"); + return; } - } - break; + + env->SetByteArrayRegion(bufferObj, 0, bufferLength, (jbyte*)buffer); + + env->CallIntMethod(ref->dataStorePutListener, + dataStorePutCallbackMethod, + nameStr, bufferObj, secure); + } else { + LOGD("JNI: Delete file: %s", p); + env->CallIntMethod(ref->dataStorePutListener, deleteMethod, nameStr); } } - long DataStoreGetFunction(ZT_Node *node, - void *userData, - const char *objectName, - void *buffer, - unsigned long bufferSize, - unsigned long bufferIndex, - unsigned long *out_objectSize) - { + int StateGetFunction( + ZT_Node *node, + void *userData, + void *threadData, + ZT_StateObjectType type, + const uint64_t id[2], + void *buffer, + unsigned int bufferLength) { + char p[4096] = {0}; + switch (type) { + case ZT_STATE_OBJECT_IDENTITY_PUBLIC: + snprintf(p, sizeof(p), "identity.public"); + break; + case ZT_STATE_OBJECT_IDENTITY_SECRET: + snprintf(p, sizeof(p), "identity.secret"); + break; + case ZT_STATE_OBJECT_PLANET: + snprintf(p, sizeof(p), "planet"); + break; + case ZT_STATE_OBJECT_MOON: + snprintf(p, sizeof(p), "moons.d/%.16llx.moon", (unsigned long long)id[0]); + break; + case ZT_STATE_OBJECT_NETWORK_CONFIG: + snprintf(p, sizeof(p), "networks.d/%.16llx.conf", (unsigned long long)id[0]); + break; + case ZT_STATE_OBJECT_PEER: + snprintf(p, sizeof(p), "peers.d/%.10llx", (unsigned long long)id[0]); + break; + default: + return -1; + } + + if (strlen(p) < 1) { + return -1; + } + JniRef *ref = (JniRef*)userData; JNIEnv *env = NULL; ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); + if (ref->dataStoreGetListener == NULL) { + LOGE("dataStoreGetListener is NULL"); + return -2; + } + jclass dataStoreGetClass = env->GetObjectClass(ref->dataStoreGetListener); if(dataStoreGetClass == NULL) { @@ -305,176 +461,254 @@ namespace { } jmethodID dataStoreGetCallbackMethod = lookup.findMethod( - dataStoreGetClass, - "onDataStoreGet", - "(Ljava/lang/String;[BJ[J)J"); + dataStoreGetClass, + "onDataStoreGet", + "(Ljava/lang/String;[B)J"); if(dataStoreGetCallbackMethod == NULL) { LOGE("Couldn't find onDataStoreGet method"); return -2; } - jstring nameStr = env->NewStringUTF(objectName); + jstring nameStr = env->NewStringUTF(p); if(nameStr == NULL) { LOGE("Error creating name string object"); return -2; // out of memory } - jbyteArray bufferObj = env->NewByteArray(bufferSize); + jbyteArray bufferObj = env->NewByteArray(bufferLength); if(bufferObj == NULL) { - LOGE("Error creating byte[] buffer of size: %lu", bufferSize); + LOGE("Error creating byte[] buffer of size: %u", bufferLength); return -2; } - jlongArray objectSizeObj = env->NewLongArray(1); - if(objectSizeObj == NULL) - { - LOGE("Error creating long[1] array for actual object size"); - return -2; // couldn't create long[1] array - } + LOGV("Calling onDataStoreGet(%s, %p)", p, buffer); - LOGV("Calling onDataStoreGet(%s, %p, %lu, %p)", - objectName, buffer, bufferIndex, objectSizeObj); + int retval = (int)env->CallLongMethod( + ref->dataStoreGetListener, + dataStoreGetCallbackMethod, + nameStr, + bufferObj); - long retval = (long)env->CallLongMethod( - ref->dataStoreGetListener, dataStoreGetCallbackMethod, - nameStr, bufferObj, (jlong)bufferIndex, objectSizeObj); + LOGV("onDataStoreGet returned %d", retval); if(retval > 0) { void *data = env->GetPrimitiveArrayCritical(bufferObj, NULL); memcpy(buffer, data, retval); env->ReleasePrimitiveArrayCritical(bufferObj, data, 0); - - jlong *objSize = (jlong*)env->GetPrimitiveArrayCritical(objectSizeObj, NULL); - *out_objectSize = (unsigned long)objSize[0]; - env->ReleasePrimitiveArrayCritical(objectSizeObj, objSize, 0); } - LOGV("Out Object Size: %lu", *out_objectSize); - return retval; } - int DataStorePutFunction(ZT_Node *node, + int WirePacketSendFunction(ZT_Node *node, void *userData, - const char *objectName, + void *threadData, + int64_t localSocket, + const struct sockaddr_storage *remoteAddress, const void *buffer, - unsigned long bufferSize, - int secure) + unsigned int bufferSize, + unsigned int ttl) { + LOGV("WirePacketSendFunction(%lld, %p, %p, %d)", (long long)localSocket, remoteAddress, buffer, bufferSize); JniRef *ref = (JniRef*)userData; + assert(ref->node == node); + JNIEnv *env = NULL; ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); + if (ref->packetSender == NULL) { + LOGE("packetSender is NULL"); + return -1; + } - jclass dataStorePutClass = env->GetObjectClass(ref->dataStorePutListener); - if(dataStorePutClass == NULL) + jclass packetSenderClass = env->GetObjectClass(ref->packetSender); + if(packetSenderClass == NULL) { - LOGE("Couldn't find class for DataStorePutListener instance"); + LOGE("Couldn't find class for PacketSender instance"); return -1; } - jmethodID dataStorePutCallbackMethod = lookup.findMethod( - dataStorePutClass, - "onDataStorePut", - "(Ljava/lang/String;[BZ)I"); - if(dataStorePutCallbackMethod == NULL) + jmethodID packetSenderCallbackMethod = lookup.findMethod(packetSenderClass, + "onSendPacketRequested", "(JLjava/net/InetSocketAddress;[BI)I"); + if(packetSenderCallbackMethod == NULL) { - LOGE("Couldn't find onDataStorePut method"); + LOGE("Couldn't find onSendPacketRequested method"); return -2; } - jmethodID deleteMethod = lookup.findMethod(dataStorePutClass, - "onDelete", "(Ljava/lang/String;)I"); - if(deleteMethod == NULL) - { - LOGE("Couldn't find onDelete method"); - return -3; + jobject remoteAddressObj = newInetSocketAddress(env, *remoteAddress); + jbyteArray bufferObj = env->NewByteArray(bufferSize); + env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer); + int retval = env->CallIntMethod(ref->packetSender, packetSenderCallbackMethod, localSocket, remoteAddressObj, bufferObj); + + LOGV("JNI Packet Sender returned: %d", retval); + return retval; + } + + int PathCheckFunction(ZT_Node *node, + void *userPtr, + void *threadPtr, + uint64_t address, + int64_t localSocket, + const struct sockaddr_storage *remoteAddress) + { + JniRef *ref = (JniRef*)userPtr; + assert(ref->node == node); + + if(ref->pathChecker == NULL) { + return true; } - jstring nameStr = env->NewStringUTF(objectName); + JNIEnv *env = NULL; + ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); - if(buffer == NULL) + jclass pathCheckerClass = env->GetObjectClass(ref->pathChecker); + if(pathCheckerClass == NULL) { - LOGD("JNI: Delete file: %s", objectName); - // delete operation - return env->CallIntMethod( - ref->dataStorePutListener, deleteMethod, nameStr); + LOGE("Couldn't find class for PathChecker instance"); + return true; } - else + + jmethodID pathCheckCallbackMethod = lookup.findMethod(pathCheckerClass, + "onPathCheck", "(JJLjava/net/InetSocketAddress;)Z"); + if(pathCheckCallbackMethod == NULL) { - 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; - } + LOGE("Couldn't find onPathCheck method implementation"); + return true; + } - env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer); - bool bsecure = secure != 0; + struct sockaddr_storage nullAddress = {0}; + jobject remoteAddressObj = NULL; - return env->CallIntMethod(ref->dataStorePutListener, - dataStorePutCallbackMethod, - nameStr, bufferObj, bsecure); + if(memcmp(remoteAddress, &nullAddress, sizeof(sockaddr_storage)) != 0) + { + remoteAddressObj = newInetSocketAddress(env, *remoteAddress); } + + return env->CallBooleanMethod(ref->pathChecker, pathCheckCallbackMethod, address, localSocket, remoteAddressObj); } - int WirePacketSendFunction(ZT_Node *node, - void *userData, - const struct sockaddr_storage *localAddress, - const struct sockaddr_storage *remoteAddress, - const void *buffer, - unsigned int bufferSize, - unsigned int ttl) + int PathLookupFunction(ZT_Node *node, + void *userPtr, + void *threadPtr, + uint64_t address, + int ss_family, + struct sockaddr_storage *result) { - LOGV("WirePacketSendFunction(%p, %p, %p, %d)", localAddress, remoteAddress, buffer, bufferSize); - JniRef *ref = (JniRef*)userData; + JniRef *ref = (JniRef*)userPtr; assert(ref->node == node); + if(ref->pathChecker == NULL) { + return false; + } + JNIEnv *env = NULL; ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6); + jclass pathCheckerClass = env->GetObjectClass(ref->pathChecker); + if(pathCheckerClass == NULL) + { + LOGE("Couldn't find class for PathChecker instance"); + return false; + } + + jmethodID pathLookupMethod = lookup.findMethod(pathCheckerClass, + "onPathLookup", "(JI)Ljava/net/InetSocketAddress;"); + if(pathLookupMethod == NULL) { + return false; + } - jclass packetSenderClass = env->GetObjectClass(ref->packetSender); - if(packetSenderClass == NULL) + jobject sockAddressObject = env->CallObjectMethod(ref->pathChecker, pathLookupMethod, address, ss_family); + if(sockAddressObject == NULL) { - LOGE("Couldn't find class for PacketSender instance"); - return -1; + LOGE("Unable to call onPathLookup implementation"); + return false; } - jmethodID packetSenderCallbackMethod = lookup.findMethod(packetSenderClass, - "onSendPacketRequested", "(Ljava/net/InetSocketAddress;Ljava/net/InetSocketAddress;[BI)I"); - if(packetSenderCallbackMethod == NULL) + jclass inetSockAddressClass = env->GetObjectClass(sockAddressObject); + if(inetSockAddressClass == NULL) { - LOGE("Couldn't find onSendPacketRequested method"); - return -2; + LOGE("Unable to find InetSocketAddress class"); + return false; + } + + jmethodID getAddressMethod = lookup.findMethod(inetSockAddressClass, "getAddress", "()Ljava/net/InetAddress;"); + if(getAddressMethod == NULL) + { + LOGE("Unable to find InetSocketAddress.getAddress() method"); + return false; + } + + jmethodID getPortMethod = lookup.findMethod(inetSockAddressClass, "getPort", "()I"); + if(getPortMethod == NULL) + { + LOGE("Unable to find InetSocketAddress.getPort() method"); + return false; } + + jint port = env->CallIntMethod(sockAddressObject, getPortMethod); + jobject addressObject = env->CallObjectMethod(sockAddressObject, getAddressMethod); - jobject localAddressObj = NULL; - if(memcmp(localAddress, &ZT_SOCKADDR_NULL, sizeof(sockaddr_storage)) != 0) + jclass inetAddressClass = lookup.findClass("java/net/InetAddress"); + if(inetAddressClass == NULL) { - localAddressObj = newInetSocketAddress(env, *localAddress); + LOGE("Unable to find InetAddress class"); + return false; } - jobject remoteAddressObj = newInetSocketAddress(env, *remoteAddress); - jbyteArray bufferObj = env->NewByteArray(bufferSize); - env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer); - int retval = env->CallIntMethod(ref->packetSender, packetSenderCallbackMethod, localAddressObj, remoteAddressObj, bufferObj); + getAddressMethod = lookup.findMethod(inetAddressClass, "getAddress", "()[B"); + if(getAddressMethod == NULL) + { + LOGE("Unable to find InetAddress.getAddress() method"); + return false; + } - LOGV("JNI Packet Sender returned: %d", retval); - return retval; + jbyteArray addressBytes = (jbyteArray)env->CallObjectMethod(addressObject, getAddressMethod); + 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 + { + return false; + } + + return true; } - typedef std::map<uint64_t, JniRef*> NodeMap; + typedef std::map<int64_t, JniRef*> NodeMap; static NodeMap nodeMap; ZeroTier::Mutex nodeMapMutex; - ZT_Node* findNode(uint64_t nodeId) + ZT_Node* findNode(int64_t nodeId) { ZeroTier::Mutex::Lock lock(nodeMapMutex); NodeMap::iterator found = nodeMap.find(nodeId); @@ -487,7 +721,7 @@ namespace { } } -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { lookup.setJavaVM(vm); return JNI_VERSION_1_6; @@ -512,7 +746,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( ZT_Node *node; JniRef *ref = new JniRef; - ref->id = (uint64_t)now; + ref->id = (int64_t)now; env->GetJavaVM(&ref->jvm); jclass cls = env->GetObjectClass(obj); @@ -602,17 +836,35 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( } ref->eventListener = env->NewGlobalRef(tmp); + fid = lookup.findField( + cls, "pathChecker", "Lcom/zerotier/sdk/PathChecker;"); + if(fid == NULL) + { + LOGE("no path checker?"); + return NULL; + } + + tmp = env->GetObjectField(obj, fid); + if(tmp != NULL) + { + ref->pathChecker = env->NewGlobalRef(tmp); + } + + ref->callbacks->stateGetFunction = &StateGetFunction; + ref->callbacks->statePutFunction = &StatePutFunction; + ref->callbacks->wirePacketSendFunction = &WirePacketSendFunction; + ref->callbacks->virtualNetworkFrameFunction = &VirtualNetworkFrameFunctionCallback; + ref->callbacks->virtualNetworkConfigFunction = &VirtualNetworkConfigFunctionCallback; + ref->callbacks->eventCallback = &EventCallback; + ref->callbacks->pathCheckFunction = &PathCheckFunction; + ref->callbacks->pathLookupFunction = &PathLookupFunction; + ZT_ResultCode rc = ZT_Node_new( &node, ref, - (uint64_t)now, - &DataStoreGetFunction, - &DataStorePutFunction, - &WirePacketSendFunction, - &VirtualNetworkFrameFunctionCallback, - &VirtualNetworkConfigFunctionCallback, NULL, - &EventCallback); + ref->callbacks, + (int64_t)now); if(rc != ZT_RESULT_OK) { @@ -628,10 +880,16 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init( return resultObject; } + uint64_t nodeId = ZT_Node_address(node); + if (nodeId != 0) { + char uniqueName[64]; + snprintf(uniqueName, sizeof(uniqueName), "ZeroTier Android/%.10llx@%u", (unsigned long long)nodeId, 9993); + ref->portMapper = new ZeroTier::PortMapper(9993, uniqueName); + } + ZeroTier::Mutex::Lock lock(nodeMapMutex); ref->node = node; nodeMap.insert(std::make_pair(ref->id, ref)); - return resultObject; } @@ -645,11 +903,11 @@ JNIEXPORT void JNICALL Java_com_zerotier_sdk_Node_node_1delete( JNIEnv *env, jobject obj, jlong id) { LOGV("Destroying ZT_Node struct"); - uint64_t nodeId = (uint64_t)id; + int64_t nodeId = (int64_t)id; NodeMap::iterator found; { - ZeroTier::Mutex::Lock lock(nodeMapMutex); + ZeroTier::Mutex::Lock lock(nodeMapMutex); found = nodeMap.find(nodeId); } @@ -675,9 +933,9 @@ JNIEXPORT void JNICALL Java_com_zerotier_sdk_Node_node_1delete( * Signature: (JJJJJII[B[J)Lcom/zerotier/sdk/ResultCode; */ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame( - JNIEnv *env, jobject obj, - jlong id, - jlong in_now, + JNIEnv *env, jobject obj, + jlong id, + jlong in_now, jlong in_nwid, jlong in_sourceMac, jlong in_destMac, @@ -686,8 +944,8 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame( jbyteArray in_frameData, jlongArray out_nextBackgroundTaskDeadline) { - uint64_t nodeId = (uint64_t) id; - + int64_t nodeId = (int64_t) id; + ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -702,7 +960,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame( return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL); } - uint64_t now = (uint64_t)in_now; + int64_t now = (int64_t)in_now; uint64_t nwid = (uint64_t)in_nwid; uint64_t sourceMac = (uint64_t)in_sourceMac; uint64_t destMac = (uint64_t)in_destMac; @@ -715,10 +973,11 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame( memcpy(localData, frameData, frameLength); env->ReleasePrimitiveArrayCritical(in_frameData, frameData, 0); - uint64_t nextBackgroundTaskDeadline = 0; + int64_t nextBackgroundTaskDeadline = 0; ZT_ResultCode rc = ZT_Node_processVirtualNetworkFrame( node, + NULL, now, nwid, sourceMac, @@ -739,18 +998,18 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame( /* * Class: com_zerotier_sdk_Node * Method: processWirePacket - * Signature: (JJLjava/net/InetSocketAddress;I[B[J)Lcom/zerotier/sdk/ResultCode; + * Signature: (JJJLjava/net/InetSocketAddress;I[B[J)Lcom/zerotier/sdk/ResultCode; */ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( - JNIEnv *env, jobject obj, + JNIEnv *env, jobject obj, jlong id, - jlong in_now, - jobject in_localAddress, + jlong in_now, + jlong in_localSocket, jobject in_remoteAddress, jbyteArray in_packetData, jlongArray out_nextBackgroundTaskDeadline) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -759,14 +1018,14 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL); } - unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline); + unsigned int nbtd_len = (unsigned int)env->GetArrayLength(out_nextBackgroundTaskDeadline); if(nbtd_len < 1) { LOGE("nbtd_len < 1"); return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL); } - uint64_t now = (uint64_t)in_now; + int64_t now = (int64_t)in_now; // get the java.net.InetSocketAddress class and getAddress() method jclass inetAddressClass = lookup.findClass("java/net/InetAddress"); @@ -794,12 +1053,6 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( jmethodID inetSockGetAddressMethod = lookup.findMethod( InetSocketAddressClass, "getAddress", "()Ljava/net/InetAddress;"); - jobject localAddrObj = NULL; - if(in_localAddress != NULL) - { - localAddrObj = env->CallObjectMethod(in_localAddress, inetSockGetAddressMethod); - } - jobject remoteAddrObject = env->CallObjectMethod(in_remoteAddress, inetSockGetAddressMethod); if(remoteAddrObject == NULL) @@ -810,7 +1063,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( jmethodID inetSock_getPort = lookup.findMethod( InetSocketAddressClass, "getPort", "()I"); - if(env->ExceptionCheck() || inetSock_getPort == NULL) + if(env->ExceptionCheck() || inetSock_getPort == NULL) { LOGE("Couldn't find getPort method on InetSocketAddress"); return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL); @@ -834,48 +1087,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( } unsigned int addrSize = env->GetArrayLength(remoteAddressArray); - - - sockaddr_storage localAddress = {}; - - if(localAddrObj == NULL) - { - localAddress = ZT_SOCKADDR_NULL; - } - else - { - int localPort = env->CallIntMethod(in_localAddress, inetSock_getPort); - jbyteArray localAddressArray = (jbyteArray)env->CallObjectMethod(localAddrObj, getAddressMethod); - if(localAddressArray != NULL) - { - unsigned int localAddrSize = env->GetArrayLength(localAddressArray); - jbyte *addr = (jbyte*)env->GetPrimitiveArrayCritical(localAddressArray, NULL); - - if(localAddrSize == 16) - { - sockaddr_in6 ipv6 = {}; - ipv6.sin6_family = AF_INET6; - ipv6.sin6_port = htons(localPort); - memcpy(ipv6.sin6_addr.s6_addr, addr, 16); - memcpy(&localAddress, &ipv6, sizeof(sockaddr_in6)); - } - else if(localAddrSize) - { - // IPV4 address - sockaddr_in ipv4 = {}; - ipv4.sin_family = AF_INET; - ipv4.sin_port = htons(localPort); - memcpy(&ipv4.sin_addr, addr, 4); - memcpy(&localAddress, &ipv4, sizeof(sockaddr_in)); - } - else - { - localAddress = ZT_SOCKADDR_NULL; - } - env->ReleasePrimitiveArrayCritical(localAddressArray, addr, 0); - } - } // get the address bytes jbyte *addr = (jbyte*)env->GetPrimitiveArrayCritical(remoteAddressArray, NULL); @@ -908,7 +1120,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( } env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0); - unsigned int packetLength = env->GetArrayLength(in_packetData); + unsigned int packetLength = (unsigned int)env->GetArrayLength(in_packetData); if(packetLength == 0) { LOGE("Empty packet?!?"); @@ -919,17 +1131,18 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( memcpy(localData, packetData, packetLength); env->ReleasePrimitiveArrayCritical(in_packetData, packetData, 0); - uint64_t nextBackgroundTaskDeadline = 0; + int64_t nextBackgroundTaskDeadline = 0; ZT_ResultCode rc = ZT_Node_processWirePacket( node, + NULL, now, - &localAddress, + in_localSocket, &remoteAddress, localData, packetLength, &nextBackgroundTaskDeadline); - if(rc != ZT_RESULT_OK) + if(rc != ZT_RESULT_OK) { LOGE("ZT_Node_processWirePacket returned: %d", rc); } @@ -949,12 +1162,12 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( * Signature: (JJ[J)Lcom/zerotier/sdk/ResultCode; */ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processBackgroundTasks( - JNIEnv *env, jobject obj, + JNIEnv *env, jobject obj, jlong id, jlong in_now, jlongArray out_nextBackgroundTaskDeadline) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -968,10 +1181,10 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processBackgroundTasks( return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL); } - uint64_t now = (uint64_t)in_now; - uint64_t nextBackgroundTaskDeadline = 0; + int64_t now = (int64_t)in_now; + int64_t nextBackgroundTaskDeadline = 0; - ZT_ResultCode rc = ZT_Node_processBackgroundTasks(node, now, &nextBackgroundTaskDeadline); + ZT_ResultCode rc = ZT_Node_processBackgroundTasks(node, NULL, now, &nextBackgroundTaskDeadline); jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL); outDeadline[0] = (jlong)nextBackgroundTaskDeadline; @@ -988,7 +1201,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processBackgroundTasks( JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_join( JNIEnv *env, jobject obj, jlong id, jlong in_nwid) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -998,7 +1211,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_join( uint64_t nwid = (uint64_t)in_nwid; - ZT_ResultCode rc = ZT_Node_join(node, nwid, NULL); + ZT_ResultCode rc = ZT_Node_join(node, nwid, NULL, NULL); return createResultObject(env, rc); } @@ -1011,7 +1224,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_join( JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_leave( JNIEnv *env, jobject obj, jlong id, jlong in_nwid) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -1021,8 +1234,8 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_leave( uint64_t nwid = (uint64_t)in_nwid; - ZT_ResultCode rc = ZT_Node_leave(node, nwid, NULL); - + ZT_ResultCode rc = ZT_Node_leave(node, nwid, NULL, NULL); + return createResultObject(env, rc); } @@ -1032,13 +1245,13 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_leave( * Signature: (JJJJ)Lcom/zerotier/sdk/ResultCode; */ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastSubscribe( - JNIEnv *env, jobject obj, - jlong id, + JNIEnv *env, jobject obj, + jlong id, jlong in_nwid, jlong in_multicastGroup, jlong in_multicastAdi) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -1051,7 +1264,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastSubscribe( unsigned long multicastAdi = (unsigned long)in_multicastAdi; ZT_ResultCode rc = ZT_Node_multicastSubscribe( - node, nwid, multicastGroup, multicastAdi); + node, NULL, nwid, multicastGroup, multicastAdi); return createResultObject(env, rc); } @@ -1062,13 +1275,13 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastSubscribe( * Signature: (JJJJ)Lcom/zerotier/sdk/ResultCode; */ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastUnsubscribe( - JNIEnv *env, jobject obj, - jlong id, + JNIEnv *env, jobject obj, + jlong id, jlong in_nwid, jlong in_multicastGroup, jlong in_multicastAdi) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -1087,6 +1300,54 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastUnsubscribe( } /* + * Class: com_zerotier_sdk_Node + * Method: orbit + * Signature: (JJJ)Lcom/zerotier/sdk/ResultCode; + */ +JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_orbit( + JNIEnv *env, jobject obj, + jlong id, + jlong in_moonWorldId, + jlong in_moonSeed) +{ + int64_t nodeId = (int64_t)id; + ZT_Node *node = findNode(nodeId); + if(node == NULL) + { + return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL); + } + + uint64_t moonWorldId = (uint64_t)in_moonWorldId; + uint64_t moonSeed = (uint64_t)in_moonSeed; + + ZT_ResultCode rc = ZT_Node_orbit(node, NULL, moonWorldId, moonSeed); + return createResultObject(env, rc); +} + +/* + * Class: com_zerotier_sdk_Node + * Method: deorbit + * Signature: (JJ)L/com/zerotier/sdk/ResultCode; + */ +JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_deorbit( + JNIEnv *env, jobject obj, + jlong id, + jlong in_moonWorldId) +{ + int64_t nodeId = (int64_t)id; + ZT_Node *node = findNode(nodeId); + if(node == NULL) + { + return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL); + } + + uint64_t moonWorldId = (uint64_t)in_moonWorldId; + + ZT_ResultCode rc = ZT_Node_deorbit(node, NULL, moonWorldId); + return createResultObject(env, rc); +} + +/* * Class: com_zerotier_sdk_Node * Method: address * Signature: (J)J @@ -1094,7 +1355,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastUnsubscribe( JNIEXPORT jlong JNICALL Java_com_zerotier_sdk_Node_address( JNIEnv *env , jobject obj, jlong id) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -1114,7 +1375,7 @@ JNIEXPORT jlong JNICALL Java_com_zerotier_sdk_Node_address( JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_status (JNIEnv *env, jobject obj, jlong id) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -1131,7 +1392,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_status { return NULL; } - + nodeStatusConstructor = lookup.findMethod( nodeStatusClass, "<init>", "()V"); if(nodeStatusConstructor == NULL) @@ -1206,7 +1467,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_status JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_networkConfig( JNIEnv *env, jobject obj, jlong id, jlong nwid) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -1215,7 +1476,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_networkConfig( } ZT_VirtualNetworkConfig *vnetConfig = ZT_Node_networkConfig(node, nwid); - + jobject vnetConfigObject = newNetworkConfig(env, *vnetConfig); ZT_Node_freeQueryResult(node, vnetConfig); @@ -1248,7 +1509,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_version( JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers( JNIEnv *env, jobject obj, jlong id) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { @@ -1257,7 +1518,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers( } ZT_PeerList *peerList = ZT_Node_peers(node); - + if(peerList == NULL) { LOGE("ZT_Node_peers returned NULL"); @@ -1296,7 +1557,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers( { jobject peerObj = newPeer(env, peerList->peers[i]); env->SetObjectArrayElement(peerArrayObj, i, peerObj); - if(env->ExceptionCheck()) + if(env->ExceptionCheck()) { LOGE("Error assigning Peer object to array"); break; @@ -1317,7 +1578,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers( JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_networks( JNIEnv *env, jobject obj, jlong id) { - uint64_t nodeId = (uint64_t) id; + int64_t nodeId = (int64_t) id; ZT_Node *node = findNode(nodeId); if(node == NULL) { diff --git a/java/jni/com_zerotierone_sdk_Node.h b/java/jni/com_zerotierone_sdk_Node.h index 7c1011ab..8487d8af 100644 --- a/java/jni/com_zerotierone_sdk_Node.h +++ b/java/jni/com_zerotierone_sdk_Node.h @@ -37,7 +37,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame * Signature: (JJLjava/net/InetSockAddress;Ljava/net/InetSockAddress;[B[J)Lcom/zerotier/sdk/ResultCode; */ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket - (JNIEnv *, jobject, jlong, jlong, jobject, jobject, jbyteArray, jlongArray); + (JNIEnv *, jobject, jlong, jlong, jlong, jobject, jbyteArray, jlongArray); /* * Class: com_zerotier_sdk_Node |