com_zerotierone_sdk_Node.cpp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310
  1. /*
  2. * ZeroTier One - Network Virtualization Everywhere
  3. * Copyright (C) 2011-2015 ZeroTier, Inc.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * --
  19. *
  20. * ZeroTier may be used and distributed under the terms of the GPLv3, which
  21. * are available at: http://www.gnu.org/licenses/gpl-3.0.html
  22. *
  23. * If you would like to embed ZeroTier into a commercial application or
  24. * redistribute it in a modified binary form, please contact ZeroTier Networks
  25. * LLC. Start here: http://www.zerotier.com/
  26. */
  27. #include "com_zerotierone_sdk_Node.h"
  28. #include "ZT_jnicache.h"
  29. #include "ZT_jniutils.h"
  30. #include <ZeroTierOne.h>
  31. #include "Mutex.hpp"
  32. #include <map>
  33. #include <string>
  34. #include <cassert>
  35. #include <cstring>
  36. #define LOG_TAG "Node"
  37. namespace {
  38. struct JniRef
  39. {
  40. JniRef()
  41. : jvm(NULL)
  42. , node(NULL)
  43. , dataStoreGetListener(NULL)
  44. , dataStorePutListener(NULL)
  45. , packetSender(NULL)
  46. , eventListener(NULL)
  47. , frameListener(NULL)
  48. , configListener(NULL)
  49. , pathChecker(NULL)
  50. , callbacks(NULL)
  51. {
  52. callbacks = (ZT_Node_Callbacks*)malloc(sizeof(ZT_Node_Callbacks));
  53. memset(callbacks, 0, sizeof(ZT_Node_Callbacks));
  54. }
  55. ~JniRef()
  56. {
  57. JNIEnv *env = NULL;
  58. jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  59. env->DeleteGlobalRef(dataStoreGetListener);
  60. env->DeleteGlobalRef(dataStorePutListener);
  61. env->DeleteGlobalRef(packetSender);
  62. env->DeleteGlobalRef(eventListener);
  63. env->DeleteGlobalRef(frameListener);
  64. env->DeleteGlobalRef(configListener);
  65. env->DeleteGlobalRef(pathChecker);
  66. free(callbacks);
  67. callbacks = NULL;
  68. }
  69. int64_t id;
  70. JavaVM *jvm;
  71. ZT_Node *node;
  72. jobject dataStoreGetListener;
  73. jobject dataStorePutListener;
  74. jobject packetSender;
  75. jobject eventListener;
  76. jobject frameListener;
  77. jobject configListener;
  78. jobject pathChecker;
  79. ZT_Node_Callbacks *callbacks;
  80. };
  81. int VirtualNetworkConfigFunctionCallback(
  82. ZT_Node *node,
  83. void *userData,
  84. void *threadData,
  85. uint64_t nwid,
  86. void **,
  87. enum ZT_VirtualNetworkConfigOperation operation,
  88. const ZT_VirtualNetworkConfig *config)
  89. {
  90. LOGV("VirtualNetworkConfigFunctionCallback");
  91. JniRef *ref = (JniRef*)userData;
  92. JNIEnv *env = NULL;
  93. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  94. if (ref->configListener == NULL) {
  95. LOGE("configListener is NULL");
  96. return -100;
  97. }
  98. jobject operationObject = createVirtualNetworkConfigOperation(env, operation);
  99. if(operationObject == NULL)
  100. {
  101. LOGE("Error creating VirtualNetworkConfigOperation object");
  102. return -101;
  103. }
  104. jobject networkConfigObject = newNetworkConfig(env, *config);
  105. if(networkConfigObject == NULL)
  106. {
  107. LOGE("Error creating VirtualNetworkConfig object");
  108. return -102;
  109. }
  110. return env->CallIntMethod(
  111. ref->configListener,
  112. VirtualNetworkConfigListener_onNetworkConfigurationUpdated_method,
  113. (jlong)nwid, operationObject, networkConfigObject);
  114. }
  115. void VirtualNetworkFrameFunctionCallback(ZT_Node *node,
  116. void *userData,
  117. void *threadData,
  118. uint64_t nwid,
  119. void**,
  120. uint64_t sourceMac,
  121. uint64_t destMac,
  122. unsigned int etherType,
  123. unsigned int vlanid,
  124. const void *frameData,
  125. unsigned int frameLength)
  126. {
  127. LOGV("VirtualNetworkFrameFunctionCallback");
  128. #ifndef NDEBUG
  129. unsigned char* local = (unsigned char*)frameData;
  130. LOGV("Type Bytes: 0x%02x%02x", local[12], local[13]);
  131. #endif
  132. JniRef *ref = (JniRef*)userData;
  133. assert(ref->node == node);
  134. JNIEnv *env = NULL;
  135. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  136. if (ref->frameListener == NULL) {
  137. LOGE("frameListener is NULL");
  138. return;
  139. }
  140. jbyteArray dataArray = env->NewByteArray(frameLength);
  141. if(env->ExceptionCheck() || dataArray == NULL)
  142. {
  143. LOGE("Couldn't create frame data array");
  144. return;
  145. }
  146. void *data = env->GetPrimitiveArrayCritical(dataArray, NULL);
  147. memcpy(data, frameData, frameLength);
  148. env->ReleasePrimitiveArrayCritical(dataArray, data, 0);
  149. if(env->ExceptionCheck())
  150. {
  151. LOGE("Error setting frame data to array");
  152. return;
  153. }
  154. env->CallVoidMethod(ref->frameListener, VirtualNetworkFrameListener_onVirtualNetworkFrame_method, (jlong)nwid, (jlong)sourceMac, (jlong)destMac, (jlong)etherType, (jlong)vlanid, dataArray);
  155. }
  156. void EventCallback(ZT_Node *node,
  157. void *userData,
  158. void *threadData,
  159. enum ZT_Event event,
  160. const void *data) {
  161. LOGV("EventCallback");
  162. JniRef *ref = (JniRef *) userData;
  163. if (ref->node != node && event != ZT_EVENT_UP) {
  164. LOGE("Nodes not equal. ref->node %p, node %p. Event: %d", ref->node, node, event);
  165. return;
  166. }
  167. JNIEnv *env = NULL;
  168. ref->jvm->GetEnv((void **) &env, JNI_VERSION_1_6);
  169. if (ref->eventListener == NULL) {
  170. LOGE("eventListener is NULL");
  171. return;
  172. }
  173. jobject eventObject = createEvent(env, event);
  174. if (eventObject == NULL) {
  175. return;
  176. }
  177. switch (event) {
  178. case ZT_EVENT_UP: {
  179. LOGD("Event Up");
  180. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, eventObject);
  181. break;
  182. }
  183. case ZT_EVENT_OFFLINE: {
  184. LOGD("Event Offline");
  185. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, eventObject);
  186. break;
  187. }
  188. case ZT_EVENT_ONLINE: {
  189. LOGD("Event Online");
  190. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, eventObject);
  191. break;
  192. }
  193. case ZT_EVENT_DOWN: {
  194. LOGD("Event Down");
  195. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, eventObject);
  196. break;
  197. }
  198. case ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION: {
  199. LOGV("Identity Collision");
  200. // call onEvent()
  201. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, eventObject);
  202. }
  203. break;
  204. case ZT_EVENT_TRACE: {
  205. LOGV("Trace Event");
  206. // call onTrace()
  207. if (data != NULL) {
  208. const char *message = (const char *) data;
  209. jstring messageStr = env->NewStringUTF(message);
  210. env->CallVoidMethod(ref->eventListener, EventListener_onTrace_method, messageStr);
  211. }
  212. }
  213. break;
  214. case ZT_EVENT_USER_MESSAGE:
  215. case ZT_EVENT_REMOTE_TRACE:
  216. default:
  217. break;
  218. }
  219. }
  220. void StatePutFunction(
  221. ZT_Node *node,
  222. void *userData,
  223. void *threadData,
  224. enum ZT_StateObjectType type,
  225. const uint64_t id[2],
  226. const void *buffer,
  227. int bufferLength) {
  228. char p[4096] = {0};
  229. bool secure = false;
  230. switch (type) {
  231. case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
  232. snprintf(p, sizeof(p), "identity.public");
  233. break;
  234. case ZT_STATE_OBJECT_IDENTITY_SECRET:
  235. snprintf(p, sizeof(p), "identity.secret");
  236. secure = true;
  237. break;
  238. case ZT_STATE_OBJECT_PLANET:
  239. snprintf(p, sizeof(p), "planet");
  240. break;
  241. case ZT_STATE_OBJECT_MOON:
  242. snprintf(p, sizeof(p), "moons.d/%.16llx.moon", (unsigned long long)id[0]);
  243. break;
  244. case ZT_STATE_OBJECT_NETWORK_CONFIG:
  245. snprintf(p, sizeof(p), "networks.d/%.16llx.conf", (unsigned long long)id[0]);
  246. break;
  247. case ZT_STATE_OBJECT_PEER:
  248. snprintf(p, sizeof(p), "peers.d/%.10llx", (unsigned long long)id[0]);
  249. break;
  250. default:
  251. return;
  252. }
  253. if (strlen(p) < 1) {
  254. return;
  255. }
  256. JniRef *ref = (JniRef*)userData;
  257. JNIEnv *env = NULL;
  258. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  259. if (ref->dataStorePutListener == NULL) {
  260. LOGE("dataStorePutListener is NULL");
  261. return;
  262. }
  263. jstring nameStr = env->NewStringUTF(p);
  264. if (bufferLength >= 0) {
  265. LOGD("JNI: Write file: %s", p);
  266. // set operation
  267. jbyteArray bufferObj = env->NewByteArray(bufferLength);
  268. if(env->ExceptionCheck() || bufferObj == NULL)
  269. {
  270. LOGE("Error creating byte array buffer!");
  271. return;
  272. }
  273. env->SetByteArrayRegion(bufferObj, 0, bufferLength, (jbyte*)buffer);
  274. env->CallIntMethod(ref->dataStorePutListener,
  275. DataStorePutListener_onDataStorePut_method,
  276. nameStr, bufferObj, secure);
  277. } else {
  278. LOGD("JNI: Delete file: %s", p);
  279. env->CallIntMethod(ref->dataStorePutListener, DataStorePutListener_onDelete_method, nameStr);
  280. }
  281. }
  282. int StateGetFunction(
  283. ZT_Node *node,
  284. void *userData,
  285. void *threadData,
  286. ZT_StateObjectType type,
  287. const uint64_t id[2],
  288. void *buffer,
  289. unsigned int bufferLength) {
  290. char p[4096] = {0};
  291. switch (type) {
  292. case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
  293. snprintf(p, sizeof(p), "identity.public");
  294. break;
  295. case ZT_STATE_OBJECT_IDENTITY_SECRET:
  296. snprintf(p, sizeof(p), "identity.secret");
  297. break;
  298. case ZT_STATE_OBJECT_PLANET:
  299. snprintf(p, sizeof(p), "planet");
  300. break;
  301. case ZT_STATE_OBJECT_MOON:
  302. snprintf(p, sizeof(p), "moons.d/%.16llx.moon", (unsigned long long)id[0]);
  303. break;
  304. case ZT_STATE_OBJECT_NETWORK_CONFIG:
  305. snprintf(p, sizeof(p), "networks.d/%.16llx.conf", (unsigned long long)id[0]);
  306. break;
  307. case ZT_STATE_OBJECT_PEER:
  308. snprintf(p, sizeof(p), "peers.d/%.10llx", (unsigned long long)id[0]);
  309. break;
  310. default:
  311. return -100;
  312. }
  313. if (strlen(p) < 1) {
  314. return -101;
  315. }
  316. JniRef *ref = (JniRef*)userData;
  317. JNIEnv *env = NULL;
  318. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  319. if (ref->dataStoreGetListener == NULL) {
  320. LOGE("dataStoreGetListener is NULL");
  321. return -102;
  322. }
  323. jstring nameStr = env->NewStringUTF(p);
  324. if(nameStr == NULL)
  325. {
  326. LOGE("Error creating name string object");
  327. return -103; // out of memory
  328. }
  329. jbyteArray bufferObj = env->NewByteArray(bufferLength);
  330. if(bufferObj == NULL)
  331. {
  332. LOGE("Error creating byte[] buffer of size: %u", bufferLength);
  333. return -104;
  334. }
  335. LOGV("Calling onDataStoreGet(%s, %p)", p, buffer);
  336. int retval = (int)env->CallLongMethod(
  337. ref->dataStoreGetListener,
  338. DataStoreGetListener_onDataStoreGet_method,
  339. nameStr,
  340. bufferObj);
  341. LOGV("onDataStoreGet returned %d", retval);
  342. if(retval > 0)
  343. {
  344. void *data = env->GetPrimitiveArrayCritical(bufferObj, NULL);
  345. memcpy(buffer, data, retval);
  346. env->ReleasePrimitiveArrayCritical(bufferObj, data, 0);
  347. }
  348. return retval;
  349. }
  350. int WirePacketSendFunction(ZT_Node *node,
  351. void *userData,
  352. void *threadData,
  353. int64_t localSocket,
  354. const struct sockaddr_storage *remoteAddress,
  355. const void *buffer,
  356. unsigned int bufferSize,
  357. unsigned int ttl)
  358. {
  359. LOGV("WirePacketSendFunction(%lld, %p, %p, %d)", (long long)localSocket, remoteAddress, buffer, bufferSize);
  360. JniRef *ref = (JniRef*)userData;
  361. assert(ref->node == node);
  362. JNIEnv *env = NULL;
  363. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  364. if (ref->packetSender == NULL) {
  365. LOGE("packetSender is NULL");
  366. return -100;
  367. }
  368. jobject remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
  369. jbyteArray bufferObj = env->NewByteArray(bufferSize);
  370. env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer);
  371. int retval = env->CallIntMethod(ref->packetSender, PacketSender_onSendPacketRequested_method, localSocket, remoteAddressObj, bufferObj);
  372. LOGV("JNI Packet Sender returned: %d", retval);
  373. return retval;
  374. }
  375. int PathCheckFunction(ZT_Node *node,
  376. void *userPtr,
  377. void *threadPtr,
  378. uint64_t address,
  379. int64_t localSocket,
  380. const struct sockaddr_storage *remoteAddress)
  381. {
  382. JniRef *ref = (JniRef*)userPtr;
  383. assert(ref->node == node);
  384. if(ref->pathChecker == NULL) {
  385. return true;
  386. }
  387. JNIEnv *env = NULL;
  388. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  389. //
  390. // was:
  391. // struct sockaddr_storage nullAddress = {0};
  392. //
  393. // but was getting this warning:
  394. // warning: suggest braces around initialization of subobject
  395. //
  396. // when building ZeroTierOne
  397. //
  398. struct sockaddr_storage nullAddress;
  399. //
  400. // It is possible to assume knowledge about internals of sockaddr_storage and construct
  401. // correct 0-initializer, but it is simpler to just treat sockaddr_storage as opaque and
  402. // use memset here to fill with 0
  403. //
  404. // This is also done in InetAddress.hpp for InetAddress
  405. //
  406. memset(&nullAddress, 0, sizeof(sockaddr_storage));
  407. jobject remoteAddressObj = NULL;
  408. if(memcmp(remoteAddress, &nullAddress, sizeof(sockaddr_storage)) != 0)
  409. {
  410. remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
  411. }
  412. return env->CallBooleanMethod(ref->pathChecker, PathChecker_onPathCheck_method, address, localSocket, remoteAddressObj);
  413. }
  414. int PathLookupFunction(ZT_Node *node,
  415. void *userPtr,
  416. void *threadPtr,
  417. uint64_t address,
  418. int ss_family,
  419. struct sockaddr_storage *result)
  420. {
  421. JniRef *ref = (JniRef*)userPtr;
  422. assert(ref->node == node);
  423. if(ref->pathChecker == NULL) {
  424. return false;
  425. }
  426. JNIEnv *env = NULL;
  427. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  428. jobject sockAddressObject = env->CallObjectMethod(ref->pathChecker, PathChecker_onPathLookup_method, address, ss_family);
  429. if(sockAddressObject == NULL)
  430. {
  431. LOGE("Unable to call onPathLookup implementation");
  432. return false;
  433. }
  434. jint port = env->CallIntMethod(sockAddressObject, InetSocketAddress_getPort_method);
  435. jobject addressObject = env->CallObjectMethod(sockAddressObject, InetSocketAddress_getAddress_method);
  436. jbyteArray addressBytes = (jbyteArray)env->CallObjectMethod(addressObject, InetAddress_getAddress_method);
  437. if(addressBytes == NULL)
  438. {
  439. LOGE("Unable to call InetAddress.getBytes()");
  440. return false;
  441. }
  442. int addressSize = env->GetArrayLength(addressBytes);
  443. if(addressSize == 4)
  444. {
  445. // IPV4
  446. sockaddr_in *addr = (sockaddr_in*)result;
  447. addr->sin_family = AF_INET;
  448. addr->sin_port = htons(port);
  449. void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL);
  450. memcpy(&addr->sin_addr, data, 4);
  451. env->ReleasePrimitiveArrayCritical(addressBytes, data, 0);
  452. }
  453. else if (addressSize == 16)
  454. {
  455. // IPV6
  456. sockaddr_in6 *addr = (sockaddr_in6*)result;
  457. addr->sin6_family = AF_INET6;
  458. addr->sin6_port = htons(port);
  459. void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL);
  460. memcpy(&addr->sin6_addr, data, 16);
  461. env->ReleasePrimitiveArrayCritical(addressBytes, data, 0);
  462. }
  463. else
  464. {
  465. return false;
  466. }
  467. return true;
  468. }
  469. typedef std::map<int64_t, JniRef*> NodeMap;
  470. static NodeMap nodeMap;
  471. ZeroTier::Mutex nodeMapMutex;
  472. ZT_Node* findNode(int64_t nodeId)
  473. {
  474. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  475. NodeMap::iterator found = nodeMap.find(nodeId);
  476. if(found != nodeMap.end())
  477. {
  478. JniRef *ref = found->second;
  479. return ref->node;
  480. }
  481. return NULL;
  482. }
  483. }
  484. #ifdef __cplusplus
  485. extern "C" {
  486. #endif
  487. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
  488. {
  489. setupJNICache(vm);
  490. return JNI_VERSION_1_6;
  491. }
  492. JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
  493. {
  494. teardownJNICache(vm);
  495. }
  496. /*
  497. * Class: com_zerotier_sdk_Node
  498. * Method: node_init
  499. * Signature: (J)Lcom/zerotier/sdk/ResultCode;
  500. */
  501. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init(
  502. JNIEnv *env, jobject obj, jlong now)
  503. {
  504. LOGV("Creating ZT_Node struct");
  505. jobject resultObject = ResultCode_RESULT_OK_enum;
  506. ZT_Node *node;
  507. JniRef *ref = new JniRef;
  508. ref->id = (int64_t)now;
  509. env->GetJavaVM(&ref->jvm);
  510. jobject dataStoreGetListener = env->GetObjectField(obj, Node_getListener_field);
  511. if(dataStoreGetListener == NULL)
  512. {
  513. return NULL;
  514. }
  515. ref->dataStoreGetListener = env->NewGlobalRef(dataStoreGetListener);
  516. jobject dataStorePutListener = env->GetObjectField(obj, Node_putListener_field);
  517. if(dataStorePutListener == NULL)
  518. {
  519. return NULL;
  520. }
  521. ref->dataStorePutListener = env->NewGlobalRef(dataStorePutListener);
  522. jobject packetSender = env->GetObjectField(obj, Node_sender_field);
  523. if(packetSender == NULL)
  524. {
  525. return NULL;
  526. }
  527. ref->packetSender = env->NewGlobalRef(packetSender);
  528. jobject frameListener = env->GetObjectField(obj, Node_frameListener_field);
  529. if(frameListener == NULL)
  530. {
  531. return NULL;
  532. }
  533. ref->frameListener = env->NewGlobalRef(frameListener);
  534. jobject configListener = env->GetObjectField(obj, Node_configListener_field);
  535. if(configListener == NULL)
  536. {
  537. return NULL;
  538. }
  539. ref->configListener = env->NewGlobalRef(configListener);
  540. jobject eventListener = env->GetObjectField(obj, Node_eventListener_field);
  541. if(eventListener == NULL)
  542. {
  543. return NULL;
  544. }
  545. ref->eventListener = env->NewGlobalRef(eventListener);
  546. jobject pathChecker = env->GetObjectField(obj, Node_pathChecker_field);
  547. if(pathChecker != NULL)
  548. {
  549. ref->pathChecker = env->NewGlobalRef(pathChecker);
  550. }
  551. ref->callbacks->stateGetFunction = &StateGetFunction;
  552. ref->callbacks->statePutFunction = &StatePutFunction;
  553. ref->callbacks->wirePacketSendFunction = &WirePacketSendFunction;
  554. ref->callbacks->virtualNetworkFrameFunction = &VirtualNetworkFrameFunctionCallback;
  555. ref->callbacks->virtualNetworkConfigFunction = &VirtualNetworkConfigFunctionCallback;
  556. ref->callbacks->eventCallback = &EventCallback;
  557. ref->callbacks->pathCheckFunction = &PathCheckFunction;
  558. ref->callbacks->pathLookupFunction = &PathLookupFunction;
  559. ZT_ResultCode rc = ZT_Node_new(
  560. &node,
  561. ref,
  562. NULL,
  563. ref->callbacks,
  564. (int64_t)now);
  565. if(rc != ZT_RESULT_OK)
  566. {
  567. LOGE("Error creating Node: %d", rc);
  568. resultObject = createResultObject(env, rc);
  569. if(node)
  570. {
  571. ZT_Node_delete(node);
  572. node = NULL;
  573. }
  574. delete ref;
  575. ref = NULL;
  576. return resultObject;
  577. }
  578. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  579. ref->node = node;
  580. nodeMap.insert(std::make_pair(ref->id, ref));
  581. return resultObject;
  582. }
  583. /*
  584. * Class: com_zerotier_sdk_Node
  585. * Method: node_delete
  586. * Signature: (J)V
  587. */
  588. JNIEXPORT void JNICALL Java_com_zerotier_sdk_Node_node_1delete(
  589. JNIEnv *env, jobject obj, jlong id)
  590. {
  591. LOGV("Destroying ZT_Node struct");
  592. int64_t nodeId = (int64_t)id;
  593. NodeMap::iterator found;
  594. {
  595. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  596. found = nodeMap.find(nodeId);
  597. }
  598. if(found != nodeMap.end())
  599. {
  600. JniRef *ref = found->second;
  601. nodeMap.erase(found);
  602. ZT_Node_delete(ref->node);
  603. delete ref;
  604. ref = NULL;
  605. }
  606. else
  607. {
  608. LOGE("Attempted to delete a node that doesn't exist!");
  609. }
  610. }
  611. /*
  612. * Class: com_zerotier_sdk_Node
  613. * Method: processVirtualNetworkFrame
  614. * Signature: (JJJJJII[B[J)Lcom/zerotier/sdk/ResultCode;
  615. */
  616. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame(
  617. JNIEnv *env, jobject obj,
  618. jlong id,
  619. jlong in_now,
  620. jlong in_nwid,
  621. jlong in_sourceMac,
  622. jlong in_destMac,
  623. jint in_etherType,
  624. jint in_vlanId,
  625. jbyteArray in_frameData,
  626. jlongArray out_nextBackgroundTaskDeadline)
  627. {
  628. int64_t nodeId = (int64_t) id;
  629. ZT_Node *node = findNode(nodeId);
  630. if(node == NULL)
  631. {
  632. // cannot find valid node. We should never get here.
  633. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  634. }
  635. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  636. if(nbtd_len < 1)
  637. {
  638. // array for next background task length has 0 elements!
  639. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  640. }
  641. int64_t now = (int64_t)in_now;
  642. uint64_t nwid = (uint64_t)in_nwid;
  643. uint64_t sourceMac = (uint64_t)in_sourceMac;
  644. uint64_t destMac = (uint64_t)in_destMac;
  645. unsigned int etherType = (unsigned int)in_etherType;
  646. unsigned int vlanId = (unsigned int)in_vlanId;
  647. unsigned int frameLength = env->GetArrayLength(in_frameData);
  648. void *frameData = env->GetPrimitiveArrayCritical(in_frameData, NULL);
  649. void *localData = malloc(frameLength);
  650. memcpy(localData, frameData, frameLength);
  651. env->ReleasePrimitiveArrayCritical(in_frameData, frameData, 0);
  652. int64_t nextBackgroundTaskDeadline = 0;
  653. ZT_ResultCode rc = ZT_Node_processVirtualNetworkFrame(
  654. node,
  655. NULL,
  656. now,
  657. nwid,
  658. sourceMac,
  659. destMac,
  660. etherType,
  661. vlanId,
  662. (const void*)localData,
  663. frameLength,
  664. &nextBackgroundTaskDeadline);
  665. free(localData);
  666. jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL);
  667. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  668. env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0);
  669. return createResultObject(env, rc);
  670. }
  671. /*
  672. * Class: com_zerotier_sdk_Node
  673. * Method: processWirePacket
  674. * Signature: (JJJLjava/net/InetSocketAddress;[B[J)Lcom/zerotier/sdk/ResultCode;
  675. */
  676. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket(
  677. JNIEnv *env, jobject obj,
  678. jlong id,
  679. jlong in_now,
  680. jlong in_localSocket,
  681. jobject in_remoteAddress,
  682. jbyteArray in_packetData,
  683. jlongArray out_nextBackgroundTaskDeadline)
  684. {
  685. int64_t nodeId = (int64_t) id;
  686. ZT_Node *node = findNode(nodeId);
  687. if(node == NULL)
  688. {
  689. // cannot find valid node. We should never get here.
  690. LOGE("Couldn't find a valid node!");
  691. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  692. }
  693. unsigned int nbtd_len = (unsigned int)env->GetArrayLength(out_nextBackgroundTaskDeadline);
  694. if(nbtd_len < 1)
  695. {
  696. LOGE("nbtd_len < 1");
  697. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  698. }
  699. int64_t now = (int64_t)in_now;
  700. jobject remoteAddrObject = env->CallObjectMethod(in_remoteAddress, InetSocketAddress_getAddress_method);
  701. if(remoteAddrObject == NULL)
  702. {
  703. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  704. }
  705. // call InetSocketAddress.getPort()
  706. int remotePort = env->CallIntMethod(in_remoteAddress, InetSocketAddress_getPort_method);
  707. if(env->ExceptionCheck())
  708. {
  709. LOGE("Exception calling InetSocketAddress.getPort()");
  710. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  711. }
  712. // Call InetAddress.getAddress()
  713. jbyteArray remoteAddressArray = (jbyteArray)env->CallObjectMethod(remoteAddrObject, InetAddress_getAddress_method);
  714. if(remoteAddressArray == NULL)
  715. {
  716. LOGE("Unable to call getAddress()");
  717. // unable to call getAddress()
  718. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  719. }
  720. unsigned int addrSize = env->GetArrayLength(remoteAddressArray);
  721. // get the address bytes
  722. jbyte *addr = (jbyte*)env->GetPrimitiveArrayCritical(remoteAddressArray, NULL);
  723. sockaddr_storage remoteAddress = {};
  724. if(addrSize == 16)
  725. {
  726. // IPV6 address
  727. sockaddr_in6 ipv6 = {};
  728. ipv6.sin6_family = AF_INET6;
  729. ipv6.sin6_port = htons(remotePort);
  730. memcpy(ipv6.sin6_addr.s6_addr, addr, 16);
  731. memcpy(&remoteAddress, &ipv6, sizeof(sockaddr_in6));
  732. }
  733. else if(addrSize == 4)
  734. {
  735. // IPV4 address
  736. sockaddr_in ipv4 = {};
  737. ipv4.sin_family = AF_INET;
  738. ipv4.sin_port = htons(remotePort);
  739. memcpy(&ipv4.sin_addr, addr, 4);
  740. memcpy(&remoteAddress, &ipv4, sizeof(sockaddr_in));
  741. }
  742. else
  743. {
  744. LOGE("Unknown IP version");
  745. // unknown address type
  746. env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0);
  747. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  748. }
  749. env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0);
  750. unsigned int packetLength = (unsigned int)env->GetArrayLength(in_packetData);
  751. if(packetLength == 0)
  752. {
  753. LOGE("Empty packet?!?");
  754. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  755. }
  756. void *packetData = env->GetPrimitiveArrayCritical(in_packetData, NULL);
  757. void *localData = malloc(packetLength);
  758. memcpy(localData, packetData, packetLength);
  759. env->ReleasePrimitiveArrayCritical(in_packetData, packetData, 0);
  760. int64_t nextBackgroundTaskDeadline = 0;
  761. ZT_ResultCode rc = ZT_Node_processWirePacket(
  762. node,
  763. NULL,
  764. now,
  765. in_localSocket,
  766. &remoteAddress,
  767. localData,
  768. packetLength,
  769. &nextBackgroundTaskDeadline);
  770. if(rc != ZT_RESULT_OK)
  771. {
  772. LOGE("ZT_Node_processWirePacket returned: %d", rc);
  773. }
  774. free(localData);
  775. jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL);
  776. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  777. env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0);
  778. return createResultObject(env, rc);
  779. }
  780. /*
  781. * Class: com_zerotier_sdk_Node
  782. * Method: processBackgroundTasks
  783. * Signature: (JJ[J)Lcom/zerotier/sdk/ResultCode;
  784. */
  785. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processBackgroundTasks(
  786. JNIEnv *env, jobject obj,
  787. jlong id,
  788. jlong in_now,
  789. jlongArray out_nextBackgroundTaskDeadline)
  790. {
  791. int64_t nodeId = (int64_t) id;
  792. ZT_Node *node = findNode(nodeId);
  793. if(node == NULL)
  794. {
  795. // cannot find valid node. We should never get here.
  796. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  797. }
  798. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  799. if(nbtd_len < 1)
  800. {
  801. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  802. }
  803. int64_t now = (int64_t)in_now;
  804. int64_t nextBackgroundTaskDeadline = 0;
  805. ZT_ResultCode rc = ZT_Node_processBackgroundTasks(node, NULL, now, &nextBackgroundTaskDeadline);
  806. jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL);
  807. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  808. env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0);
  809. return createResultObject(env, rc);
  810. }
  811. /*
  812. * Class: com_zerotier_sdk_Node
  813. * Method: join
  814. * Signature: (JJ)Lcom/zerotier/sdk/ResultCode;
  815. */
  816. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_join(
  817. JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  818. {
  819. int64_t nodeId = (int64_t) id;
  820. ZT_Node *node = findNode(nodeId);
  821. if(node == NULL)
  822. {
  823. // cannot find valid node. We should never get here.
  824. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  825. }
  826. uint64_t nwid = (uint64_t)in_nwid;
  827. ZT_ResultCode rc = ZT_Node_join(node, nwid, NULL, NULL);
  828. return createResultObject(env, rc);
  829. }
  830. /*
  831. * Class: com_zerotier_sdk_Node
  832. * Method: leave
  833. * Signature: (JJ)Lcom/zerotier/sdk/ResultCode;
  834. */
  835. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_leave(
  836. JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  837. {
  838. int64_t nodeId = (int64_t) id;
  839. ZT_Node *node = findNode(nodeId);
  840. if(node == NULL)
  841. {
  842. // cannot find valid node. We should never get here.
  843. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  844. }
  845. uint64_t nwid = (uint64_t)in_nwid;
  846. ZT_ResultCode rc = ZT_Node_leave(node, nwid, NULL, NULL);
  847. return createResultObject(env, rc);
  848. }
  849. /*
  850. * Class: com_zerotier_sdk_Node
  851. * Method: multicastSubscribe
  852. * Signature: (JJJJ)Lcom/zerotier/sdk/ResultCode;
  853. */
  854. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastSubscribe(
  855. JNIEnv *env, jobject obj,
  856. jlong id,
  857. jlong in_nwid,
  858. jlong in_multicastGroup,
  859. jlong in_multicastAdi)
  860. {
  861. int64_t nodeId = (int64_t) id;
  862. ZT_Node *node = findNode(nodeId);
  863. if(node == NULL)
  864. {
  865. // cannot find valid node. We should never get here.
  866. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  867. }
  868. uint64_t nwid = (uint64_t)in_nwid;
  869. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  870. unsigned long multicastAdi = (unsigned long)in_multicastAdi;
  871. ZT_ResultCode rc = ZT_Node_multicastSubscribe(
  872. node, NULL, nwid, multicastGroup, multicastAdi);
  873. return createResultObject(env, rc);
  874. }
  875. /*
  876. * Class: com_zerotier_sdk_Node
  877. * Method: multicastUnsubscribe
  878. * Signature: (JJJJ)Lcom/zerotier/sdk/ResultCode;
  879. */
  880. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastUnsubscribe(
  881. JNIEnv *env, jobject obj,
  882. jlong id,
  883. jlong in_nwid,
  884. jlong in_multicastGroup,
  885. jlong in_multicastAdi)
  886. {
  887. int64_t nodeId = (int64_t) id;
  888. ZT_Node *node = findNode(nodeId);
  889. if(node == NULL)
  890. {
  891. // cannot find valid node. We should never get here.
  892. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  893. }
  894. uint64_t nwid = (uint64_t)in_nwid;
  895. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  896. unsigned long multicastAdi = (unsigned long)in_multicastAdi;
  897. ZT_ResultCode rc = ZT_Node_multicastUnsubscribe(
  898. node, nwid, multicastGroup, multicastAdi);
  899. return createResultObject(env, rc);
  900. }
  901. /*
  902. * Class: com_zerotier_sdk_Node
  903. * Method: orbit
  904. * Signature: (JJJ)Lcom/zerotier/sdk/ResultCode;
  905. */
  906. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_orbit(
  907. JNIEnv *env, jobject obj,
  908. jlong id,
  909. jlong in_moonWorldId,
  910. jlong in_moonSeed)
  911. {
  912. int64_t nodeId = (int64_t)id;
  913. ZT_Node *node = findNode(nodeId);
  914. if(node == NULL)
  915. {
  916. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  917. }
  918. uint64_t moonWorldId = (uint64_t)in_moonWorldId;
  919. uint64_t moonSeed = (uint64_t)in_moonSeed;
  920. ZT_ResultCode rc = ZT_Node_orbit(node, NULL, moonWorldId, moonSeed);
  921. return createResultObject(env, rc);
  922. }
  923. /*
  924. * Class: com_zerotier_sdk_Node
  925. * Method: deorbit
  926. * Signature: (JJ)L/com/zerotier/sdk/ResultCode;
  927. */
  928. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_deorbit(
  929. JNIEnv *env, jobject obj,
  930. jlong id,
  931. jlong in_moonWorldId)
  932. {
  933. int64_t nodeId = (int64_t)id;
  934. ZT_Node *node = findNode(nodeId);
  935. if(node == NULL)
  936. {
  937. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  938. }
  939. uint64_t moonWorldId = (uint64_t)in_moonWorldId;
  940. ZT_ResultCode rc = ZT_Node_deorbit(node, NULL, moonWorldId);
  941. return createResultObject(env, rc);
  942. }
  943. /*
  944. * Class: com_zerotier_sdk_Node
  945. * Method: address
  946. * Signature: (J)J
  947. */
  948. JNIEXPORT jlong JNICALL Java_com_zerotier_sdk_Node_address(
  949. JNIEnv *env , jobject obj, jlong id)
  950. {
  951. int64_t nodeId = (int64_t) id;
  952. ZT_Node *node = findNode(nodeId);
  953. if(node == NULL)
  954. {
  955. // cannot find valid node. We should never get here.
  956. return 0;
  957. }
  958. uint64_t address = ZT_Node_address(node);
  959. return (jlong)address;
  960. }
  961. /*
  962. * Class: com_zerotier_sdk_Node
  963. * Method: status
  964. * Signature: (J)Lcom/zerotier/sdk/NodeStatus;
  965. */
  966. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_status
  967. (JNIEnv *env, jobject obj, jlong id)
  968. {
  969. int64_t nodeId = (int64_t) id;
  970. ZT_Node *node = findNode(nodeId);
  971. if(node == NULL)
  972. {
  973. // cannot find valid node. We should never get here.
  974. return 0;
  975. }
  976. // create a com.zerotier.sdk.NodeStatus object
  977. jobject nodeStatusObj = env->NewObject(NodeStatus_class, NodeStatus_ctor);
  978. if(nodeStatusObj == NULL)
  979. {
  980. return NULL;
  981. }
  982. ZT_NodeStatus nodeStatus;
  983. ZT_Node_status(node, &nodeStatus);
  984. env->SetLongField(nodeStatusObj, NodeStatus_address_field, nodeStatus.address);
  985. jstring pubIdentStr = env->NewStringUTF(nodeStatus.publicIdentity);
  986. if(pubIdentStr == NULL)
  987. {
  988. return NULL; // out of memory
  989. }
  990. env->SetObjectField(nodeStatusObj, NodeStatus_publicIdentity_field, pubIdentStr);
  991. jstring secIdentStr = env->NewStringUTF(nodeStatus.secretIdentity);
  992. if(secIdentStr == NULL)
  993. {
  994. return NULL; // out of memory
  995. }
  996. env->SetObjectField(nodeStatusObj, NodeStatus_secretIdentity_field, secIdentStr);
  997. env->SetBooleanField(nodeStatusObj, NodeStatus_online_field, nodeStatus.online);
  998. return nodeStatusObj;
  999. }
  1000. /*
  1001. * Class: com_zerotier_sdk_Node
  1002. * Method: networkConfig
  1003. * Signature: (JJ)Lcom/zerotier/sdk/VirtualNetworkConfig;
  1004. */
  1005. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_networkConfig(
  1006. JNIEnv *env, jobject obj, jlong id, jlong nwid)
  1007. {
  1008. int64_t nodeId = (int64_t) id;
  1009. ZT_Node *node = findNode(nodeId);
  1010. if(node == NULL)
  1011. {
  1012. // cannot find valid node. We should never get here.
  1013. return 0;
  1014. }
  1015. ZT_VirtualNetworkConfig *vnetConfig = ZT_Node_networkConfig(node, nwid);
  1016. jobject vnetConfigObject = newNetworkConfig(env, *vnetConfig);
  1017. ZT_Node_freeQueryResult(node, vnetConfig);
  1018. return vnetConfigObject;
  1019. }
  1020. /*
  1021. * Class: com_zerotier_sdk_Node
  1022. * Method: version
  1023. * Signature: ()Lcom/zerotier/sdk/Version;
  1024. */
  1025. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_version(
  1026. JNIEnv *env, jobject obj)
  1027. {
  1028. int major = 0;
  1029. int minor = 0;
  1030. int revision = 0;
  1031. ZT_version(&major, &minor, &revision);
  1032. return newVersion(env, major, minor, revision);
  1033. }
  1034. /*
  1035. * Class: com_zerotier_sdk_Node
  1036. * Method: peers
  1037. * Signature: (J)[Lcom/zerotier/sdk/Peer;
  1038. */
  1039. JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers(
  1040. JNIEnv *env, jobject obj, jlong id)
  1041. {
  1042. int64_t nodeId = (int64_t) id;
  1043. ZT_Node *node = findNode(nodeId);
  1044. if(node == NULL)
  1045. {
  1046. // cannot find valid node. We should never get here.
  1047. return 0;
  1048. }
  1049. ZT_PeerList *peerList = ZT_Node_peers(node);
  1050. if(peerList == NULL)
  1051. {
  1052. LOGE("ZT_Node_peers returned NULL");
  1053. return NULL;
  1054. }
  1055. jobjectArray peerArrayObj = env->NewObjectArray(
  1056. peerList->peerCount, Peer_class, NULL);
  1057. if(env->ExceptionCheck() || peerArrayObj == NULL)
  1058. {
  1059. LOGE("Error creating Peer[] array");
  1060. ZT_Node_freeQueryResult(node, peerList);
  1061. return NULL;
  1062. }
  1063. for(unsigned int i = 0; i < peerList->peerCount; ++i)
  1064. {
  1065. jobject peerObj = newPeer(env, peerList->peers[i]);
  1066. env->SetObjectArrayElement(peerArrayObj, i, peerObj);
  1067. if(env->ExceptionCheck())
  1068. {
  1069. LOGE("Error assigning Peer object to array");
  1070. break;
  1071. }
  1072. env->DeleteLocalRef(peerObj);
  1073. }
  1074. ZT_Node_freeQueryResult(node, peerList);
  1075. peerList = NULL;
  1076. return peerArrayObj;
  1077. }
  1078. /*
  1079. * Class: com_zerotier_sdk_Node
  1080. * Method: networks
  1081. * Signature: (J)[Lcom/zerotier/sdk/VirtualNetworkConfig;
  1082. */
  1083. JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_networks(
  1084. JNIEnv *env, jobject obj, jlong id)
  1085. {
  1086. int64_t nodeId = (int64_t) id;
  1087. ZT_Node *node = findNode(nodeId);
  1088. if(node == NULL)
  1089. {
  1090. // cannot find valid node. We should never get here.
  1091. return 0;
  1092. }
  1093. ZT_VirtualNetworkList *networkList = ZT_Node_networks(node);
  1094. if(networkList == NULL)
  1095. {
  1096. return NULL;
  1097. }
  1098. jobjectArray networkListObject = env->NewObjectArray(
  1099. networkList->networkCount, VirtualNetworkConfig_class, NULL);
  1100. if(env->ExceptionCheck() || networkListObject == NULL)
  1101. {
  1102. LOGE("Error creating VirtualNetworkConfig[] array");
  1103. ZT_Node_freeQueryResult(node, networkList);
  1104. return NULL;
  1105. }
  1106. for(unsigned int i = 0; i < networkList->networkCount; ++i)
  1107. {
  1108. jobject networkObject = newNetworkConfig(env, networkList->networks[i]);
  1109. env->SetObjectArrayElement(networkListObject, i, networkObject);
  1110. if(env->ExceptionCheck())
  1111. {
  1112. LOGE("Error assigning VirtualNetworkConfig object to array");
  1113. break;
  1114. }
  1115. env->DeleteLocalRef(networkObject);
  1116. }
  1117. ZT_Node_freeQueryResult(node, networkList);
  1118. return networkListObject;
  1119. }
  1120. #ifdef __cplusplus
  1121. } // extern "C"
  1122. #endif