natpmp-jni.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #ifdef __CYGWIN__
  2. #include <stdint.h>
  3. #define __int64 uint64_t
  4. #endif
  5. #ifdef WIN32
  6. #include <windows.h>
  7. #include <winsock2.h>
  8. #include <ws2tcpip.h>
  9. #endif
  10. #include <stdlib.h>
  11. #include "natpmp.h"
  12. #include "fr_free_miniupnp_libnatpmp_NatPmp.h"
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. JNIEXPORT void JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_init (JNIEnv *env, jobject obj, jint forcegw, jint forcedgw) {
  17. natpmp_t *p = malloc (sizeof(natpmp_t));
  18. if (p == NULL) return;
  19. initnatpmp(p, forcegw, (in_addr_t) forcedgw);
  20. jobject wrapped = (*env)->NewDirectByteBuffer(env, p, sizeof(natpmp_t));
  21. if (wrapped == NULL) return;
  22. jclass thisClass = (*env)->GetObjectClass(env,obj);
  23. if (thisClass == NULL) return;
  24. jfieldID fid = (*env)->GetFieldID(env, thisClass, "natpmp", "Ljava/nio/ByteBuffer;");
  25. if (fid == NULL) return;
  26. (*env)->SetObjectField(env, obj, fid, wrapped);
  27. }
  28. JNIEXPORT void JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_free (JNIEnv *env, jobject obj) {
  29. jclass thisClass = (*env)->GetObjectClass(env,obj);
  30. if (thisClass == NULL) return;
  31. jfieldID fid = (*env)->GetFieldID(env, thisClass, "natpmp", "Ljava/nio/ByteBuffer;");
  32. if (fid == NULL) return;
  33. jobject wrapped = (*env)->GetObjectField(env, obj, fid);
  34. if (wrapped == NULL) return;
  35. natpmp_t* natpmp = (natpmp_t*) (*env)->GetDirectBufferAddress(env, wrapped);
  36. closenatpmp(natpmp);
  37. if (natpmp == NULL) return;
  38. free(natpmp);
  39. (*env)->SetObjectField(env, obj, fid, NULL);
  40. }
  41. static natpmp_t* getNatPmp(JNIEnv* env, jobject obj) {
  42. jclass thisClass = (*env)->GetObjectClass(env,obj);
  43. if (thisClass == NULL) return NULL;
  44. jfieldID fid = (*env)->GetFieldID(env, thisClass, "natpmp", "Ljava/nio/ByteBuffer;");
  45. if (fid == NULL) return NULL;
  46. jobject wrapped = (*env)->GetObjectField(env, obj, fid);
  47. if (wrapped == NULL) return NULL;
  48. natpmp_t* natpmp = (natpmp_t*) (*env)->GetDirectBufferAddress(env, wrapped);
  49. return natpmp;
  50. }
  51. JNIEXPORT jint JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_sendPublicAddressRequest(JNIEnv* env, jobject obj) {
  52. natpmp_t* natpmp = getNatPmp(env, obj);
  53. if (natpmp == NULL) return -1;
  54. return sendpublicaddressrequest(natpmp);
  55. }
  56. JNIEXPORT void JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_startup(JNIEnv* env, jclass cls) {
  57. (void)env;
  58. (void)cls;
  59. #ifdef WIN32
  60. WSADATA wsaData;
  61. WORD wVersionRequested = MAKEWORD(2, 2);
  62. WSAStartup(wVersionRequested, &wsaData);
  63. #endif
  64. }
  65. JNIEXPORT jint JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_sendNewPortMappingRequest(JNIEnv* env, jobject obj, jint protocol, jint privateport, jint publicport, jint lifetime) {
  66. natpmp_t* natpmp = getNatPmp(env, obj);
  67. if (natpmp == NULL) return -1;
  68. return sendnewportmappingrequest(natpmp, protocol, privateport, publicport, lifetime);
  69. }
  70. JNIEXPORT jlong JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_getNatPmpRequestTimeout(JNIEnv* env, jobject obj) {
  71. natpmp_t* natpmp = getNatPmp(env, obj);
  72. struct timeval timeout;
  73. getnatpmprequesttimeout(natpmp, &timeout);
  74. return ((jlong) timeout.tv_sec) * 1000 + (timeout.tv_usec / 1000);
  75. }
  76. #define SET_FIELD(prefix, name, type, longtype) { \
  77. jfieldID fid = (*env)->GetFieldID(env, thisClass, #name, type); \
  78. if (fid == NULL) return -1; \
  79. (*env)->Set ## longtype ## Field(env, response, fid, resp. prefix name); \
  80. }
  81. JNIEXPORT jint JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_readNatPmpResponseOrRetry(JNIEnv* env, jobject obj, jobject response) {
  82. natpmp_t* natpmp = getNatPmp(env, obj);
  83. natpmpresp_t resp;
  84. int result = readnatpmpresponseorretry(natpmp, &resp);
  85. if (result != 0) {
  86. return result;
  87. }
  88. jclass thisClass = (*env)->GetObjectClass(env, response);
  89. if (thisClass == NULL) return -1;
  90. SET_FIELD(,type, "S", Short);
  91. SET_FIELD(,resultcode, "S", Short);
  92. jfieldID fid = (*env)->GetFieldID(env, thisClass, "epoch", "J");
  93. if (fid == NULL) return -1;
  94. (*env)->SetLongField(env, response, fid, ((jlong)resp.epoch) * 1000);
  95. if (resp.type == 0) {
  96. jfieldID fid = (*env)->GetFieldID(env, thisClass, "addr", "I");
  97. if (fid == NULL) return -1;
  98. (*env)->SetIntField(env, response, fid, resp.pnu.publicaddress.addr.s_addr);
  99. } else {
  100. SET_FIELD(pnu.newportmapping., privateport, "I", Int);
  101. SET_FIELD(pnu.newportmapping., mappedpublicport, "I", Int);
  102. jfieldID fid = (*env)->GetFieldID(env, thisClass, "lifetime", "J");
  103. if (fid == NULL) return -1;
  104. (*env)->SetLongField(env, response, fid, ((jlong) resp.pnu.newportmapping.lifetime) * 1000 * 1000);
  105. }
  106. return result;
  107. }
  108. #ifdef __cplusplus
  109. }
  110. #endif