com_zerotierone_sdk_Node.cpp 28 KB

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