com_zerotierone_sdk_Node.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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 <ZeroTierOne.h>
  29. #include <map>
  30. #include <assert.h>
  31. #ifdef __cplusplus
  32. extern "C" {
  33. #endif
  34. namespace {
  35. struct JniRef
  36. {
  37. JniRef()
  38. : env(NULL)
  39. , node(NULL)
  40. , dataStoreGetListener(NULL)
  41. , dataStorePutListener(NULL)
  42. , packetSender(NULL)
  43. , frameListener(NULL)
  44. , configListener(NULL)
  45. {}
  46. uint64_t id;
  47. JNIEnv *env;
  48. ZT1_Node *node;
  49. jobject dataStoreGetListener;
  50. jobject dataStorePutListener;
  51. jobject packetSender;
  52. jobject frameListener;
  53. jobject configListener;
  54. };
  55. int VirtualNetworkConfigFunctionCallback(ZT1_Node *node,void *userData,uint64_t,enum ZT1_VirtualNetworkConfigOperation,const ZT1_VirtualNetworkConfig *)
  56. {
  57. JniRef *ref = (JniRef*)userData;
  58. assert(ref->node == node);
  59. JNIEnv *env = ref->env;
  60. return 0;
  61. }
  62. void VirtualNetworkFrameFunctionCallback(ZT1_Node *node,void *userData,uint64_t,uint64_t,uint64_t,unsigned int,unsigned int,const void *,unsigned int)
  63. {
  64. JniRef *ref = (JniRef*)userData;
  65. assert(ref->node == node);
  66. JNIEnv *env = ref->env;
  67. }
  68. void EventCallback(ZT1_Node *node,void *userData,enum ZT1_Event,const void *)
  69. {
  70. JniRef *ref = (JniRef*)userData;
  71. assert(ref->node == node);
  72. JNIEnv *env = ref->env;
  73. }
  74. long DataStoreGetFunction(ZT1_Node *node,void *userData,const char *,void *,unsigned long,unsigned long,unsigned long *)
  75. {
  76. JniRef *ref = (JniRef*)userData;
  77. assert(ref->node == node);
  78. JNIEnv *env = ref->env;
  79. return 0;
  80. }
  81. int DataStorePutFunction(ZT1_Node *node,void *userData,const char *,const void *,unsigned long,int)
  82. {
  83. JniRef *ref = (JniRef*)userData;
  84. assert(ref->node == node);
  85. JNIEnv *env = ref->env;
  86. return 0;
  87. }
  88. int WirePacketSendFunction(ZT1_Node *node,void *userData,const struct sockaddr_storage *,unsigned int,const void *,unsigned int)
  89. {
  90. JniRef *ref = (JniRef*)userData;
  91. assert(ref->node == node);
  92. JNIEnv *env = ref->env;
  93. return 0;
  94. }
  95. typedef std::map<uint64_t, JniRef*> NodeMap;
  96. static NodeMap nodeMap;
  97. jobject createResultObject(JNIEnv *env, ZT1_ResultCode code)
  98. {
  99. // cache the class and constructor so we don't have to
  100. // look them up every time we need to create a java
  101. // ResultCode object
  102. static jclass resultClass = NULL;
  103. static jmethodID constructorId = NULL;
  104. jobject resultObject = NULL;
  105. if(resultClass == NULL)
  106. {
  107. resultClass = env->FindClass("com/zerotierone/sdk/ResultCode");
  108. if(resultClass == NULL)
  109. {
  110. return NULL; // exception thrown
  111. }
  112. }
  113. if(constructorId = NULL)
  114. {
  115. constructorId = env->GetMethodID(resultClass, "<init>", "(I)V");
  116. if(constructorId == NULL)
  117. {
  118. return NULL; // exception thrown
  119. }
  120. }
  121. resultObject = env->NewObject(resultClass, constructorId, (jlong)code);
  122. return resultObject;
  123. }
  124. ZT1_Node* findNode(uint64_t nodeId)
  125. {
  126. NodeMap::iterator found = nodeMap.find(nodeId);
  127. if(found != nodeMap.end())
  128. {
  129. JniRef *ref = found->second;
  130. return ref->node;
  131. }
  132. return NULL;
  133. }
  134. }
  135. /*
  136. * Class: com_zerotierone_sdk_Node
  137. * Method: node_init
  138. * Signature: (J)Lcom/zerotierone/sdk/ResultCode;
  139. */
  140. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_node_1init
  141. (JNIEnv *env, jobject obj, jlong now)
  142. {
  143. jobject resultObject = createResultObject(env, ZT1_RESULT_OK);
  144. ZT1_Node *node;
  145. JniRef *ref = new JniRef;
  146. ZT1_ResultCode rc = ZT1_Node_new(
  147. &node,
  148. ref,
  149. (uint64_t)now,
  150. &DataStoreGetFunction,
  151. &DataStorePutFunction,
  152. &WirePacketSendFunction,
  153. &VirtualNetworkFrameFunctionCallback,
  154. &VirtualNetworkConfigFunctionCallback,
  155. &EventCallback);
  156. if(rc != ZT1_RESULT_OK)
  157. {
  158. resultObject = createResultObject(env, rc);
  159. if(node)
  160. {
  161. ZT1_Node_delete(node);
  162. node = NULL;
  163. }
  164. delete ref;
  165. ref = NULL;
  166. return resultObject;
  167. }
  168. ref->id = (uint64_t)now;
  169. ref->env = env;
  170. ref->node = node;
  171. jclass cls = env->GetObjectClass(obj);
  172. jfieldID fid = env->GetFieldID(
  173. cls, "getListener", "Lcom.zerotierone.sdk.DataStoreGetListener;");
  174. if(fid == NULL)
  175. {
  176. return NULL; // exception already thrown
  177. }
  178. ref->dataStoreGetListener = env->GetObjectField(obj, fid);
  179. if(ref->dataStoreGetListener == NULL)
  180. {
  181. return NULL;
  182. }
  183. fid = env->GetFieldID(
  184. cls, "putListener", "Lcom.zerotierone.sdk.DataStorePutLisetner;");
  185. if(fid == NULL)
  186. {
  187. return NULL; // exception already thrown
  188. }
  189. ref->dataStorePutListener = env->GetObjectField(obj, fid);
  190. if(ref->dataStorePutListener == NULL)
  191. {
  192. return NULL;
  193. }
  194. fid = env->GetFieldID(
  195. cls, "sender", "Lcom.zerotierone.sdk.PacketSender;");
  196. if(fid == NULL)
  197. {
  198. return NULL; // exception already thrown
  199. }
  200. ref->packetSender = env->GetObjectField(obj, fid);
  201. if(ref->packetSender == NULL)
  202. {
  203. return NULL;
  204. }
  205. fid = env->GetFieldID(
  206. cls, "frameListener", "Lcom.zerotierone.sdk.VirtualNetworkFrameListener;");
  207. if(fid == NULL)
  208. {
  209. return NULL; // exception already thrown
  210. }
  211. ref->frameListener = env->GetObjectField(obj, fid);
  212. if(ref->frameListener = NULL)
  213. {
  214. return NULL;
  215. }
  216. fid = env->GetFieldID(
  217. cls, "configListener", "Lcom.zerotierone.sdk.VirtualNetworkConfigListener;");
  218. if(fid == NULL)
  219. {
  220. return NULL; // exception already thrown
  221. }
  222. ref->configListener = env->GetObjectField(obj, fid);
  223. if(ref->configListener == NULL)
  224. {
  225. return NULL;
  226. }
  227. nodeMap.insert(std::make_pair(ref->id, ref));
  228. return resultObject;
  229. }
  230. /*
  231. * Class: com_zerotierone_sdk_Node
  232. * Method: node_delete
  233. * Signature: (J)V
  234. */
  235. JNIEXPORT void JNICALL Java_com_zerotierone_sdk_Node_node_1delete
  236. (JNIEnv *env, jobject obj, jlong id)
  237. {
  238. uint64_t nodeId = (uint64_t)id;
  239. NodeMap::iterator found = nodeMap.find(nodeId);
  240. if(found != nodeMap.end())
  241. {
  242. JniRef *ref = found->second;
  243. nodeMap.erase(found);
  244. delete ref;
  245. ref = NULL;
  246. }
  247. }
  248. /*
  249. * Class: com_zerotierone_sdk_Node
  250. * Method: processVirtualNetworkFrame
  251. * Signature: (JJJJJII[B[J)Lcom/zerotierone/sdk/ResultCode;
  252. */
  253. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processVirtualNetworkFrame
  254. (JNIEnv *env, jobject obj,
  255. jlong id,
  256. jlong in_now,
  257. jlong in_nwid,
  258. jlong in_sourceMac,
  259. jlong in_destMac,
  260. jint in_etherType,
  261. jint in_vlanId,
  262. jbyteArray in_frameData,
  263. jlongArray out_nextBackgroundTaskDeadline)
  264. {
  265. uint64_t nodeId = (uint64_t) id;
  266. ZT1_Node *node = findNode(nodeId);
  267. if(node == NULL)
  268. {
  269. // cannot find valid node. We should never get here.
  270. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  271. }
  272. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  273. if(nbtd_len < 1)
  274. {
  275. // array for next background task length has 0 elements!
  276. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  277. }
  278. uint64_t now = (uint64_t)in_now;
  279. uint64_t nwid = (uint64_t)in_nwid;
  280. uint64_t sourceMac = (uint64_t)in_sourceMac;
  281. uint64_t destMac = (uint64_t)in_destMac;
  282. unsigned int etherType = (unsigned int)in_etherType;
  283. unsigned int vlanId = (unsigned int)in_vlanId;
  284. unsigned int frameLength = env->GetArrayLength(in_frameData);
  285. jbyte *frameData =env->GetByteArrayElements(in_frameData, NULL);
  286. uint64_t nextBackgroundTaskDeadline = 0;
  287. ZT1_ResultCode rc = ZT1_Node_processVirtualNetworkFrame(
  288. node,
  289. now,
  290. nwid,
  291. sourceMac,
  292. destMac,
  293. etherType,
  294. vlanId,
  295. (const void*)frameData,
  296. frameLength,
  297. &nextBackgroundTaskDeadline);
  298. jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL);
  299. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  300. env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0);
  301. env->ReleaseByteArrayElements(in_frameData, frameData, 0);
  302. return createResultObject(env, rc);
  303. }
  304. #ifdef __cplusplus
  305. } // extern "C"
  306. #endif