com_zerotierone_sdk_Node.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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. }
  125. /*
  126. * Class: com_zerotierone_sdk_Node
  127. * Method: node_init
  128. * Signature: (J)Lcom/zerotierone/sdk/ResultCode;
  129. */
  130. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_node_1init
  131. (JNIEnv *env, jobject obj, jlong now)
  132. {
  133. jobject resultObject = createResultObject(env, ZT1_RESULT_OK);
  134. ZT1_Node *node;
  135. JniRef *ref = new JniRef;
  136. ZT1_ResultCode rc = ZT1_Node_new(
  137. &node,
  138. ref,
  139. (uint64_t)now,
  140. &DataStoreGetFunction,
  141. &DataStorePutFunction,
  142. &WirePacketSendFunction,
  143. &VirtualNetworkFrameFunctionCallback,
  144. &VirtualNetworkConfigFunctionCallback,
  145. &EventCallback);
  146. if(rc != ZT1_RESULT_OK)
  147. {
  148. resultObject = createResultObject(env, rc);
  149. if(node)
  150. {
  151. ZT1_Node_delete(node);
  152. node = NULL;
  153. }
  154. delete ref;
  155. ref = NULL;
  156. return resultObject;
  157. }
  158. ref->id = (uint64_t)now;
  159. ref->env = env;
  160. ref->node = node;
  161. jclass cls = env->GetObjectClass(obj);
  162. jfieldID fid = env->GetFieldID(
  163. cls, "getListener", "Lcom.zerotierone.sdk.DataStoreGetListener;");
  164. if(fid == NULL)
  165. {
  166. return NULL; // exception already thrown
  167. }
  168. ref->dataStoreGetListener = env->GetObjectField(obj, fid);
  169. if(ref->dataStoreGetListener == NULL)
  170. {
  171. return NULL;
  172. }
  173. fid = env->GetFieldID(
  174. cls, "putListener", "Lcom.zerotierone.sdk.DataStorePutLisetner;");
  175. if(fid == NULL)
  176. {
  177. return NULL; // exception already thrown
  178. }
  179. ref->dataStorePutListener = env->GetObjectField(obj, fid);
  180. if(ref->dataStorePutListener == NULL)
  181. {
  182. return NULL;
  183. }
  184. fid = env->GetFieldID(
  185. cls, "sender", "Lcom.zerotierone.sdk.PacketSender;");
  186. if(fid == NULL)
  187. {
  188. return NULL; // exception already thrown
  189. }
  190. ref->packetSender = env->GetObjectField(obj, fid);
  191. if(ref->packetSender == NULL)
  192. {
  193. return NULL;
  194. }
  195. fid = env->GetFieldID(
  196. cls, "frameListener", "Lcom.zerotierone.sdk.VirtualNetworkFrameListener;");
  197. if(fid == NULL)
  198. {
  199. return NULL; // exception already thrown
  200. }
  201. ref->frameListener = env->GetObjectField(obj, fid);
  202. if(ref->frameListener = NULL)
  203. {
  204. return NULL;
  205. }
  206. fid = env->GetFieldID(
  207. cls, "configListener", "Lcom.zerotierone.sdk.VirtualNetworkConfigListener;");
  208. if(fid == NULL)
  209. {
  210. return NULL; // exception already thrown
  211. }
  212. ref->configListener = env->GetObjectField(obj, fid);
  213. if(ref->configListener == NULL)
  214. {
  215. return NULL;
  216. }
  217. nodeMap.insert(std::make_pair(ref->id, ref));
  218. return resultObject;
  219. }
  220. /*
  221. * Class: com_zerotierone_sdk_Node
  222. * Method: node_delete
  223. * Signature: (J)V
  224. */
  225. JNIEXPORT void JNICALL Java_com_zerotierone_sdk_Node_node_1delete
  226. (JNIEnv *env, jobject obj, jlong id)
  227. {
  228. uint64_t nodeId = (uint64_t)id;
  229. NodeMap::iterator found = nodeMap.find(nodeId);
  230. if(found != nodeMap.end())
  231. {
  232. JniRef *ref = found->second;
  233. nodeMap.erase(found);
  234. delete ref;
  235. ref = NULL;
  236. }
  237. }
  238. /*
  239. * Class: com_zerotierone_sdk_Node
  240. * Method: processVirtualNetworkFrame
  241. * Signature: (JJJJJII[B[J)Lcom/zerotierone/sdk/ResultCode;
  242. */
  243. JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_processVirtualNetworkFrame
  244. (JNIEnv *env, jobject obj,
  245. jlong id,
  246. jlong in_now,
  247. jlong in_nwid,
  248. jlong in_sourceMac,
  249. jlong in_destMac,
  250. jint in_etherType,
  251. jint in_vlanId,
  252. jbyteArray in_frameData,
  253. jlongArray out_nextBackgroundTaskDeadline)
  254. {
  255. uint64_t nodeId = (uint64_t) id;
  256. NodeMap::iterator found = nodeMap.find(nodeId);
  257. if(found == nodeMap.end())
  258. {
  259. // cannot find valid node. We should never get here.
  260. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  261. }
  262. unsigned int nbtd_len = env->GetArrayLength(out_nextBackgroundTaskDeadline);
  263. if(nbtd_len < 1)
  264. {
  265. // array for next background task length has 0 elements!
  266. return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL);
  267. }
  268. ZT1_Node *node = found->second;
  269. uint64_t now = (uint64_t)in_now;
  270. uint64_t nwid = (uint64_t)in_nwid;
  271. uint64_t sourceMac = (uint64_t)in_sourceMac;
  272. uint64_t destMac = (uint64_t)in_destMac;
  273. unsigned int etherType = (unsigned int)in_etherType;
  274. unsigned int vlanId = (unsigned int)in_vlanId;
  275. unsigned int frameLength = env->GetArrayLength(in_frameData);
  276. jbyte *frameData =env->GetByteArrayElements(in_frameData, NULL);
  277. uint64_t nextBackgroundTaskDeadline = 0;
  278. ZT1_ResultCode rc = ZT1_Node_processVirtualNetworkFrame(
  279. node,
  280. now,
  281. nwid,
  282. sourceMac,
  283. destMac,
  284. etherType,
  285. vlanId,
  286. (const void*)frameData,
  287. frameLength,
  288. &nextBackgroundTaskDeadline);
  289. jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL);
  290. outDeadline[0] = (jlong)nextBackgroundTaskDeadline;
  291. env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0);
  292. env->ReleaseByteArrayElements(in_frameData, frameData, 0);
  293. return createResultObject(env, rc);
  294. }
  295. #ifdef __cplusplus
  296. } // extern "C"
  297. #endif