com_zerotierone_sdk_Node.cpp 40 KB

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