com_zerotierone_sdk_Node.cpp 35 KB

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