com_zerotierone_sdk_Node.cpp 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633
  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_jniutils.h"
  29. #include "ZT_jnilookup.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. // global static JNI Lookup Object
  38. JniLookup lookup;
  39. namespace {
  40. struct JniRef
  41. {
  42. JniRef()
  43. : jvm(NULL)
  44. , node(NULL)
  45. , dataStoreGetListener(NULL)
  46. , dataStorePutListener(NULL)
  47. , packetSender(NULL)
  48. , eventListener(NULL)
  49. , frameListener(NULL)
  50. , configListener(NULL)
  51. , pathChecker(NULL)
  52. , callbacks(NULL)
  53. {
  54. callbacks = (ZT_Node_Callbacks*)malloc(sizeof(ZT_Node_Callbacks));
  55. memset(callbacks, 0, sizeof(ZT_Node_Callbacks));
  56. }
  57. ~JniRef()
  58. {
  59. JNIEnv *env = NULL;
  60. jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  61. env->DeleteGlobalRef(dataStoreGetListener);
  62. env->DeleteGlobalRef(dataStorePutListener);
  63. env->DeleteGlobalRef(packetSender);
  64. env->DeleteGlobalRef(eventListener);
  65. env->DeleteGlobalRef(frameListener);
  66. env->DeleteGlobalRef(configListener);
  67. env->DeleteGlobalRef(pathChecker);
  68. free(callbacks);
  69. callbacks = NULL;
  70. }
  71. int64_t id;
  72. JavaVM *jvm;
  73. ZT_Node *node;
  74. jobject dataStoreGetListener;
  75. jobject dataStorePutListener;
  76. jobject packetSender;
  77. jobject eventListener;
  78. jobject frameListener;
  79. jobject configListener;
  80. jobject pathChecker;
  81. ZT_Node_Callbacks *callbacks;
  82. };
  83. int VirtualNetworkConfigFunctionCallback(
  84. ZT_Node *node,
  85. void *userData,
  86. void *threadData,
  87. uint64_t nwid,
  88. void **,
  89. enum ZT_VirtualNetworkConfigOperation operation,
  90. const ZT_VirtualNetworkConfig *config)
  91. {
  92. LOGV("VirtualNetworkConfigFunctionCallback");
  93. JniRef *ref = (JniRef*)userData;
  94. JNIEnv *env = NULL;
  95. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  96. if (ref->configListener == NULL) {
  97. LOGE("configListener is NULL");
  98. return -100;
  99. }
  100. jclass configListenerClass = env->GetObjectClass(ref->configListener);
  101. if(configListenerClass == NULL)
  102. {
  103. LOGE("Couldn't find class for VirtualNetworkConfigListener instance");
  104. return -101;
  105. }
  106. jmethodID configListenerCallbackMethod = lookup.findMethod(configListenerClass,
  107. "onNetworkConfigurationUpdated",
  108. "(JLcom/zerotier/sdk/VirtualNetworkConfigOperation;Lcom/zerotier/sdk/VirtualNetworkConfig;)I");
  109. if(configListenerCallbackMethod == NULL)
  110. {
  111. LOGE("Couldn't find onVirtualNetworkFrame() method");
  112. return -102;
  113. }
  114. jobject operationObject = createVirtualNetworkConfigOperation(env, operation);
  115. if(operationObject == NULL)
  116. {
  117. LOGE("Error creating VirtualNetworkConfigOperation object");
  118. return -103;
  119. }
  120. jobject networkConfigObject = newNetworkConfig(env, *config);
  121. if(networkConfigObject == NULL)
  122. {
  123. LOGE("Error creating VirtualNetworkConfig object");
  124. return -104;
  125. }
  126. return env->CallIntMethod(
  127. ref->configListener,
  128. configListenerCallbackMethod,
  129. (jlong)nwid, operationObject, networkConfigObject);
  130. }
  131. void VirtualNetworkFrameFunctionCallback(ZT_Node *node,
  132. void *userData,
  133. void *threadData,
  134. uint64_t nwid,
  135. void**,
  136. uint64_t sourceMac,
  137. uint64_t destMac,
  138. unsigned int etherType,
  139. unsigned int vlanid,
  140. const void *frameData,
  141. unsigned int frameLength)
  142. {
  143. LOGV("VirtualNetworkFrameFunctionCallback");
  144. #ifndef NDEBUG
  145. unsigned char* local = (unsigned char*)frameData;
  146. LOGV("Type Bytes: 0x%02x%02x", local[12], local[13]);
  147. #endif
  148. JniRef *ref = (JniRef*)userData;
  149. assert(ref->node == node);
  150. JNIEnv *env = NULL;
  151. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  152. if (ref->frameListener == NULL) {
  153. LOGE("frameListener is NULL");
  154. return;
  155. }
  156. jclass frameListenerClass = env->GetObjectClass(ref->frameListener);
  157. if(env->ExceptionCheck() || frameListenerClass == NULL)
  158. {
  159. LOGE("Couldn't find class for VirtualNetworkFrameListener instance");
  160. return;
  161. }
  162. jmethodID frameListenerCallbackMethod = lookup.findMethod(
  163. frameListenerClass,
  164. "onVirtualNetworkFrame", "(JJJJJ[B)V");
  165. if(env->ExceptionCheck() || frameListenerCallbackMethod == NULL)
  166. {
  167. LOGE("Couldn't find onVirtualNetworkFrame() method");
  168. return;
  169. }
  170. jbyteArray dataArray = env->NewByteArray(frameLength);
  171. if(env->ExceptionCheck() || dataArray == NULL)
  172. {
  173. LOGE("Couldn't create frame data array");
  174. return;
  175. }
  176. void *data = env->GetPrimitiveArrayCritical(dataArray, NULL);
  177. memcpy(data, frameData, frameLength);
  178. env->ReleasePrimitiveArrayCritical(dataArray, data, 0);
  179. if(env->ExceptionCheck())
  180. {
  181. LOGE("Error setting frame data to array");
  182. return;
  183. }
  184. env->CallVoidMethod(ref->frameListener, frameListenerCallbackMethod, (jlong)nwid, (jlong)sourceMac, (jlong)destMac, (jlong)etherType, (jlong)vlanid, dataArray);
  185. }
  186. void EventCallback(ZT_Node *node,
  187. void *userData,
  188. void *threadData,
  189. enum ZT_Event event,
  190. const void *data) {
  191. LOGV("EventCallback");
  192. JniRef *ref = (JniRef *) userData;
  193. if (ref->node != node && event != ZT_EVENT_UP) {
  194. LOGE("Nodes not equal. ref->node %p, node %p. Event: %d", ref->node, node, event);
  195. return;
  196. }
  197. JNIEnv *env = NULL;
  198. ref->jvm->GetEnv((void **) &env, JNI_VERSION_1_6);
  199. if (ref->eventListener == NULL) {
  200. LOGE("eventListener is NULL");
  201. return;
  202. }
  203. jclass eventListenerClass = env->GetObjectClass(ref->eventListener);
  204. if (eventListenerClass == NULL) {
  205. LOGE("Couldn't class for EventListener instance");
  206. return;
  207. }
  208. jmethodID onEventMethod = lookup.findMethod(eventListenerClass,
  209. "onEvent", "(Lcom/zerotier/sdk/Event;)V");
  210. if (onEventMethod == NULL) {
  211. LOGE("Couldn't find onEvent method");
  212. return;
  213. }
  214. jmethodID onTraceMethod = lookup.findMethod(eventListenerClass,
  215. "onTrace", "(Ljava/lang/String;)V");
  216. if (onTraceMethod == NULL) {
  217. LOGE("Couldn't find onTrace method");
  218. return;
  219. }
  220. jobject eventObject = createEvent(env, event);
  221. if (eventObject == NULL) {
  222. return;
  223. }
  224. switch (event) {
  225. case ZT_EVENT_UP: {
  226. LOGD("Event Up");
  227. env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject);
  228. break;
  229. }
  230. case ZT_EVENT_OFFLINE: {
  231. LOGD("Event Offline");
  232. env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject);
  233. break;
  234. }
  235. case ZT_EVENT_ONLINE: {
  236. LOGD("Event Online");
  237. env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject);
  238. break;
  239. }
  240. case ZT_EVENT_DOWN: {
  241. LOGD("Event Down");
  242. env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject);
  243. break;
  244. }
  245. case ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION: {
  246. LOGV("Identity Collision");
  247. // call onEvent()
  248. env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject);
  249. }
  250. break;
  251. case ZT_EVENT_TRACE: {
  252. LOGV("Trace Event");
  253. // call onTrace()
  254. if (data != NULL) {
  255. const char *message = (const char *) data;
  256. jstring messageStr = env->NewStringUTF(message);
  257. env->CallVoidMethod(ref->eventListener, onTraceMethod, messageStr);
  258. }
  259. }
  260. break;
  261. case ZT_EVENT_USER_MESSAGE:
  262. case ZT_EVENT_REMOTE_TRACE:
  263. default:
  264. break;
  265. }
  266. }
  267. void StatePutFunction(
  268. ZT_Node *node,
  269. void *userData,
  270. void *threadData,
  271. enum ZT_StateObjectType type,
  272. const uint64_t id[2],
  273. const void *buffer,
  274. int bufferLength) {
  275. char p[4096] = {0};
  276. bool secure = false;
  277. switch (type) {
  278. case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
  279. snprintf(p, sizeof(p), "identity.public");
  280. break;
  281. case ZT_STATE_OBJECT_IDENTITY_SECRET:
  282. snprintf(p, sizeof(p), "identity.secret");
  283. secure = true;
  284. break;
  285. case ZT_STATE_OBJECT_PLANET:
  286. snprintf(p, sizeof(p), "planet");
  287. break;
  288. case ZT_STATE_OBJECT_MOON:
  289. snprintf(p, sizeof(p), "moons.d/%.16llx.moon", (unsigned long long)id[0]);
  290. break;
  291. case ZT_STATE_OBJECT_NETWORK_CONFIG:
  292. snprintf(p, sizeof(p), "networks.d/%.16llx.conf", (unsigned long long)id[0]);
  293. break;
  294. case ZT_STATE_OBJECT_PEER:
  295. snprintf(p, sizeof(p), "peers.d/%.10llx", (unsigned long long)id[0]);
  296. break;
  297. default:
  298. return;
  299. }
  300. if (strlen(p) < 1) {
  301. return;
  302. }
  303. JniRef *ref = (JniRef*)userData;
  304. JNIEnv *env = NULL;
  305. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  306. if (ref->dataStorePutListener == NULL) {
  307. LOGE("dataStorePutListener is NULL");
  308. return;
  309. }
  310. jclass dataStorePutClass = env->GetObjectClass(ref->dataStorePutListener);
  311. if (dataStorePutClass == NULL)
  312. {
  313. LOGE("Couldn't find class for DataStorePutListener instance");
  314. return;
  315. }
  316. jmethodID dataStorePutCallbackMethod = lookup.findMethod(
  317. dataStorePutClass,
  318. "onDataStorePut",
  319. "(Ljava/lang/String;[BZ)I");
  320. if(dataStorePutCallbackMethod == NULL)
  321. {
  322. LOGE("Couldn't find onDataStorePut method");
  323. return;
  324. }
  325. jmethodID deleteMethod = lookup.findMethod(dataStorePutClass,
  326. "onDelete", "(Ljava/lang/String;)I");
  327. if(deleteMethod == NULL)
  328. {
  329. LOGE("Couldn't find onDelete method");
  330. return;
  331. }
  332. jstring nameStr = env->NewStringUTF(p);
  333. if (bufferLength >= 0) {
  334. LOGD("JNI: Write file: %s", p);
  335. // set operation
  336. jbyteArray bufferObj = env->NewByteArray(bufferLength);
  337. if(env->ExceptionCheck() || bufferObj == NULL)
  338. {
  339. LOGE("Error creating byte array buffer!");
  340. return;
  341. }
  342. env->SetByteArrayRegion(bufferObj, 0, bufferLength, (jbyte*)buffer);
  343. env->CallIntMethod(ref->dataStorePutListener,
  344. dataStorePutCallbackMethod,
  345. nameStr, bufferObj, secure);
  346. } else {
  347. LOGD("JNI: Delete file: %s", p);
  348. env->CallIntMethod(ref->dataStorePutListener, deleteMethod, nameStr);
  349. }
  350. }
  351. int StateGetFunction(
  352. ZT_Node *node,
  353. void *userData,
  354. void *threadData,
  355. ZT_StateObjectType type,
  356. const uint64_t id[2],
  357. void *buffer,
  358. unsigned int bufferLength) {
  359. char p[4096] = {0};
  360. switch (type) {
  361. case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
  362. snprintf(p, sizeof(p), "identity.public");
  363. break;
  364. case ZT_STATE_OBJECT_IDENTITY_SECRET:
  365. snprintf(p, sizeof(p), "identity.secret");
  366. break;
  367. case ZT_STATE_OBJECT_PLANET:
  368. snprintf(p, sizeof(p), "planet");
  369. break;
  370. case ZT_STATE_OBJECT_MOON:
  371. snprintf(p, sizeof(p), "moons.d/%.16llx.moon", (unsigned long long)id[0]);
  372. break;
  373. case ZT_STATE_OBJECT_NETWORK_CONFIG:
  374. snprintf(p, sizeof(p), "networks.d/%.16llx.conf", (unsigned long long)id[0]);
  375. break;
  376. case ZT_STATE_OBJECT_PEER:
  377. snprintf(p, sizeof(p), "peers.d/%.10llx", (unsigned long long)id[0]);
  378. break;
  379. default:
  380. return -100;
  381. }
  382. if (strlen(p) < 1) {
  383. return -101;
  384. }
  385. JniRef *ref = (JniRef*)userData;
  386. JNIEnv *env = NULL;
  387. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  388. if (ref->dataStoreGetListener == NULL) {
  389. LOGE("dataStoreGetListener is NULL");
  390. return -102;
  391. }
  392. jclass dataStoreGetClass = env->GetObjectClass(ref->dataStoreGetListener);
  393. if(dataStoreGetClass == NULL)
  394. {
  395. LOGE("Couldn't find class for DataStoreGetListener instance");
  396. return -103;
  397. }
  398. jmethodID dataStoreGetCallbackMethod = lookup.findMethod(
  399. dataStoreGetClass,
  400. "onDataStoreGet",
  401. "(Ljava/lang/String;[B)J");
  402. if(dataStoreGetCallbackMethod == NULL)
  403. {
  404. LOGE("Couldn't find onDataStoreGet method");
  405. return -104;
  406. }
  407. jstring nameStr = env->NewStringUTF(p);
  408. if(nameStr == NULL)
  409. {
  410. LOGE("Error creating name string object");
  411. return -105; // out of memory
  412. }
  413. jbyteArray bufferObj = env->NewByteArray(bufferLength);
  414. if(bufferObj == NULL)
  415. {
  416. LOGE("Error creating byte[] buffer of size: %u", bufferLength);
  417. return -106;
  418. }
  419. LOGV("Calling onDataStoreGet(%s, %p)", p, buffer);
  420. int retval = (int)env->CallLongMethod(
  421. ref->dataStoreGetListener,
  422. dataStoreGetCallbackMethod,
  423. nameStr,
  424. bufferObj);
  425. LOGV("onDataStoreGet returned %d", retval);
  426. if(retval > 0)
  427. {
  428. void *data = env->GetPrimitiveArrayCritical(bufferObj, NULL);
  429. memcpy(buffer, data, retval);
  430. env->ReleasePrimitiveArrayCritical(bufferObj, data, 0);
  431. }
  432. return retval;
  433. }
  434. int WirePacketSendFunction(ZT_Node *node,
  435. void *userData,
  436. void *threadData,
  437. int64_t localSocket,
  438. const struct sockaddr_storage *remoteAddress,
  439. const void *buffer,
  440. unsigned int bufferSize,
  441. unsigned int ttl)
  442. {
  443. LOGV("WirePacketSendFunction(%lld, %p, %p, %d)", (long long)localSocket, remoteAddress, buffer, bufferSize);
  444. JniRef *ref = (JniRef*)userData;
  445. assert(ref->node == node);
  446. JNIEnv *env = NULL;
  447. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  448. if (ref->packetSender == NULL) {
  449. LOGE("packetSender is NULL");
  450. return -100;
  451. }
  452. jclass packetSenderClass = env->GetObjectClass(ref->packetSender);
  453. if(packetSenderClass == NULL)
  454. {
  455. LOGE("Couldn't find class for PacketSender instance");
  456. return -101;
  457. }
  458. jmethodID packetSenderCallbackMethod = lookup.findMethod(packetSenderClass,
  459. "onSendPacketRequested", "(JLjava/net/InetSocketAddress;[BI)I");
  460. if(packetSenderCallbackMethod == NULL)
  461. {
  462. LOGE("Couldn't find onSendPacketRequested method");
  463. return -102;
  464. }
  465. jobject remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
  466. jbyteArray bufferObj = env->NewByteArray(bufferSize);
  467. env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer);
  468. int retval = env->CallIntMethod(ref->packetSender, packetSenderCallbackMethod, localSocket, remoteAddressObj, bufferObj);
  469. LOGV("JNI Packet Sender returned: %d", retval);
  470. return retval;
  471. }
  472. int PathCheckFunction(ZT_Node *node,
  473. void *userPtr,
  474. void *threadPtr,
  475. uint64_t address,
  476. int64_t localSocket,
  477. const struct sockaddr_storage *remoteAddress)
  478. {
  479. JniRef *ref = (JniRef*)userPtr;
  480. assert(ref->node == node);
  481. if(ref->pathChecker == NULL) {
  482. return true;
  483. }
  484. JNIEnv *env = NULL;
  485. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  486. jclass pathCheckerClass = env->GetObjectClass(ref->pathChecker);
  487. if(pathCheckerClass == NULL)
  488. {
  489. LOGE("Couldn't find class for PathChecker instance");
  490. return true;
  491. }
  492. jmethodID pathCheckCallbackMethod = lookup.findMethod(pathCheckerClass,
  493. "onPathCheck", "(JJLjava/net/InetSocketAddress;)Z");
  494. if(pathCheckCallbackMethod == NULL)
  495. {
  496. LOGE("Couldn't find onPathCheck method implementation");
  497. return true;
  498. }
  499. //
  500. // was:
  501. // struct sockaddr_storage nullAddress = {0};
  502. //
  503. // but was getting this warning:
  504. // warning: suggest braces around initialization of subobject
  505. //
  506. // when building ZeroTierOne
  507. //
  508. struct sockaddr_storage nullAddress;
  509. //
  510. // It is possible to assume knowledge about internals of sockaddr_storage and construct
  511. // correct 0-initializer, but it is simpler to just treat sockaddr_storage as opaque and
  512. // use memset here to fill with 0
  513. //
  514. // This is also done in InetAddress.hpp for InetAddress
  515. //
  516. memset(&nullAddress, 0, sizeof(sockaddr_storage));
  517. jobject remoteAddressObj = NULL;
  518. if(memcmp(remoteAddress, &nullAddress, sizeof(sockaddr_storage)) != 0)
  519. {
  520. remoteAddressObj = newInetSocketAddress(env, *remoteAddress);
  521. }
  522. return env->CallBooleanMethod(ref->pathChecker, pathCheckCallbackMethod, address, localSocket, remoteAddressObj);
  523. }
  524. int PathLookupFunction(ZT_Node *node,
  525. void *userPtr,
  526. void *threadPtr,
  527. uint64_t address,
  528. int ss_family,
  529. struct sockaddr_storage *result)
  530. {
  531. JniRef *ref = (JniRef*)userPtr;
  532. assert(ref->node == node);
  533. if(ref->pathChecker == NULL) {
  534. return false;
  535. }
  536. JNIEnv *env = NULL;
  537. ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
  538. jclass pathCheckerClass = env->GetObjectClass(ref->pathChecker);
  539. if(pathCheckerClass == NULL)
  540. {
  541. LOGE("Couldn't find class for PathChecker instance");
  542. return false;
  543. }
  544. jmethodID pathLookupMethod = lookup.findMethod(pathCheckerClass,
  545. "onPathLookup", "(JI)Ljava/net/InetSocketAddress;");
  546. if(pathLookupMethod == NULL) {
  547. return false;
  548. }
  549. jobject sockAddressObject = env->CallObjectMethod(ref->pathChecker, pathLookupMethod, address, ss_family);
  550. if(sockAddressObject == NULL)
  551. {
  552. LOGE("Unable to call onPathLookup implementation");
  553. return false;
  554. }
  555. jclass inetSockAddressClass = env->GetObjectClass(sockAddressObject);
  556. if(inetSockAddressClass == NULL)
  557. {
  558. LOGE("Unable to find InetSocketAddress class");
  559. return false;
  560. }
  561. jmethodID getAddressMethod = lookup.findMethod(inetSockAddressClass, "getAddress", "()Ljava/net/InetAddress;");
  562. if(getAddressMethod == NULL)
  563. {
  564. LOGE("Unable to find InetSocketAddress.getAddress() method");
  565. return false;
  566. }
  567. jmethodID getPortMethod = lookup.findMethod(inetSockAddressClass, "getPort", "()I");
  568. if(getPortMethod == NULL)
  569. {
  570. LOGE("Unable to find InetSocketAddress.getPort() method");
  571. return false;
  572. }
  573. jint port = env->CallIntMethod(sockAddressObject, getPortMethod);
  574. jobject addressObject = env->CallObjectMethod(sockAddressObject, getAddressMethod);
  575. jclass inetAddressClass = lookup.findClass("java/net/InetAddress");
  576. if(inetAddressClass == NULL)
  577. {
  578. LOGE("Unable to find InetAddress class");
  579. return false;
  580. }
  581. getAddressMethod = lookup.findMethod(inetAddressClass, "getAddress", "()[B");
  582. if(getAddressMethod == NULL)
  583. {
  584. LOGE("Unable to find InetAddress.getAddress() method");
  585. return false;
  586. }
  587. jbyteArray addressBytes = (jbyteArray)env->CallObjectMethod(addressObject, getAddressMethod);
  588. if(addressBytes == NULL)
  589. {
  590. LOGE("Unable to call InetAddress.getBytes()");
  591. return false;
  592. }
  593. int addressSize = env->GetArrayLength(addressBytes);
  594. if(addressSize == 4)
  595. {
  596. // IPV4
  597. sockaddr_in *addr = (sockaddr_in*)result;
  598. addr->sin_family = AF_INET;
  599. addr->sin_port = htons(port);
  600. void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL);
  601. memcpy(&addr->sin_addr, data, 4);
  602. env->ReleasePrimitiveArrayCritical(addressBytes, data, 0);
  603. }
  604. else if (addressSize == 16)
  605. {
  606. // IPV6
  607. sockaddr_in6 *addr = (sockaddr_in6*)result;
  608. addr->sin6_family = AF_INET6;
  609. addr->sin6_port = htons(port);
  610. void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL);
  611. memcpy(&addr->sin6_addr, data, 16);
  612. env->ReleasePrimitiveArrayCritical(addressBytes, data, 0);
  613. }
  614. else
  615. {
  616. return false;
  617. }
  618. return true;
  619. }
  620. typedef std::map<int64_t, JniRef*> NodeMap;
  621. static NodeMap nodeMap;
  622. ZeroTier::Mutex nodeMapMutex;
  623. ZT_Node* findNode(int64_t nodeId)
  624. {
  625. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  626. NodeMap::iterator found = nodeMap.find(nodeId);
  627. if(found != nodeMap.end())
  628. {
  629. JniRef *ref = found->second;
  630. return ref->node;
  631. }
  632. return NULL;
  633. }
  634. }
  635. #ifdef __cplusplus
  636. extern "C" {
  637. #endif
  638. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
  639. {
  640. lookup.setJavaVM(vm);
  641. return JNI_VERSION_1_6;
  642. }
  643. JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
  644. {
  645. }
  646. /*
  647. * Class: com_zerotier_sdk_Node
  648. * Method: node_init
  649. * Signature: (J)Lcom/zerotier/sdk/ResultCode;
  650. */
  651. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init(
  652. JNIEnv *env, jobject obj, jlong now)
  653. {
  654. LOGV("Creating ZT_Node struct");
  655. jobject resultObject = createResultObject(env, ZT_RESULT_OK);
  656. ZT_Node *node;
  657. JniRef *ref = new JniRef;
  658. ref->id = (int64_t)now;
  659. env->GetJavaVM(&ref->jvm);
  660. jclass cls = env->GetObjectClass(obj);
  661. jfieldID fid = lookup.findField(
  662. cls, "getListener", "Lcom/zerotier/sdk/DataStoreGetListener;");
  663. if(fid == NULL)
  664. {
  665. return NULL; // exception already thrown
  666. }
  667. jobject tmp = env->GetObjectField(obj, fid);
  668. if(tmp == NULL)
  669. {
  670. return NULL;
  671. }
  672. ref->dataStoreGetListener = env->NewGlobalRef(tmp);
  673. fid = lookup.findField(
  674. cls, "putListener", "Lcom/zerotier/sdk/DataStorePutListener;");
  675. if(fid == NULL)
  676. {
  677. return NULL; // exception already thrown
  678. }
  679. tmp = env->GetObjectField(obj, fid);
  680. if(tmp == NULL)
  681. {
  682. return NULL;
  683. }
  684. ref->dataStorePutListener = env->NewGlobalRef(tmp);
  685. fid = lookup.findField(
  686. cls, "sender", "Lcom/zerotier/sdk/PacketSender;");
  687. if(fid == NULL)
  688. {
  689. return NULL; // exception already thrown
  690. }
  691. tmp = env->GetObjectField(obj, fid);
  692. if(tmp == NULL)
  693. {
  694. return NULL;
  695. }
  696. ref->packetSender = env->NewGlobalRef(tmp);
  697. fid = lookup.findField(
  698. cls, "frameListener", "Lcom/zerotier/sdk/VirtualNetworkFrameListener;");
  699. if(fid == NULL)
  700. {
  701. return NULL; // exception already thrown
  702. }
  703. tmp = env->GetObjectField(obj, fid);
  704. if(tmp == NULL)
  705. {
  706. return NULL;
  707. }
  708. ref->frameListener = env->NewGlobalRef(tmp);
  709. fid = lookup.findField(
  710. cls, "configListener", "Lcom/zerotier/sdk/VirtualNetworkConfigListener;");
  711. if(fid == NULL)
  712. {
  713. return NULL; // exception already thrown
  714. }
  715. tmp = env->GetObjectField(obj, fid);
  716. if(tmp == NULL)
  717. {
  718. return NULL;
  719. }
  720. ref->configListener = env->NewGlobalRef(tmp);
  721. fid = lookup.findField(
  722. cls, "eventListener", "Lcom/zerotier/sdk/EventListener;");
  723. if(fid == NULL)
  724. {
  725. return NULL;
  726. }
  727. tmp = env->GetObjectField(obj, fid);
  728. if(tmp == NULL)
  729. {
  730. return NULL;
  731. }
  732. ref->eventListener = env->NewGlobalRef(tmp);
  733. fid = lookup.findField(
  734. cls, "pathChecker", "Lcom/zerotier/sdk/PathChecker;");
  735. if(fid == NULL)
  736. {
  737. LOGE("no path checker?");
  738. return NULL;
  739. }
  740. tmp = env->GetObjectField(obj, fid);
  741. if(tmp != NULL)
  742. {
  743. ref->pathChecker = env->NewGlobalRef(tmp);
  744. }
  745. ref->callbacks->stateGetFunction = &StateGetFunction;
  746. ref->callbacks->statePutFunction = &StatePutFunction;
  747. ref->callbacks->wirePacketSendFunction = &WirePacketSendFunction;
  748. ref->callbacks->virtualNetworkFrameFunction = &VirtualNetworkFrameFunctionCallback;
  749. ref->callbacks->virtualNetworkConfigFunction = &VirtualNetworkConfigFunctionCallback;
  750. ref->callbacks->eventCallback = &EventCallback;
  751. ref->callbacks->pathCheckFunction = &PathCheckFunction;
  752. ref->callbacks->pathLookupFunction = &PathLookupFunction;
  753. ZT_ResultCode rc = ZT_Node_new(
  754. &node,
  755. ref,
  756. NULL,
  757. ref->callbacks,
  758. (int64_t)now);
  759. if(rc != ZT_RESULT_OK)
  760. {
  761. LOGE("Error creating Node: %d", rc);
  762. resultObject = createResultObject(env, rc);
  763. if(node)
  764. {
  765. ZT_Node_delete(node);
  766. node = NULL;
  767. }
  768. delete ref;
  769. ref = NULL;
  770. return resultObject;
  771. }
  772. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  773. ref->node = node;
  774. nodeMap.insert(std::make_pair(ref->id, ref));
  775. return resultObject;
  776. }
  777. /*
  778. * Class: com_zerotier_sdk_Node
  779. * Method: node_delete
  780. * Signature: (J)V
  781. */
  782. JNIEXPORT void JNICALL Java_com_zerotier_sdk_Node_node_1delete(
  783. JNIEnv *env, jobject obj, jlong id)
  784. {
  785. LOGV("Destroying ZT_Node struct");
  786. int64_t nodeId = (int64_t)id;
  787. NodeMap::iterator found;
  788. {
  789. ZeroTier::Mutex::Lock lock(nodeMapMutex);
  790. found = nodeMap.find(nodeId);
  791. }
  792. if(found != nodeMap.end())
  793. {
  794. JniRef *ref = found->second;
  795. nodeMap.erase(found);
  796. ZT_Node_delete(ref->node);
  797. delete ref;
  798. ref = NULL;
  799. }
  800. else
  801. {
  802. LOGE("Attempted to delete a node that doesn't exist!");
  803. }
  804. }
  805. /*
  806. * Class: com_zerotier_sdk_Node
  807. * Method: processVirtualNetworkFrame
  808. * Signature: (JJJJJII[B[J)Lcom/zerotier/sdk/ResultCode;
  809. */
  810. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame(
  811. JNIEnv *env, jobject obj,
  812. jlong id,
  813. jlong in_now,
  814. jlong in_nwid,
  815. jlong in_sourceMac,
  816. jlong in_destMac,
  817. jint in_etherType,
  818. jint in_vlanId,
  819. jbyteArray in_frameData,
  820. jlongArray out_nextBackgroundTaskDeadline)
  821. {
  822. int64_t nodeId = (int64_t) id;
  823. ZT_Node *node = findNode(nodeId);
  824. if(node == NULL)
  825. {
  826. // cannot find valid node. We should never get here.
  827. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  828. }
  829. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  830. if(nbtd_len < 1)
  831. {
  832. // array for next background task length has 0 elements!
  833. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  834. }
  835. int64_t now = (int64_t)in_now;
  836. uint64_t nwid = (uint64_t)in_nwid;
  837. uint64_t sourceMac = (uint64_t)in_sourceMac;
  838. uint64_t destMac = (uint64_t)in_destMac;
  839. unsigned int etherType = (unsigned int)in_etherType;
  840. unsigned int vlanId = (unsigned int)in_vlanId;
  841. unsigned int frameLength = env->GetArrayLength(in_frameData);
  842. void *frameData = env->GetPrimitiveArrayCritical(in_frameData, NULL);
  843. void *localData = malloc(frameLength);
  844. memcpy(localData, frameData, frameLength);
  845. env->ReleasePrimitiveArrayCritical(in_frameData, frameData, 0);
  846. int64_t nextBackgroundTaskDeadline = 0;
  847. ZT_ResultCode rc = ZT_Node_processVirtualNetworkFrame(
  848. node,
  849. NULL,
  850. now,
  851. nwid,
  852. sourceMac,
  853. destMac,
  854. etherType,
  855. vlanId,
  856. (const void*)localData,
  857. frameLength,
  858. &nextBackgroundTaskDeadline);
  859. free(localData);
  860. jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL);
  861. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  862. env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0);
  863. return createResultObject(env, rc);
  864. }
  865. /*
  866. * Class: com_zerotier_sdk_Node
  867. * Method: processWirePacket
  868. * Signature: (JJJLjava/net/InetSocketAddress;[B[J)Lcom/zerotier/sdk/ResultCode;
  869. */
  870. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket(
  871. JNIEnv *env, jobject obj,
  872. jlong id,
  873. jlong in_now,
  874. jlong in_localSocket,
  875. jobject in_remoteAddress,
  876. jbyteArray in_packetData,
  877. jlongArray out_nextBackgroundTaskDeadline)
  878. {
  879. int64_t nodeId = (int64_t) id;
  880. ZT_Node *node = findNode(nodeId);
  881. if(node == NULL)
  882. {
  883. // cannot find valid node. We should never get here.
  884. LOGE("Couldn't find a valid node!");
  885. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  886. }
  887. unsigned int nbtd_len = (unsigned int)env->GetArrayLength(out_nextBackgroundTaskDeadline);
  888. if(nbtd_len < 1)
  889. {
  890. LOGE("nbtd_len < 1");
  891. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  892. }
  893. int64_t now = (int64_t)in_now;
  894. // get the java.net.InetSocketAddress class and getAddress() method
  895. jclass inetAddressClass = lookup.findClass("java/net/InetAddress");
  896. if(inetAddressClass == NULL)
  897. {
  898. LOGE("Can't find InetAddress class");
  899. // can't find java.net.InetAddress
  900. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  901. }
  902. jmethodID getAddressMethod = lookup.findMethod(
  903. inetAddressClass, "getAddress", "()[B");
  904. if(getAddressMethod == NULL)
  905. {
  906. // cant find InetAddress.getAddress()
  907. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  908. }
  909. jclass InetSocketAddressClass = lookup.findClass("java/net/InetSocketAddress");
  910. if(InetSocketAddressClass == NULL)
  911. {
  912. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  913. }
  914. jmethodID inetSockGetAddressMethod = lookup.findMethod(
  915. InetSocketAddressClass, "getAddress", "()Ljava/net/InetAddress;");
  916. jobject remoteAddrObject = env->CallObjectMethod(in_remoteAddress, inetSockGetAddressMethod);
  917. if(remoteAddrObject == NULL)
  918. {
  919. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  920. }
  921. jmethodID inetSock_getPort = lookup.findMethod(
  922. InetSocketAddressClass, "getPort", "()I");
  923. if(env->ExceptionCheck() || inetSock_getPort == NULL)
  924. {
  925. LOGE("Couldn't find getPort method on InetSocketAddress");
  926. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  927. }
  928. // call InetSocketAddress.getPort()
  929. int remotePort = env->CallIntMethod(in_remoteAddress, inetSock_getPort);
  930. if(env->ExceptionCheck())
  931. {
  932. LOGE("Exception calling InetSocketAddress.getPort()");
  933. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  934. }
  935. // Call InetAddress.getAddress()
  936. jbyteArray remoteAddressArray = (jbyteArray)env->CallObjectMethod(remoteAddrObject, getAddressMethod);
  937. if(remoteAddressArray == NULL)
  938. {
  939. LOGE("Unable to call getAddress()");
  940. // unable to call getAddress()
  941. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  942. }
  943. unsigned int addrSize = env->GetArrayLength(remoteAddressArray);
  944. // get the address bytes
  945. jbyte *addr = (jbyte*)env->GetPrimitiveArrayCritical(remoteAddressArray, NULL);
  946. sockaddr_storage remoteAddress = {};
  947. if(addrSize == 16)
  948. {
  949. // IPV6 address
  950. sockaddr_in6 ipv6 = {};
  951. ipv6.sin6_family = AF_INET6;
  952. ipv6.sin6_port = htons(remotePort);
  953. memcpy(ipv6.sin6_addr.s6_addr, addr, 16);
  954. memcpy(&remoteAddress, &ipv6, sizeof(sockaddr_in6));
  955. }
  956. else if(addrSize == 4)
  957. {
  958. // IPV4 address
  959. sockaddr_in ipv4 = {};
  960. ipv4.sin_family = AF_INET;
  961. ipv4.sin_port = htons(remotePort);
  962. memcpy(&ipv4.sin_addr, addr, 4);
  963. memcpy(&remoteAddress, &ipv4, sizeof(sockaddr_in));
  964. }
  965. else
  966. {
  967. LOGE("Unknown IP version");
  968. // unknown address type
  969. env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0);
  970. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  971. }
  972. env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0);
  973. unsigned int packetLength = (unsigned int)env->GetArrayLength(in_packetData);
  974. if(packetLength == 0)
  975. {
  976. LOGE("Empty packet?!?");
  977. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  978. }
  979. void *packetData = env->GetPrimitiveArrayCritical(in_packetData, NULL);
  980. void *localData = malloc(packetLength);
  981. memcpy(localData, packetData, packetLength);
  982. env->ReleasePrimitiveArrayCritical(in_packetData, packetData, 0);
  983. int64_t nextBackgroundTaskDeadline = 0;
  984. ZT_ResultCode rc = ZT_Node_processWirePacket(
  985. node,
  986. NULL,
  987. now,
  988. in_localSocket,
  989. &remoteAddress,
  990. localData,
  991. packetLength,
  992. &nextBackgroundTaskDeadline);
  993. if(rc != ZT_RESULT_OK)
  994. {
  995. LOGE("ZT_Node_processWirePacket returned: %d", rc);
  996. }
  997. free(localData);
  998. jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL);
  999. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  1000. env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0);
  1001. return createResultObject(env, rc);
  1002. }
  1003. /*
  1004. * Class: com_zerotier_sdk_Node
  1005. * Method: processBackgroundTasks
  1006. * Signature: (JJ[J)Lcom/zerotier/sdk/ResultCode;
  1007. */
  1008. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processBackgroundTasks(
  1009. JNIEnv *env, jobject obj,
  1010. jlong id,
  1011. jlong in_now,
  1012. jlongArray out_nextBackgroundTaskDeadline)
  1013. {
  1014. int64_t nodeId = (int64_t) id;
  1015. ZT_Node *node = findNode(nodeId);
  1016. if(node == NULL)
  1017. {
  1018. // cannot find valid node. We should never get here.
  1019. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  1020. }
  1021. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  1022. if(nbtd_len < 1)
  1023. {
  1024. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  1025. }
  1026. int64_t now = (int64_t)in_now;
  1027. int64_t nextBackgroundTaskDeadline = 0;
  1028. ZT_ResultCode rc = ZT_Node_processBackgroundTasks(node, NULL, now, &nextBackgroundTaskDeadline);
  1029. jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL);
  1030. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  1031. env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0);
  1032. return createResultObject(env, rc);
  1033. }
  1034. /*
  1035. * Class: com_zerotier_sdk_Node
  1036. * Method: join
  1037. * Signature: (JJ)Lcom/zerotier/sdk/ResultCode;
  1038. */
  1039. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_join(
  1040. JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  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 createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  1048. }
  1049. uint64_t nwid = (uint64_t)in_nwid;
  1050. ZT_ResultCode rc = ZT_Node_join(node, nwid, NULL, NULL);
  1051. return createResultObject(env, rc);
  1052. }
  1053. /*
  1054. * Class: com_zerotier_sdk_Node
  1055. * Method: leave
  1056. * Signature: (JJ)Lcom/zerotier/sdk/ResultCode;
  1057. */
  1058. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_leave(
  1059. JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  1060. {
  1061. int64_t nodeId = (int64_t) id;
  1062. ZT_Node *node = findNode(nodeId);
  1063. if(node == NULL)
  1064. {
  1065. // cannot find valid node. We should never get here.
  1066. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  1067. }
  1068. uint64_t nwid = (uint64_t)in_nwid;
  1069. ZT_ResultCode rc = ZT_Node_leave(node, nwid, NULL, NULL);
  1070. return createResultObject(env, rc);
  1071. }
  1072. /*
  1073. * Class: com_zerotier_sdk_Node
  1074. * Method: multicastSubscribe
  1075. * Signature: (JJJJ)Lcom/zerotier/sdk/ResultCode;
  1076. */
  1077. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastSubscribe(
  1078. JNIEnv *env, jobject obj,
  1079. jlong id,
  1080. jlong in_nwid,
  1081. jlong in_multicastGroup,
  1082. jlong in_multicastAdi)
  1083. {
  1084. int64_t nodeId = (int64_t) id;
  1085. ZT_Node *node = findNode(nodeId);
  1086. if(node == NULL)
  1087. {
  1088. // cannot find valid node. We should never get here.
  1089. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  1090. }
  1091. uint64_t nwid = (uint64_t)in_nwid;
  1092. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  1093. unsigned long multicastAdi = (unsigned long)in_multicastAdi;
  1094. ZT_ResultCode rc = ZT_Node_multicastSubscribe(
  1095. node, NULL, nwid, multicastGroup, multicastAdi);
  1096. return createResultObject(env, rc);
  1097. }
  1098. /*
  1099. * Class: com_zerotier_sdk_Node
  1100. * Method: multicastUnsubscribe
  1101. * Signature: (JJJJ)Lcom/zerotier/sdk/ResultCode;
  1102. */
  1103. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_multicastUnsubscribe(
  1104. JNIEnv *env, jobject obj,
  1105. jlong id,
  1106. jlong in_nwid,
  1107. jlong in_multicastGroup,
  1108. jlong in_multicastAdi)
  1109. {
  1110. int64_t nodeId = (int64_t) id;
  1111. ZT_Node *node = findNode(nodeId);
  1112. if(node == NULL)
  1113. {
  1114. // cannot find valid node. We should never get here.
  1115. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  1116. }
  1117. uint64_t nwid = (uint64_t)in_nwid;
  1118. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  1119. unsigned long multicastAdi = (unsigned long)in_multicastAdi;
  1120. ZT_ResultCode rc = ZT_Node_multicastUnsubscribe(
  1121. node, nwid, multicastGroup, multicastAdi);
  1122. return createResultObject(env, rc);
  1123. }
  1124. /*
  1125. * Class: com_zerotier_sdk_Node
  1126. * Method: orbit
  1127. * Signature: (JJJ)Lcom/zerotier/sdk/ResultCode;
  1128. */
  1129. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_orbit(
  1130. JNIEnv *env, jobject obj,
  1131. jlong id,
  1132. jlong in_moonWorldId,
  1133. jlong in_moonSeed)
  1134. {
  1135. int64_t nodeId = (int64_t)id;
  1136. ZT_Node *node = findNode(nodeId);
  1137. if(node == NULL)
  1138. {
  1139. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  1140. }
  1141. uint64_t moonWorldId = (uint64_t)in_moonWorldId;
  1142. uint64_t moonSeed = (uint64_t)in_moonSeed;
  1143. ZT_ResultCode rc = ZT_Node_orbit(node, NULL, moonWorldId, moonSeed);
  1144. return createResultObject(env, rc);
  1145. }
  1146. /*
  1147. * Class: com_zerotier_sdk_Node
  1148. * Method: deorbit
  1149. * Signature: (JJ)L/com/zerotier/sdk/ResultCode;
  1150. */
  1151. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_deorbit(
  1152. JNIEnv *env, jobject obj,
  1153. jlong id,
  1154. jlong in_moonWorldId)
  1155. {
  1156. int64_t nodeId = (int64_t)id;
  1157. ZT_Node *node = findNode(nodeId);
  1158. if(node == NULL)
  1159. {
  1160. return createResultObject(env, ZT_RESULT_FATAL_ERROR_INTERNAL);
  1161. }
  1162. uint64_t moonWorldId = (uint64_t)in_moonWorldId;
  1163. ZT_ResultCode rc = ZT_Node_deorbit(node, NULL, moonWorldId);
  1164. return createResultObject(env, rc);
  1165. }
  1166. /*
  1167. * Class: com_zerotier_sdk_Node
  1168. * Method: address
  1169. * Signature: (J)J
  1170. */
  1171. JNIEXPORT jlong JNICALL Java_com_zerotier_sdk_Node_address(
  1172. JNIEnv *env , jobject obj, jlong id)
  1173. {
  1174. int64_t nodeId = (int64_t) id;
  1175. ZT_Node *node = findNode(nodeId);
  1176. if(node == NULL)
  1177. {
  1178. // cannot find valid node. We should never get here.
  1179. return 0;
  1180. }
  1181. uint64_t address = ZT_Node_address(node);
  1182. return (jlong)address;
  1183. }
  1184. /*
  1185. * Class: com_zerotier_sdk_Node
  1186. * Method: status
  1187. * Signature: (J)Lcom/zerotier/sdk/NodeStatus;
  1188. */
  1189. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_status
  1190. (JNIEnv *env, jobject obj, jlong id)
  1191. {
  1192. int64_t nodeId = (int64_t) id;
  1193. ZT_Node *node = findNode(nodeId);
  1194. if(node == NULL)
  1195. {
  1196. // cannot find valid node. We should never get here.
  1197. return 0;
  1198. }
  1199. jclass nodeStatusClass = NULL;
  1200. jmethodID nodeStatusConstructor = NULL;
  1201. // create a com.zerotier.sdk.NodeStatus object
  1202. nodeStatusClass = lookup.findClass("com/zerotier/sdk/NodeStatus");
  1203. if(nodeStatusClass == NULL)
  1204. {
  1205. return NULL;
  1206. }
  1207. nodeStatusConstructor = lookup.findMethod(
  1208. nodeStatusClass, "<init>", "()V");
  1209. if(nodeStatusConstructor == NULL)
  1210. {
  1211. return NULL;
  1212. }
  1213. jobject nodeStatusObj = env->NewObject(nodeStatusClass, nodeStatusConstructor);
  1214. if(nodeStatusObj == NULL)
  1215. {
  1216. return NULL;
  1217. }
  1218. ZT_NodeStatus nodeStatus;
  1219. ZT_Node_status(node, &nodeStatus);
  1220. jfieldID addressField = NULL;
  1221. jfieldID publicIdentityField = NULL;
  1222. jfieldID secretIdentityField = NULL;
  1223. jfieldID onlineField = NULL;
  1224. addressField = lookup.findField(nodeStatusClass, "address", "J");
  1225. if(addressField == NULL)
  1226. {
  1227. return NULL;
  1228. }
  1229. publicIdentityField = lookup.findField(nodeStatusClass, "publicIdentity", "Ljava/lang/String;");
  1230. if(publicIdentityField == NULL)
  1231. {
  1232. return NULL;
  1233. }
  1234. secretIdentityField = lookup.findField(nodeStatusClass, "secretIdentity", "Ljava/lang/String;");
  1235. if(secretIdentityField == NULL)
  1236. {
  1237. return NULL;
  1238. }
  1239. onlineField = lookup.findField(nodeStatusClass, "online", "Z");
  1240. if(onlineField == NULL)
  1241. {
  1242. return NULL;
  1243. }
  1244. env->SetLongField(nodeStatusObj, addressField, nodeStatus.address);
  1245. jstring pubIdentStr = env->NewStringUTF(nodeStatus.publicIdentity);
  1246. if(pubIdentStr == NULL)
  1247. {
  1248. return NULL; // out of memory
  1249. }
  1250. env->SetObjectField(nodeStatusObj, publicIdentityField, pubIdentStr);
  1251. jstring secIdentStr = env->NewStringUTF(nodeStatus.secretIdentity);
  1252. if(secIdentStr == NULL)
  1253. {
  1254. return NULL; // out of memory
  1255. }
  1256. env->SetObjectField(nodeStatusObj, secretIdentityField, secIdentStr);
  1257. env->SetBooleanField(nodeStatusObj, onlineField, nodeStatus.online);
  1258. return nodeStatusObj;
  1259. }
  1260. /*
  1261. * Class: com_zerotier_sdk_Node
  1262. * Method: networkConfig
  1263. * Signature: (JJ)Lcom/zerotier/sdk/VirtualNetworkConfig;
  1264. */
  1265. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_networkConfig(
  1266. JNIEnv *env, jobject obj, jlong id, jlong nwid)
  1267. {
  1268. int64_t nodeId = (int64_t) id;
  1269. ZT_Node *node = findNode(nodeId);
  1270. if(node == NULL)
  1271. {
  1272. // cannot find valid node. We should never get here.
  1273. return 0;
  1274. }
  1275. ZT_VirtualNetworkConfig *vnetConfig = ZT_Node_networkConfig(node, nwid);
  1276. jobject vnetConfigObject = newNetworkConfig(env, *vnetConfig);
  1277. ZT_Node_freeQueryResult(node, vnetConfig);
  1278. return vnetConfigObject;
  1279. }
  1280. /*
  1281. * Class: com_zerotier_sdk_Node
  1282. * Method: version
  1283. * Signature: ()Lcom/zerotier/sdk/Version;
  1284. */
  1285. JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_version(
  1286. JNIEnv *env, jobject obj)
  1287. {
  1288. int major = 0;
  1289. int minor = 0;
  1290. int revision = 0;
  1291. ZT_version(&major, &minor, &revision);
  1292. return newVersion(env, major, minor, revision);
  1293. }
  1294. /*
  1295. * Class: com_zerotier_sdk_Node
  1296. * Method: peers
  1297. * Signature: (J)[Lcom/zerotier/sdk/Peer;
  1298. */
  1299. JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_peers(
  1300. JNIEnv *env, jobject obj, jlong id)
  1301. {
  1302. int64_t nodeId = (int64_t) id;
  1303. ZT_Node *node = findNode(nodeId);
  1304. if(node == NULL)
  1305. {
  1306. // cannot find valid node. We should never get here.
  1307. return 0;
  1308. }
  1309. ZT_PeerList *peerList = ZT_Node_peers(node);
  1310. if(peerList == NULL)
  1311. {
  1312. LOGE("ZT_Node_peers returned NULL");
  1313. return NULL;
  1314. }
  1315. jclass peerClass = lookup.findClass("com/zerotier/sdk/Peer");
  1316. if(env->ExceptionCheck() || peerClass == NULL)
  1317. {
  1318. LOGE("Error finding Peer class");
  1319. ZT_Node_freeQueryResult(node, peerList);
  1320. return NULL;
  1321. }
  1322. jobjectArray peerArrayObj = env->NewObjectArray(
  1323. peerList->peerCount, peerClass, NULL);
  1324. if(env->ExceptionCheck() || peerArrayObj == NULL)
  1325. {
  1326. LOGE("Error creating Peer[] array");
  1327. ZT_Node_freeQueryResult(node, peerList);
  1328. return NULL;
  1329. }
  1330. for(unsigned int i = 0; i < peerList->peerCount; ++i)
  1331. {
  1332. jobject peerObj = newPeer(env, peerList->peers[i]);
  1333. env->SetObjectArrayElement(peerArrayObj, i, peerObj);
  1334. if(env->ExceptionCheck())
  1335. {
  1336. LOGE("Error assigning Peer object to array");
  1337. break;
  1338. }
  1339. env->DeleteLocalRef(peerObj);
  1340. }
  1341. ZT_Node_freeQueryResult(node, peerList);
  1342. peerList = NULL;
  1343. return peerArrayObj;
  1344. }
  1345. /*
  1346. * Class: com_zerotier_sdk_Node
  1347. * Method: networks
  1348. * Signature: (J)[Lcom/zerotier/sdk/VirtualNetworkConfig;
  1349. */
  1350. JNIEXPORT jobjectArray JNICALL Java_com_zerotier_sdk_Node_networks(
  1351. JNIEnv *env, jobject obj, jlong id)
  1352. {
  1353. int64_t nodeId = (int64_t) id;
  1354. ZT_Node *node = findNode(nodeId);
  1355. if(node == NULL)
  1356. {
  1357. // cannot find valid node. We should never get here.
  1358. return 0;
  1359. }
  1360. ZT_VirtualNetworkList *networkList = ZT_Node_networks(node);
  1361. if(networkList == NULL)
  1362. {
  1363. return NULL;
  1364. }
  1365. jclass vnetConfigClass = lookup.findClass("com/zerotier/sdk/VirtualNetworkConfig");
  1366. if(env->ExceptionCheck() || vnetConfigClass == NULL)
  1367. {
  1368. LOGE("Error finding VirtualNetworkConfig class");
  1369. ZT_Node_freeQueryResult(node, networkList);
  1370. return NULL;
  1371. }
  1372. jobjectArray networkListObject = env->NewObjectArray(
  1373. networkList->networkCount, vnetConfigClass, NULL);
  1374. if(env->ExceptionCheck() || networkListObject == NULL)
  1375. {
  1376. LOGE("Error creating VirtualNetworkConfig[] array");
  1377. ZT_Node_freeQueryResult(node, networkList);
  1378. return NULL;
  1379. }
  1380. for(unsigned int i = 0; i < networkList->networkCount; ++i)
  1381. {
  1382. jobject networkObject = newNetworkConfig(env, networkList->networks[i]);
  1383. env->SetObjectArrayElement(networkListObject, i, networkObject);
  1384. if(env->ExceptionCheck())
  1385. {
  1386. LOGE("Error assigning VirtualNetworkConfig object to array");
  1387. break;
  1388. }
  1389. env->DeleteLocalRef(networkObject);
  1390. }
  1391. ZT_Node_freeQueryResult(node, networkList);
  1392. return networkListObject;
  1393. }
  1394. #ifdef __cplusplus
  1395. } // extern "C"
  1396. #endif