/* * $Id: ul_mod.c,v 1.42.2.1 2005/03/29 11:54:35 janakj Exp $ * * Usrloc module interface * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of ser, a free SIP server. * * ser 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 * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * ser 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * History: * --------- * 2003-01-27 timer activity printing #ifdef-ed to EXTRA_DEBUG (jiri) * 2003-03-11 New module interface (janakj) * 2003-03-12 added replication and state columns (nils) * 2003-03-16 flags export parameter added (janakj) * 2003-04-05: default_uri #define used (jiri) * 2003-04-21 failed fifo init stops init process (jiri) * 2004-03-17 generic callbacks added (bogdan) * 2004-06-07 updated to the new DB api (andrei) */ #include #include "ul_mod.h" #include "../../sr_module.h" #include "../../dprint.h" #include "../../timer.h" /* register_timer */ #include "../../globals.h" /* is_main */ #include "dlist.h" /* register_udomain */ #include "udomain.h" /* {insert,delete,get,release}_urecord */ #include "urecord.h" /* {insert,delete,get}_ucontact */ #include "ucontact.h" /* update_ucontact */ #include "ul_fifo.h" #include "ul_unixsock.h" #include "ul_callback.h" #include "notify.h" #include "usrloc.h" MODULE_VERSION #define USER_COL "username" #define DOMAIN_COL "domain" #define CONTACT_COL "contact" #define EXPIRES_COL "expires" #define Q_COL "q" #define CALLID_COL "callid" #define CSEQ_COL "cseq" #define METHOD_COL "method" #define STATE_COL "state" #define FLAGS_COL "flags" #define USER_AGENT_COL "user_agent" #define RECEIVED_COL "received" static int mod_init(void); /* Module initialization function */ static void destroy(void); /* Module destroy function */ static void timer(unsigned int ticks, void* param); /* Timer handler */ static int child_init(int rank); /* Per-child init function */ extern int bind_usrloc(usrloc_api_t* api); /* * Module parameters and their default values */ str user_col = {USER_COL, sizeof(USER_COL) - 1}; /* Name of column containing usernames */ str domain_col = {DOMAIN_COL, sizeof(DOMAIN_COL) - 1}; /* Name of column containing domains */ str contact_col = {CONTACT_COL, sizeof(CONTACT_COL) - 1}; /* Name of column containing contact addresses */ str expires_col = {EXPIRES_COL, sizeof(EXPIRES_COL) - 1}; /* Name of column containing expires values */ str q_col = {Q_COL, sizeof(Q_COL) - 1}; /* Name of column containing q values */ str callid_col = {CALLID_COL, sizeof(CALLID_COL) - 1}; /* Name of column containing callid string */ str cseq_col = {CSEQ_COL, sizeof(CSEQ_COL) - 1}; /* Name of column containing cseq values */ str method_col = {METHOD_COL, sizeof(METHOD_COL) - 1}; /* Name of column containing supported method */ str state_col = {STATE_COL, sizeof(STATE_COL) - 1}; /* Name of column containing contact state */ str flags_col = {FLAGS_COL, sizeof(FLAGS_COL) - 1}; /* Name of column containing flags */ str user_agent_col = {USER_AGENT_COL, sizeof(USER_AGENT_COL) - 1}; /* Name of column containing user agent string */ str received_col = {RECEIVED_COL, sizeof(RECEIVED_COL) - 1}; /* Name of column containing transport info of REGISTER */ str db_url = {DEFAULT_DB_URL, sizeof(DEFAULT_DB_URL) - 1}; /* Database URL */ int timer_interval = 60; /* Timer interval in seconds */ int db_mode = 0; /* Database sync scheme: 0-no db, 1-write through, 2-write back */ int use_domain = 0; /* Whether usrloc should use domain part of aor */ int desc_time_order = 0; /* By default do not enable timestamp ordering */ db_con_t* ul_dbh; /* Database connection handle */ db_func_t ul_dbf; /* * Exported functions */ static cmd_export_t cmds[] = { {"ul_register_udomain", (cmd_function)register_udomain, 1, 0, 0}, {"ul_insert_urecord", (cmd_function)insert_urecord, 1, 0, 0}, {"ul_delete_urecord", (cmd_function)delete_urecord, 1, 0, 0}, {"ul_get_urecord", (cmd_function)get_urecord, 1, 0, 0}, {"ul_lock_udomain", (cmd_function)lock_udomain, 1, 0, 0}, {"ul_unlock_udomain", (cmd_function)unlock_udomain, 1, 0, 0}, {"ul_release_urecord", (cmd_function)release_urecord, 1, 0, 0}, {"ul_insert_ucontact", (cmd_function)insert_ucontact, 1, 0, 0}, {"ul_delete_ucontact", (cmd_function)delete_ucontact, 1, 0, 0}, {"ul_get_ucontact", (cmd_function)get_ucontact, 1, 0, 0}, {"ul_get_all_ucontacts", (cmd_function)get_all_ucontacts, 1, 0, 0}, {"ul_update_ucontact", (cmd_function)update_ucontact, 1, 0, 0}, {"ul_register_watcher", (cmd_function)register_watcher, 1, 0, 0}, {"ul_unregister_watcher", (cmd_function)unregister_watcher, 1, 0, 0}, {"ul_bind_usrloc", (cmd_function)bind_usrloc, 1, 0, 0}, {"ul_register_ulcb", (cmd_function)register_ulcb, 1, 0, 0}, {0, 0, 0, 0, 0} }; /* * Exported parameters */ static param_export_t params[] = { {"user_column", STR_PARAM, &user_col.s }, {"domain_column", STR_PARAM, &domain_col.s }, {"contact_column", STR_PARAM, &contact_col.s }, {"expires_column", STR_PARAM, &expires_col.s }, {"q_column", STR_PARAM, &q_col.s }, {"callid_column", STR_PARAM, &callid_col.s }, {"cseq_column", STR_PARAM, &cseq_col.s }, {"method_column", STR_PARAM, &method_col.s }, {"flags_column", STR_PARAM, &flags_col.s }, {"db_url", STR_PARAM, &db_url.s }, {"timer_interval", INT_PARAM, &timer_interval }, {"db_mode", INT_PARAM, &db_mode }, {"use_domain", INT_PARAM, &use_domain }, {"desc_time_order", INT_PARAM, &desc_time_order}, {"user_agent_column", STR_PARAM, &user_agent_col }, {"received_column", STR_PARAM, &received_col }, {0, 0, 0} }; struct module_exports exports = { "usrloc", cmds, /* Exported functions */ params, /* Export parameters */ mod_init, /* Module initialization function */ 0, /* Response function */ destroy, /* Destroy function */ 0, /* OnCancel function */ child_init /* Child initialization function */ }; /* * Module initialization function */ static int mod_init(void) { DBG("usrloc - initializing\n"); /* Compute the lengths of string parameters */ user_col.len = strlen(user_col.s); domain_col.len = strlen(domain_col.s); contact_col.len = strlen(contact_col.s); expires_col.len = strlen(expires_col.s); q_col.len = strlen(q_col.s); callid_col.len = strlen(callid_col.s); cseq_col.len = strlen(cseq_col.s); method_col.len = strlen(method_col.s); flags_col.len = strlen(flags_col.s); user_agent_col.len = strlen(user_agent_col.s); received_col.len = strlen(received_col.s); db_url.len = strlen(db_url.s); /* Register cache timer */ register_timer(timer, 0, timer_interval); /* Initialize fifo interface */ if (init_ul_fifo() < 0) { LOG(L_ERR, "ERROR: usrloc/fifo initialization failed\n"); return -1; } if (init_ul_unixsock() < 0) { LOG(L_ERR, "ERROR: usrloc/unixsock initialization failed\n"); return -1; } /* init the callbacks list */ if ( init_ulcb_list() < 0) { LOG(L_ERR, "ERROR: usrloc/callbacks initialization failed\n"); return -1; } /* Shall we use database ? */ if (db_mode != NO_DB) { /* Yes */ if (bind_dbmod(db_url.s, &ul_dbf) < 0) { /* Find database module */ LOG(L_ERR, "ERROR: mod_init(): Can't bind database module\n"); return -1; } if (!DB_CAPABILITY(ul_dbf, DB_CAP_ALL)) { LOG(L_ERR, "usrloc:mod_init: Database module does not implement" " all functions needed by the module\n"); return -1; } } return 0; } static int child_init(int _rank) { /* Shall we use database ? */ if (db_mode != NO_DB) { /* Yes */ ul_dbh = ul_dbf.init(db_url.s); /* Get a new database connection */ if (!ul_dbh) { LOG(L_ERR, "ERROR: child_init(%d): " "Error while connecting database\n", _rank); return -1; } } return 0; } /* * Module destroy function */ static void destroy(void) { /* Parent only, synchronize the world * and then nuke it */ if (is_main) { if (synchronize_all_udomains() != 0) { LOG(L_ERR, "timer(): Error while flushing cache\n"); } free_all_udomains(); } /* All processes close database connection */ if (ul_dbh) ul_dbf.close(ul_dbh); /* free callbacks list */ destroy_ulcb_list(); } /* * Timer handler */ static void timer(unsigned int ticks, void* param) { if (synchronize_all_udomains() != 0) { LOG(L_ERR, "timer(): Error while synchronizing cache\n"); } }