com_zerotierone_sdk_Node.cpp 33 KB

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