com_zerotierone_sdk_Node.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382
  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. #include <cinttypes> // for PRId64
  37. #define LOG_TAG "Node"
  38. namespace {
  39. struct JniRef
  40. {
  41. JniRef(
  42. int64_t id,
  43. JavaVM *jvm,
  44. jobject dataStoreGetListenerLocalIn,
  45. jobject dataStorePutListenerLocalIn,
  46. jobject packetSenderLocalIn,
  47. jobject eventListenerLocalIn,
  48. jobject frameListenerLocalIn,
  49. jobject configListenerLocalIn,
  50. jobject pathCheckerLocalIn)
  51. : id(id)
  52. , jvm(jvm)
  53. , node()
  54. , dataStoreGetListener()
  55. , dataStorePutListener()
  56. , packetSender()
  57. , eventListener()
  58. , frameListener()
  59. , configListener()
  60. , pathChecker()
  61. , inited() {
  62. JNIEnv *env;
  63. GETENV(env, jvm);
  64. dataStoreGetListener = env->NewGlobalRef(dataStoreGetListenerLocalIn);
  65. dataStorePutListener = env->NewGlobalRef(dataStorePutListenerLocalIn);
  66. packetSender = env->NewGlobalRef(packetSenderLocalIn);
  67. eventListener = env->NewGlobalRef(eventListenerLocalIn);
  68. frameListener = env->NewGlobalRef(frameListenerLocalIn);
  69. configListener = env->NewGlobalRef(configListenerLocalIn);
  70. pathChecker = env->NewGlobalRef(pathCheckerLocalIn);
  71. };
  72. ~JniRef()
  73. {
  74. JNIEnv *env;
  75. GETENV(env, jvm);
  76. env->DeleteGlobalRef(dataStoreGetListener);
  77. env->DeleteGlobalRef(dataStorePutListener);
  78. env->DeleteGlobalRef(packetSender);
  79. env->DeleteGlobalRef(eventListener);
  80. env->DeleteGlobalRef(frameListener);
  81. env->DeleteGlobalRef(configListener);
  82. env->DeleteGlobalRef(pathChecker);
  83. }
  84. int64_t id;
  85. JavaVM *jvm;
  86. ZT_Node *node;
  87. jobject dataStoreGetListener;
  88. jobject dataStorePutListener;
  89. jobject packetSender;
  90. jobject eventListener;
  91. jobject frameListener;
  92. jobject configListener;
  93. jobject pathChecker;
  94. bool inited;
  95. bool finishInitializing();
  96. };
  97. /*
  98. * This must return 0 on success. It can return any OS-dependent error code
  99. * on failure, and this results in the network being placed into the
  100. * PORT_ERROR state.
  101. */
  102. int VirtualNetworkConfigFunctionCallback(
  103. ZT_Node *node,
  104. void *userData,
  105. void *threadData,
  106. uint64_t nwid,
  107. void **nuptr,
  108. enum ZT_VirtualNetworkConfigOperation operation,
  109. const ZT_VirtualNetworkConfig *config)
  110. {
  111. LOGV("VirtualNetworkConfigFunctionCallback");
  112. JniRef *ref = (JniRef*)userData;
  113. assert(ref);
  114. JNIEnv *env;
  115. GETENV(env, ref->jvm);
  116. if (env->ExceptionCheck()) {
  117. LOGE("Unhandled pending exception");
  118. return -100;
  119. }
  120. if (ref->configListener == NULL) {
  121. LOGE("configListener is NULL");
  122. return -101;
  123. }
  124. jobject operationObject = createVirtualNetworkConfigOperation(env, operation);
  125. if(env->ExceptionCheck() || operationObject == NULL)
  126. {
  127. return -102;
  128. }
  129. if (config == NULL) {
  130. LOGE("Config is NULL");
  131. return -103;
  132. }
  133. jobject networkConfigObject = newNetworkConfig(env, *config);
  134. if(env->ExceptionCheck() || networkConfigObject == NULL)
  135. {
  136. return -104;
  137. }
  138. jint ret = env->CallIntMethod(
  139. ref->configListener,
  140. VirtualNetworkConfigListener_onNetworkConfigurationUpdated_method,
  141. (jlong)nwid, (jobject)operationObject, (jobject)networkConfigObject);
  142. if (env->ExceptionCheck()) {
  143. LOGE("Exception calling onNetworkConfigurationUpdated");
  144. return -105;
  145. }
  146. return ret;
  147. }
  148. void VirtualNetworkFrameFunctionCallback(ZT_Node *node,
  149. void *userData,
  150. void *threadData,
  151. uint64_t nwid,
  152. void** nuptr,
  153. uint64_t sourceMac,
  154. uint64_t destMac,
  155. unsigned int etherType,
  156. unsigned int vlanid,
  157. const void *frameData,
  158. unsigned int frameLength)
  159. {
  160. LOGV("VirtualNetworkFrameFunctionCallback");
  161. #ifndef NDEBUG
  162. if (frameLength >= 14) {
  163. unsigned char* local = (unsigned char*)frameData;
  164. LOGV("Type Bytes: 0x%02x%02x", local[12], local[13]);
  165. }
  166. #endif
  167. JniRef *ref = (JniRef*)userData;
  168. assert(ref);
  169. assert(ref->node == node);
  170. JNIEnv *env;
  171. jint getEnvRet;
  172. assert(ref->jvm);
  173. if ((getEnvRet = ref->jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)) != JNI_OK) {
  174. LOGE("Error calling GetEnv: %d", getEnvRet);
  175. assert(false && "Error calling GetEnv");
  176. }
  177. if (env->ExceptionCheck()) {
  178. LOGE("Unhandled pending exception");
  179. return;
  180. }
  181. if (ref->frameListener == NULL) {
  182. LOGE("frameListener is NULL");
  183. return;
  184. }
  185. const unsigned char *bytes = static_cast<const unsigned char*>(frameData);
  186. jbyteArray dataArray = newByteArray(env, bytes, frameLength);
  187. if(env->ExceptionCheck() || dataArray == NULL)
  188. {
  189. return;
  190. }
  191. env->CallVoidMethod(ref->frameListener, VirtualNetworkFrameListener_onVirtualNetworkFrame_method, (jlong)nwid, (jlong)sourceMac, (jlong)destMac, (jlong)etherType, (jlong)vlanid, (jbyteArray)dataArray);
  192. if (env->ExceptionCheck()) {
  193. LOGE("Exception calling onVirtualNetworkFrame");
  194. return;
  195. }
  196. }
  197. void EventCallback(ZT_Node *node,
  198. void *userData,
  199. void *threadData,
  200. enum ZT_Event event,
  201. const void *data) {
  202. LOGV("EventCallback");
  203. JniRef *ref = (JniRef *) userData;
  204. assert(ref);
  205. if (ref->node != node && event != ZT_EVENT_UP) {
  206. LOGE("Nodes not equal. ref->node %p, node %p. Event: %d", ref->node, node, event);
  207. return;
  208. }
  209. JNIEnv *env;
  210. GETENV(env, ref->jvm);
  211. if (env->ExceptionCheck()) {
  212. LOGE("Unhandled pending exception");
  213. return;
  214. }
  215. if (ref->eventListener == NULL) {
  216. LOGE("eventListener is NULL");
  217. return;
  218. }
  219. jobject eventObject = createEvent(env, event);
  220. if (env->ExceptionCheck() || eventObject == NULL) {
  221. return;
  222. }
  223. switch (event) {
  224. case ZT_EVENT_UP: {
  225. LOGD("Event Up");
  226. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, (jobject)eventObject);
  227. if (env->ExceptionCheck()) {
  228. LOGE("Exception calling onEvent");
  229. return;
  230. }
  231. break;
  232. }
  233. case ZT_EVENT_OFFLINE: {
  234. LOGD("Event Offline");
  235. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, (jobject)eventObject);
  236. if (env->ExceptionCheck()) {
  237. LOGE("Exception calling onEvent");
  238. return;
  239. }
  240. break;
  241. }
  242. case ZT_EVENT_ONLINE: {
  243. LOGD("Event Online");
  244. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, (jobject)eventObject);
  245. if (env->ExceptionCheck()) {
  246. LOGE("Exception calling onEvent");
  247. return;
  248. }
  249. break;
  250. }
  251. case ZT_EVENT_DOWN: {
  252. LOGD("Event Down");
  253. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, (jobject)eventObject);
  254. if (env->ExceptionCheck()) {
  255. LOGE("Exception calling onEvent");
  256. return;
  257. }
  258. break;
  259. }
  260. case ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION: {
  261. LOGV("Identity Collision");
  262. // call onEvent()
  263. env->CallVoidMethod(ref->eventListener, EventListener_onEvent_method, (jobject)eventObject);
  264. if (env->ExceptionCheck()) {
  265. LOGE("Exception calling onEvent");
  266. return;
  267. }
  268. }
  269. break;
  270. case ZT_EVENT_TRACE: {
  271. LOGV("Trace Event");
  272. // call onTrace()
  273. if (data == NULL) {
  274. break;
  275. }
  276. const char *message = (const char *) data;
  277. jstring messageStr = env->NewStringUTF(message);
  278. if (env->ExceptionCheck() || messageStr == NULL) {
  279. LOGE("Exception creating new string");
  280. return;
  281. }
  282. env->CallVoidMethod(ref->eventListener, EventListener_onTrace_method, (jstring)messageStr);
  283. if (env->ExceptionCheck()) {
  284. LOGE("Exception calling onTrace");
  285. return;
  286. }
  287. }
  288. break;
  289. case ZT_EVENT_USER_MESSAGE:
  290. case ZT_EVENT_REMOTE_TRACE:
  291. break;
  292. }
  293. }
  294. void StatePutFunction(
  295. ZT_Node *node,
  296. void *userData,
  297. void *threadData,
  298. enum ZT_StateObjectType type,
  299. const uint64_t id[2],
  300. const void *buffer,
  301. int bufferLength) {
  302. LOGV("StatePutFunction");
  303. char p[4096] = {0};
  304. bool secure = false;
  305. int res = 0;
  306. switch (type) {
  307. case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
  308. res = snprintf(p, sizeof(p), "identity.public");
  309. break;
  310. case ZT_STATE_OBJECT_IDENTITY_SECRET:
  311. res = snprintf(p, sizeof(p), "identity.secret");
  312. secure = true;
  313. break;
  314. case ZT_STATE_OBJECT_PLANET:
  315. res = snprintf(p, sizeof(p), "planet");
  316. break;
  317. case ZT_STATE_OBJECT_MOON:
  318. res = snprintf(p, sizeof(p), "moons.d/%.16" PRIx64 ".moon", id[0]);
  319. break;
  320. case ZT_STATE_OBJECT_NETWORK_CONFIG:
  321. res = snprintf(p, sizeof(p), "networks.d/%.16" PRIx64 ".conf", id[0]);
  322. break;
  323. case ZT_STATE_OBJECT_PEER:
  324. res = snprintf(p, sizeof(p), "peers.d/%.10" PRIx64, id[0]);
  325. break;
  326. case ZT_STATE_OBJECT_NULL:
  327. return;
  328. }
  329. if (!(0 <= res && res < sizeof(p))) {
  330. LOGE("snprintf error: %d", res);
  331. return;
  332. }
  333. JniRef *ref = (JniRef*)userData;
  334. assert(ref);
  335. JNIEnv *env;
  336. GETENV(env, ref->jvm);
  337. if (env->ExceptionCheck()) {
  338. LOGE("Unhandled pending exception");
  339. return;
  340. }
  341. if (ref->dataStorePutListener == NULL) {
  342. LOGE("dataStorePutListener is NULL");
  343. return;
  344. }
  345. jstring nameStr = env->NewStringUTF(p);
  346. if (env->ExceptionCheck() || nameStr == NULL) {
  347. LOGE("Exception creating new string");
  348. return;
  349. }
  350. if (bufferLength >= 0) {
  351. LOGD("JNI: Write file: %s", p);
  352. const unsigned char *bytes = static_cast<const unsigned char *>(buffer);
  353. jbyteArray bufferObj = newByteArray(env, bytes, bufferLength);
  354. if(env->ExceptionCheck() || bufferObj == NULL)
  355. {
  356. return;
  357. }
  358. int retval = env->CallIntMethod(ref->dataStorePutListener,
  359. DataStorePutListener_onDataStorePut_method,
  360. (jstring)nameStr, (jbyteArray)bufferObj, (jboolean)secure);
  361. if (env->ExceptionCheck()) {
  362. LOGE("Exception calling onDataStorePut");
  363. return;
  364. }
  365. if (retval != 0) {
  366. LOGE("onDataStorePut error: %d", retval);
  367. }
  368. } else {
  369. LOGD("JNI: Delete file: %s", p);
  370. int retval = env->CallIntMethod(ref->dataStorePutListener, DataStorePutListener_onDelete_method, (jstring)nameStr);
  371. if (env->ExceptionCheck()) {
  372. LOGE("Exception calling onDelete");
  373. return;
  374. }
  375. if (retval != 0) {
  376. LOGE("onDelete error: %d", retval);
  377. }
  378. }
  379. }
  380. /**
  381. * This function should return the number of bytes actually stored to the
  382. * buffer or -1 if the state object was not found or the buffer was too
  383. * small to store it.
  384. */
  385. int StateGetFunction(
  386. ZT_Node *node,
  387. void *userData,
  388. void *threadData,
  389. ZT_StateObjectType type,
  390. const uint64_t id[2],
  391. void *buffer,
  392. unsigned int bufferLength) {
  393. LOGV("StateGetFunction");
  394. char p[4096] = {0};
  395. int res = 0;
  396. switch (type) {
  397. case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
  398. res = snprintf(p, sizeof(p), "identity.public");
  399. break;
  400. case ZT_STATE_OBJECT_IDENTITY_SECRET:
  401. res = snprintf(p, sizeof(p), "identity.secret");
  402. break;
  403. case ZT_STATE_OBJECT_PLANET:
  404. res = snprintf(p, sizeof(p), "planet");
  405. break;
  406. case ZT_STATE_OBJECT_MOON:
  407. res = snprintf(p, sizeof(p), "moons.d/%.16" PRIx64 ".moon", id[0]);
  408. break;
  409. case ZT_STATE_OBJECT_NETWORK_CONFIG:
  410. res = snprintf(p, sizeof(p), "networks.d/%.16" PRIx64 ".conf", id[0]);
  411. break;
  412. case ZT_STATE_OBJECT_PEER:
  413. res = snprintf(p, sizeof(p), "peers.d/%.10" PRIx64, id[0]);
  414. break;
  415. case ZT_STATE_OBJECT_NULL:
  416. return -100;
  417. }
  418. if (!(0 <= res && res < sizeof(p))) {
  419. LOGE("snprintf error: %d", res);
  420. return -101;
  421. }
  422. JniRef *ref = (JniRef*)userData;
  423. assert(ref);
  424. JNIEnv *env;
  425. GETENV(env, ref->jvm);
  426. if (env->ExceptionCheck()) {
  427. LOGE("Unhandled pending exception");
  428. return -102;
  429. }
  430. if (ref->dataStoreGetListener == NULL) {
  431. LOGE("dataStoreGetListener is NULL");
  432. return -103;
  433. }
  434. jstring nameStr = env->NewStringUTF(p);
  435. if(env->ExceptionCheck() || nameStr == NULL)
  436. {
  437. LOGE("Error creating name string object");
  438. return -104; // out of memory
  439. }
  440. jbyteArray bufferObj = newByteArray(env, bufferLength);
  441. if(env->ExceptionCheck() || bufferObj == NULL)
  442. {
  443. return -105;
  444. }
  445. LOGV("Calling onDataStoreGet(%s, %p)", p, buffer);
  446. int retval = (int)env->CallLongMethod(
  447. ref->dataStoreGetListener,
  448. DataStoreGetListener_onDataStoreGet_method,
  449. (jstring)nameStr,
  450. (jbyteArray)bufferObj);
  451. if (env->ExceptionCheck()) {
  452. LOGE("Exception calling onDataStoreGet");
  453. return -106;
  454. }
  455. LOGV("onDataStoreGet returned %d", retval);
  456. if(retval > 0)
  457. {
  458. if (retval > bufferLength) {
  459. LOGE("retval > bufferLength. retval: %d, bufferLength: %u", retval, bufferLength);
  460. return -107;
  461. }
  462. void *data = env->GetPrimitiveArrayCritical(bufferObj, NULL);
  463. memcpy(buffer, data, retval);
  464. env->ReleasePrimitiveArrayCritical(bufferObj, data, 0);
  465. }
  466. return retval;
  467. }
  468. /**
  469. * The function must return zero on success and may return any error code
  470. * on failure. Note that success does not (of course) guarantee packet
  471. * delivery. It only means that the packet appears to have been sent.
  472. */
  473. int WirePacketSendFunction(ZT_Node *node,
  474. void *userData,
  475. void *threadData,
  476. int64_t localSocket,
  477. const struct sockaddr_storage *remoteAddress,
  478. const void *buffer,
  479. unsigned int bufferSize,
  480. unsigned int ttl)
  481. {
  482. LOGV("WirePacketSendFunction(%" PRId64 ", %p, %p, %u, %u)", localSocket, remoteAddress, buffer, bufferSize, ttl);
  483. JniRef *ref = (JniRef*)userData;
  484. assert(ref);
  485. assert(ref->node == node);
  486. JNIEnv *env;
  487. GETENV(env, ref->jvm);
  488. if (env->ExceptionCheck()) {
  489. LOGE("Unhandled pending exception");
  490. return -100;
  491. }
  492. if (ref->packetSender == NULL) {
  493. LOGE("packetSender is NULL");
  494. return -101;
  495. }
  496. //
  497. // may be NULL
  498. //
  499. jobject remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
  500. if (env->ExceptionCheck()) {
  501. return -102;
  502. }
  503. const unsigned char *bytes = static_cast<const unsigned char *>(buffer);
  504. jbyteArray bufferObj = newByteArray(env, bytes, bufferSize);
  505. if (env->ExceptionCheck() || bufferObj == NULL)
  506. {
  507. return -103;
  508. }
  509. int retval = env->CallIntMethod(ref->packetSender, PacketSender_onSendPacketRequested_method, (jlong)localSocket, (jobject)remoteAddressObj, (jbyteArray)bufferObj, (jint)0);
  510. if (env->ExceptionCheck()) {
  511. LOGE("Exception calling onSendPacketRequested");
  512. return -104;
  513. }
  514. LOGV("JNI Packet Sender returned: %d", retval);
  515. return retval;
  516. }
  517. /**
  518. * This function must return nonzero (true) if the path should be used.
  519. */
  520. int PathCheckFunction(ZT_Node *node,
  521. void *userPtr,
  522. void *threadPtr,
  523. uint64_t address,
  524. int64_t localSocket,
  525. const struct sockaddr_storage *remoteAddress)
  526. {
  527. LOGV("PathCheckFunction");
  528. JniRef *ref = (JniRef*)userPtr;
  529. assert(ref);
  530. assert(ref->node == node);
  531. if(ref->pathChecker == NULL) {
  532. return true;
  533. }
  534. JNIEnv *env;
  535. GETENV(env, ref->jvm);
  536. if (env->ExceptionCheck()) {
  537. LOGE("Unhandled pending exception");
  538. return true;
  539. }
  540. //
  541. // may be NULL
  542. //
  543. jobject remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
  544. if (env->ExceptionCheck()) {
  545. return true;
  546. }
  547. jboolean ret = env->CallBooleanMethod(ref->pathChecker, PathChecker_onPathCheck_method, (jlong)address, (jlong)localSocket, (jobject)remoteAddressObj);
  548. if (env->ExceptionCheck()) {
  549. LOGE("Exception calling onPathCheck");
  550. return true;
  551. }
  552. return ret;
  553. }
  554. /**
  555. * It must return a nonzero (true) value if the result buffer has been filled with an address.
  556. */
  557. int PathLookupFunction(ZT_Node *node,
  558. void *userPtr,
  559. void *threadPtr,
  560. uint64_t address,
  561. int ss_family,
  562. struct sockaddr_storage *result)
  563. {
  564. LOGV("PathLookupFunction");
  565. JniRef *ref = (JniRef*)userPtr;
  566. assert(ref);
  567. assert(ref->node == node);
  568. if(ref->pathChecker == NULL) {
  569. return false;
  570. }
  571. JNIEnv *env;
  572. GETENV(env, ref->jvm);
  573. if (env->ExceptionCheck()) {
  574. LOGE("Unhandled pending exception");
  575. return false;
  576. }
  577. //
  578. // may be NULL
  579. //
  580. jobject sockAddressObject = env->CallObjectMethod(ref->pathChecker, PathChecker_onPathLookup_method, (jlong)address, (jint)ss_family);
  581. if (env->ExceptionCheck()) {
  582. LOGE("Unable to call onPathLookup implementation");
  583. return false;
  584. }
  585. if(sockAddressObject == NULL)
  586. {
  587. LOGE("Unable to call onPathLookup implementation");
  588. return false;
  589. }
  590. *result = fromSocketAddressObject(env, sockAddressObject);
  591. if (env->ExceptionCheck() || isSocketAddressEmpty(*result)) {
  592. return false;
  593. }
  594. return true;
  595. }
  596. typedef std::map<int64_t, JniRef*> NodeMap;
  597. NodeMap nodeMap;
  598. ZeroTier::Mutex nodeMapMutex;
  599. bool isInited(int64_t nodeId) {
  600. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  601. NodeMap::iterator found = nodeMap.find(nodeId);
  602. if (found == nodeMap.end()) {
  603. //
  604. // not in map yet, or has been removed from map
  605. //
  606. return false;
  607. }
  608. JniRef *ref = found->second;
  609. assert(ref);
  610. return ref->inited;
  611. }
  612. bool JniRef::finishInitializing() {
  613. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  614. NodeMap::iterator found = nodeMap.find(id);
  615. if (found != nodeMap.end()) {
  616. //
  617. // already in map
  618. //
  619. LOGE("Cannot finish initializing; node is already in map");
  620. return false;
  621. }
  622. nodeMap.insert(std::make_pair(id, this));
  623. assert(!inited);
  624. inited = true;
  625. return true;
  626. }
  627. ZT_Node* findNode(int64_t nodeId)
  628. {
  629. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  630. NodeMap::iterator found = nodeMap.find(nodeId);
  631. assert(found != nodeMap.end());
  632. JniRef *ref = found->second;
  633. assert(ref);
  634. return ref->node;
  635. }
  636. JniRef *removeRef(int64_t nodeId) {
  637. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  638. NodeMap::iterator found = nodeMap.find(nodeId);
  639. if (found == nodeMap.end()) {
  640. return nullptr;
  641. }
  642. JniRef *ref = found->second;
  643. assert(ref);
  644. nodeMap.erase(nodeId);
  645. return ref;
  646. }
  647. }
  648. #ifdef __cplusplus
  649. extern "C" {
  650. #endif
  651. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
  652. {
  653. setupJNICache(vm);
  654. return JNI_VERSION_1_6;
  655. }
  656. JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
  657. {
  658. teardownJNICache(vm);
  659. }
  660. /*
  661. * Class: com_zerotier_sdk_Node
  662. * Method: node_init
  663. * Signature: (JLcom/zerotier/sdk/DataStoreGetListener;Lcom/zerotier/sdk/DataStorePutListener;Lcom/zerotier/sdk/PacketSender;Lcom/zerotier/sdk/EventListener;Lcom/zerotier/sdk/VirtualNetworkFrameListener;Lcom/zerotier/sdk/VirtualNetworkConfigListener;Lcom/zerotier/sdk/PathChecker;)Lcom/zerotier/sdk/ResultCode;
  664. */
  665. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init(
  666. JNIEnv *env, jobject obj, jlong now, jobject dataStoreGetListener,
  667. jobject dataStorePutListener, jobject packetSender, jobject eventListener,
  668. jobject frameListener, jobject configListener,
  669. jobject pathChecker)
  670. {
  671. LOGV("Creating ZT_Node struct");
  672. jobject resultObject = ResultCode_RESULT_OK_enum;
  673. JavaVM *vm;
  674. GETJAVAVM(env, vm);
  675. assert(dataStoreGetListener != NULL);
  676. assert(dataStorePutListener != NULL);
  677. assert(packetSender != NULL);
  678. assert(frameListener != NULL);
  679. assert(configListener != NULL);
  680. assert(eventListener != NULL);
  681. //
  682. // OPTIONAL, pathChecker may be NULL
  683. //
  684. // assert(pathChecker != NULL);
  685. ZT_Node_Callbacks callbacks{};
  686. callbacks.stateGetFunction = &StateGetFunction;
  687. callbacks.statePutFunction = &StatePutFunction;
  688. callbacks.wirePacketSendFunction = &WirePacketSendFunction;
  689. callbacks.virtualNetworkFrameFunction = &VirtualNetworkFrameFunctionCallback;
  690. callbacks.virtualNetworkConfigFunction = &VirtualNetworkConfigFunctionCallback;
  691. callbacks.eventCallback = &EventCallback;
  692. callbacks.pathCheckFunction = &PathCheckFunction;
  693. callbacks.pathLookupFunction = &PathLookupFunction;
  694. //
  695. // a bit of a confusing dance here where ref and node both know about each other
  696. //
  697. JniRef *ref = new JniRef(
  698. now,
  699. vm,
  700. dataStoreGetListener,
  701. dataStorePutListener,
  702. packetSender,
  703. eventListener,
  704. frameListener,
  705. configListener,
  706. pathChecker);
  707. ZT_Node *node;
  708. ZT_ResultCode rc = ZT_Node_new(
  709. &node,
  710. ref,
  711. NULL,
  712. &callbacks,
  713. (int64_t)now);
  714. if (env->ExceptionCheck()) {
  715. LOGE("Exception creating Node");
  716. if(node)
  717. {
  718. ZT_Node_delete(node);
  719. node = NULL;
  720. }
  721. delete ref;
  722. ref = NULL;
  723. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  724. }
  725. if(rc != ZT_RESULT_OK)
  726. {
  727. LOGE("Error creating Node: %d", rc);
  728. resultObject = createResultObject(env, rc);
  729. if (env->ExceptionCheck() || resultObject == NULL) {
  730. return NULL;
  731. }
  732. if(node)
  733. {
  734. ZT_Node_delete(node);
  735. node = NULL;
  736. }
  737. delete ref;
  738. ref = NULL;
  739. return resultObject;
  740. }
  741. //
  742. // node is now updated
  743. //
  744. ref->node = node;
  745. if (!ref->finishInitializing()) {
  746. LOGE("finishInitializing() failed");
  747. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  748. }
  749. return resultObject;
  750. }
  751. /*
  752. * Class: com_zerotier_sdk_Node
  753. * Method: node_isInited
  754. * Signature: (J)Z
  755. */
  756. JNIEXPORT jboolean JNICALL Java_com_zerotier_sdk_Node_node_1isInited
  757. (JNIEnv *env, jobject obj, jlong nodeId) {
  758. return isInited(nodeId);
  759. }
  760. /*
  761. * Class: com_zerotier_sdk_Node
  762. * Method: node_delete
  763. * Signature: (J)V
  764. */
  765. JNIEXPORT void JNICALL Java_com_zerotier_sdk_Node_node_1delete(
  766. JNIEnv *env, jobject obj, jlong id)
  767. {
  768. LOGV("Destroying ZT_Node struct");
  769. int64_t nodeId = (int64_t)id;
  770. JniRef *ref = removeRef(nodeId);
  771. if (!ref) {
  772. return;
  773. }
  774. ZT_Node_delete(ref->node);
  775. delete ref;
  776. }
  777. /*
  778. * Class: com_zerotier_sdk_Node
  779. * Method: processVirtualNetworkFrame
  780. * Signature: (JJJJJII[B[J)Lcom/zerotier/sdk/ResultCode;
  781. */
  782. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame(
  783. JNIEnv *env, jobject obj,
  784. jlong id,
  785. jlong in_now,
  786. jlong in_nwid,
  787. jlong in_sourceMac,
  788. jlong in_destMac,
  789. jint in_etherType,
  790. jint in_vlanId,
  791. jbyteArray in_frameData,
  792. jlongArray out_nextBackgroundTaskDeadline)
  793. {
  794. int64_t nodeId = (int64_t) id;
  795. ZT_Node *node = findNode(nodeId);
  796. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  797. if(nbtd_len < 1)
  798. {
  799. // array for next background task length has 0 elements!
  800. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  801. }
  802. int64_t now = (int64_t)in_now;
  803. uint64_t nwid = (uint64_t)in_nwid;
  804. uint64_t sourceMac = (uint64_t)in_sourceMac;
  805. uint64_t destMac = (uint64_t)in_destMac;
  806. unsigned int etherType = (unsigned int)in_etherType;
  807. unsigned int vlanId = (unsigned int)in_vlanId;
  808. unsigned int frameLength = env->GetArrayLength(in_frameData);
  809. void *frameData = env->GetPrimitiveArrayCritical(in_frameData, NULL);
  810. //
  811. // need local copy of frameData because arbitrary code may run in ZT_Node_processVirtualNetworkFrame and no other JNI work may happen between GetPrimitiveArrayCritical / ReleasePrimitiveArrayCritical
  812. //
  813. void *localData = malloc(frameLength);
  814. memcpy(localData, frameData, frameLength);
  815. env->ReleasePrimitiveArrayCritical(in_frameData, frameData, 0);
  816. int64_t nextBackgroundTaskDeadline = 0;
  817. ZT_ResultCode rc = ZT_Node_processVirtualNetworkFrame(
  818. node,
  819. NULL,
  820. now,
  821. nwid,
  822. sourceMac,
  823. destMac,
  824. etherType,
  825. vlanId,
  826. (const void*)localData,
  827. frameLength,
  828. &nextBackgroundTaskDeadline);
  829. if (env->ExceptionCheck()) {
  830. LOGE("Exception calling ZT_Node_processVirtualNetworkFrame");
  831. free(localData);
  832. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  833. }
  834. if (rc != ZT_RESULT_OK) {
  835. LOGE("ZT_Node_processVirtualNetworkFrame returned: %d", rc);
  836. }
  837. free(localData);
  838. jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL);
  839. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  840. env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0);
  841. return createResultObject(env, rc);
  842. }
  843. /*
  844. * Class: com_zerotier_sdk_Node
  845. * Method: processWirePacket
  846. * Signature: (JJJLjava/net/InetSocketAddress;[B[J)Lcom/zerotier/sdk/ResultCode;
  847. */
  848. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket(
  849. JNIEnv *env, jobject obj,
  850. jlong id,
  851. jlong in_now,
  852. jlong in_localSocket,
  853. jobject in_remoteAddress,
  854. jbyteArray in_packetData,
  855. jlongArray out_nextBackgroundTaskDeadline)
  856. {
  857. int64_t nodeId = (int64_t) id;
  858. ZT_Node *node = findNode(nodeId);
  859. unsigned int nbtd_len = (unsigned int)env->GetArrayLength(out_nextBackgroundTaskDeadline);
  860. if(nbtd_len < 1)
  861. {
  862. LOGE("nbtd_len < 1");
  863. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  864. }
  865. int64_t now = (int64_t)in_now;
  866. sockaddr_storage remoteAddress = fromSocketAddressObject(env, in_remoteAddress);
  867. if (env->ExceptionCheck() || isSocketAddressEmpty(remoteAddress)) {
  868. return NULL;
  869. }
  870. unsigned int packetLength = (unsigned int)env->GetArrayLength(in_packetData);
  871. if(packetLength == 0)
  872. {
  873. LOGE("Empty packet?!?");
  874. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  875. }
  876. void *packetData = env->GetPrimitiveArrayCritical(in_packetData, NULL);
  877. //
  878. // need local copy of packetData because arbitrary code may run in ZT_Node_processWirePacket and no other JNI work may happen between GetPrimitiveArrayCritical / ReleasePrimitiveArrayCritical
  879. //
  880. void *localData = malloc(packetLength);
  881. memcpy(localData, packetData, packetLength);
  882. env->ReleasePrimitiveArrayCritical(in_packetData, packetData, 0);
  883. int64_t nextBackgroundTaskDeadline = 0;
  884. ZT_ResultCode rc = ZT_Node_processWirePacket(
  885. node,
  886. NULL,
  887. now,
  888. in_localSocket,
  889. &remoteAddress,
  890. localData,
  891. packetLength,
  892. &nextBackgroundTaskDeadline);
  893. if (env->ExceptionCheck()) {
  894. LOGE("Exception calling ZT_Node_processWirePacket");
  895. free(localData);
  896. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  897. }
  898. if(rc != ZT_RESULT_OK)
  899. {
  900. LOGE("ZT_Node_processWirePacket returned: %d", rc);
  901. }
  902. free(localData);
  903. jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL);
  904. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  905. env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0);
  906. return createResultObject(env, rc);
  907. }
  908. /*
  909. * Class: com_zerotier_sdk_Node
  910. * Method: processBackgroundTasks
  911. * Signature: (JJ[J)Lcom/zerotier/sdk/ResultCode;
  912. */
  913. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processBackgroundTasks(
  914. JNIEnv *env, jobject obj,
  915. jlong id,
  916. jlong in_now,
  917. jlongArray out_nextBackgroundTaskDeadline)
  918. {
  919. int64_t nodeId = (int64_t) id;
  920. ZT_Node *node = findNode(nodeId);
  921. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  922. if(nbtd_len < 1)
  923. {
  924. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  925. }
  926. int64_t now = (int64_t)in_now;
  927. int64_t nextBackgroundTaskDeadline = 0;
  928. ZT_ResultCode rc = ZT_Node_processBackgroundTasks(node, NULL, now, &nextBackgroundTaskDeadline);
  929. if (env->ExceptionCheck()) {
  930. LOGE("Exception calling ZT_Node_processBackgroundTasks");
  931. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  932. }
  933. if (rc != ZT_RESULT_OK) {
  934. LOGE("ZT_Node_processBackgroundTasks returned: %d", rc);
  935. }
  936. jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL);
  937. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  938. env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0);
  939. return createResultObject(env, rc);
  940. }
  941. /*
  942. * Class: com_zerotier_sdk_Node
  943. * Method: join
  944. * Signature: (JJ)Lcom/zerotier/sdk/ResultCode;
  945. */
  946. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_join(
  947. JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  948. {
  949. int64_t nodeId = (int64_t) id;
  950. ZT_Node *node = findNode(nodeId);
  951. uint64_t nwid = (uint64_t)in_nwid;
  952. ZT_ResultCode rc = ZT_Node_join(node, nwid, NULL, NULL);
  953. if (env->ExceptionCheck()) {
  954. LOGE("Exception calling ZT_Node_join");
  955. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  956. }
  957. return createResultObject(env, rc);
  958. }
  959. /*
  960. * Class: com_zerotier_sdk_Node
  961. * Method: leave
  962. * Signature: (JJ)Lcom/zerotier/sdk/ResultCode;
  963. */
  964. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_leave(
  965. JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  966. {
  967. int64_t nodeId = (int64_t) id;
  968. ZT_Node *node = findNode(nodeId);
  969. uint64_t nwid = (uint64_t)in_nwid;
  970. ZT_ResultCode rc = ZT_Node_leave(node, nwid, NULL, NULL);
  971. if (env->ExceptionCheck()) {
  972. LOGE("Exception calling ZT_Node_leave");
  973. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  974. }
  975. return createResultObject(env, rc);
  976. }
  977. /*
  978. * Class: com_zerotier_sdk_Node
  979. * Method: multicastSubscribe
  980. * Signature: (JJJJ)Lcom/zerotier/sdk/ResultCode;
  981. */
  982. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastSubscribe(
  983. JNIEnv *env, jobject obj,
  984. jlong id,
  985. jlong in_nwid,
  986. jlong in_multicastGroup,
  987. jlong in_multicastAdi)
  988. {
  989. int64_t nodeId = (int64_t) id;
  990. ZT_Node *node = findNode(nodeId);
  991. uint64_t nwid = (uint64_t)in_nwid;
  992. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  993. unsigned long multicastAdi = (unsigned long)in_multicastAdi;
  994. ZT_ResultCode rc = ZT_Node_multicastSubscribe(
  995. node, NULL, nwid, multicastGroup, multicastAdi);
  996. if (env->ExceptionCheck()) {
  997. LOGE("Exception calling ZT_Node_multicastSubscribe");
  998. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  999. }
  1000. return createResultObject(env, rc);
  1001. }
  1002. /*
  1003. * Class: com_zerotier_sdk_Node
  1004. * Method: multicastUnsubscribe
  1005. * Signature: (JJJJ)Lcom/zerotier/sdk/ResultCode;
  1006. */
  1007. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastUnsubscribe(
  1008. JNIEnv *env, jobject obj,
  1009. jlong id,
  1010. jlong in_nwid,
  1011. jlong in_multicastGroup,
  1012. jlong in_multicastAdi)
  1013. {
  1014. int64_t nodeId = (int64_t) id;
  1015. ZT_Node *node = findNode(nodeId);
  1016. uint64_t nwid = (uint64_t)in_nwid;
  1017. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  1018. unsigned long multicastAdi = (unsigned long)in_multicastAdi;
  1019. ZT_ResultCode rc = ZT_Node_multicastUnsubscribe(
  1020. node, nwid, multicastGroup, multicastAdi);
  1021. if (env->ExceptionCheck()) {
  1022. LOGE("Exception calling ZT_Node_multicastUnsubscribe");
  1023. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  1024. }
  1025. return createResultObject(env, rc);
  1026. }
  1027. /*
  1028. * Class: com_zerotier_sdk_Node
  1029. * Method: orbit
  1030. * Signature: (JJJ)Lcom/zerotier/sdk/ResultCode;
  1031. */
  1032. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_orbit(
  1033. JNIEnv *env, jobject obj,
  1034. jlong id,
  1035. jlong in_moonWorldId,
  1036. jlong in_moonSeed)
  1037. {
  1038. int64_t nodeId = (int64_t)id;
  1039. ZT_Node *node = findNode(nodeId);
  1040. uint64_t moonWorldId = (uint64_t)in_moonWorldId;
  1041. uint64_t moonSeed = (uint64_t)in_moonSeed;
  1042. ZT_ResultCode rc = ZT_Node_orbit(node, NULL, moonWorldId, moonSeed);
  1043. if (env->ExceptionCheck()) {
  1044. LOGE("Exception calling ZT_Node_orbit");
  1045. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  1046. }
  1047. return createResultObject(env, rc);
  1048. }
  1049. /*
  1050. * Class: com_zerotier_sdk_Node
  1051. * Method: deorbit
  1052. * Signature: (JJ)L/com/zerotier/sdk/ResultCode;
  1053. */
  1054. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_deorbit(
  1055. JNIEnv *env, jobject obj,
  1056. jlong id,
  1057. jlong in_moonWorldId)
  1058. {
  1059. int64_t nodeId = (int64_t)id;
  1060. ZT_Node *node = findNode(nodeId);
  1061. uint64_t moonWorldId = (uint64_t)in_moonWorldId;
  1062. ZT_ResultCode rc = ZT_Node_deorbit(node, NULL, moonWorldId);
  1063. if (env->ExceptionCheck()) {
  1064. LOGE("Exception calling ZT_Node_deorbit");
  1065. return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
  1066. }
  1067. return createResultObject(env, rc);
  1068. }
  1069. /*
  1070. * Class: com_zerotier_sdk_Node
  1071. * Method: address
  1072. * Signature: (J)J
  1073. */
  1074. JNIEXPORT jlong JNICALL Java_com_zerotier_sdk_Node_address(
  1075. JNIEnv *env , jobject obj, jlong id)
  1076. {
  1077. int64_t nodeId = (int64_t) id;
  1078. ZT_Node *node = findNode(nodeId);
  1079. uint64_t address = ZT_Node_address(node);
  1080. return (jlong)address;
  1081. }
  1082. /*
  1083. * Class: com_zerotier_sdk_Node
  1084. * Method: status
  1085. * Signature: (J)Lcom/zerotier/sdk/NodeStatus;
  1086. */
  1087. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_status
  1088. (JNIEnv *env, jobject obj, jlong id)
  1089. {
  1090. int64_t nodeId = (int64_t) id;
  1091. ZT_Node *node = findNode(nodeId);
  1092. ZT_NodeStatus nodeStatus;
  1093. ZT_Node_status(node, &nodeStatus);
  1094. return newNodeStatus(env, nodeStatus);
  1095. }
  1096. /*
  1097. * Class: com_zerotier_sdk_Node
  1098. * Method: networkConfig
  1099. * Signature: (JJ)Lcom/zerotier/sdk/VirtualNetworkConfig;
  1100. */
  1101. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_networkConfig(
  1102. JNIEnv *env, jobject obj, jlong id, jlong nwid)
  1103. {
  1104. int64_t nodeId = (int64_t) id;
  1105. ZT_Node *node = findNode(nodeId);
  1106. ZT_VirtualNetworkConfig *vnetConfig = ZT_Node_networkConfig(node, nwid);
  1107. if (vnetConfig == NULL) {
  1108. LOGE("vnetConfig == NULL");
  1109. return NULL;
  1110. }
  1111. jobject vnetConfigObject = newNetworkConfig(env, *vnetConfig);
  1112. ZT_Node_freeQueryResult(node, vnetConfig);
  1113. return vnetConfigObject;
  1114. }
  1115. /*
  1116. * Class: com_zerotier_sdk_Node
  1117. * Method: version
  1118. * Signature: ()Lcom/zerotier/sdk/Version;
  1119. */
  1120. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_version(
  1121. JNIEnv *env, jobject obj)
  1122. {
  1123. int major = 0;
  1124. int minor = 0;
  1125. int revision = 0;
  1126. ZT_version(&major, &minor, &revision);
  1127. return newVersion(env, major, minor, revision);
  1128. }
  1129. /*
  1130. * Class: com_zerotier_sdk_Node
  1131. * Method: peers
  1132. * Signature: (J)[Lcom/zerotier/sdk/Peer;
  1133. */
  1134. JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers(
  1135. JNIEnv *env, jobject obj, jlong id)
  1136. {
  1137. int64_t nodeId = (int64_t) id;
  1138. ZT_Node *node = findNode(nodeId);
  1139. ZT_PeerList *peerList = ZT_Node_peers(node);
  1140. if(peerList == NULL)
  1141. {
  1142. LOGE("ZT_Node_peers returned NULL");
  1143. return NULL;
  1144. }
  1145. jobjectArray peerArrayObj = newPeerArray(env, peerList->peers, peerList->peerCount);
  1146. ZT_Node_freeQueryResult(node, peerList);
  1147. peerList = NULL;
  1148. return peerArrayObj;
  1149. }
  1150. /*
  1151. * Class: com_zerotier_sdk_Node
  1152. * Method: networkConfigs
  1153. * Signature: (J)[Lcom/zerotier/sdk/VirtualNetworkConfig;
  1154. */
  1155. JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_networkConfigs(
  1156. JNIEnv *env, jobject obj, jlong id)
  1157. {
  1158. int64_t nodeId = (int64_t) id;
  1159. ZT_Node *node = findNode(nodeId);
  1160. ZT_VirtualNetworkList *networkList = ZT_Node_networks(node);
  1161. if(networkList == NULL)
  1162. {
  1163. LOGE("ZT_Node_networks returned NULL");
  1164. return NULL;
  1165. }
  1166. jobjectArray networkListObject = newVirtualNetworkConfigArray(env, networkList->networks, networkList->networkCount);
  1167. ZT_Node_freeQueryResult(node, networkList);
  1168. return networkListObject;
  1169. }
  1170. #ifdef __cplusplus
  1171. } // extern "C"
  1172. #endif