evapi_mod.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /**
  2. * Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com)
  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. *
  12. * This file is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. #include <stdio.h>
  23. #include <unistd.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <ev.h>
  27. #include "../../sr_module.h"
  28. #include "../../dprint.h"
  29. #include "../../ut.h"
  30. #include "../../pt.h"
  31. #include "../../pvar.h"
  32. #include "../../mem/shm_mem.h"
  33. #include "../../mod_fix.h"
  34. #include "../../pvar.h"
  35. #include "../../cfg/cfg_struct.h"
  36. #include "../../lib/kcore/faked_msg.h"
  37. #include "../../modules/tm/tm_load.h"
  38. #include "evapi_dispatch.h"
  39. MODULE_VERSION
  40. static int _evapi_workers = 1;
  41. static char *_evapi_bind_addr = "127.0.0.1";
  42. static int _evapi_bind_port = 8448;
  43. static char *_evapi_bind_param = NULL;
  44. static int _evapi_netstring_format_param = 1;
  45. static tm_api_t tmb;
  46. static int mod_init(void);
  47. static int child_init(int);
  48. static void mod_destroy(void);
  49. static int w_evapi_relay(sip_msg_t* msg, char* evdata, char* p2);
  50. static int w_evapi_async_relay(sip_msg_t* msg, char* evdata, char* p2);
  51. static int w_evapi_close(sip_msg_t* msg, char* p1, char* p2);
  52. static int fixup_evapi_relay(void** param, int param_no);
  53. static cmd_export_t cmds[]={
  54. {"evapi_relay", (cmd_function)w_evapi_relay, 1, fixup_evapi_relay,
  55. 0, ANY_ROUTE},
  56. {"evapi_async_relay", (cmd_function)w_evapi_async_relay, 1, fixup_evapi_relay,
  57. 0, REQUEST_ROUTE},
  58. {"evapi_close", (cmd_function)w_evapi_close, 1, NULL,
  59. 0, ANY_ROUTE},
  60. {0, 0, 0, 0, 0, 0}
  61. };
  62. static param_export_t params[]={
  63. {"workers", INT_PARAM, &_evapi_workers},
  64. {"bind_addr", PARAM_STRING, &_evapi_bind_param},
  65. {"netstring_format", INT_PARAM, &_evapi_netstring_format_param},
  66. {0, 0, 0}
  67. };
  68. static pv_export_t mod_pvs[] = {
  69. { {"evapi", (sizeof("evapi")-1)}, PVT_OTHER, pv_get_evapi,
  70. pv_set_evapi, pv_parse_evapi_name, 0, 0, 0},
  71. { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
  72. };
  73. struct module_exports exports = {
  74. "evapi",
  75. DEFAULT_DLFLAGS, /* dlopen flags */
  76. cmds,
  77. params,
  78. 0,
  79. 0, /* exported MI functions */
  80. mod_pvs, /* exported pseudo-variables */
  81. 0, /* extra processes */
  82. mod_init, /* module initialization function */
  83. 0, /* response function */
  84. mod_destroy, /* destroy function */
  85. child_init /* per child init function */
  86. };
  87. /**
  88. * init module function
  89. */
  90. static int mod_init(void)
  91. {
  92. char *p;
  93. /* init faked sip msg */
  94. if(faked_msg_init()<0) {
  95. LM_ERR("failed to init faked sip msg\n");
  96. return -1;
  97. }
  98. if(load_tm_api( &tmb ) < 0) {
  99. LM_INFO("cannot load the TM-functions - async relay disabled\n");
  100. memset(&tmb, 0, sizeof(tm_api_t));
  101. }
  102. if(_evapi_bind_param!=NULL) {
  103. p = strchr(_evapi_bind_param, ':');
  104. if(p!=NULL) {
  105. *p++ = '\0';
  106. _evapi_bind_port = (short)atoi(p);
  107. if (_evapi_bind_port <= 0) {
  108. LM_ERR("invalid port: %d\n", _evapi_bind_port);
  109. return -1;
  110. }
  111. }
  112. _evapi_bind_addr = _evapi_bind_param;
  113. }
  114. /* add space for one extra process */
  115. register_procs(1 + _evapi_workers);
  116. /* add child to update local config framework structures */
  117. cfg_register_child(1 + _evapi_workers);
  118. evapi_init_environment(_evapi_netstring_format_param);
  119. return 0;
  120. }
  121. /**
  122. * @brief Initialize async module children
  123. */
  124. static int child_init(int rank)
  125. {
  126. int pid;
  127. int i;
  128. if (rank==PROC_INIT) {
  129. if(evapi_init_notify_sockets()<0) {
  130. LM_ERR("failed to initialize notify sockets\n");
  131. return -1;
  132. }
  133. return 0;
  134. }
  135. if (rank!=PROC_MAIN) {
  136. evapi_close_notify_sockets_parent();
  137. return 0;
  138. }
  139. pid=fork_process(PROC_NOCHLDINIT, "EvAPI Dispatcher", 1);
  140. if (pid<0)
  141. return -1; /* error */
  142. if(pid==0) {
  143. /* child */
  144. /* initialize the config framework */
  145. if (cfg_child_init())
  146. return -1;
  147. /* main function for dispatcher */
  148. evapi_close_notify_sockets_child();
  149. if(evapi_run_dispatcher(_evapi_bind_addr, _evapi_bind_port)<0) {
  150. LM_ERR("failed to initialize disptacher process\n");
  151. return -1;
  152. }
  153. }
  154. for(i=0; i<_evapi_workers; i++) {
  155. pid=fork_process(PROC_RPC, "EvAPI Worker", 1);
  156. if (pid<0)
  157. return -1; /* error */
  158. if(pid==0) {
  159. /* child */
  160. /* initialize the config framework */
  161. if (cfg_child_init())
  162. return -1;
  163. /* main function for workers */
  164. if(evapi_run_worker(i+1)<0) {
  165. LM_ERR("failed to initialize worker process: %d\n", i);
  166. return -1;
  167. }
  168. }
  169. }
  170. return 0;
  171. }
  172. /**
  173. * destroy module function
  174. */
  175. static void mod_destroy(void)
  176. {
  177. }
  178. /**
  179. *
  180. */
  181. static int w_evapi_relay(sip_msg_t *msg, char *evdata, char *p2)
  182. {
  183. str sdata;
  184. if(evdata==0) {
  185. LM_ERR("invalid parameters\n");
  186. return -1;
  187. }
  188. if(fixup_get_svalue(msg, (gparam_t*)evdata, &sdata)!=0) {
  189. LM_ERR("unable to get data\n");
  190. return -1;
  191. }
  192. if(sdata.s==NULL || sdata.len == 0) {
  193. LM_ERR("invalid data parameter\n");
  194. return -1;
  195. }
  196. if(evapi_relay(&sdata)<0) {
  197. LM_ERR("failed to relay event: %.*s\n", sdata.len, sdata.s);
  198. return -1;
  199. }
  200. return 1;
  201. }
  202. /**
  203. *
  204. */
  205. static int w_evapi_async_relay(sip_msg_t *msg, char *evdata, char *p2)
  206. {
  207. str sdata;
  208. unsigned int tindex;
  209. unsigned int tlabel;
  210. tm_cell_t *t = 0;
  211. if(evdata==0) {
  212. LM_ERR("invalid parameters\n");
  213. return -1;
  214. }
  215. if(tmb.t_suspend==NULL) {
  216. LM_ERR("evapi async relay is disabled - tm module not loaded\n");
  217. return -1;
  218. }
  219. t = tmb.t_gett();
  220. if (t==NULL || t==T_UNDEFINED)
  221. {
  222. if(tmb.t_newtran(msg)<0)
  223. {
  224. LM_ERR("cannot create the transaction\n");
  225. return -1;
  226. }
  227. t = tmb.t_gett();
  228. if (t==NULL || t==T_UNDEFINED)
  229. {
  230. LM_ERR("cannot lookup the transaction\n");
  231. return -1;
  232. }
  233. }
  234. if(tmb.t_suspend(msg, &tindex, &tlabel)<0)
  235. {
  236. LM_ERR("failed to suppend request processing\n");
  237. return -1;
  238. }
  239. LM_DBG("transaction suspended [%u:%u]\n", tindex, tlabel);
  240. if(fixup_get_svalue(msg, (gparam_t*)evdata, &sdata)!=0) {
  241. LM_ERR("unable to get data\n");
  242. return -1;
  243. }
  244. if(sdata.s==NULL || sdata.len == 0) {
  245. LM_ERR("invalid data parameter\n");
  246. return -1;
  247. }
  248. if(evapi_relay(&sdata)<0) {
  249. LM_ERR("failed to relay event: %.*s\n", sdata.len, sdata.s);
  250. return -2;
  251. }
  252. return 1;
  253. }
  254. /**
  255. *
  256. */
  257. static int fixup_evapi_relay(void** param, int param_no)
  258. {
  259. return fixup_spve_null(param, param_no);
  260. }
  261. /**
  262. *
  263. */
  264. static int w_evapi_close(sip_msg_t* msg, char* p1, char* p2)
  265. {
  266. int ret;
  267. ret = evapi_cfg_close(msg);
  268. if(ret>=0)
  269. return ret+1;
  270. return ret;
  271. }