com_zerotierone_sdk_Node.cpp 31 KB

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