com_zerotierone_sdk_Node.cpp 48 KB

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