com_zerotierone_sdk_Node.cpp 47 KB

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