com_zerotierone_sdk_Node.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  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 <ZeroTierOne.h>
  29. #include <map>
  30. #include <string>
  31. #include <assert.h>
  32. #include <string.h>
  33. #ifdef __cplusplus
  34. extern "C" {
  35. #endif
  36. namespace {
  37. struct JniRef
  38. {
  39. JniRef()
  40. : env(NULL)
  41. , node(NULL)
  42. , dataStoreGetListener(NULL)
  43. , dataStorePutListener(NULL)
  44. , packetSender(NULL)
  45. , frameListener(NULL)
  46. , configListener(NULL)
  47. {}
  48. uint64_t id;
  49. JNIEnv *env;
  50. ZT1_Node *node;
  51. jobject dataStoreGetListener;
  52. jobject dataStorePutListener;
  53. jobject packetSender;
  54. jobject frameListener;
  55. jobject configListener;
  56. };
  57. int VirtualNetworkConfigFunctionCallback(ZT1_Node *node,void *userData,uint64_t,enum ZT1_VirtualNetworkConfigOperation,const ZT1_VirtualNetworkConfig *)
  58. {
  59. JniRef *ref = (JniRef*)userData;
  60. assert(ref->node == node);
  61. JNIEnv *env = ref->env;
  62. return 0;
  63. }
  64. void VirtualNetworkFrameFunctionCallback(ZT1_Node *node,void *userData,uint64_t,uint64_t,uint64_t,unsigned int,unsigned int,const void *,unsigned int)
  65. {
  66. JniRef *ref = (JniRef*)userData;
  67. assert(ref->node == node);
  68. JNIEnv *env = ref->env;
  69. }
  70. void EventCallback(ZT1_Node *node,void *userData,enum ZT1_Event,const void *)
  71. {
  72. JniRef *ref = (JniRef*)userData;
  73. assert(ref->node == node);
  74. JNIEnv *env = ref->env;
  75. }
  76. long DataStoreGetFunction(ZT1_Node *node,void *userData,const char *,void *,unsigned long,unsigned long,unsigned long *)
  77. {
  78. JniRef *ref = (JniRef*)userData;
  79. assert(ref->node == node);
  80. JNIEnv *env = ref->env;
  81. return 0;
  82. }
  83. int DataStorePutFunction(ZT1_Node *node,void *userData,const char *,const void *,unsigned long,int)
  84. {
  85. JniRef *ref = (JniRef*)userData;
  86. assert(ref->node == node);
  87. JNIEnv *env = ref->env;
  88. return 0;
  89. }
  90. int WirePacketSendFunction(ZT1_Node *node,void *userData,const struct sockaddr_storage *,unsigned int,const void *,unsigned int)
  91. {
  92. JniRef *ref = (JniRef*)userData;
  93. assert(ref->node == node);
  94. JNIEnv *env = ref->env;
  95. return 0;
  96. }
  97. typedef std::map<uint64_t, JniRef*> NodeMap;
  98. static NodeMap nodeMap;
  99. jobject createResultObject(JNIEnv *env, ZT1_ResultCode code)
  100. {
  101. // cache the class so we don't have to
  102. // look it up every time we need to create a java
  103. // ResultCode object
  104. static jclass resultClass = NULL;
  105. jobject resultObject = NULL;
  106. if(resultClass == NULL)
  107. {
  108. resultClass = env->FindClass("com/zerotierone/sdk/ResultCode");
  109. if(resultClass == NULL)
  110. {
  111. return NULL; // exception thrown
  112. }
  113. }
  114. std::string fieldName;
  115. switch(code)
  116. {
  117. case ZT1_RESULT_OK:
  118. fieldName = "ZT1_RESULT_OK";
  119. break;
  120. case ZT1_RESULT_FATAL_ERROR_OUT_OF_MEMORY:
  121. fieldName = "ZT1_RESULT_FATAL_ERROR_OUT_OF_MEMORY";
  122. break;
  123. case ZT1_RESULT_FATAL_ERROR_DATA_STORE_FAILED:
  124. fieldName = "ZT1_RESULT_FATAL_ERROR_DATA_STORE_FAILED";
  125. break;
  126. case ZT1_RESULT_ERROR_NETWORK_NOT_FOUND:
  127. fieldName = "ZT1_RESULT_ERROR_NETWORK_NOT_FOUND";
  128. break;
  129. case ZT1_RESULT_FATAL_ERROR_INTERNAL:
  130. default:
  131. fieldName = "ZT1_RESULT_FATAL_ERROR_INTERNAL";
  132. break;
  133. }
  134. jfieldID enumField = env->GetStaticFieldID(resultClass, fieldName.c_str(), "Lcom/zerotierone/sdk/ResultCode");
  135. resultObject = env->GetStaticObjectField(resultClass, enumField);
  136. return resultObject;
  137. }
  138. ZT1_Node* findNode(uint64_t nodeId)
  139. {
  140. NodeMap::iterator found = nodeMap.find(nodeId);
  141. if(found != nodeMap.end())
  142. {
  143. JniRef *ref = found->second;
  144. return ref->node;
  145. }
  146. return NULL;
  147. }
  148. }
  149. /*
  150. * Class: com_zerotierone_sdk_Node
  151. * Method: node_init
  152. * Signature: (J)Lcom/zerotierone/sdk/ResultCode;
  153. */
  154. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_node_1init
  155. (JNIEnv *env, jobject obj, jlong now)
  156. {
  157. jobject resultObject = createResultObject(env, ZT1_RESULT_OK);
  158. ZT1_Node *node;
  159. JniRef *ref = new JniRef;
  160. ZT1_ResultCode rc = ZT1_Node_new(
  161. &node,
  162. ref,
  163. (uint64_t)now,
  164. &DataStoreGetFunction,
  165. &DataStorePutFunction,
  166. &WirePacketSendFunction,
  167. &VirtualNetworkFrameFunctionCallback,
  168. &VirtualNetworkConfigFunctionCallback,
  169. &EventCallback);
  170. if(rc != ZT1_RESULT_OK)
  171. {
  172. resultObject = createResultObject(env, rc);
  173. if(node)
  174. {
  175. ZT1_Node_delete(node);
  176. node = NULL;
  177. }
  178. delete ref;
  179. ref = NULL;
  180. return resultObject;
  181. }
  182. ref->id = (uint64_t)now;
  183. ref->env = env;
  184. ref->node = node;
  185. jclass cls = env->GetObjectClass(obj);
  186. jfieldID fid = env->GetFieldID(
  187. cls, "getListener", "Lcom.zerotierone.sdk.DataStoreGetListener;");
  188. if(fid == NULL)
  189. {
  190. return NULL; // exception already thrown
  191. }
  192. ref->dataStoreGetListener = env->GetObjectField(obj, fid);
  193. if(ref->dataStoreGetListener == NULL)
  194. {
  195. return NULL;
  196. }
  197. fid = env->GetFieldID(
  198. cls, "putListener", "Lcom.zerotierone.sdk.DataStorePutLisetner;");
  199. if(fid == NULL)
  200. {
  201. return NULL; // exception already thrown
  202. }
  203. ref->dataStorePutListener = env->GetObjectField(obj, fid);
  204. if(ref->dataStorePutListener == NULL)
  205. {
  206. return NULL;
  207. }
  208. fid = env->GetFieldID(
  209. cls, "sender", "Lcom.zerotierone.sdk.PacketSender;");
  210. if(fid == NULL)
  211. {
  212. return NULL; // exception already thrown
  213. }
  214. ref->packetSender = env->GetObjectField(obj, fid);
  215. if(ref->packetSender == NULL)
  216. {
  217. return NULL;
  218. }
  219. fid = env->GetFieldID(
  220. cls, "frameListener", "Lcom.zerotierone.sdk.VirtualNetworkFrameListener;");
  221. if(fid == NULL)
  222. {
  223. return NULL; // exception already thrown
  224. }
  225. ref->frameListener = env->GetObjectField(obj, fid);
  226. if(ref->frameListener = NULL)
  227. {
  228. return NULL;
  229. }
  230. fid = env->GetFieldID(
  231. cls, "configListener", "Lcom.zerotierone.sdk.VirtualNetworkConfigListener;");
  232. if(fid == NULL)
  233. {
  234. return NULL; // exception already thrown
  235. }
  236. ref->configListener = env->GetObjectField(obj, fid);
  237. if(ref->configListener == NULL)
  238. {
  239. return NULL;
  240. }
  241. nodeMap.insert(std::make_pair(ref->id, ref));
  242. return resultObject;
  243. }
  244. /*
  245. * Class: com_zerotierone_sdk_Node
  246. * Method: node_delete
  247. * Signature: (J)V
  248. */
  249. JNIEXPORT void JNICALL Java_com_zerotierone_sdk_Node_node_1delete
  250. (JNIEnv *env, jobject obj, jlong id)
  251. {
  252. uint64_t nodeId = (uint64_t)id;
  253. NodeMap::iterator found = nodeMap.find(nodeId);
  254. if(found != nodeMap.end())
  255. {
  256. JniRef *ref = found->second;
  257. nodeMap.erase(found);
  258. ZT1_Node_delete(ref->node);
  259. delete ref;
  260. ref = NULL;
  261. }
  262. }
  263. /*
  264. * Class: com_zerotierone_sdk_Node
  265. * Method: processVirtualNetworkFrame
  266. * Signature: (JJJJJII[B[J)Lcom/zerotierone/sdk/ResultCode;
  267. */
  268. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processVirtualNetworkFrame
  269. (JNIEnv *env, jobject obj,
  270. jlong id,
  271. jlong in_now,
  272. jlong in_nwid,
  273. jlong in_sourceMac,
  274. jlong in_destMac,
  275. jint in_etherType,
  276. jint in_vlanId,
  277. jbyteArray in_frameData,
  278. jlongArray out_nextBackgroundTaskDeadline)
  279. {
  280. uint64_t nodeId = (uint64_t) id;
  281. ZT1_Node *node = findNode(nodeId);
  282. if(node == NULL)
  283. {
  284. // cannot find valid node. We should never get here.
  285. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  286. }
  287. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  288. if(nbtd_len < 1)
  289. {
  290. // array for next background task length has 0 elements!
  291. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  292. }
  293. uint64_t now = (uint64_t)in_now;
  294. uint64_t nwid = (uint64_t)in_nwid;
  295. uint64_t sourceMac = (uint64_t)in_sourceMac;
  296. uint64_t destMac = (uint64_t)in_destMac;
  297. unsigned int etherType = (unsigned int)in_etherType;
  298. unsigned int vlanId = (unsigned int)in_vlanId;
  299. unsigned int frameLength = env->GetArrayLength(in_frameData);
  300. jbyte *frameData =env->GetByteArrayElements(in_frameData, NULL);
  301. uint64_t nextBackgroundTaskDeadline = 0;
  302. ZT1_ResultCode rc = ZT1_Node_processVirtualNetworkFrame(
  303. node,
  304. now,
  305. nwid,
  306. sourceMac,
  307. destMac,
  308. etherType,
  309. vlanId,
  310. (const void*)frameData,
  311. frameLength,
  312. &nextBackgroundTaskDeadline);
  313. jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL);
  314. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  315. env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0);
  316. env->ReleaseByteArrayElements(in_frameData, frameData, 0);
  317. return createResultObject(env, rc);
  318. }
  319. /*
  320. * Class: com_zerotierone_sdk_Node
  321. * Method: processWirePacket
  322. * Signature: (JJLjava/net/InetAddress;I[B[J)Lcom/zerotierone/sdk/ResultCode;
  323. */
  324. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processWirePacket
  325. (JNIEnv *env, jobject obj,
  326. jlong id,
  327. jlong in_now,
  328. jobject in_remoteAddress,
  329. jint in_linkDesparation,
  330. jbyteArray in_packetData,
  331. jlongArray out_nextBackgroundTaskDeadline)
  332. {
  333. uint64_t nodeId = (uint64_t) id;
  334. ZT1_Node *node = findNode(nodeId);
  335. if(node == NULL)
  336. {
  337. // cannot find valid node. We should never get here.
  338. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  339. }
  340. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  341. if(nbtd_len < 1)
  342. {
  343. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  344. }
  345. uint64_t now = (uint64_t)in_now;
  346. unsigned int linkDesparation = (unsigned int)in_linkDesparation;
  347. // get the java.net.InetAddress class and getAddress() method
  348. jclass inetAddressClass = env->FindClass("java/net/InetAddress");
  349. if(inetAddressClass == NULL)
  350. {
  351. // can't find java.net.InetAddress
  352. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  353. }
  354. jmethodID getAddressMethod = env->GetMethodID(
  355. inetAddressClass, "getAddress", "()[B");
  356. if(getAddressMethod == NULL)
  357. {
  358. // cant find InetAddress.getAddres()
  359. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  360. }
  361. // Call InetAddress.getAddress()
  362. jbyteArray addressArray = (jbyteArray)env->CallObjectMethod(in_remoteAddress, getAddressMethod);
  363. if(addressArray == NULL)
  364. {
  365. // unable to call getAddress()
  366. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  367. }
  368. unsigned int addrSize = env->GetArrayLength(addressArray);
  369. // get the address bytes
  370. jbyte *addr = env->GetByteArrayElements(addressArray, NULL);
  371. sockaddr_storage remoteAddress = {};
  372. if(addrSize == 16)
  373. {
  374. // IPV6 address
  375. sockaddr_in6 ipv6 = {};
  376. ipv6.sin6_family = AF_INET6;
  377. memcpy(ipv6.sin6_addr.s6_addr, addr, 16);
  378. memcpy(&remoteAddress, &ipv6, sizeof(sockaddr_in6));
  379. }
  380. else if(addrSize = 4)
  381. {
  382. // IPV4 address
  383. sockaddr_in ipv4 = {};
  384. ipv4.sin_family = AF_INET;
  385. memcpy(&ipv4.sin_addr, addr, 4);
  386. memcpy(&remoteAddress, &ipv4, sizeof(sockaddr_in));
  387. }
  388. else
  389. {
  390. // unknown address type
  391. env->ReleaseByteArrayElements(addressArray, addr, 0);
  392. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  393. }
  394. unsigned int packetLength = env->GetArrayLength(in_packetData);
  395. jbyte *packetData = env->GetByteArrayElements(in_packetData, NULL);
  396. uint64_t nextBackgroundTaskDeadline = 0;
  397. ZT1_ResultCode rc = ZT1_Node_processWirePacket(
  398. node,
  399. now,
  400. &remoteAddress,
  401. linkDesparation,
  402. packetData,
  403. packetLength,
  404. &nextBackgroundTaskDeadline);
  405. jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL);
  406. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  407. env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0);
  408. env->ReleaseByteArrayElements(addressArray, addr, 0);
  409. env->ReleaseByteArrayElements(in_packetData, packetData, 0);
  410. return createResultObject(env, ZT1_RESULT_OK);
  411. }
  412. /*
  413. * Class: com_zerotierone_sdk_Node
  414. * Method: processBackgroundTasks
  415. * Signature: (JJ[J)Lcom/zerotierone/sdk/ResultCode;
  416. */
  417. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processBackgroundTasks
  418. (JNIEnv *env, jobject obj,
  419. jlong id,
  420. jlong in_now,
  421. jlongArray out_nextBackgroundTaskDeadline)
  422. {
  423. uint64_t nodeId = (uint64_t) id;
  424. ZT1_Node *node = findNode(nodeId);
  425. if(node == NULL)
  426. {
  427. // cannot find valid node. We should never get here.
  428. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  429. }
  430. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  431. if(nbtd_len < 1)
  432. {
  433. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  434. }
  435. uint64_t now = (uint64_t)in_now;
  436. uint64_t nextBackgroundTaskDeadline = 0;
  437. ZT1_ResultCode rc = ZT1_Node_processBackgroundTasks(node, now, &nextBackgroundTaskDeadline);
  438. jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL);
  439. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  440. env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0);
  441. return createResultObject(env, rc);
  442. }
  443. /*
  444. * Class: com_zerotierone_sdk_Node
  445. * Method: join
  446. * Signature: (JJ)Lcom/zerotierone/sdk/ResultCode;
  447. */
  448. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_join
  449. (JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  450. {
  451. uint64_t nodeId = (uint64_t) id;
  452. ZT1_Node *node = findNode(nodeId);
  453. if(node == NULL)
  454. {
  455. // cannot find valid node. We should never get here.
  456. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  457. }
  458. uint64_t nwid = (uint64_t)in_nwid;
  459. ZT1_ResultCode rc = ZT1_Node_join(node, nwid);
  460. return createResultObject(env, rc);
  461. }
  462. /*
  463. * Class: com_zerotierone_sdk_Node
  464. * Method: leave
  465. * Signature: (JJ)Lcom/zerotierone/sdk/ResultCode;
  466. */
  467. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_leave
  468. (JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  469. {
  470. uint64_t nodeId = (uint64_t) id;
  471. ZT1_Node *node = findNode(nodeId);
  472. if(node == NULL)
  473. {
  474. // cannot find valid node. We should never get here.
  475. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  476. }
  477. uint64_t nwid = (uint64_t)in_nwid;
  478. ZT1_ResultCode rc = ZT1_Node_leave(node, nwid);
  479. return createResultObject(env, rc);
  480. }
  481. /*
  482. * Class: com_zerotierone_sdk_Node
  483. * Method: multicastSubscribe
  484. * Signature: (JJJJ)Lcom/zerotierone/sdk/ResultCode;
  485. */
  486. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_multicastSubscribe
  487. (JNIEnv *env, jobject obj,
  488. jlong id,
  489. jlong in_nwid,
  490. jlong in_multicastGroup,
  491. jlong in_multicastAdi)
  492. {
  493. uint64_t nodeId = (uint64_t) id;
  494. ZT1_Node *node = findNode(nodeId);
  495. if(node == NULL)
  496. {
  497. // cannot find valid node. We should never get here.
  498. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  499. }
  500. uint64_t nwid = (uint64_t)in_nwid;
  501. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  502. uint64_t multicastAdi = (uint64_t)in_multicastAdi;
  503. ZT1_ResultCode rc = ZT1_Node_multicastSubscribe(
  504. node, nwid, multicastGroup, multicastAdi);
  505. return createResultObject(env, rc);
  506. }
  507. /*
  508. * Class: com_zerotierone_sdk_Node
  509. * Method: multicastUnsubscribe
  510. * Signature: (JJJJ)Lcom/zerotierone/sdk/ResultCode;
  511. */
  512. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_multicastUnsubscribe
  513. (JNIEnv *env, jobject obj,
  514. jlong id,
  515. jlong in_nwid,
  516. jlong in_multicastGroup,
  517. jlong in_multicastAdi)
  518. {
  519. uint64_t nodeId = (uint64_t) id;
  520. ZT1_Node *node = findNode(nodeId);
  521. if(node == NULL)
  522. {
  523. // cannot find valid node. We should never get here.
  524. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  525. }
  526. uint64_t nwid = (uint64_t)in_nwid;
  527. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  528. uint64_t multicastAdi = (uint64_t)in_multicastAdi;
  529. ZT1_ResultCode rc = ZT1_Node_multicastUnsubscribe(
  530. node, nwid, multicastGroup, multicastAdi);
  531. return createResultObject(env, rc);
  532. }
  533. /*
  534. * Class: com_zerotierone_sdk_Node
  535. * Method: address
  536. * Signature: (J)J
  537. */
  538. JNIEXPORT jlong JNICALL Java_com_zerotierone_sdk_Node_address
  539. (JNIEnv *env , jobject obj, jlong id)
  540. {
  541. uint64_t nodeId = (uint64_t) id;
  542. ZT1_Node *node = findNode(nodeId);
  543. if(node == NULL)
  544. {
  545. // cannot find valid node. We should never get here.
  546. return 0;
  547. }
  548. uint64_t address = ZT1_Node_address(node);
  549. return (jlong)address;
  550. }
  551. * Method: version
  552. * Signature: (J)Lcom/zerotierone/sdk/Version;
  553. */
  554. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_version
  555. (JNIEnv *env, jobject obj)
  556. {
  557. // create a com.zerotierone.sdk.Version object
  558. jclass versionClass = env->FindClass("com.zerotierone.sdk.Version");
  559. if(versionClass == NULL)
  560. {
  561. return NULL;
  562. }
  563. jmethodID versionConstructor = env->GetMethodID(
  564. versionClass, "<init>", "()V");
  565. if(versionConstructor == NULL)
  566. {
  567. return NULL;
  568. }
  569. jobject versionObj = env->NewObject(versionClass, versionConstructor);
  570. if(versionObj == NULL)
  571. {
  572. return NULL;
  573. }
  574. int major = 0;
  575. int minor = 0;
  576. int revision = 0;
  577. unsigned long featureFlags = 0;
  578. ZT1_version(&major, &minor, &revision, &featureFlags);
  579. // copy data to Version object
  580. static jfieldID majorField = NULL;
  581. static jfieldID minorField = NULL;
  582. static jfieldID revisionField = NULL;
  583. static jfieldID featureFlagsField = NULL;
  584. if(majorField == NULL)
  585. {
  586. majorField = env->GetFieldID(versionClass, "major", "Lcom.zerotierone.sdk.Version");
  587. if(majorField = NULL)
  588. {
  589. return NULL;
  590. }
  591. }
  592. if(minorField == NULL)
  593. {
  594. minorField = env->GetFieldID(versionClass, "minor", "Lcom.zerotierone.sdk.Version");
  595. if(minorField == NULL)
  596. {
  597. return NULL;
  598. }
  599. }
  600. if(revisionField == NULL)
  601. {
  602. revisionField = env->GetFieldID(versionClass, "revision", "Lcom.zerotierone.sdk.Version");
  603. if(revisionField == NULL)
  604. {
  605. return NULL;
  606. }
  607. }
  608. if(featureFlagsField == NULL)
  609. {
  610. featureFlagsField = env->GetFieldID(versionClass, "featureFlags", "Lcom.zerotierone.sdk.Version");
  611. if(featureFlagsField == NULL)
  612. {
  613. return NULL;
  614. }
  615. }
  616. env->SetIntField(versionObj, majorField, (jint)major);
  617. env->SetIntField(versionObj, minorField, (jint)minor);
  618. env->SetIntField(versionObj, revisionField, (jint)revision);
  619. env->SetLongField(versionObj, featureFlagsField, (jlong)featureFlags);
  620. return versionObj;
  621. }
  622. #ifdef __cplusplus
  623. } // extern "C"
  624. #endif