123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- /*
- * $Id$
- *
- * Copyright (C) 2013 Robert Boisvert
- *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
- *
- * The mohqueue module is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * The mohqueue module is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
- #include <sys/types.h>
- #include <stdlib.h>
- #include "mohq.h"
- #include "mohq_db.h"
- #include "mohq_funcs.h"
- MODULE_VERSION
- /**********
- * local function declarations
- **********/
- int fixup_count (void **, int);
- static int mod_child_init (int);
- static void mod_destroy (void);
- static int mod_init (void);
- /**********
- * global varbs
- **********/
- mod_data *pmod_data;
- /**********
- * module exports
- **********/
- /* COMMANDS */
- static cmd_export_t mod_cmds [] = {
- { "mohq_count", (cmd_function) mohq_count, 2, fixup_count, 0,
- REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
- { "mohq_process", (cmd_function) mohq_process, 0, NULL, 0, REQUEST_ROUTE },
- { "mohq_retrieve", (cmd_function) mohq_retrieve, 2, fixup_spve_spve, 0,
- REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
- { "mohq_send", (cmd_function) mohq_send, 1, fixup_spve_spve, 0, REQUEST_ROUTE },
- { NULL, NULL, -1, 0, 0 },
- };
- /* PARAMETERS */
- str db_url = str_init(DEFAULT_DB_URL);
- str db_ctable = str_init("mohqcalls");
- str db_qtable = str_init("mohqueues");
- char *mohdir = "";
- int moh_maxcalls = 50;
- static param_export_t mod_parms [] = {
- { "db_url", PARAM_STR, &db_url },
- { "db_ctable", PARAM_STR, &db_ctable },
- { "db_qtable", PARAM_STR, &db_qtable },
- { "mohdir", PARAM_STRING, &mohdir },
- { "moh_maxcalls", INT_PARAM, &moh_maxcalls },
- { NULL, 0, NULL },
- };
- /* MI COMMANDS */
- static mi_export_t mi_cmds [] = {
- { "debug", mi_debug, 0, 0, 0 },
- { "drop_call", mi_drop_call, 0, 0, 0 },
- { 0, 0, 0, 0, 0 }
- };
- /* MODULE EXPORTS */
- struct module_exports exports = {
- "mohqueue", /* module name */
- DEFAULT_DLFLAGS, /* dlopen flags */
- mod_cmds, /* exported functions */
- mod_parms, /* exported parameters */
- 0, /* statistics */
- mi_cmds, /* MI functions */
- 0, /* exported pseudo-variables */
- 0, /* extra processes */
- mod_init, /* module initialization function */
- 0, /* response handling function */
- mod_destroy, /* destructor function */
- mod_child_init, /* per-child initialization function */
- };
- /**********
- * local functions
- **********/
- /**********
- * Fixup Count
- *
- * INPUT:
- * Arg (1) = parameter array pointer
- * Arg (1) = parameter number
- * OUTPUT: -1 if failed; 0 if saved as pv_elem_t
- **********/
- int fixup_count (void **param, int param_no)
- {
- if (param_no == 1)
- { return fixup_spve_spve (param, 1); }
- if (param_no == 2)
- { return fixup_pvar_null (param, 1); }
- return 0;
- }
- /**********
- * Configuration Initialization
- *
- * INPUT:
- * pmod_data memory allocated
- * configuration values set
- * OUTPUT: 0 if failed; else pmod_data has config values
- **********/
- static int init_cfg (void)
- {
- /**********
- * db_url, db_ctable, db_qtable exist?
- **********/
- if (!db_url.s || db_url.len<=0)
- {
- LM_ERR ("db_url parameter not set!");
- return 0;
- }
- pmod_data->pcfg->db_url = db_url;
- if (!db_ctable.s || db_ctable.len<=0)
- {
- LM_ERR ("db_ctable parameter not set!");
- return 0;
- }
- pmod_data->pcfg->db_ctable = db_ctable;
- if (!db_qtable.s || db_qtable.len<=0)
- {
- LM_ERR ("db_qtable parameter not set!");
- return 0;
- }
- pmod_data->pcfg->db_qtable = db_qtable;
- /**********
- * mohdir
- * o exists?
- * o directory?
- **********/
- if (!*mohdir)
- {
- LM_ERR ("mohdir parameter not set!");
- return 0;
- }
- if (strlen(mohdir) > MOHDIRLEN)
- {
- LM_ERR ("mohdir too long!");
- return 0;
- }
- pmod_data->pcfg->mohdir = mohdir;
- int bfnd = 0;
- struct stat psb [1];
- if (!lstat (mohdir, psb))
- {
- if ((psb->st_mode & S_IFMT) == S_IFDIR)
- { bfnd = 1; }
- }
- if (!bfnd)
- {
- LM_ERR ("mohdir is not a directory!");
- return 0;
- }
- /**********
- * max calls
- * o valid count?
- * o alloc memory
- **********/
- if (moh_maxcalls < 1 || moh_maxcalls > 5000)
- {
- LM_ERR ("moh_maxcalls not in range of 1-5000!");
- return 0;
- }
- pmod_data->pcall_lst =
- (call_lst *) shm_malloc (sizeof (call_lst) * moh_maxcalls);
- if (!pmod_data->pcall_lst)
- {
- LM_ERR ("Unable to allocate shared memory");
- return -1;
- }
- memset (pmod_data->pcall_lst, 0, sizeof (call_lst) * moh_maxcalls);
- pmod_data->call_cnt = moh_maxcalls;
- return -1;
- }
- /**********
- * DB Initialization
- *
- * INPUT:
- * pmod_data memory allocated and cfg values set
- * OUTPUT: 0 if failed; else pmod_data has db_api
- **********/
- static int init_db (void)
- {
- /**********
- * o bind to DB
- * o check capabilities
- * o init DB
- **********/
- str *pdb_url = &pmod_data->pcfg->db_url;
- if (db_bind_mod (pdb_url, pmod_data->pdb))
- {
- LM_ERR ("Unable to bind DB API using %s", pdb_url->s);
- return 0;
- }
- db_func_t *pdb = pmod_data->pdb;
- if (!DB_CAPABILITY ((*pdb), DB_CAP_ALL))
- {
- LM_ERR ("Selected database %s lacks required capabilities", pdb_url->s);
- return 0;
- }
- db1_con_t *pconn = mohq_dbconnect ();
- if (!pconn)
- { return 0; }
- /**********
- * o check schema
- * o remove all call recs
- * o load queue list
- **********/
- if (db_check_table_version (pdb, pconn,
- &pmod_data->pcfg->db_ctable, MOHQ_CTABLE_VERSION) < 0)
- {
- LM_ERR ("%s table in DB %s not at version %d",
- pmod_data->pcfg->db_ctable.s, pdb_url->s, MOHQ_CTABLE_VERSION);
- goto dberr;
- }
- if (db_check_table_version (pdb, pconn,
- &pmod_data->pcfg->db_qtable, MOHQ_QTABLE_VERSION) < 0)
- {
- LM_ERR ("%s table in DB %s not at version %d",
- pmod_data->pcfg->db_qtable.s, pdb_url->s, MOHQ_QTABLE_VERSION);
- goto dberr;
- }
- clear_calls (pconn);
- update_mohq_lst (pconn);
- pmod_data->mohq_update = time (0);
- mohq_dbdisconnect (pconn);
- return -1;
- /**********
- * close DB
- **********/
- dberr:
- pdb->close (pconn);
- return 0;
- }
- /**********
- * Child Module Initialization
- *
- * INPUT:
- * Arg (1) = child type
- * OUTPUT: -1 if db_api not ready; else 0
- **********/
- int mod_child_init (int rank)
- {
- /**********
- * o seed random number generator
- * o make sure DB initialized
- **********/
- srand (getpid () + time (0));
- if (rank == PROC_INIT || rank == PROC_TCP_MAIN || rank == PROC_MAIN)
- { return 0; }
- if (!pmod_data->pdb->init)
- {
- LM_CRIT ("DB API not loaded!");
- return -1;
- }
- return 0;
- }
- /**********
- * Module Teardown
- *
- * INPUT: none
- * OUTPUT: none
- **********/
- void mod_destroy (void)
- {
- /**********
- * o destroy MOH can call queue locks
- * o deallocate shared mem
- **********/
- if (!pmod_data)
- { return; }
- if (pmod_data->pmohq_lock->plock)
- { mohq_lock_destroy (pmod_data->pmohq_lock); }
- if (pmod_data->pcall_lock->plock)
- { mohq_lock_destroy (pmod_data->pcall_lock); }
- if (pmod_data->pmohq_lst)
- { shm_free (pmod_data->pmohq_lst); }
- if (pmod_data->pcall_lst)
- { shm_free (pmod_data->pcall_lst); }
- shm_free (pmod_data);
- return;
- }
- /**********
- * Module Initialization
- *
- * INPUT: none
- * OUTPUT: -1 if failed; 0 if success
- **********/
- int mod_init (void)
- {
- /**********
- * o allocate shared mem and init
- * o init configuration data
- * o init DB
- **********/
- pmod_data = (mod_data *) shm_malloc (sizeof (mod_data));
- if (!pmod_data)
- {
- LM_ERR ("Unable to allocate shared memory");
- return -1;
- }
- memset (pmod_data, 0, sizeof (mod_data));
- if (!init_cfg ())
- { goto initerr; }
- if (!init_db ())
- { goto initerr; }
- /**********
- * o bind to SL/TM/RR modules
- * o bind to RTPPROXY functions
- **********/
- if (sl_load_api (pmod_data->psl))
- {
- LM_ERR ("Unable to load SL module");
- goto initerr;
- }
- if (load_tm_api (pmod_data->ptm))
- {
- LM_ERR ("Unable to load TM module");
- goto initerr;
- }
- if (load_rr_api (pmod_data->prr))
- {
- LM_ERR ("Unable to load RR module");
- goto initerr;
- }
- pmod_data->fn_rtp_answer = find_export ("rtpproxy_answer", 0, 0);
- if (!pmod_data->fn_rtp_answer)
- {
- LM_ERR ("Unable to load rtpproxy_answer");
- goto initerr;
- }
- pmod_data->fn_rtp_offer = find_export ("rtpproxy_offer", 0, 0);
- if (!pmod_data->fn_rtp_offer)
- {
- LM_ERR ("Unable to load rtpproxy_offer");
- goto initerr;
- }
- pmod_data->fn_rtp_stream_c = find_export ("rtpproxy_stream2uac", 2, 0);
- if (!pmod_data->fn_rtp_stream_c)
- {
- LM_ERR ("Unable to load rtpproxy_stream2uac");
- goto initerr;
- }
- pmod_data->fn_rtp_stream_s = find_export ("rtpproxy_stream2uas", 2, 0);
- if (!pmod_data->fn_rtp_stream_s)
- {
- LM_ERR ("Unable to load rtpproxy_stream2uas");
- goto initerr;
- }
- pmod_data->fn_rtp_destroy = find_export ("rtpproxy_destroy", 0, 0);
- if (!pmod_data->fn_rtp_destroy)
- {
- LM_ERR ("Unable to load rtpproxy_destroy");
- goto initerr;
- }
- /**********
- * init MOH and call queue locks
- **********/
- if (!mohq_lock_init (pmod_data->pmohq_lock))
- { goto initerr; }
- if (!mohq_lock_init (pmod_data->pcall_lock))
- { goto initerr; }
- return 0;
- /**********
- * o release shared mem
- * o exit with error
- **********/
- initerr:
- if (pmod_data->mohq_cnt)
- { shm_free (pmod_data->pmohq_lst); }
- if (pmod_data->pcall_lock->plock)
- { mohq_lock_destroy (pmod_data->pcall_lock); }
- shm_free (pmod_data);
- pmod_data = NULL;
- return -1;
- }
|