app_java_mod.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /**
  2. * Copyright (C) 2013 Konstantin Mosesov
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * This file is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * This file is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. */
  21. #include <libgen.h>
  22. #include "../../str.h"
  23. #include "../../sr_module.h"
  24. #include <jni.h>
  25. #include "global.h"
  26. #include "utils.h"
  27. #include "app_java_mod.h"
  28. #include "java_iface.h"
  29. #include "java_support.h"
  30. #include "java_native_methods.h"
  31. MODULE_VERSION
  32. static char* class_name = "Kamailio";
  33. static char* child_init_mname = "child_init";
  34. static char* java_options_str = "-Djava.compiler=NONE";
  35. static int mod_init(void);
  36. static int child_init(int rank);
  37. static void mod_destroy(void);
  38. /** module parameters */
  39. static param_export_t params[] = {
  40. {"class_name", PARAM_STRING, &class_name },
  41. {"child_init_method", PARAM_STRING, &child_init_mname }, /* Unused parameter? */
  42. {"java_options", PARAM_STRING, &java_options_str },
  43. {"force_cmd_exec", INT_PARAM, &force_cmd_exec },
  44. {0,0,0}
  45. };
  46. /*
  47. * Exported functions
  48. */
  49. static cmd_export_t cmds[] = {
  50. { "java_method_exec", (cmd_function)j_nst_exec_0, 2, NULL, 0, ANY_ROUTE },
  51. { "java_method_exec", (cmd_function)j_nst_exec_1, 3, NULL, 0, ANY_ROUTE },
  52. { "java_s_method_exec", (cmd_function)j_s_nst_exec_0, 2, NULL, 0, ANY_ROUTE },
  53. { "java_s_method_exec", (cmd_function)j_s_nst_exec_1, 3, NULL, 0, ANY_ROUTE },
  54. { "java_staticmethod_exec", (cmd_function)j_st_exec_0, 2, NULL, 0, ANY_ROUTE },
  55. { "java_staticmethod_exec", (cmd_function)j_st_exec_1, 3, NULL, 0, ANY_ROUTE },
  56. { "java_s_staticmethod_exec", (cmd_function)j_s_st_exec_0, 2, NULL, 0, ANY_ROUTE },
  57. { "java_s_staticmethod_exec", (cmd_function)j_s_st_exec_1, 3, NULL, 0, ANY_ROUTE },
  58. { 0, 0, 0, 0, 0, 0 }
  59. };
  60. /** module exports */
  61. struct module_exports exports = {
  62. APP_NAME, /* module name */
  63. // RTLD_NOW | RTLD_GLOBAL, /* dlopen flags */
  64. DEFAULT_DLFLAGS, /* dlopen flags */
  65. cmds, /* exported functions */
  66. params, /* exported parameters */
  67. 0, /* exported statistics */
  68. 0, /* exported MI functions */
  69. 0, /* exported pseudo-variables */
  70. 0, /* extra processes */
  71. mod_init, /* module initialization function */
  72. (response_function) NULL, /* response handling function */
  73. (destroy_function) mod_destroy, /* destroy function */
  74. child_init /* per-child init function */
  75. };
  76. static int mod_init(void)
  77. {
  78. JavaVMInitArgs vm_args;
  79. jint res;
  80. JavaVMOption *options;
  81. char **opts;
  82. int nOptions;
  83. if (force_cmd_exec < 0 || force_cmd_exec > 1)
  84. {
  85. LM_ERR("Parameter force_cmd_exec should be either 0 or 1\n");
  86. return -1;
  87. }
  88. if (force_cmd_exec)
  89. {
  90. LM_NOTICE("%s: Parameter force_cmd_exec may cause a memory leaks if used from embedded languages\n", APP_NAME);
  91. }
  92. options = (JavaVMOption *)pkg_malloc(sizeof(JavaVMOption));
  93. if (!options)
  94. {
  95. LM_ERR("pkg_malloc() failed: Couldn't initialize Java VM: Not enough memory\n");
  96. return -1;
  97. }
  98. memset(options, 0, sizeof(JavaVMOption));
  99. LM_INFO("Initializing Java VM with options: %s\n", java_options_str);
  100. opts = split(java_options_str, " ");
  101. for (nOptions=0; opts[nOptions] != NULL; nOptions++)
  102. {
  103. options[nOptions].optionString = opts[nOptions];
  104. }
  105. /* IMPORTANT: specify vm_args version # if you use JDK1.1.2 and beyond */
  106. vm_args.version = JNI_VERSION_1_2;
  107. vm_args.nOptions = nOptions;
  108. vm_args.ignoreUnrecognized = JNI_FALSE;
  109. vm_args.options = options;
  110. res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
  111. if (res < 0)
  112. {
  113. handle_VM_init_failure(res);
  114. return -1;
  115. }
  116. LM_INFO("%s: Java VM initialization OK\n", APP_NAME);
  117. // attach to current thread
  118. (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
  119. if ((*env)->ExceptionCheck(env))
  120. {
  121. handle_exception();
  122. return -1;
  123. }
  124. KamailioClass = (*env)->FindClass(env, class_name);
  125. if (!KamailioClass || (*env)->ExceptionCheck(env))
  126. {
  127. handle_exception();
  128. (*jvm)->DetachCurrentThread(jvm);
  129. return -1;
  130. }
  131. KamailioClassRef = (*env)->NewGlobalRef(env, KamailioClass);
  132. if (!KamailioClassRef || (*env)->ExceptionCheck(env))
  133. {
  134. handle_exception();
  135. (*jvm)->DetachCurrentThread(jvm);
  136. return -1;
  137. }
  138. KamailioID = (*env)->GetMethodID(env, KamailioClass, "<init>", "()V");
  139. if (!KamailioID || (*env)->ExceptionCheck(env))
  140. {
  141. handle_exception();
  142. (*jvm)->DetachCurrentThread(jvm);
  143. return -1;
  144. }
  145. // calling constructor
  146. KamailioClassInstance = (*env)->NewObject(env, KamailioClass, KamailioID);
  147. if (!KamailioClassInstance || (*env)->ExceptionCheck(env))
  148. {
  149. handle_exception();
  150. (*jvm)->DetachCurrentThread(jvm);
  151. return -1;
  152. }
  153. // keep a reference to kamailio class instance
  154. KamailioClassInstanceRef = (*env)->NewGlobalRef(env, KamailioClassInstance);
  155. if (!KamailioClassInstanceRef || (*env)->ExceptionCheck(env))
  156. {
  157. handle_exception();
  158. (*jvm)->DetachCurrentThread(jvm);
  159. return -1;
  160. }
  161. LM_INFO("%s: module initialization OK\n", APP_NAME);
  162. if (jvm != NULL)
  163. (*jvm)->DetachCurrentThread(jvm);
  164. return 0;
  165. }
  166. static int child_init(int rank)
  167. {
  168. int retval;
  169. jmethodID child_init_id;
  170. // attach to current thread
  171. (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
  172. if ((*env)->ExceptionCheck(env))
  173. {
  174. handle_exception();
  175. return -1;
  176. }
  177. child_init_id = (*env)->GetMethodID(env, KamailioClass, "child_init", "(I)I");
  178. if ((*env)->ExceptionCheck(env))
  179. {
  180. handle_exception();
  181. (*jvm)->DetachCurrentThread(jvm);
  182. return -1;
  183. }
  184. retval = (int)(*env)->CallIntMethod(env, KamailioClassInstanceRef, child_init_id, rank);
  185. if ((*env)->ExceptionCheck(env))
  186. {
  187. handle_exception();
  188. (*jvm)->DetachCurrentThread(jvm);
  189. return -1;
  190. }
  191. (*env)->DeleteLocalRef(env, child_init_id);
  192. (*jvm)->DetachCurrentThread(jvm);
  193. msg = NULL;
  194. return retval;
  195. }
  196. static void mod_destroy(void)
  197. {
  198. if (env != NULL)
  199. {
  200. (*env)->DeleteGlobalRef(env, KamailioClassInstanceRef);
  201. (*env)->DeleteGlobalRef(env, KamailioClassRef);
  202. }
  203. if (jvm != NULL)
  204. {
  205. (*jvm)->DetachCurrentThread(jvm);
  206. (*jvm)->DestroyJavaVM(jvm);
  207. }
  208. if (msg)
  209. {
  210. pkg_free(msg);
  211. }
  212. }