com_zerotierone_sdk_Node.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  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 "ZT1_jniutils.h"
  29. #include <ZeroTierOne.h>
  30. #include <map>
  31. #include <string>
  32. #include <assert.h>
  33. #include <string.h>
  34. #ifdef __cplusplus
  35. extern "C" {
  36. #endif
  37. namespace {
  38. struct JniRef
  39. {
  40. JniRef()
  41. : env(NULL)
  42. , node(NULL)
  43. , dataStoreGetListener(NULL)
  44. , dataStorePutListener(NULL)
  45. , packetSender(NULL)
  46. , frameListener(NULL)
  47. , configListener(NULL)
  48. {}
  49. uint64_t id;
  50. JNIEnv *env;
  51. ZT1_Node *node;
  52. jobject dataStoreGetListener;
  53. jobject dataStorePutListener;
  54. jobject packetSender;
  55. jobject frameListener;
  56. jobject configListener;
  57. };
  58. int VirtualNetworkConfigFunctionCallback(ZT1_Node *node,void *userData,uint64_t nwid,enum ZT1_VirtualNetworkConfigOperation operation, const ZT1_VirtualNetworkConfig *config)
  59. {
  60. JniRef *ref = (JniRef*)userData;
  61. assert(ref->node == node);
  62. JNIEnv *env = ref->env;
  63. static jclass configListenerClass = NULL;
  64. static jmethodID callbackMethod = NULL;
  65. if(configListenerClass == NULL)
  66. {
  67. configListenerClass = env->GetObjectClass(ref->configListener);
  68. if(configListenerClass == NULL)
  69. {
  70. return -1;
  71. }
  72. }
  73. if(callbackMethod == NULL)
  74. {
  75. callbackMethod = env->GetMethodID(configListenerClass,
  76. "onNetworkConfigurationUpdated",
  77. "(JLcom/zerotierone/sdk/VirtualNetworkConfigOperation;Lcom/zerotierone/sdk/VirtualNetworkConfig;)I");
  78. if(callbackMethod == NULL)
  79. {
  80. return -2;
  81. }
  82. }
  83. jobject operationObject = createVirtualNetworkConfigOperation(env, operation);
  84. if(operationObject == NULL)
  85. {
  86. return -3;
  87. }
  88. jobject networkConfigObject = newNetworkConfig(env, *config);
  89. if(networkConfigObject == NULL)
  90. {
  91. return -4;
  92. }
  93. return env->CallIntMethod(ref->configListener, callbackMethod, (jlong)nwid, operationObject, networkConfigObject);
  94. }
  95. void VirtualNetworkFrameFunctionCallback(ZT1_Node *node,void *userData,uint64_t,uint64_t,uint64_t,unsigned int,unsigned int,const void *,unsigned int)
  96. {
  97. JniRef *ref = (JniRef*)userData;
  98. assert(ref->node == node);
  99. JNIEnv *env = ref->env;
  100. }
  101. void EventCallback(ZT1_Node *node,void *userData,enum ZT1_Event,const void *)
  102. {
  103. JniRef *ref = (JniRef*)userData;
  104. assert(ref->node == node);
  105. JNIEnv *env = ref->env;
  106. }
  107. long DataStoreGetFunction(ZT1_Node *node,void *userData,const char *,void *,unsigned long,unsigned long,unsigned long *)
  108. {
  109. JniRef *ref = (JniRef*)userData;
  110. assert(ref->node == node);
  111. JNIEnv *env = ref->env;
  112. return 0;
  113. }
  114. int DataStorePutFunction(ZT1_Node *node,void *userData,const char *,const void *,unsigned long,int)
  115. {
  116. JniRef *ref = (JniRef*)userData;
  117. assert(ref->node == node);
  118. JNIEnv *env = ref->env;
  119. return 0;
  120. }
  121. int WirePacketSendFunction(ZT1_Node *node,void *userData,const struct sockaddr_storage *,unsigned int,const void *,unsigned int)
  122. {
  123. JniRef *ref = (JniRef*)userData;
  124. assert(ref->node == node);
  125. JNIEnv *env = ref->env;
  126. return 0;
  127. }
  128. typedef std::map<uint64_t, JniRef*> NodeMap;
  129. static NodeMap nodeMap;
  130. ZT1_Node* findNode(uint64_t nodeId)
  131. {
  132. NodeMap::iterator found = nodeMap.find(nodeId);
  133. if(found != nodeMap.end())
  134. {
  135. JniRef *ref = found->second;
  136. return ref->node;
  137. }
  138. return NULL;
  139. }
  140. }
  141. /*
  142. * Class: com_zerotierone_sdk_Node
  143. * Method: node_init
  144. * Signature: (J)Lcom/zerotierone/sdk/ResultCode;
  145. */
  146. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_node_1init(
  147. JNIEnv *env, jobject obj, jlong now)
  148. {
  149. jobject resultObject = createResultObject(env, ZT1_RESULT_OK);
  150. ZT1_Node *node;
  151. JniRef *ref = new JniRef;
  152. ZT1_ResultCode rc = ZT1_Node_new(
  153. &node,
  154. ref,
  155. (uint64_t)now,
  156. &DataStoreGetFunction,
  157. &DataStorePutFunction,
  158. &WirePacketSendFunction,
  159. &VirtualNetworkFrameFunctionCallback,
  160. &VirtualNetworkConfigFunctionCallback,
  161. &EventCallback);
  162. if(rc != ZT1_RESULT_OK)
  163. {
  164. resultObject = createResultObject(env, rc);
  165. if(node)
  166. {
  167. ZT1_Node_delete(node);
  168. node = NULL;
  169. }
  170. delete ref;
  171. ref = NULL;
  172. return resultObject;
  173. }
  174. ref->id = (uint64_t)now;
  175. ref->env = env;
  176. ref->node = node;
  177. jclass cls = env->GetObjectClass(obj);
  178. jfieldID fid = env->GetFieldID(
  179. cls, "getListener", "Lcom/zerotierone/sdk/DataStoreGetListener;");
  180. if(fid == NULL)
  181. {
  182. return NULL; // exception already thrown
  183. }
  184. ref->dataStoreGetListener = env->GetObjectField(obj, fid);
  185. if(ref->dataStoreGetListener == NULL)
  186. {
  187. return NULL;
  188. }
  189. fid = env->GetFieldID(
  190. cls, "putListener", "Lcom/zerotierone/sdk/DataStorePutLisetner;");
  191. if(fid == NULL)
  192. {
  193. return NULL; // exception already thrown
  194. }
  195. ref->dataStorePutListener = env->GetObjectField(obj, fid);
  196. if(ref->dataStorePutListener == NULL)
  197. {
  198. return NULL;
  199. }
  200. fid = env->GetFieldID(
  201. cls, "sender", "Lcom/zerotierone/sdk/PacketSender;");
  202. if(fid == NULL)
  203. {
  204. return NULL; // exception already thrown
  205. }
  206. ref->packetSender = env->GetObjectField(obj, fid);
  207. if(ref->packetSender == NULL)
  208. {
  209. return NULL;
  210. }
  211. fid = env->GetFieldID(
  212. cls, "frameListener", "Lcom/zerotierone/sdk/VirtualNetworkFrameListener;");
  213. if(fid == NULL)
  214. {
  215. return NULL; // exception already thrown
  216. }
  217. ref->frameListener = env->GetObjectField(obj, fid);
  218. if(ref->frameListener = NULL)
  219. {
  220. return NULL;
  221. }
  222. fid = env->GetFieldID(
  223. cls, "configListener", "Lcom/zerotierone/sdk/VirtualNetworkConfigListener;");
  224. if(fid == NULL)
  225. {
  226. return NULL; // exception already thrown
  227. }
  228. ref->configListener = env->GetObjectField(obj, fid);
  229. if(ref->configListener == NULL)
  230. {
  231. return NULL;
  232. }
  233. nodeMap.insert(std::make_pair(ref->id, ref));
  234. return resultObject;
  235. }
  236. /*
  237. * Class: com_zerotierone_sdk_Node
  238. * Method: node_delete
  239. * Signature: (J)V
  240. */
  241. JNIEXPORT void JNICALL Java_com_zerotierone_sdk_Node_node_1delete(
  242. JNIEnv *env, jobject obj, jlong id)
  243. {
  244. uint64_t nodeId = (uint64_t)id;
  245. NodeMap::iterator found = nodeMap.find(nodeId);
  246. if(found != nodeMap.end())
  247. {
  248. JniRef *ref = found->second;
  249. nodeMap.erase(found);
  250. ZT1_Node_delete(ref->node);
  251. delete ref;
  252. ref = NULL;
  253. }
  254. }
  255. /*
  256. * Class: com_zerotierone_sdk_Node
  257. * Method: processVirtualNetworkFrame
  258. * Signature: (JJJJJII[B[J)Lcom/zerotierone/sdk/ResultCode;
  259. */
  260. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processVirtualNetworkFrame(
  261. JNIEnv *env, jobject obj,
  262. jlong id,
  263. jlong in_now,
  264. jlong in_nwid,
  265. jlong in_sourceMac,
  266. jlong in_destMac,
  267. jint in_etherType,
  268. jint in_vlanId,
  269. jbyteArray in_frameData,
  270. jlongArray out_nextBackgroundTaskDeadline)
  271. {
  272. uint64_t nodeId = (uint64_t) id;
  273. ZT1_Node *node = findNode(nodeId);
  274. if(node == NULL)
  275. {
  276. // cannot find valid node. We should never get here.
  277. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  278. }
  279. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  280. if(nbtd_len < 1)
  281. {
  282. // array for next background task length has 0 elements!
  283. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  284. }
  285. uint64_t now = (uint64_t)in_now;
  286. uint64_t nwid = (uint64_t)in_nwid;
  287. uint64_t sourceMac = (uint64_t)in_sourceMac;
  288. uint64_t destMac = (uint64_t)in_destMac;
  289. unsigned int etherType = (unsigned int)in_etherType;
  290. unsigned int vlanId = (unsigned int)in_vlanId;
  291. unsigned int frameLength = env->GetArrayLength(in_frameData);
  292. jbyte *frameData =env->GetByteArrayElements(in_frameData, NULL);
  293. uint64_t nextBackgroundTaskDeadline = 0;
  294. ZT1_ResultCode rc = ZT1_Node_processVirtualNetworkFrame(
  295. node,
  296. now,
  297. nwid,
  298. sourceMac,
  299. destMac,
  300. etherType,
  301. vlanId,
  302. (const void*)frameData,
  303. frameLength,
  304. &nextBackgroundTaskDeadline);
  305. jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL);
  306. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  307. env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0);
  308. env->ReleaseByteArrayElements(in_frameData, frameData, 0);
  309. return createResultObject(env, rc);
  310. }
  311. /*
  312. * Class: com_zerotierone_sdk_Node
  313. * Method: processWirePacket
  314. * Signature: (JJLjava/net/InetAddress;I[B[J)Lcom/zerotierone/sdk/ResultCode;
  315. */
  316. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processWirePacket(
  317. JNIEnv *env, jobject obj,
  318. jlong id,
  319. jlong in_now,
  320. jobject in_remoteAddress,
  321. jint in_linkDesparation,
  322. jbyteArray in_packetData,
  323. jlongArray out_nextBackgroundTaskDeadline)
  324. {
  325. uint64_t nodeId = (uint64_t) id;
  326. ZT1_Node *node = findNode(nodeId);
  327. if(node == NULL)
  328. {
  329. // cannot find valid node. We should never get here.
  330. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  331. }
  332. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  333. if(nbtd_len < 1)
  334. {
  335. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  336. }
  337. uint64_t now = (uint64_t)in_now;
  338. unsigned int linkDesparation = (unsigned int)in_linkDesparation;
  339. // get the java.net.InetAddress class and getAddress() method
  340. jclass inetAddressClass = env->FindClass("java/net/InetAddress");
  341. if(inetAddressClass == NULL)
  342. {
  343. // can't find java.net.InetAddress
  344. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  345. }
  346. jmethodID getAddressMethod = env->GetMethodID(
  347. inetAddressClass, "getAddress", "()[B");
  348. if(getAddressMethod == NULL)
  349. {
  350. // cant find InetAddress.getAddres()
  351. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  352. }
  353. // Call InetAddress.getAddress()
  354. jbyteArray addressArray = (jbyteArray)env->CallObjectMethod(in_remoteAddress, getAddressMethod);
  355. if(addressArray == NULL)
  356. {
  357. // unable to call getAddress()
  358. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  359. }
  360. unsigned int addrSize = env->GetArrayLength(addressArray);
  361. // get the address bytes
  362. jbyte *addr = env->GetByteArrayElements(addressArray, NULL);
  363. sockaddr_storage remoteAddress = {};
  364. if(addrSize == 16)
  365. {
  366. // IPV6 address
  367. sockaddr_in6 ipv6 = {};
  368. ipv6.sin6_family = AF_INET6;
  369. memcpy(ipv6.sin6_addr.s6_addr, addr, 16);
  370. memcpy(&remoteAddress, &ipv6, sizeof(sockaddr_in6));
  371. }
  372. else if(addrSize = 4)
  373. {
  374. // IPV4 address
  375. sockaddr_in ipv4 = {};
  376. ipv4.sin_family = AF_INET;
  377. memcpy(&ipv4.sin_addr, addr, 4);
  378. memcpy(&remoteAddress, &ipv4, sizeof(sockaddr_in));
  379. }
  380. else
  381. {
  382. // unknown address type
  383. env->ReleaseByteArrayElements(addressArray, addr, 0);
  384. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  385. }
  386. unsigned int packetLength = env->GetArrayLength(in_packetData);
  387. jbyte *packetData = env->GetByteArrayElements(in_packetData, NULL);
  388. uint64_t nextBackgroundTaskDeadline = 0;
  389. ZT1_ResultCode rc = ZT1_Node_processWirePacket(
  390. node,
  391. now,
  392. &remoteAddress,
  393. linkDesparation,
  394. packetData,
  395. packetLength,
  396. &nextBackgroundTaskDeadline);
  397. jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL);
  398. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  399. env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0);
  400. env->ReleaseByteArrayElements(addressArray, addr, 0);
  401. env->ReleaseByteArrayElements(in_packetData, packetData, 0);
  402. return createResultObject(env, ZT1_RESULT_OK);
  403. }
  404. /*
  405. * Class: com_zerotierone_sdk_Node
  406. * Method: processBackgroundTasks
  407. * Signature: (JJ[J)Lcom/zerotierone/sdk/ResultCode;
  408. */
  409. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processBackgroundTasks(
  410. JNIEnv *env, jobject obj,
  411. jlong id,
  412. jlong in_now,
  413. jlongArray out_nextBackgroundTaskDeadline)
  414. {
  415. uint64_t nodeId = (uint64_t) id;
  416. ZT1_Node *node = findNode(nodeId);
  417. if(node == NULL)
  418. {
  419. // cannot find valid node. We should never get here.
  420. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  421. }
  422. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  423. if(nbtd_len < 1)
  424. {
  425. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  426. }
  427. uint64_t now = (uint64_t)in_now;
  428. uint64_t nextBackgroundTaskDeadline = 0;
  429. ZT1_ResultCode rc = ZT1_Node_processBackgroundTasks(node, now, &nextBackgroundTaskDeadline);
  430. jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL);
  431. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  432. env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0);
  433. return createResultObject(env, rc);
  434. }
  435. /*
  436. * Class: com_zerotierone_sdk_Node
  437. * Method: join
  438. * Signature: (JJ)Lcom/zerotierone/sdk/ResultCode;
  439. */
  440. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_join(
  441. JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  442. {
  443. uint64_t nodeId = (uint64_t) id;
  444. ZT1_Node *node = findNode(nodeId);
  445. if(node == NULL)
  446. {
  447. // cannot find valid node. We should never get here.
  448. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  449. }
  450. uint64_t nwid = (uint64_t)in_nwid;
  451. ZT1_ResultCode rc = ZT1_Node_join(node, nwid);
  452. return createResultObject(env, rc);
  453. }
  454. /*
  455. * Class: com_zerotierone_sdk_Node
  456. * Method: leave
  457. * Signature: (JJ)Lcom/zerotierone/sdk/ResultCode;
  458. */
  459. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_leave(
  460. JNIEnv *env, jobject obj, jlong id, jlong in_nwid)
  461. {
  462. uint64_t nodeId = (uint64_t) id;
  463. ZT1_Node *node = findNode(nodeId);
  464. if(node == NULL)
  465. {
  466. // cannot find valid node. We should never get here.
  467. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  468. }
  469. uint64_t nwid = (uint64_t)in_nwid;
  470. ZT1_ResultCode rc = ZT1_Node_leave(node, nwid);
  471. return createResultObject(env, rc);
  472. }
  473. /*
  474. * Class: com_zerotierone_sdk_Node
  475. * Method: multicastSubscribe
  476. * Signature: (JJJJ)Lcom/zerotierone/sdk/ResultCode;
  477. */
  478. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_multicastSubscribe(
  479. JNIEnv *env, jobject obj,
  480. jlong id,
  481. jlong in_nwid,
  482. jlong in_multicastGroup,
  483. jlong in_multicastAdi)
  484. {
  485. uint64_t nodeId = (uint64_t) id;
  486. ZT1_Node *node = findNode(nodeId);
  487. if(node == NULL)
  488. {
  489. // cannot find valid node. We should never get here.
  490. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  491. }
  492. uint64_t nwid = (uint64_t)in_nwid;
  493. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  494. uint64_t multicastAdi = (uint64_t)in_multicastAdi;
  495. ZT1_ResultCode rc = ZT1_Node_multicastSubscribe(
  496. node, nwid, multicastGroup, multicastAdi);
  497. return createResultObject(env, rc);
  498. }
  499. /*
  500. * Class: com_zerotierone_sdk_Node
  501. * Method: multicastUnsubscribe
  502. * Signature: (JJJJ)Lcom/zerotierone/sdk/ResultCode;
  503. */
  504. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_multicastUnsubscribe(
  505. JNIEnv *env, jobject obj,
  506. jlong id,
  507. jlong in_nwid,
  508. jlong in_multicastGroup,
  509. jlong in_multicastAdi)
  510. {
  511. uint64_t nodeId = (uint64_t) id;
  512. ZT1_Node *node = findNode(nodeId);
  513. if(node == NULL)
  514. {
  515. // cannot find valid node. We should never get here.
  516. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  517. }
  518. uint64_t nwid = (uint64_t)in_nwid;
  519. uint64_t multicastGroup = (uint64_t)in_multicastGroup;
  520. uint64_t multicastAdi = (uint64_t)in_multicastAdi;
  521. ZT1_ResultCode rc = ZT1_Node_multicastUnsubscribe(
  522. node, nwid, multicastGroup, multicastAdi);
  523. return createResultObject(env, rc);
  524. }
  525. /*
  526. * Class: com_zerotierone_sdk_Node
  527. * Method: address
  528. * Signature: (J)J
  529. */
  530. JNIEXPORT jlong JNICALL Java_com_zerotierone_sdk_Node_address(
  531. JNIEnv *env , jobject obj, jlong id)
  532. {
  533. uint64_t nodeId = (uint64_t) id;
  534. ZT1_Node *node = findNode(nodeId);
  535. if(node == NULL)
  536. {
  537. // cannot find valid node. We should never get here.
  538. return 0;
  539. }
  540. uint64_t address = ZT1_Node_address(node);
  541. return (jlong)address;
  542. }
  543. /*
  544. * Class: com_zerotierone_sdk_Node
  545. * Method: status
  546. * Signature: (J)Lcom/zerotierone/sdk/NodeStatus;
  547. */
  548. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_status
  549. (JNIEnv *env, jobject obj, jlong id)
  550. {
  551. uint64_t nodeId = (uint64_t) id;
  552. ZT1_Node *node = findNode(nodeId);
  553. if(node == NULL)
  554. {
  555. // cannot find valid node. We should never get here.
  556. return 0;
  557. }
  558. // static so we only have to look these up once
  559. static jclass nodeStatusClass = NULL;
  560. static jmethodID nodeStatusConstructor = NULL;
  561. // create a com.zerotierone.sdk.NodeStatus object
  562. if(nodeStatusClass == NULL)
  563. {
  564. nodeStatusClass = env->FindClass("com/zerotierone/sdk/NodeStatus");
  565. if(nodeStatusClass == NULL)
  566. {
  567. return NULL;
  568. }
  569. }
  570. if(nodeStatusConstructor == NULL)
  571. {
  572. nodeStatusConstructor = env->GetMethodID(
  573. nodeStatusClass, "<init>", "()V");
  574. if(nodeStatusConstructor == NULL)
  575. {
  576. return NULL;
  577. }
  578. }
  579. jobject nodeStatusObj = env->NewObject(nodeStatusClass, nodeStatusConstructor);
  580. if(nodeStatusObj == NULL)
  581. {
  582. return NULL;
  583. }
  584. ZT1_NodeStatus nodeStatus;
  585. ZT1_Node_status(node, &nodeStatus);
  586. static jfieldID addressField = NULL;
  587. static jfieldID publicIdentityField = NULL;
  588. static jfieldID secretIdentityField = NULL;
  589. static jfieldID onlineField = NULL;
  590. if(addressField == NULL)
  591. {
  592. addressField = env->GetFieldID(nodeStatusClass, "address", "J");
  593. if(addressField == NULL)
  594. {
  595. return NULL;
  596. }
  597. }
  598. if(publicIdentityField == NULL)
  599. {
  600. publicIdentityField = env->GetFieldID(nodeStatusClass, "publicIdentity", "Ljava/lang/String;");
  601. if(publicIdentityField == NULL)
  602. {
  603. return NULL;
  604. }
  605. }
  606. if(secretIdentityField == NULL)
  607. {
  608. secretIdentityField = env->GetFieldID(nodeStatusClass, "secretIdentity", "Ljava/lang/String;");
  609. if(secretIdentityField == NULL)
  610. {
  611. return NULL;
  612. }
  613. }
  614. if(onlineField == NULL)
  615. {
  616. onlineField = env->GetFieldID(nodeStatusClass, "online", "Z");
  617. if(onlineField == NULL)
  618. {
  619. return NULL;
  620. }
  621. }
  622. env->SetLongField(nodeStatusObj, addressField, nodeStatus.address);
  623. jstring pubIdentStr = env->NewStringUTF(nodeStatus.publicIdentity);
  624. if(pubIdentStr == NULL)
  625. {
  626. return NULL; // out of memory
  627. }
  628. env->SetObjectField(nodeStatusObj, publicIdentityField, pubIdentStr);
  629. jstring secIdentStr = env->NewStringUTF(nodeStatus.secretIdentity);
  630. if(secIdentStr == NULL)
  631. {
  632. return NULL; // out of memory
  633. }
  634. env->SetObjectField(nodeStatusObj, secretIdentityField, secIdentStr);
  635. env->SetBooleanField(nodeStatusObj, onlineField, nodeStatus.online);
  636. return nodeStatusObj;
  637. }
  638. /*
  639. * Class: com_zerotierone_sdk_Node
  640. * Method: networkConfig
  641. * Signature: (J)Lcom/zerotierone/sdk/VirtualNetworkConfig;
  642. */
  643. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_networkConfig(
  644. JNIEnv *env, jobject obj, jlong id, jlong nwid)
  645. {
  646. uint64_t nodeId = (uint64_t) id;
  647. ZT1_Node *node = findNode(nodeId);
  648. if(node == NULL)
  649. {
  650. // cannot find valid node. We should never get here.
  651. return 0;
  652. }
  653. ZT1_VirtualNetworkConfig *vnetConfig = ZT1_Node_networkConfig(node, nwid);
  654. jobject vnetConfigObject = newNetworkConfig(env, *vnetConfig);
  655. ZT1_Node_freeQueryResult(node, vnetConfig);
  656. return vnetConfigObject;
  657. }
  658. /*
  659. * Class: com_zerotierone_sdk_Node
  660. * Method: version
  661. * Signature: (J)Lcom/zerotierone/sdk/Version;
  662. */
  663. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_version(
  664. JNIEnv *env, jobject obj)
  665. {
  666. // create a com.zerotierone.sdk.Version object
  667. jclass versionClass = env->FindClass("com/zerotierone/sdk/Version");
  668. if(versionClass == NULL)
  669. {
  670. return NULL;
  671. }
  672. jmethodID versionConstructor = env->GetMethodID(
  673. versionClass, "<init>", "()V");
  674. if(versionConstructor == NULL)
  675. {
  676. return NULL;
  677. }
  678. jobject versionObj = env->NewObject(versionClass, versionConstructor);
  679. if(versionObj == NULL)
  680. {
  681. return NULL;
  682. }
  683. int major = 0;
  684. int minor = 0;
  685. int revision = 0;
  686. unsigned long featureFlags = 0;
  687. ZT1_version(&major, &minor, &revision, &featureFlags);
  688. // copy data to Version object
  689. static jfieldID majorField = NULL;
  690. static jfieldID minorField = NULL;
  691. static jfieldID revisionField = NULL;
  692. static jfieldID featureFlagsField = NULL;
  693. if(majorField == NULL)
  694. {
  695. majorField = env->GetFieldID(versionClass, "major", "I");
  696. if(majorField = NULL)
  697. {
  698. return NULL;
  699. }
  700. }
  701. if(minorField == NULL)
  702. {
  703. minorField = env->GetFieldID(versionClass, "minor", "I");
  704. if(minorField == NULL)
  705. {
  706. return NULL;
  707. }
  708. }
  709. if(revisionField == NULL)
  710. {
  711. revisionField = env->GetFieldID(versionClass, "revision", "I");
  712. if(revisionField == NULL)
  713. {
  714. return NULL;
  715. }
  716. }
  717. if(featureFlagsField == NULL)
  718. {
  719. featureFlagsField = env->GetFieldID(versionClass, "featureFlags", "J");
  720. if(featureFlagsField == NULL)
  721. {
  722. return NULL;
  723. }
  724. }
  725. env->SetIntField(versionObj, majorField, (jint)major);
  726. env->SetIntField(versionObj, minorField, (jint)minor);
  727. env->SetIntField(versionObj, revisionField, (jint)revision);
  728. env->SetLongField(versionObj, featureFlagsField, (jlong)featureFlags);
  729. return versionObj;
  730. }
  731. /*
  732. * Class: com_zerotierone_sdk_Node
  733. * Method: peers
  734. * Signature: (J)Ljava/util/ArrayList;
  735. */
  736. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_peers(
  737. JNIEnv *env, jobject obj, jlong id)
  738. {
  739. uint64_t nodeId = (uint64_t) id;
  740. ZT1_Node *node = findNode(nodeId);
  741. if(node == NULL)
  742. {
  743. // cannot find valid node. We should never get here.
  744. return 0;
  745. }
  746. ZT1_PeerList *peerList = ZT1_Node_peers(node);
  747. if(peerList == NULL)
  748. {
  749. return NULL;
  750. }
  751. jobject peerListObject = newArrayList(env);
  752. if(peerListObject == NULL)
  753. {
  754. ZT1_Node_freeQueryResult(node, peerList);
  755. return NULL;
  756. }
  757. for(unsigned int i = 0; i < peerList->peerCount; ++i)
  758. {
  759. jobject peerObj = newPeer(env, peerList->peers[i]);
  760. appendItemToArrayList(env, peerListObject, peerObj);
  761. }
  762. ZT1_Node_freeQueryResult(node, peerList);
  763. peerList = NULL;
  764. return peerListObject;
  765. }
  766. /*
  767. * Class: com_zerotierone_sdk_Node
  768. * Method: networks
  769. * Signature: (J)Ljava/util/ArrayList;
  770. */
  771. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_networks(
  772. JNIEnv *env, jobject obj, jlong id)
  773. {
  774. uint64_t nodeId = (uint64_t) id;
  775. ZT1_Node *node = findNode(nodeId);
  776. if(node == NULL)
  777. {
  778. // cannot find valid node. We should never get here.
  779. return 0;
  780. }
  781. ZT1_VirtualNetworkList *networkList = ZT1_Node_networks(node);
  782. if(networkList == NULL)
  783. {
  784. return NULL;
  785. }
  786. jobject networkListObject = newArrayList(env);
  787. if(networkListObject == NULL)
  788. {
  789. ZT1_Node_freeQueryResult(node, networkList);
  790. return NULL;
  791. }
  792. for(unsigned int i = 0; i < networkList->networkCount; ++i)
  793. {
  794. jobject networkObject = newNetworkConfig(env, networkList->networks[i]);
  795. appendItemToArrayList(env, networkListObject, networkObject);
  796. }
  797. ZT1_Node_freeQueryResult(node, networkList);
  798. return networkListObject;
  799. }
  800. #ifdef __cplusplus
  801. } // extern "C"
  802. #endif