|
@@ -56,6 +56,7 @@ namespace {
|
|
, eventListener(NULL)
|
|
, eventListener(NULL)
|
|
, frameListener(NULL)
|
|
, frameListener(NULL)
|
|
, configListener(NULL)
|
|
, configListener(NULL)
|
|
|
|
+ , pathChecker(NULL)
|
|
, callbacks(NULL)
|
|
, callbacks(NULL)
|
|
{
|
|
{
|
|
callbacks = (ZT_Node_Callbacks*)malloc(sizeof(ZT_Node_Callbacks));
|
|
callbacks = (ZT_Node_Callbacks*)malloc(sizeof(ZT_Node_Callbacks));
|
|
@@ -73,6 +74,7 @@ namespace {
|
|
env->DeleteGlobalRef(eventListener);
|
|
env->DeleteGlobalRef(eventListener);
|
|
env->DeleteGlobalRef(frameListener);
|
|
env->DeleteGlobalRef(frameListener);
|
|
env->DeleteGlobalRef(configListener);
|
|
env->DeleteGlobalRef(configListener);
|
|
|
|
+ env->DeleteGlobalRef(pathChecker);
|
|
|
|
|
|
free(callbacks);
|
|
free(callbacks);
|
|
callbacks = NULL;
|
|
callbacks = NULL;
|
|
@@ -90,6 +92,7 @@ namespace {
|
|
jobject eventListener;
|
|
jobject eventListener;
|
|
jobject frameListener;
|
|
jobject frameListener;
|
|
jobject configListener;
|
|
jobject configListener;
|
|
|
|
+ jobject pathChecker;
|
|
|
|
|
|
ZT_Node_Callbacks *callbacks;
|
|
ZT_Node_Callbacks *callbacks;
|
|
};
|
|
};
|
|
@@ -487,6 +490,165 @@ namespace {
|
|
return retval;
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ int PathCheckFunction(ZT_Node *node,
|
|
|
|
+ void *userPtr,
|
|
|
|
+ void *threadPtr,
|
|
|
|
+ uint64_t address,
|
|
|
|
+ const struct sockaddr_storage *localAddress,
|
|
|
|
+ const struct sockaddr_storage *remoteAddress)
|
|
|
|
+ {
|
|
|
|
+ JniRef *ref = (JniRef*)userPtr;
|
|
|
|
+ assert(ref->node == node);
|
|
|
|
+
|
|
|
|
+ if(ref->pathChecker == NULL) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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 true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ jmethodID pathCheckCallbackMethod = lookup.findMethod(pathCheckerClass,
|
|
|
|
+ "onPathCheck", "(JLjava/net/InetSocketAddress;Ljava/net/InetSocketAddress;)Z");
|
|
|
|
+ if(pathCheckCallbackMethod == NULL)
|
|
|
|
+ {
|
|
|
|
+ LOGE("Couldn't find onPathCheck method implementation");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ jobject localAddressObj = NULL;
|
|
|
|
+ jobject remoteAddressObj = NULL;
|
|
|
|
+
|
|
|
|
+ if(memcmp(localAddress, &ZT_SOCKADDR_NULL, sizeof(sockaddr_storage)) != 0)
|
|
|
|
+ {
|
|
|
|
+ localAddressObj = newInetSocketAddress(env, *localAddress);
|
|
|
|
+ }
|
|
|
|
+ if(memcmp(remoteAddress, &ZT_SOCKADDR_NULL, sizeof(sockaddr_storage)) != 0)
|
|
|
|
+ {
|
|
|
|
+ remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return env->CallBooleanMethod(ref->pathChecker, pathCheckCallbackMethod, address, localAddressObj, remoteAddressObj);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int PathLookupFunction(ZT_Node *node,
|
|
|
|
+ void *userPtr,
|
|
|
|
+ void *threadPtr,
|
|
|
|
+ uint64_t address,
|
|
|
|
+ int ss_family,
|
|
|
|
+ struct sockaddr_storage *result)
|
|
|
|
+ {
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ jobject sockAddressObject = env->CallObjectMethod(ref->pathChecker, pathLookupMethod, address, ss_family);
|
|
|
|
+ if(sockAddressObject == NULL)
|
|
|
|
+ {
|
|
|
|
+ LOGE("Unable to call onPathLookup implementation");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ jclass inetSockAddressClass = env->GetObjectClass(sockAddressObject);
|
|
|
|
+ if(inetSockAddressClass == NULL)
|
|
|
|
+ {
|
|
|
|
+ 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);
|
|
|
|
+
|
|
|
|
+ jclass inetAddressClass = lookup.findClass("java/net/InetAddress");
|
|
|
|
+ if(inetAddressClass == NULL)
|
|
|
|
+ {
|
|
|
|
+ LOGE("Unable to find InetAddress class");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getAddressMethod = lookup.findMethod(inetAddressClass, "getAddress", "()[B");
|
|
|
|
+ if(getAddressMethod == NULL)
|
|
|
|
+ {
|
|
|
|
+ LOGE("Unable to find InetAddress.getAddress() method");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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<uint64_t, JniRef*> NodeMap;
|
|
static NodeMap nodeMap;
|
|
static NodeMap nodeMap;
|
|
ZeroTier::Mutex nodeMapMutex;
|
|
ZeroTier::Mutex nodeMapMutex;
|
|
@@ -619,12 +781,28 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init(
|
|
}
|
|
}
|
|
ref->eventListener = env->NewGlobalRef(tmp);
|
|
ref->eventListener = env->NewGlobalRef(tmp);
|
|
|
|
|
|
|
|
+ fid = lookup.findField(
|
|
|
|
+ cls, "pathChecker", "Lcom/zerotier/sdk/PathChecker;");
|
|
|
|
+ if(fid == NULL)
|
|
|
|
+ {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ tmp = env->GetObjectField(obj, fid);
|
|
|
|
+ if(tmp == NULL)
|
|
|
|
+ {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ ref->pathChecker = env->NewGlobalRef(tmp);
|
|
|
|
+
|
|
ref->callbacks->dataStoreGetFunction = &DataStoreGetFunction;
|
|
ref->callbacks->dataStoreGetFunction = &DataStoreGetFunction;
|
|
ref->callbacks->dataStorePutFunction = &DataStorePutFunction;
|
|
ref->callbacks->dataStorePutFunction = &DataStorePutFunction;
|
|
ref->callbacks->wirePacketSendFunction = &WirePacketSendFunction;
|
|
ref->callbacks->wirePacketSendFunction = &WirePacketSendFunction;
|
|
ref->callbacks->virtualNetworkFrameFunction = &VirtualNetworkFrameFunctionCallback;
|
|
ref->callbacks->virtualNetworkFrameFunction = &VirtualNetworkFrameFunctionCallback;
|
|
ref->callbacks->virtualNetworkConfigFunction = &VirtualNetworkConfigFunctionCallback;
|
|
ref->callbacks->virtualNetworkConfigFunction = &VirtualNetworkConfigFunctionCallback;
|
|
ref->callbacks->eventCallback = &EventCallback;
|
|
ref->callbacks->eventCallback = &EventCallback;
|
|
|
|
+ ref->callbacks->pathCheckFunction = &PathCheckFunction;
|
|
|
|
+ ref->callbacks->pathLookupFunction = &PathLookupFunction;
|
|
|
|
|
|
ZT_ResultCode rc = ZT_Node_new(
|
|
ZT_ResultCode rc = ZT_Node_new(
|
|
&node,
|
|
&node,
|