evapi_mod.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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, 0, NULL,
  59. 0, ANY_ROUTE},
  60. {"evapi_close", (cmd_function)w_evapi_close, 1, NULL,
  61. 0, ANY_ROUTE},
  62. {0, 0, 0, 0, 0, 0}
  63. };
  64. static param_export_t params[]={
  65. {"workers", INT_PARAM, &_evapi_workers},
  66. {"bind_addr", PARAM_STRING, &_evapi_bind_param},
  67. {"netstring_format", INT_PARAM, &_evapi_netstring_format_param},
  68. {0, 0, 0}
  69. };
  70. static pv_export_t mod_pvs[] = {
  71. { {"evapi", (sizeof("evapi")-1)}, PVT_OTHER, pv_get_evapi,
  72. pv_set_evapi, pv_parse_evapi_name, 0, 0, 0},
  73. { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
  74. };
  75. struct module_exports exports = {
  76. "evapi",
  77. DEFAULT_DLFLAGS, /* dlopen flags */
  78. cmds,
  79. params,
  80. 0,
  81. 0, /* exported MI functions */
  82. mod_pvs, /* exported pseudo-variables */
  83. 0, /* extra processes */
  84. mod_init, /* module initialization function */
  85. 0, /* response function */
  86. mod_destroy, /* destroy function */
  87. child_init /* per child init function */
  88. };
  89. /**
  90. * init module function
  91. */
  92. static int mod_init(void)
  93. {
  94. char *p;
  95. /* init faked sip msg */
  96. if(faked_msg_init()<0) {
  97. LM_ERR("failed to init faked sip msg\n");
  98. return -1;
  99. }
  100. if(load_tm_api( &tmb ) < 0) {
  101. LM_INFO("cannot load the TM-functions - async relay disabled\n");
  102. memset(&tmb, 0, sizeof(tm_api_t));
  103. }
  104. if(_evapi_bind_param!=NULL) {
  105. p = strchr(_evapi_bind_param, ':');
  106. if(p!=NULL) {
  107. *p++ = '\0';
  108. _evapi_bind_port = (short)atoi(p);
  109. if (_evapi_bind_port <= 0) {
  110. LM_ERR("invalid port: %d\n", _evapi_bind_port);
  111. return -1;
  112. }
  113. }
  114. _evapi_bind_addr = _evapi_bind_param;
  115. }
  116. /* add space for one extra process */
  117. register_procs(1 + _evapi_workers);
  118. /* add child to update local config framework structures */
  119. cfg_register_child(1 + _evapi_workers);
  120. evapi_init_environment(_evapi_netstring_format_param);
  121. return 0;
  122. }
  123. /**
  124. * @brief Initialize async module children
  125. */
  126. static int child_init(int rank)
  127. {
  128. int pid;
  129. int i;
  130. if (rank==PROC_INIT) {
  131. if(evapi_init_notify_sockets()<0) {
  132. LM_ERR("failed to initialize notify sockets\n");
  133. return -1;
  134. }
  135. return 0;
  136. }
  137. if (rank!=PROC_MAIN) {
  138. evapi_close_notify_sockets_parent();
  139. return 0;
  140. }
  141. pid=fork_process(PROC_RPC, "EvAPI Dispatcher", 1);
  142. if (pid<0)
  143. return -1; /* error */
  144. if(pid==0) {
  145. /* child */
  146. /* initialize the config framework */
  147. if (cfg_child_init())
  148. return -1;
  149. /* main function for dispatcher */
  150. evapi_close_notify_sockets_child();
  151. if(evapi_run_dispatcher(_evapi_bind_addr, _evapi_bind_port)<0) {
  152. LM_ERR("failed to initialize disptacher process\n");
  153. return -1;
  154. }
  155. }
  156. for(i=0; i<_evapi_workers; i++) {
  157. pid=fork_process(PROC_RPC, "EvAPI Worker", 1);
  158. if (pid<0)
  159. return -1; /* error */
  160. if(pid==0) {
  161. /* child */
  162. /* initialize the config framework */
  163. if (cfg_child_init())
  164. return -1;
  165. /* main function for workers */
  166. if(evapi_run_worker(i+1)<0) {
  167. LM_ERR("failed to initialize worker process: %d\n", i);
  168. return -1;
  169. }
  170. }
  171. }
  172. return 0;
  173. }
  174. /**
  175. * destroy module function
  176. */
  177. static void mod_destroy(void)
  178. {
  179. }
  180. /**
  181. *
  182. */
  183. static int w_evapi_relay(sip_msg_t *msg, char *evdata, char *p2)
  184. {
  185. str sdata;
  186. if(evdata==0) {
  187. LM_ERR("invalid parameters\n");
  188. return -1;
  189. }
  190. if(fixup_get_svalue(msg, (gparam_t*)evdata, &sdata)!=0) {
  191. LM_ERR("unable to get data\n");
  192. return -1;
  193. }
  194. if(sdata.s==NULL || sdata.len == 0) {
  195. LM_ERR("invalid data parameter\n");
  196. return -1;
  197. }
  198. if(evapi_relay(&sdata)<0) {
  199. LM_ERR("failed to relay event: %.*s\n", sdata.len, sdata.s);
  200. return -1;
  201. }
  202. return 1;
  203. }
  204. /**
  205. *
  206. */
  207. static int w_evapi_async_relay(sip_msg_t *msg, char *evdata, char *p2)
  208. {
  209. str sdata;
  210. unsigned int tindex;
  211. unsigned int tlabel;
  212. tm_cell_t *t = 0;
  213. if(evdata==0) {
  214. LM_ERR("invalid parameters\n");
  215. return -1;
  216. }
  217. if(tmb.t_suspend==NULL) {
  218. LM_ERR("evapi async relay is disabled - tm module not loaded\n");
  219. return -1;
  220. }
  221. t = tmb.t_gett();
  222. if (t==NULL || t==T_UNDEFINED)
  223. {
  224. if(tmb.t_newtran(msg)<0)
  225. {
  226. LM_ERR("cannot create the transaction\n");
  227. return -1;
  228. }
  229. t = tmb.t_gett();
  230. if (t==NULL || t==T_UNDEFINED)
  231. {
  232. LM_ERR("cannot lookup the transaction\n");
  233. return -1;
  234. }
  235. }
  236. if(tmb.t_suspend(msg, &tindex, &tlabel)<0)
  237. {
  238. LM_ERR("failed to suppend request processing\n");
  239. return -1;
  240. }
  241. LM_DBG("transaction suspended [%u:%u]\n", tindex, tlabel);
  242. if(fixup_get_svalue(msg, (gparam_t*)evdata, &sdata)!=0) {
  243. LM_ERR("unable to get data\n");
  244. return -1;
  245. }
  246. if(sdata.s==NULL || sdata.len == 0) {
  247. LM_ERR("invalid data parameter\n");
  248. return -1;
  249. }
  250. if(evapi_relay(&sdata)<0) {
  251. LM_ERR("failed to relay event: %.*s\n", sdata.len, sdata.s);
  252. return -2;
  253. }
  254. return 1;
  255. }
  256. /**
  257. *
  258. */
  259. static int fixup_evapi_relay(void** param, int param_no)
  260. {
  261. return fixup_spve_null(param, param_no);
  262. }
  263. /**
  264. *
  265. */
  266. static int w_evapi_close(sip_msg_t* msg, char* p1, char* p2)
  267. {
  268. int ret;
  269. ret = evapi_cfg_close(msg);
  270. if(ret>=0)
  271. return ret+1;
  272. return ret;
  273. }