You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1048 lines
28 KiB
1048 lines
28 KiB
/* |
|
* ZeroTier One - Network Virtualization Everywhere |
|
* Copyright (C) 2011-2015 ZeroTier, Inc. |
|
* |
|
* 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/>. |
|
* |
|
* -- |
|
* |
|
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
|
* are available at: http://www.gnu.org/licenses/gpl-3.0.html |
|
* |
|
* If you would like to embed ZeroTier into a commercial application or |
|
* redistribute it in a modified binary form, please contact ZeroTier Networks |
|
* LLC. Start here: http://www.zerotier.com/ |
|
*/ |
|
|
|
#include "com_zerotierone_sdk_Node.h" |
|
#include "ZT1_jniutils.h" |
|
|
|
#include <ZeroTierOne.h> |
|
|
|
#include <map> |
|
#include <string> |
|
#include <assert.h> |
|
#include <string.h> |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
namespace { |
|
struct JniRef |
|
{ |
|
JniRef() |
|
: env(NULL) |
|
, node(NULL) |
|
, dataStoreGetListener(NULL) |
|
, dataStorePutListener(NULL) |
|
, packetSender(NULL) |
|
, frameListener(NULL) |
|
, configListener(NULL) |
|
{} |
|
uint64_t id; |
|
|
|
JNIEnv *env; |
|
|
|
ZT1_Node *node; |
|
|
|
jobject dataStoreGetListener; |
|
jobject dataStorePutListener; |
|
jobject packetSender; |
|
jobject frameListener; |
|
jobject configListener; |
|
}; |
|
|
|
|
|
int VirtualNetworkConfigFunctionCallback(ZT1_Node *node,void *userData,uint64_t,enum ZT1_VirtualNetworkConfigOperation,const ZT1_VirtualNetworkConfig *) |
|
{ |
|
JniRef *ref = (JniRef*)userData; |
|
assert(ref->node == node); |
|
|
|
JNIEnv *env = ref->env; |
|
|
|
return 0; |
|
} |
|
|
|
void VirtualNetworkFrameFunctionCallback(ZT1_Node *node,void *userData,uint64_t,uint64_t,uint64_t,unsigned int,unsigned int,const void *,unsigned int) |
|
{ |
|
JniRef *ref = (JniRef*)userData; |
|
assert(ref->node == node); |
|
|
|
JNIEnv *env = ref->env; |
|
} |
|
|
|
void EventCallback(ZT1_Node *node,void *userData,enum ZT1_Event,const void *) |
|
{ |
|
JniRef *ref = (JniRef*)userData; |
|
assert(ref->node == node); |
|
|
|
JNIEnv *env = ref->env; |
|
} |
|
|
|
long DataStoreGetFunction(ZT1_Node *node,void *userData,const char *,void *,unsigned long,unsigned long,unsigned long *) |
|
{ |
|
JniRef *ref = (JniRef*)userData; |
|
assert(ref->node == node); |
|
|
|
JNIEnv *env = ref->env; |
|
|
|
return 0; |
|
} |
|
|
|
int DataStorePutFunction(ZT1_Node *node,void *userData,const char *,const void *,unsigned long,int) |
|
{ |
|
JniRef *ref = (JniRef*)userData; |
|
assert(ref->node == node); |
|
|
|
JNIEnv *env = ref->env; |
|
|
|
return 0; |
|
} |
|
|
|
int WirePacketSendFunction(ZT1_Node *node,void *userData,const struct sockaddr_storage *,unsigned int,const void *,unsigned int) |
|
{ |
|
JniRef *ref = (JniRef*)userData; |
|
assert(ref->node == node); |
|
|
|
JNIEnv *env = ref->env; |
|
|
|
return 0; |
|
} |
|
|
|
typedef std::map<uint64_t, JniRef*> NodeMap; |
|
static NodeMap nodeMap; |
|
|
|
ZT1_Node* findNode(uint64_t nodeId) |
|
{ |
|
NodeMap::iterator found = nodeMap.find(nodeId); |
|
if(found != nodeMap.end()) |
|
{ |
|
JniRef *ref = found->second; |
|
return ref->node; |
|
} |
|
return NULL; |
|
} |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: node_init |
|
* Signature: (J)Lcom/zerotierone/sdk/ResultCode; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_node_1init |
|
(JNIEnv *env, jobject obj, jlong now) |
|
{ |
|
jobject resultObject = createResultObject(env, ZT1_RESULT_OK); |
|
|
|
ZT1_Node *node; |
|
JniRef *ref = new JniRef; |
|
|
|
ZT1_ResultCode rc = ZT1_Node_new( |
|
&node, |
|
ref, |
|
(uint64_t)now, |
|
&DataStoreGetFunction, |
|
&DataStorePutFunction, |
|
&WirePacketSendFunction, |
|
&VirtualNetworkFrameFunctionCallback, |
|
&VirtualNetworkConfigFunctionCallback, |
|
&EventCallback); |
|
|
|
if(rc != ZT1_RESULT_OK) |
|
{ |
|
resultObject = createResultObject(env, rc); |
|
if(node) |
|
{ |
|
ZT1_Node_delete(node); |
|
node = NULL; |
|
} |
|
delete ref; |
|
ref = NULL; |
|
return resultObject; |
|
} |
|
|
|
|
|
ref->id = (uint64_t)now; |
|
ref->env = env; |
|
ref->node = node; |
|
|
|
jclass cls = env->GetObjectClass(obj); |
|
jfieldID fid = env->GetFieldID( |
|
cls, "getListener", "Lcom/zerotierone/sdk/DataStoreGetListener;"); |
|
|
|
if(fid == NULL) |
|
{ |
|
return NULL; // exception already thrown |
|
} |
|
|
|
ref->dataStoreGetListener = env->GetObjectField(obj, fid); |
|
if(ref->dataStoreGetListener == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
fid = env->GetFieldID( |
|
cls, "putListener", "Lcom/zerotierone/sdk/DataStorePutLisetner;"); |
|
|
|
if(fid == NULL) |
|
{ |
|
return NULL; // exception already thrown |
|
} |
|
|
|
ref->dataStorePutListener = env->GetObjectField(obj, fid); |
|
if(ref->dataStorePutListener == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
fid = env->GetFieldID( |
|
cls, "sender", "Lcom/zerotierone/sdk/PacketSender;"); |
|
if(fid == NULL) |
|
{ |
|
return NULL; // exception already thrown |
|
} |
|
|
|
ref->packetSender = env->GetObjectField(obj, fid); |
|
if(ref->packetSender == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
fid = env->GetFieldID( |
|
cls, "frameListener", "Lcom/zerotierone/sdk/VirtualNetworkFrameListener;"); |
|
if(fid == NULL) |
|
{ |
|
return NULL; // exception already thrown |
|
} |
|
|
|
ref->frameListener = env->GetObjectField(obj, fid); |
|
if(ref->frameListener = NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
fid = env->GetFieldID( |
|
cls, "configListener", "Lcom/zerotierone/sdk/VirtualNetworkConfigListener;"); |
|
if(fid == NULL) |
|
{ |
|
return NULL; // exception already thrown |
|
} |
|
|
|
ref->configListener = env->GetObjectField(obj, fid); |
|
if(ref->configListener == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
nodeMap.insert(std::make_pair(ref->id, ref)); |
|
|
|
return resultObject; |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: node_delete |
|
* Signature: (J)V |
|
*/ |
|
JNIEXPORT void JNICALL Java_com_zerotierone_sdk_Node_node_1delete |
|
(JNIEnv *env, jobject obj, jlong id) |
|
{ |
|
uint64_t nodeId = (uint64_t)id; |
|
|
|
NodeMap::iterator found = nodeMap.find(nodeId); |
|
if(found != nodeMap.end()) |
|
{ |
|
JniRef *ref = found->second; |
|
nodeMap.erase(found); |
|
|
|
ZT1_Node_delete(ref->node); |
|
|
|
delete ref; |
|
ref = NULL; |
|
} |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: processVirtualNetworkFrame |
|
* Signature: (JJJJJII[B[J)Lcom/zerotierone/sdk/ResultCode; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processVirtualNetworkFrame |
|
(JNIEnv *env, jobject obj, |
|
jlong id, |
|
jlong in_now, |
|
jlong in_nwid, |
|
jlong in_sourceMac, |
|
jlong in_destMac, |
|
jint in_etherType, |
|
jint in_vlanId, |
|
jbyteArray in_frameData, |
|
jlongArray out_nextBackgroundTaskDeadline) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
|
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline); |
|
if(nbtd_len < 1) |
|
{ |
|
// array for next background task length has 0 elements! |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
uint64_t now = (uint64_t)in_now; |
|
uint64_t nwid = (uint64_t)in_nwid; |
|
uint64_t sourceMac = (uint64_t)in_sourceMac; |
|
uint64_t destMac = (uint64_t)in_destMac; |
|
unsigned int etherType = (unsigned int)in_etherType; |
|
unsigned int vlanId = (unsigned int)in_vlanId; |
|
|
|
unsigned int frameLength = env->GetArrayLength(in_frameData); |
|
jbyte *frameData =env->GetByteArrayElements(in_frameData, NULL); |
|
|
|
uint64_t nextBackgroundTaskDeadline = 0; |
|
|
|
ZT1_ResultCode rc = ZT1_Node_processVirtualNetworkFrame( |
|
node, |
|
now, |
|
nwid, |
|
sourceMac, |
|
destMac, |
|
etherType, |
|
vlanId, |
|
(const void*)frameData, |
|
frameLength, |
|
&nextBackgroundTaskDeadline); |
|
|
|
jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL); |
|
outDeadline[0] = (jlong)nextBackgroundTaskDeadline; |
|
env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0); |
|
|
|
env->ReleaseByteArrayElements(in_frameData, frameData, 0); |
|
|
|
return createResultObject(env, rc); |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: processWirePacket |
|
* Signature: (JJLjava/net/InetAddress;I[B[J)Lcom/zerotierone/sdk/ResultCode; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processWirePacket |
|
(JNIEnv *env, jobject obj, |
|
jlong id, |
|
jlong in_now, |
|
jobject in_remoteAddress, |
|
jint in_linkDesparation, |
|
jbyteArray in_packetData, |
|
jlongArray out_nextBackgroundTaskDeadline) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline); |
|
if(nbtd_len < 1) |
|
{ |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
uint64_t now = (uint64_t)in_now; |
|
unsigned int linkDesparation = (unsigned int)in_linkDesparation; |
|
|
|
// get the java.net.InetAddress class and getAddress() method |
|
jclass inetAddressClass = env->FindClass("java/net/InetAddress"); |
|
if(inetAddressClass == NULL) |
|
{ |
|
// can't find java.net.InetAddress |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
jmethodID getAddressMethod = env->GetMethodID( |
|
inetAddressClass, "getAddress", "()[B"); |
|
if(getAddressMethod == NULL) |
|
{ |
|
// cant find InetAddress.getAddres() |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
// Call InetAddress.getAddress() |
|
jbyteArray addressArray = (jbyteArray)env->CallObjectMethod(in_remoteAddress, getAddressMethod); |
|
if(addressArray == NULL) |
|
{ |
|
// 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); |
|
|
|
|
|
sockaddr_storage remoteAddress = {}; |
|
|
|
if(addrSize == 16) |
|
{ |
|
// IPV6 address |
|
sockaddr_in6 ipv6 = {}; |
|
ipv6.sin6_family = AF_INET6; |
|
memcpy(ipv6.sin6_addr.s6_addr, addr, 16); |
|
memcpy(&remoteAddress, &ipv6, sizeof(sockaddr_in6)); |
|
} |
|
else if(addrSize = 4) |
|
{ |
|
// IPV4 address |
|
sockaddr_in ipv4 = {}; |
|
ipv4.sin_family = AF_INET; |
|
memcpy(&ipv4.sin_addr, addr, 4); |
|
memcpy(&remoteAddress, &ipv4, sizeof(sockaddr_in)); |
|
} |
|
else |
|
{ |
|
// unknown address type |
|
env->ReleaseByteArrayElements(addressArray, addr, 0); |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
|
|
unsigned int packetLength = env->GetArrayLength(in_packetData); |
|
jbyte *packetData = env->GetByteArrayElements(in_packetData, NULL); |
|
|
|
uint64_t nextBackgroundTaskDeadline = 0; |
|
|
|
ZT1_ResultCode rc = ZT1_Node_processWirePacket( |
|
node, |
|
now, |
|
&remoteAddress, |
|
linkDesparation, |
|
packetData, |
|
packetLength, |
|
&nextBackgroundTaskDeadline); |
|
|
|
jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL); |
|
outDeadline[0] = (jlong)nextBackgroundTaskDeadline; |
|
env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0); |
|
|
|
env->ReleaseByteArrayElements(addressArray, addr, 0); |
|
env->ReleaseByteArrayElements(in_packetData, packetData, 0); |
|
|
|
return createResultObject(env, ZT1_RESULT_OK); |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: processBackgroundTasks |
|
* Signature: (JJ[J)Lcom/zerotierone/sdk/ResultCode; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processBackgroundTasks |
|
(JNIEnv *env, jobject obj, |
|
jlong id, |
|
jlong in_now, |
|
jlongArray out_nextBackgroundTaskDeadline) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline); |
|
if(nbtd_len < 1) |
|
{ |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
uint64_t now = (uint64_t)in_now; |
|
uint64_t nextBackgroundTaskDeadline = 0; |
|
|
|
ZT1_ResultCode rc = ZT1_Node_processBackgroundTasks(node, now, &nextBackgroundTaskDeadline); |
|
|
|
jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL); |
|
outDeadline[0] = (jlong)nextBackgroundTaskDeadline; |
|
env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0); |
|
|
|
return createResultObject(env, rc); |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: join |
|
* Signature: (JJ)Lcom/zerotierone/sdk/ResultCode; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_join |
|
(JNIEnv *env, jobject obj, jlong id, jlong in_nwid) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
uint64_t nwid = (uint64_t)in_nwid; |
|
|
|
ZT1_ResultCode rc = ZT1_Node_join(node, nwid); |
|
|
|
return createResultObject(env, rc); |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: leave |
|
* Signature: (JJ)Lcom/zerotierone/sdk/ResultCode; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_leave |
|
(JNIEnv *env, jobject obj, jlong id, jlong in_nwid) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
uint64_t nwid = (uint64_t)in_nwid; |
|
|
|
ZT1_ResultCode rc = ZT1_Node_leave(node, nwid); |
|
|
|
return createResultObject(env, rc); |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: multicastSubscribe |
|
* Signature: (JJJJ)Lcom/zerotierone/sdk/ResultCode; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_multicastSubscribe |
|
(JNIEnv *env, jobject obj, |
|
jlong id, |
|
jlong in_nwid, |
|
jlong in_multicastGroup, |
|
jlong in_multicastAdi) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
uint64_t nwid = (uint64_t)in_nwid; |
|
uint64_t multicastGroup = (uint64_t)in_multicastGroup; |
|
uint64_t multicastAdi = (uint64_t)in_multicastAdi; |
|
|
|
ZT1_ResultCode rc = ZT1_Node_multicastSubscribe( |
|
node, nwid, multicastGroup, multicastAdi); |
|
|
|
return createResultObject(env, rc); |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: multicastUnsubscribe |
|
* Signature: (JJJJ)Lcom/zerotierone/sdk/ResultCode; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_multicastUnsubscribe |
|
(JNIEnv *env, jobject obj, |
|
jlong id, |
|
jlong in_nwid, |
|
jlong in_multicastGroup, |
|
jlong in_multicastAdi) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); |
|
} |
|
|
|
uint64_t nwid = (uint64_t)in_nwid; |
|
uint64_t multicastGroup = (uint64_t)in_multicastGroup; |
|
uint64_t multicastAdi = (uint64_t)in_multicastAdi; |
|
|
|
ZT1_ResultCode rc = ZT1_Node_multicastUnsubscribe( |
|
node, nwid, multicastGroup, multicastAdi); |
|
|
|
return createResultObject(env, rc); |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: address |
|
* Signature: (J)J |
|
*/ |
|
JNIEXPORT jlong JNICALL Java_com_zerotierone_sdk_Node_address |
|
(JNIEnv *env , jobject obj, jlong id) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return 0; |
|
} |
|
|
|
uint64_t address = ZT1_Node_address(node); |
|
return (jlong)address; |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: status |
|
* Signature: (J)Lcom/zerotierone/sdk/NodeStatus; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_status |
|
(JNIEnv *env, jobject obj, jlong id) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return 0; |
|
} |
|
|
|
// static so we only have to look these up once |
|
static jclass nodeStatusClass = NULL; |
|
static jmethodID nodeStatusConstructor = NULL; |
|
|
|
// create a com.zerotierone.sdk.NodeStatus object |
|
if(nodeStatusClass == NULL) |
|
{ |
|
nodeStatusClass = env->FindClass("com/zerotierone/sdk/NodeStatus"); |
|
if(nodeStatusClass == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(nodeStatusConstructor == NULL) |
|
{ |
|
nodeStatusConstructor = env->GetMethodID( |
|
nodeStatusClass, "<init>", "()V"); |
|
if(nodeStatusConstructor == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
jobject nodeStatusObj = env->NewObject(nodeStatusClass, nodeStatusConstructor); |
|
if(nodeStatusObj == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
ZT1_NodeStatus nodeStatus; |
|
ZT1_Node_status(node, &nodeStatus); |
|
|
|
static jfieldID addressField = NULL; |
|
static jfieldID publicIdentityField = NULL; |
|
static jfieldID secretIdentityField = NULL; |
|
static jfieldID onlineField = NULL; |
|
|
|
if(addressField == NULL) |
|
{ |
|
addressField = env->GetFieldID(nodeStatusClass, "address", "J"); |
|
if(addressField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(publicIdentityField == NULL) |
|
{ |
|
publicIdentityField = env->GetFieldID(nodeStatusClass, "publicIdentity", "Ljava/lang/String;"); |
|
if(publicIdentityField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(secretIdentityField == NULL) |
|
{ |
|
secretIdentityField = env->GetFieldID(nodeStatusClass, "secretIdentity", "Ljava/lang/String;"); |
|
if(secretIdentityField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(onlineField == NULL) |
|
{ |
|
onlineField = env->GetFieldID(nodeStatusClass, "online", "Z"); |
|
if(onlineField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
env->SetLongField(nodeStatusObj, addressField, nodeStatus.address); |
|
|
|
jstring pubIdentStr = env->NewStringUTF(nodeStatus.publicIdentity); |
|
if(pubIdentStr == NULL) |
|
{ |
|
return NULL; // out of memory |
|
} |
|
env->SetObjectField(nodeStatusObj, publicIdentityField, pubIdentStr); |
|
|
|
jstring secIdentStr = env->NewStringUTF(nodeStatus.secretIdentity); |
|
if(secIdentStr == NULL) |
|
{ |
|
return NULL; // out of memory |
|
} |
|
env->SetObjectField(nodeStatusObj, secretIdentityField, secIdentStr); |
|
|
|
env->SetBooleanField(nodeStatusObj, onlineField, nodeStatus.online); |
|
|
|
return nodeStatusObj; |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: networkConfig |
|
* Signature: (J)Lcom/zerotierone/sdk/VirtualNetworkConfig; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_networkConfig |
|
(JNIEnv *env, jobject obj, jlong id, jlong nwid) |
|
{ |
|
uint64_t nodeId = (uint64_t) id; |
|
ZT1_Node *node = findNode(nodeId); |
|
if(node == NULL) |
|
{ |
|
// cannot find valid node. We should never get here. |
|
return 0; |
|
} |
|
|
|
// create a com.zerotierone.sdk.VirtualNetworkConfig object |
|
jclass vnetConfigClass = env->FindClass("com/zerotierone/sdk/VirtualNetworkConfig"); |
|
if(vnetConfigClass == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
jmethodID vnetConfigConstructor = env->GetMethodID( |
|
vnetConfigClass, "<init>", "()V"); |
|
if(vnetConfigConstructor == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
jobject vnetConfigObj = env->NewObject(vnetConfigClass, vnetConfigConstructor); |
|
if(vnetConfigObj == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
ZT1_VirtualNetworkConfig *vnetConfig = ZT1_Node_networkConfig(node, nwid); |
|
|
|
static jfieldID nwidField = NULL; |
|
static jfieldID macField = NULL; |
|
static jfieldID nameField = NULL; |
|
static jfieldID statusField = NULL; |
|
static jfieldID typeField = NULL; |
|
static jfieldID mtuField = NULL; |
|
static jfieldID dhcpField = NULL; |
|
static jfieldID bridgeField = NULL; |
|
static jfieldID broadcastEnabledField = NULL; |
|
static jfieldID portErrorField = NULL; |
|
static jfieldID enabledField = NULL; |
|
static jfieldID netconfRevisionField = NULL; |
|
static jfieldID multicastSubscriptionsField = NULL; |
|
static jfieldID assignedAddressesField = NULL; |
|
|
|
if(nwidField == NULL) |
|
{ |
|
nwidField = env->GetFieldID(vnetConfigClass, "nwid", "J"); |
|
if(nwidField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(macField == NULL) |
|
{ |
|
macField = env->GetFieldID(vnetConfigClass, "mac", "J"); |
|
if(macField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(nameField == NULL) |
|
{ |
|
nameField = env->GetFieldID(vnetConfigClass, "name", "Ljava/lang/String;"); |
|
if(nameField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(statusField == NULL) |
|
{ |
|
statusField = env->GetFieldID(vnetConfigClass, "status", "Lcom/zerotierone/sdk/VirtualNetworStatus;"); |
|
if(statusField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(typeField == NULL) |
|
{ |
|
typeField = env->GetFieldID(vnetConfigClass, "type", "Lcom/zerotierone/sdk/VirtualNetworkType;"); |
|
if(typeField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(mtuField == NULL) |
|
{ |
|
mtuField = env->GetFieldID(vnetConfigClass, "mtu", "I"); |
|
if(mtuField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(dhcpField == NULL) |
|
{ |
|
dhcpField = env->GetFieldID(vnetConfigClass, "dhcp", "Z"); |
|
if(dhcpField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(bridgeField == NULL) |
|
{ |
|
bridgeField = env->GetFieldID(vnetConfigClass, "bridge", "Z"); |
|
if(bridgeField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(broadcastEnabledField == NULL) |
|
{ |
|
broadcastEnabledField = env->GetFieldID(vnetConfigClass, "broadcastEnabled", "Z"); |
|
if(broadcastEnabledField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(portErrorField == NULL) |
|
{ |
|
portErrorField == env->GetFieldID(vnetConfigClass, "portError", "Z"); |
|
if(portErrorField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(enabledField == NULL) |
|
{ |
|
enabledField = env->GetFieldID(vnetConfigClass, "enabled", "Z"); |
|
if(enabledField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(netconfRevisionField == NULL) |
|
{ |
|
netconfRevisionField = env->GetFieldID(vnetConfigClass, "netconfRevision", "J"); |
|
if(netconfRevisionField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(multicastSubscriptionsField == NULL) |
|
{ |
|
multicastSubscriptionsField = env->GetFieldID(vnetConfigClass, "multicastSubscriptions", "Ljava/util/ArrayList;"); |
|
if(multicastSubscriptionsField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(assignedAddressesField == NULL) |
|
{ |
|
assignedAddressesField = env->GetFieldID(vnetConfigClass, "assignedAddresses", "Ljava/util/ArrayList;"); |
|
if(assignedAddressesField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
env->SetLongField(vnetConfigObj, nwidField, vnetConfig->nwid); |
|
env->SetLongField(vnetConfigObj, macField, vnetConfig->mac); |
|
jstring nameStr = env->NewStringUTF(vnetConfig->name); |
|
if(nameStr == NULL) |
|
{ |
|
return NULL; // out of memory |
|
} |
|
env->SetObjectField(vnetConfigObj, nameField, nameStr); |
|
|
|
jobject statusObject = createVirtualNetworkStatus(env, vnetConfig->status); |
|
if(statusObject == NULL) |
|
{ |
|
return NULL; |
|
} |
|
env->SetObjectField(vnetConfigObj, statusField, statusObject); |
|
|
|
jobject typeObject = createVirtualNetworkType(env, vnetConfig->type); |
|
if(typeObject == NULL) |
|
{ |
|
return NULL; |
|
} |
|
env->SetObjectField(vnetConfigObj, typeField, typeObject); |
|
|
|
env->SetIntField(vnetConfigObj, mtuField, vnetConfig->mtu); |
|
env->SetBooleanField(vnetConfigObj, dhcpField, vnetConfig->dhcp); |
|
env->SetBooleanField(vnetConfigObj, bridgeField, vnetConfig->bridge); |
|
env->SetBooleanField(vnetConfigObj, broadcastEnabledField, vnetConfig->broadcastEnabled); |
|
env->SetBooleanField(vnetConfigObj, portErrorField, vnetConfig->portError); |
|
|
|
|
|
jobject mcastSubsArrayObj = newArrayList(env); |
|
for(unsigned int i = 0; i < vnetConfig->multicastSubscriptionCount; ++i) |
|
{ |
|
jobject mcastObj = newMulticastGroup(env, vnetConfig->multicastSubscriptions[i]); |
|
appendItemToArrayList(env, mcastSubsArrayObj, mcastObj); |
|
} |
|
env->SetObjectField(vnetConfigObj, multicastSubscriptionsField, mcastSubsArrayObj); |
|
|
|
|
|
jobject assignedAddrArrayObj = newArrayList(env); |
|
for(unsigned int i = 0; i < vnetConfig->assignedAddressCount; ++i) |
|
{ |
|
jobject inetAddrObj = newInetAddress(env, vnetConfig->assignedAddresses[i]); |
|
appendItemToArrayList(env, assignedAddrArrayObj, inetAddrObj); |
|
} |
|
|
|
env->SetObjectField(vnetConfigObj, assignedAddressesField, assignedAddrArrayObj); |
|
|
|
ZT1_Node_freeQueryResult(node, vnetConfig); |
|
vnetConfig = NULL; |
|
|
|
return vnetConfigObj; |
|
} |
|
|
|
/* |
|
* Class: com_zerotierone_sdk_Node |
|
* Method: version |
|
* Signature: (J)Lcom/zerotierone/sdk/Version; |
|
*/ |
|
JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_version |
|
(JNIEnv *env, jobject obj) |
|
{ |
|
// create a com.zerotierone.sdk.Version object |
|
jclass versionClass = env->FindClass("com/zerotierone/sdk/Version"); |
|
if(versionClass == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
jmethodID versionConstructor = env->GetMethodID( |
|
versionClass, "<init>", "()V"); |
|
if(versionConstructor == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
jobject versionObj = env->NewObject(versionClass, versionConstructor); |
|
if(versionObj == NULL) |
|
{ |
|
return NULL; |
|
} |
|
|
|
int major = 0; |
|
int minor = 0; |
|
int revision = 0; |
|
unsigned long featureFlags = 0; |
|
|
|
ZT1_version(&major, &minor, &revision, &featureFlags); |
|
|
|
// copy data to Version object |
|
static jfieldID majorField = NULL; |
|
static jfieldID minorField = NULL; |
|
static jfieldID revisionField = NULL; |
|
static jfieldID featureFlagsField = NULL; |
|
|
|
if(majorField == NULL) |
|
{ |
|
majorField = env->GetFieldID(versionClass, "major", "I"); |
|
if(majorField = NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(minorField == NULL) |
|
{ |
|
minorField = env->GetFieldID(versionClass, "minor", "I"); |
|
if(minorField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(revisionField == NULL) |
|
{ |
|
revisionField = env->GetFieldID(versionClass, "revision", "I"); |
|
if(revisionField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
if(featureFlagsField == NULL) |
|
{ |
|
featureFlagsField = env->GetFieldID(versionClass, "featureFlags", "J"); |
|
if(featureFlagsField == NULL) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
env->SetIntField(versionObj, majorField, (jint)major); |
|
env->SetIntField(versionObj, minorField, (jint)minor); |
|
env->SetIntField(versionObj, revisionField, (jint)revision); |
|
env->SetLongField(versionObj, featureFlagsField, (jlong)featureFlags); |
|
|
|
|
|
return versionObj; |
|
} |
|
|
|
#ifdef __cplusplus |
|
} // extern "C" |
|
#endif |