mohq.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2013 Robert Boisvert
  5. *
  6. * This file is part of the mohqueue module for sip-router, a free SIP server.
  7. *
  8. * The mohqueue module is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * The mohqueue module is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. */
  23. #include <sys/types.h>
  24. #include <stdlib.h>
  25. #include "mohq.h"
  26. #include "mohq_db.h"
  27. #include "mohq_funcs.h"
  28. MODULE_VERSION
  29. /**********
  30. * local function declarations
  31. **********/
  32. int fixup_count (void **, int);
  33. static int mod_child_init (int);
  34. static void mod_destroy (void);
  35. static int mod_init (void);
  36. /**********
  37. * global varbs
  38. **********/
  39. mod_data *pmod_data;
  40. /**********
  41. * module exports
  42. **********/
  43. /* COMMANDS */
  44. static cmd_export_t mod_cmds [] = {
  45. { "mohq_count", (cmd_function) mohq_count, 2, fixup_count, 0,
  46. REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
  47. { "mohq_process", (cmd_function) mohq_process, 0, NULL, 0, REQUEST_ROUTE },
  48. { "mohq_retrieve", (cmd_function) mohq_retrieve, 2, fixup_spve_spve, 0,
  49. REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
  50. { "mohq_send", (cmd_function) mohq_send, 1, fixup_spve_spve, 0, REQUEST_ROUTE },
  51. { NULL, NULL, -1, 0, 0 },
  52. };
  53. /* PARAMETERS */
  54. str db_url = str_init(DEFAULT_DB_URL);
  55. str db_ctable = str_init("mohqcalls");
  56. str db_qtable = str_init("mohqueues");
  57. char *mohdir = "";
  58. int moh_maxcalls = 50;
  59. static param_export_t mod_parms [] = {
  60. { "db_url", PARAM_STR, &db_url },
  61. { "db_ctable", PARAM_STR, &db_ctable },
  62. { "db_qtable", PARAM_STR, &db_qtable },
  63. { "mohdir", PARAM_STRING, &mohdir },
  64. { "moh_maxcalls", INT_PARAM, &moh_maxcalls },
  65. { NULL, 0, NULL },
  66. };
  67. /* MI COMMANDS */
  68. static mi_export_t mi_cmds [] = {
  69. { "debug", mi_debug, 0, 0, 0 },
  70. { "drop_call", mi_drop_call, 0, 0, 0 },
  71. { 0, 0, 0, 0, 0 }
  72. };
  73. /* MODULE EXPORTS */
  74. struct module_exports exports = {
  75. "mohqueue", /* module name */
  76. DEFAULT_DLFLAGS, /* dlopen flags */
  77. mod_cmds, /* exported functions */
  78. mod_parms, /* exported parameters */
  79. 0, /* statistics */
  80. mi_cmds, /* MI functions */
  81. 0, /* exported pseudo-variables */
  82. 0, /* extra processes */
  83. mod_init, /* module initialization function */
  84. 0, /* response handling function */
  85. mod_destroy, /* destructor function */
  86. mod_child_init, /* per-child initialization function */
  87. };
  88. /**********
  89. * local functions
  90. **********/
  91. /**********
  92. * Fixup Count
  93. *
  94. * INPUT:
  95. * Arg (1) = parameter array pointer
  96. * Arg (1) = parameter number
  97. * OUTPUT: -1 if failed; 0 if saved as pv_elem_t
  98. **********/
  99. int fixup_count (void **param, int param_no)
  100. {
  101. if (param_no == 1)
  102. { return fixup_spve_spve (param, 1); }
  103. if (param_no == 2)
  104. { return fixup_pvar_null (param, 1); }
  105. return 0;
  106. }
  107. /**********
  108. * Configuration Initialization
  109. *
  110. * INPUT:
  111. * pmod_data memory allocated
  112. * configuration values set
  113. * OUTPUT: 0 if failed; else pmod_data has config values
  114. **********/
  115. static int init_cfg (void)
  116. {
  117. /**********
  118. * db_url, db_ctable, db_qtable exist?
  119. **********/
  120. if (!db_url.s || db_url.len<=0)
  121. {
  122. LM_ERR ("db_url parameter not set!");
  123. return 0;
  124. }
  125. pmod_data->pcfg->db_url = db_url;
  126. if (!db_ctable.s || db_ctable.len<=0)
  127. {
  128. LM_ERR ("db_ctable parameter not set!");
  129. return 0;
  130. }
  131. pmod_data->pcfg->db_ctable = db_ctable;
  132. if (!db_qtable.s || db_qtable.len<=0)
  133. {
  134. LM_ERR ("db_qtable parameter not set!");
  135. return 0;
  136. }
  137. pmod_data->pcfg->db_qtable = db_qtable;
  138. /**********
  139. * mohdir
  140. * o exists?
  141. * o directory?
  142. **********/
  143. if (!*mohdir)
  144. {
  145. LM_ERR ("mohdir parameter not set!");
  146. return 0;
  147. }
  148. if (strlen(mohdir) > MOHDIRLEN)
  149. {
  150. LM_ERR ("mohdir too long!");
  151. return 0;
  152. }
  153. pmod_data->pcfg->mohdir = mohdir;
  154. int bfnd = 0;
  155. struct stat psb [1];
  156. if (!lstat (mohdir, psb))
  157. {
  158. if ((psb->st_mode & S_IFMT) == S_IFDIR)
  159. { bfnd = 1; }
  160. }
  161. if (!bfnd)
  162. {
  163. LM_ERR ("mohdir is not a directory!");
  164. return 0;
  165. }
  166. /**********
  167. * max calls
  168. * o valid count?
  169. * o alloc memory
  170. **********/
  171. if (moh_maxcalls < 1 || moh_maxcalls > 5000)
  172. {
  173. LM_ERR ("moh_maxcalls not in range of 1-5000!");
  174. return 0;
  175. }
  176. pmod_data->pcall_lst =
  177. (call_lst *) shm_malloc (sizeof (call_lst) * moh_maxcalls);
  178. if (!pmod_data->pcall_lst)
  179. {
  180. LM_ERR ("Unable to allocate shared memory");
  181. return -1;
  182. }
  183. memset (pmod_data->pcall_lst, 0, sizeof (call_lst) * moh_maxcalls);
  184. pmod_data->call_cnt = moh_maxcalls;
  185. return -1;
  186. }
  187. /**********
  188. * DB Initialization
  189. *
  190. * INPUT:
  191. * pmod_data memory allocated and cfg values set
  192. * OUTPUT: 0 if failed; else pmod_data has db_api
  193. **********/
  194. static int init_db (void)
  195. {
  196. /**********
  197. * o bind to DB
  198. * o check capabilities
  199. * o init DB
  200. **********/
  201. str *pdb_url = &pmod_data->pcfg->db_url;
  202. if (db_bind_mod (pdb_url, pmod_data->pdb))
  203. {
  204. LM_ERR ("Unable to bind DB API using %s", pdb_url->s);
  205. return 0;
  206. }
  207. db_func_t *pdb = pmod_data->pdb;
  208. if (!DB_CAPABILITY ((*pdb), DB_CAP_ALL))
  209. {
  210. LM_ERR ("Selected database %s lacks required capabilities", pdb_url->s);
  211. return 0;
  212. }
  213. db1_con_t *pconn = mohq_dbconnect ();
  214. if (!pconn)
  215. { return 0; }
  216. /**********
  217. * o check schema
  218. * o remove all call recs
  219. * o load queue list
  220. **********/
  221. if (db_check_table_version (pdb, pconn,
  222. &pmod_data->pcfg->db_ctable, MOHQ_CTABLE_VERSION) < 0)
  223. {
  224. LM_ERR ("%s table in DB %s not at version %d",
  225. pmod_data->pcfg->db_ctable.s, pdb_url->s, MOHQ_CTABLE_VERSION);
  226. goto dberr;
  227. }
  228. if (db_check_table_version (pdb, pconn,
  229. &pmod_data->pcfg->db_qtable, MOHQ_QTABLE_VERSION) < 0)
  230. {
  231. LM_ERR ("%s table in DB %s not at version %d",
  232. pmod_data->pcfg->db_qtable.s, pdb_url->s, MOHQ_QTABLE_VERSION);
  233. goto dberr;
  234. }
  235. clear_calls (pconn);
  236. update_mohq_lst (pconn);
  237. pmod_data->mohq_update = time (0);
  238. mohq_dbdisconnect (pconn);
  239. return -1;
  240. /**********
  241. * close DB
  242. **********/
  243. dberr:
  244. pdb->close (pconn);
  245. return 0;
  246. }
  247. /**********
  248. * Child Module Initialization
  249. *
  250. * INPUT:
  251. * Arg (1) = child type
  252. * OUTPUT: -1 if db_api not ready; else 0
  253. **********/
  254. int mod_child_init (int rank)
  255. {
  256. /**********
  257. * o seed random number generator
  258. * o make sure DB initialized
  259. **********/
  260. srand (getpid () + time (0));
  261. if (rank == PROC_INIT || rank == PROC_TCP_MAIN || rank == PROC_MAIN)
  262. { return 0; }
  263. if (!pmod_data->pdb->init)
  264. {
  265. LM_CRIT ("DB API not loaded!");
  266. return -1;
  267. }
  268. return 0;
  269. }
  270. /**********
  271. * Module Teardown
  272. *
  273. * INPUT: none
  274. * OUTPUT: none
  275. **********/
  276. void mod_destroy (void)
  277. {
  278. /**********
  279. * o destroy MOH can call queue locks
  280. * o deallocate shared mem
  281. **********/
  282. if (!pmod_data)
  283. { return; }
  284. if (pmod_data->pmohq_lock->plock)
  285. { mohq_lock_destroy (pmod_data->pmohq_lock); }
  286. if (pmod_data->pcall_lock->plock)
  287. { mohq_lock_destroy (pmod_data->pcall_lock); }
  288. if (pmod_data->pmohq_lst)
  289. { shm_free (pmod_data->pmohq_lst); }
  290. if (pmod_data->pcall_lst)
  291. { shm_free (pmod_data->pcall_lst); }
  292. shm_free (pmod_data);
  293. return;
  294. }
  295. /**********
  296. * Module Initialization
  297. *
  298. * INPUT: none
  299. * OUTPUT: -1 if failed; 0 if success
  300. **********/
  301. int mod_init (void)
  302. {
  303. /**********
  304. * o allocate shared mem and init
  305. * o init configuration data
  306. * o init DB
  307. **********/
  308. pmod_data = (mod_data *) shm_malloc (sizeof (mod_data));
  309. if (!pmod_data)
  310. {
  311. LM_ERR ("Unable to allocate shared memory");
  312. return -1;
  313. }
  314. memset (pmod_data, 0, sizeof (mod_data));
  315. if (!init_cfg ())
  316. { goto initerr; }
  317. if (!init_db ())
  318. { goto initerr; }
  319. /**********
  320. * o bind to SL/TM/RR modules
  321. * o bind to RTPPROXY functions
  322. **********/
  323. if (sl_load_api (pmod_data->psl))
  324. {
  325. LM_ERR ("Unable to load SL module");
  326. goto initerr;
  327. }
  328. if (load_tm_api (pmod_data->ptm))
  329. {
  330. LM_ERR ("Unable to load TM module");
  331. goto initerr;
  332. }
  333. if (load_rr_api (pmod_data->prr))
  334. {
  335. LM_ERR ("Unable to load RR module");
  336. goto initerr;
  337. }
  338. pmod_data->fn_rtp_answer = find_export ("rtpproxy_answer", 0, 0);
  339. if (!pmod_data->fn_rtp_answer)
  340. {
  341. LM_ERR ("Unable to load rtpproxy_answer");
  342. goto initerr;
  343. }
  344. pmod_data->fn_rtp_offer = find_export ("rtpproxy_offer", 0, 0);
  345. if (!pmod_data->fn_rtp_offer)
  346. {
  347. LM_ERR ("Unable to load rtpproxy_offer");
  348. goto initerr;
  349. }
  350. pmod_data->fn_rtp_stream_c = find_export ("rtpproxy_stream2uac", 2, 0);
  351. if (!pmod_data->fn_rtp_stream_c)
  352. {
  353. LM_ERR ("Unable to load rtpproxy_stream2uac");
  354. goto initerr;
  355. }
  356. pmod_data->fn_rtp_stream_s = find_export ("rtpproxy_stream2uas", 2, 0);
  357. if (!pmod_data->fn_rtp_stream_s)
  358. {
  359. LM_ERR ("Unable to load rtpproxy_stream2uas");
  360. goto initerr;
  361. }
  362. pmod_data->fn_rtp_destroy = find_export ("rtpproxy_destroy", 0, 0);
  363. if (!pmod_data->fn_rtp_destroy)
  364. {
  365. LM_ERR ("Unable to load rtpproxy_destroy");
  366. goto initerr;
  367. }
  368. /**********
  369. * init MOH and call queue locks
  370. **********/
  371. if (!mohq_lock_init (pmod_data->pmohq_lock))
  372. { goto initerr; }
  373. if (!mohq_lock_init (pmod_data->pcall_lock))
  374. { goto initerr; }
  375. return 0;
  376. /**********
  377. * o release shared mem
  378. * o exit with error
  379. **********/
  380. initerr:
  381. if (pmod_data->mohq_cnt)
  382. { shm_free (pmod_data->pmohq_lst); }
  383. if (pmod_data->pcall_lock->plock)
  384. { mohq_lock_destroy (pmod_data->pcall_lock); }
  385. shm_free (pmod_data);
  386. pmod_data = NULL;
  387. return -1;
  388. }