src/modules/usrloc/usrloc_mod.c
31ccf6a2
 /*
  * Usrloc module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
27642a08
  * This file is part of Kamailio, a free SIP server.
31ccf6a2
  *
27642a08
  * Kamailio is free software; you can redistribute it and/or modify
31ccf6a2
  * 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
  *
27642a08
  * Kamailio is distributed in the hope that it will be useful,
31ccf6a2
  * 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.
  *
10d6b2b7
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
31ccf6a2
  *
  */
 
adfa93a7
 /*! \file
  *  \brief USRLOC - Usrloc module interface
  *  \ingroup usrloc
35882b72
  *
  * - Module \ref usrloc
adfa93a7
  */
 
4d87f9db
 /*!
  * \defgroup usrloc Usrloc :: User location module
  * \brief User location module
  *
  * The module keeps a user location table and provides access
  * to the table to other modules. The module exports no functions
  * that could be used directly from scripts, all access is done
  * over a API. A main user of this API is the registrar module.
  * \see registrar
adfa93a7
  */
 
31ccf6a2
 #include <stdio.h>
10d6b2b7
 #include "usrloc_mod.h"
cf83221d
 #include "../../core/sr_module.h"
 #include "../../core/dprint.h"
 #include "../../core/rpc_lookup.h"
 #include "../../core/timer.h"     /* register_timer */
 #include "../../core/timer_proc.h" /* register_sync_timer */
3a00526b
 #include "../../core/globals.h"
cf83221d
 #include "../../core/ut.h"        /* str_init */
0076124b
 #include "../../core/utils/sruid.h"
31ccf6a2
 #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 */
99b02d1e
 #include "ul_rpc.h"
31ccf6a2
 #include "ul_callback.h"
87c5d45a
 #include "ul_keepalive.h"
31ccf6a2
 #include "usrloc.h"
 
 MODULE_VERSION
 
05823430
 #define RUID_COL       "ruid"
31ccf6a2
 #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 FLAGS_COL      "flags"
cffbf08f
 #define CFLAGS_COL     "cflags"
31ccf6a2
 #define USER_AGENT_COL "user_agent"
 #define RECEIVED_COL   "received"
79bf803d
 #define PATH_COL       "path"
31ccf6a2
 #define SOCK_COL       "socket"
0b7b6f4f
 #define METHODS_COL    "methods"
05823430
 #define INSTANCE_COL   "instance"
221073eb
 #define REG_ID_COL     "reg_id"
9679b230
 #define LAST_MOD_COL   "last_modified"
67e40ec0
 #define SRV_ID_COL     "server_id"
 #define CON_ID_COL     "connection_id"
 #define KEEPALIVE_COL  "keepalive"
8f8d4f5d
 #define PARTITION_COL  "partition"
31ccf6a2
 
5463e46f
 #define ULATTRS_USER_COL       "username"
 #define ULATTRS_DOMAIN_COL     "domain"
 #define ULATTRS_RUID_COL       "ruid"
 #define ULATTRS_ANAME_COL      "aname"
 #define ULATTRS_ATYPE_COL      "atype"
 #define ULATTRS_AVALUE_COL     "avalue"
 #define ULATTRS_LAST_MOD_COL   "last_modified"
 
adfa93a7
 static int mod_init(void);                          /*!< Module initialization function */
 static void destroy(void);                          /*!< Module destroy function */
c642e504
 static void ul_core_timer(unsigned int ticks, void* param);  /*!< Core timer handler */
 static void ul_local_timer(unsigned int ticks, void* param); /*!< Local timer handler */
93b5d2e5
 static void ul_db_clean_timer(unsigned int ticks, void* param); /*!< DB clean timer handler */
adfa93a7
 static int child_init(int rank);                    /*!< Per-child init function */
87c5d45a
 static int ul_sip_reply_received(sip_msg_t *msg); /*!< SIP response handling */
31ccf6a2
 
16679e6d
 #define UL_PRELOAD_SIZE	8
 static char* ul_preload_list[UL_PRELOAD_SIZE];
 static int ul_preload_index = 0;
 static int ul_preload_param(modparam_t type, void* val);
 
31ccf6a2
 extern int bind_usrloc(usrloc_api_t* api);
d66b9903
 int ul_db_update_as_insert = 0;
c642e504
 int ul_timer_procs = 0;
4b68b3ca
 int ul_db_check_update = 0;
36845cc5
 int ul_keepalive_timeout = 0;
d66b9903
 
6a0201d8
 int ul_db_ops_ruid = 1;
cb6e934a
 int ul_expires_type = 0;
ec1dfe89
 int ul_db_raw_fetch_type = 0;
3de21172
 int ul_rm_expired_delay = 0;
da922966
 int ul_version_table = 1;
61e08282
 
8ea264ac
 int ul_load_rank = PROC_SIPINIT;
e6ad428f
 str ul_xavp_contact_name = {0};
 
b3677f75
 str ul_ka_from = str_init("sip:server@kamailio.org");
 str ul_ka_domain = str_init("kamailio.org");
 str ul_ka_method = str_init("OPTIONS");
 int ul_ka_mode = 0;
c4f3de7b
 int ul_ka_filter = 0;
0d912f11
 int ul_ka_loglevel = 255;
8525a26f
 str ul_ka_logmsg = str_init(" to-uri: [$tu] remote-addr: [$sas]");
0d912f11
 pv_elem_t *ul_ka_logfmt = NULL;
b3677f75
 
1984f288
 /* sruid to get internal uid for mi/rpc commands */
 sruid_t _ul_sruid;
 
31ccf6a2
 /*
  * Module parameters and their default values
  */
0b7b6f4f
 
ae2f1fdc
 str ul_ruid_col        = str_init(RUID_COL); 		/*!< Name of column containing record unique id */
 str ul_user_col        = str_init(USER_COL); 		/*!< Name of column containing usernames */
 str ul_domain_col      = str_init(DOMAIN_COL); 	/*!< Name of column containing domains */
 str ul_contact_col     = str_init(CONTACT_COL);	/*!< Name of column containing contact addresses */
 str ul_expires_col     = str_init(EXPIRES_COL);	/*!< Name of column containing expires values */
 str ul_q_col           = str_init(Q_COL);			/*!< Name of column containing q values */
 str ul_callid_col      = str_init(CALLID_COL);		/*!< Name of column containing callid string */
 str ul_cseq_col        = str_init(CSEQ_COL);		/*!< Name of column containing cseq values */
 str ul_flags_col       = str_init(FLAGS_COL);		/*!< Name of column containing internal flags */
 str ul_cflags_col      = str_init(CFLAGS_COL);		/*!< Name of column containing contact flags */
 str ul_user_agent_col  = str_init(USER_AGENT_COL);	/*!< Name of column containing user agent string */
 str ul_received_col    = str_init(RECEIVED_COL);	/*!< Name of column containing transport info of REGISTER */
 str ul_path_col        = str_init(PATH_COL);		/*!< Name of column containing the Path header */
 str ul_sock_col        = str_init(SOCK_COL);		/*!< Name of column containing the received socket */
 str ul_methods_col     = str_init(METHODS_COL);	/*!< Name of column containing the supported methods */
 str ul_instance_col    = str_init(INSTANCE_COL);	/*!< Name of column containing the SIP instance value */
 str ul_reg_id_col      = str_init(REG_ID_COL);		/*!< Name of column containing the reg-id value */
 str ul_last_mod_col    = str_init(LAST_MOD_COL);	/*!< Name of column containing the last modified date */
 str ul_srv_id_col      = str_init(SRV_ID_COL);		/*!< Name of column containing the server id value */
 str ul_con_id_col      = str_init(CON_ID_COL);		/*!< Name of column containing the connection id value */
 str ul_keepalive_col   = str_init(KEEPALIVE_COL);	/*!< Name of column containing the keepalive value */
 str ul_partition_col   = str_init(PARTITION_COL);	/*!< Name of column containing the partition value */
5463e46f
 
 str ulattrs_user_col   = str_init(ULATTRS_USER_COL);   /*!< Name of column containing username */
 str ulattrs_domain_col = str_init(ULATTRS_DOMAIN_COL); /*!< Name of column containing domain */
 str ulattrs_ruid_col   = str_init(ULATTRS_RUID_COL);   /*!< Name of column containing record unique id */
 str ulattrs_aname_col  = str_init(ULATTRS_ANAME_COL);  /*!< Name of column containing attribute name */
 str ulattrs_atype_col  = str_init(ULATTRS_ATYPE_COL);  /*!< Name of column containing attribute type */
 str ulattrs_avalue_col = str_init(ULATTRS_AVALUE_COL); /*!< Name of column containing attribute value */
 str ulattrs_last_mod_col = str_init(ULATTRS_LAST_MOD_COL);	/*!< Name of column containing the last modified date */
 
ae2f1fdc
 str ul_db_url          = str_init(DEFAULT_DB_URL);	/*!< Database URL */
 int ul_timer_interval  = 60;				/*!< Timer interval in seconds */
 int ul_db_mode         = 0;				/*!< Database sync scheme: 0-no db, 1-write through, 2-write back, 3-only db */
 int ul_db_load         = 1;				/*!< Database load after restart: 1- true, 0- false (only the db_mode allows it) */
 int ul_db_insert_update = 0;				/*!< Database : update on duplicate key instead of error */
 int ul_use_domain      = 0;				/*!< Whether usrloc should use domain part of aor */
 int ul_desc_time_order = 0;				/*!< By default do not enable timestamp ordering */
 int ul_handle_lost_tcp = 0;				/*!< By default do not remove contacts before expiration time */
 int ul_close_expired_tcp = 0;				/*!< By default do not close TCP connections for expired contacts */
 int ul_skip_remote_socket = 0;				/*!< By default do not skip remote socket */
18b7337a
 int ul_db_clean_tcp = 0;				/*!< Clean TCP/TLS/WSS contacts in DB before loading records */
adfa93a7
 
 int ul_fetch_rows = 2000;				/*!< number of rows to fetch from result */
1f1b81ed
 int ul_hash_size = 10;
c1edef1f
 int ul_db_insert_null = 0;
93b5d2e5
 int ul_db_timer_clean = 0;
31ccf6a2
 
4d87f9db
 /* flags */
ae2f1fdc
 unsigned int ul_nat_bflag = (unsigned int)-1;
 unsigned int ul_init_flag = 0;
cffbf08f
 
90ab2605
 db1_con_t* ul_dbh = 0; /* Database connection handle */
31ccf6a2
 db_func_t ul_dbf;
 
7fdbdd44
 /* filter on load and during cleanup by server id */
aedd970a
 unsigned int ul_db_srvid = 0;
50098d1d
 
adfa93a7
 /*! \brief
31ccf6a2
  * Exported functions
  */
 static cmd_export_t cmds[] = {
80998a7f
 	{"ul_bind_usrloc",        (cmd_function)bind_usrloc,        1, 0, 0, 0},
 	{0, 0, 0, 0, 0, 0}
31ccf6a2
 };
 
 
adfa93a7
 /*! \brief
bc80696a
  * Exported parameters
31ccf6a2
  */
 static param_export_t params[] = {
ae2f1fdc
 	{"ruid_column",         PARAM_STR, &ul_ruid_col      },
 	{"user_column",         PARAM_STR, &ul_user_col      },
 	{"domain_column",       PARAM_STR, &ul_domain_col    },
 	{"contact_column",      PARAM_STR, &ul_contact_col   },
 	{"expires_column",      PARAM_STR, &ul_expires_col   },
 	{"q_column",            PARAM_STR, &ul_q_col         },
 	{"callid_column",       PARAM_STR, &ul_callid_col    },
 	{"cseq_column",         PARAM_STR, &ul_cseq_col      },
 	{"flags_column",        PARAM_STR, &ul_flags_col     },
 	{"cflags_column",       PARAM_STR, &ul_cflags_col    },
 	{"db_url",              PARAM_STR, &ul_db_url        },
 	{"timer_interval",      INT_PARAM, &ul_timer_interval  },
 	{"db_mode",             INT_PARAM, &ul_db_mode         },
 	{"db_load",             INT_PARAM, &ul_db_load         },
 	{"db_insert_update",    INT_PARAM, &ul_db_insert_update },
 	{"use_domain",          INT_PARAM, &ul_use_domain      },
 	{"desc_time_order",     INT_PARAM, &ul_desc_time_order },
 	{"user_agent_column",   PARAM_STR, &ul_user_agent_col},
 	{"received_column",     PARAM_STR, &ul_received_col  },
 	{"path_column",         PARAM_STR, &ul_path_col      },
 	{"socket_column",       PARAM_STR, &ul_sock_col      },
 	{"methods_column",      PARAM_STR, &ul_methods_col   },
 	{"instance_column",     PARAM_STR, &ul_instance_col  },
 	{"reg_id_column",       PARAM_STR, &ul_reg_id_col    },
 	{"server_id_column",    PARAM_STR, &ul_srv_id_col    },
 	{"connection_id_column",PARAM_STR, &ul_con_id_col    },
 	{"keepalive_column",    PARAM_STR, &ul_keepalive_col },
 	{"partition_column",    PARAM_STR, &ul_partition_col },
4c9bcb4c
 	{"matching_mode",       INT_PARAM, &ul_matching_mode },
ae2f1fdc
 	{"cseq_delay",          INT_PARAM, &ul_cseq_delay      },
d66b9903
 	{"fetch_rows",          INT_PARAM, &ul_fetch_rows   },
 	{"hash_size",           INT_PARAM, &ul_hash_size    },
ae2f1fdc
 	{"nat_bflag",           INT_PARAM, &ul_nat_bflag       },
 	{"handle_lost_tcp",     INT_PARAM, &ul_handle_lost_tcp },
 	{"close_expired_tcp",   INT_PARAM, &ul_close_expired_tcp },
 	{"skip_remote_socket",  INT_PARAM, &ul_skip_remote_socket },
93a5ece8
 	{"preload",             PARAM_STRING|USE_FUNC_PARAM, (void*)ul_preload_param},
d66b9903
 	{"db_update_as_insert", INT_PARAM, &ul_db_update_as_insert},
c642e504
 	{"timer_procs",         INT_PARAM, &ul_timer_procs},
4b68b3ca
 	{"db_check_update",     INT_PARAM, &ul_db_check_update},
93a5ece8
 	{"xavp_contact",        PARAM_STR, &ul_xavp_contact_name},
61e08282
 	{"db_ops_ruid",         INT_PARAM, &ul_db_ops_ruid},
cb6e934a
 	{"expires_type",        PARAM_INT, &ul_expires_type},
ec1dfe89
 	{"db_raw_fetch_type",   PARAM_INT, &ul_db_raw_fetch_type},
c1edef1f
 	{"db_insert_null",      PARAM_INT, &ul_db_insert_null},
aedd970a
 	{"server_id_filter",    PARAM_INT, &ul_db_srvid},
93b5d2e5
 	{"db_timer_clean",      PARAM_INT, &ul_db_timer_clean},
3de21172
 	{"rm_expired_delay",    PARAM_INT, &ul_rm_expired_delay},
da922966
 	{"version_table",       PARAM_INT, &ul_version_table},
b3677f75
 	{"ka_mode",             PARAM_INT, &ul_ka_mode},
 	{"ka_from",             PARAM_STR, &ul_ka_from},
91bf474a
 	{"ka_domain",           PARAM_STR, &ul_ka_domain},
 	{"ka_method",           PARAM_STR, &ul_ka_method},
c4f3de7b
 	{"ka_filter",           PARAM_INT, &ul_ka_filter},
9331044b
 	{"ka_timeout",          PARAM_INT, &ul_keepalive_timeout},
0d912f11
 	{"ka_loglevel",         PARAM_INT, &ul_ka_loglevel},
d74ab365
 	{"ka_logmsg",           PARAM_STR, &ul_ka_logmsg},
8ea264ac
 	{"load_rank",           PARAM_INT, &ul_load_rank},
18b7337a
 	{"db_clean_tcp",        PARAM_INT, &ul_db_clean_tcp},
31ccf6a2
 	{0, 0, 0}
 };
 
 
50098d1d
 stat_export_t mod_stats[] = {
 	{"registered_users" ,  STAT_IS_FUNC, (stat_var**)get_number_of_users  },
 	{0,0,0}
 };
 
 
31ccf6a2
 struct module_exports exports = {
8b1ca47b
 	"usrloc",        /*!< module name */
adfa93a7
 	DEFAULT_DLFLAGS, /*!< dlopen flags */
8b1ca47b
 	cmds,            /*!< exported functions */
 	params,          /*!< exported parameters */
 	0,               /*!< exported rpc functions */
 	0,               /*!< exported pseudo-variables */
87c5d45a
 	ul_sip_reply_received, /*!< response handling function */
8b1ca47b
 	mod_init,        /*!< module init function */
 	child_init,      /*!< child init function */
 	destroy          /*!< destroy function */
31ccf6a2
 };
 
 
adfa93a7
 /*! \brief
31ccf6a2
  * Module initialization function
  */
 static int mod_init(void)
 {
16679e6d
 	int i;
 	udomain_t* d;
 
3de21172
 	if(ul_rm_expired_delay!=0) {
ae2f1fdc
 		if(ul_db_mode != DB_ONLY) {
3de21172
 			LM_ERR("rm expired delay feature is available for db only mode\n");
 			return -1;
 		}
 	}
 	if(ul_rm_expired_delay<0) {
 		LM_WARN("rm expired delay value is negative (%d) - setting it to 0\n",
 				ul_rm_expired_delay);
 		ul_rm_expired_delay = 0;
 	}
22fa8367
 	if(sruid_init(&_ul_sruid, '-', "ulcx", SRUID_INC)<0) {
1984f288
 		return -1;
22fa8367
 	}
1984f288
 
29494fc2
 #ifdef STATISTICS
 	/* register statistics */
ae2f1fdc
 	if (register_module_stats(exports.name, mod_stats)!=0 ) {
29494fc2
 		LM_ERR("failed to register core statistics\n");
 		return -1;
 	}
 #endif
212e75b5
 
22fa8367
 	if (rpc_register_array(ul_rpc)!=0) {
99b02d1e
 		LM_ERR("failed to register RPC commands\n");
 		return -1;
 	}
 
22fa8367
 	if(ul_hash_size<=1) {
5d5a0c00
 		ul_hash_size = 512;
22fa8367
 	} else {
5d5a0c00
 		ul_hash_size = 1<<ul_hash_size;
22fa8367
 	}
5d5a0c00
 
3877e72f
 	/* check matching mode */
4c9bcb4c
 	switch (ul_matching_mode) {
3877e72f
 		case CONTACT_ONLY:
 		case CONTACT_CALLID:
d6fbd5a1
 		case CONTACT_PATH:
a6609f5f
 		case CONTACT_CALLID_ONLY:
3877e72f
 			break;
 		default:
4c9bcb4c
 			LM_ERR("invalid matching mode %d\n", ul_matching_mode);
3877e72f
 	}
 
d8a9e006
 	/* Register cache timer */
22fa8367
 	if(ul_timer_procs<=0) {
ae2f1fdc
 		if (ul_timer_interval > 0) {
 			register_timer(ul_core_timer, 0, ul_timer_interval);
22fa8367
 		}
 	} else {
c642e504
 		register_sync_timers(ul_timer_procs);
22fa8367
 	}
31ccf6a2
 
 	/* init the callbacks list */
ae2f1fdc
 	if (init_ulcb_list() < 0) {
de7fe5e9
 		LM_ERR("usrloc/callbacks initialization failed\n");
31ccf6a2
 		return -1;
 	}
 
 	/* Shall we use database ? */
4780d469
 	switch (ul_db_mode) {
 		case DB_ONLY:
 		case WRITE_THROUGH:
 		case WRITE_BACK:
 		/*
 		 * register the need to be called post-fork of all children
 		 * with the special rank PROC_POSTCHILDINIT
 		 */
 		ksr_module_set_flag(KSRMOD_FLAG_POSTCHILDINIT);
 	}
ae2f1fdc
 	if (ul_db_mode != NO_DB) { /* Yes */
 		if (db_bind_mod(&ul_db_url, &ul_dbf) < 0) { /* Find database module */
de7fe5e9
 			LM_ERR("failed to bind database module\n");
31ccf6a2
 			return -1;
 		}
 		if (!DB_CAPABILITY(ul_dbf, DB_CAP_ALL)) {
de7fe5e9
 			LM_ERR("database module does not implement all functions"
 					" needed by the module\n");
31ccf6a2
 			return -1;
 		}
b53534e7
 		if(ul_fetch_rows<=0) {
de7fe5e9
 			LM_ERR("invalid fetch_rows number '%d'\n", ul_fetch_rows);
b53534e7
 			return -1;
 		}
31ccf6a2
 	}
ae2f1fdc
 	if(ul_db_mode==WRITE_THROUGH || ul_db_mode==WRITE_BACK) {
93b5d2e5
 		if(ul_db_timer_clean!=0) {
ae2f1fdc
 			if(sr_wtimer_add(ul_db_clean_timer, 0, ul_timer_interval)<0) {
9a152cbd
 				LM_ERR("failed to add db clean timer routine\n");
 				return -1;
 			}
93b5d2e5
 		}
 	}
31ccf6a2
 
ae2f1fdc
 	if (ul_nat_bflag==(unsigned int)-1) {
 		ul_nat_bflag = 0;
 	} else if (ul_nat_bflag>=8*sizeof(ul_nat_bflag) ) {
 		LM_ERR("bflag index (%d) too big!\n", ul_nat_bflag);
cffbf08f
 		return -1;
 	} else {
ae2f1fdc
 		ul_nat_bflag = 1<<ul_nat_bflag;
cffbf08f
 	}
 
16679e6d
 	for(i=0; i<ul_preload_index; i++) {
 		if(register_udomain((const char*)ul_preload_list[i], &d)<0) {
 			LM_ERR("cannot register preloaded table %s\n", ul_preload_list[i]);
 			return -1;
 		}
 	}
72996942
 
ae2f1fdc
 	if (ul_handle_lost_tcp && ul_db_mode == DB_ONLY) {
72996942
 		LM_WARN("handle_lost_tcp option makes nothing in DB_ONLY mode\n");
22fa8367
 	}
72996942
 
ae2f1fdc
 	if(ul_db_mode != DB_ONLY) {
76f0fa8a
 		ul_set_xavp_contact_clone(1);
 	}
cffbf08f
 
0d912f11
 	if(ul_ka_mode != ULKA_NONE) {
 		/* set max partition number for timers processing of db records */
 		if (ul_timer_procs > 1) {
 			ul_set_max_partition((unsigned int)ul_timer_procs);
 		}
 		if(ul_ka_logmsg.len > 0) {
 			if(pv_parse_format(&ul_ka_logmsg, &ul_ka_logfmt) < 0) {
 				LM_ERR("failed parsing ka log message format\n");
 				return -1;
 			}
 		}
c4f3de7b
 	}
 
ae2f1fdc
 	ul_init_flag = 1;
31ccf6a2
 	return 0;
 }
 
 
 static int child_init(int _rank)
 {
0f33e47c
 	dlist_t* ptr;
c642e504
 	int i;
 
20646b53
 	if(sruid_init(&_ul_sruid, '-', "ulcx", SRUID_INC)<0)
 		return -1;
 
c642e504
 	if(_rank==PROC_MAIN && ul_timer_procs>0)
 	{
 		for(i=0; i<ul_timer_procs; i++)
 		{
 			if(fork_sync_timer(PROC_TIMER, "USRLOC Timer", 1 /*socks flag*/,
ae2f1fdc
 					ul_local_timer, (void*)(long)i, ul_timer_interval /*sec*/)<0) {
c642e504
 				LM_ERR("failed to start timer routine as process\n");
 				return -1; /* error */
 			}
 		}
 	}
0f33e47c
 
30986225
 	/* connecting to DB ? */
ae2f1fdc
 	switch (ul_db_mode) {
30986225
 		case NO_DB:
 			return 0;
 		case DB_ONLY:
 		case WRITE_THROUGH:
ee11732b
 			/* connect to db only from SIP workers, TIMER and MAIN processes,
 			 *  and RPC processes */
4780d469
 			if (_rank<=0 && _rank!=PROC_TIMER && _rank!=PROC_POSTCHILDINIT
ee11732b
 					 && _rank!=PROC_RPC)
30986225
 				return 0;
 			break;
 		case WRITE_BACK:
d80ea02f
 			/* connect to db only from TIMER (for flush), from MAIN (for
2956c789
 			 * final flush() and from child 1 for preload */
4780d469
 			if (_rank!=PROC_TIMER && _rank!=PROC_POSTCHILDINIT && _rank!=PROC_SIPINIT)
d80ea02f
 				return 0;
 			break;
 		case DB_READONLY:
 			/* connect to db only from child 1 for preload */
ae2f1fdc
 			ul_db_load=1; /* we always load from the db in this mode */
d80ea02f
 			if(_rank!=PROC_SIPINIT)
30986225
 				return 0;
 			break;
 	}
 
ae2f1fdc
 	ul_dbh = ul_dbf.init(&ul_db_url); /* Get a database connection per child */
30986225
 	if (!ul_dbh) {
de7fe5e9
 		LM_ERR("child(%d): failed to connect to database\n", _rank);
30986225
 		return -1;
 	}
c5ca00dc
 	/* _rank==PROC_SIPINIT is used even when fork is disabled */
8ea264ac
 	if (_rank==ul_load_rank && ul_db_mode!=DB_ONLY && ul_db_load) {
30986225
 		/* if cache is used, populate domains from DB */
bef747a3
 		for(ptr=_ksr_ul_root ; ptr ; ptr=ptr->next) {
30986225
 			if (preload_udomain(ul_dbh, ptr->d) < 0) {
de7fe5e9
 				LM_ERR("child(%d): failed to preload domain '%.*s'\n",
 						_rank, ptr->name.len, ZSW(ptr->name.s));
30986225
 				return -1;
0f33e47c
 			}
5463e46f
 			uldb_preload_attrs(ptr->d);
0f33e47c
 		}
31ccf6a2
 	}
 
 	return 0;
 }
 
 
adfa93a7
 /*! \brief
31ccf6a2
  * Module destroy function
  */
 static void destroy(void)
 {
30986225
 	/* we need to sync DB in order to flush the cache */
 	if (ul_dbh) {
c642e504
 		if (synchronize_all_udomains(0, 1) != 0) {
de7fe5e9
 			LM_ERR("flushing cache failed\n");
31ccf6a2
 		}
30986225
 		ul_dbf.close(ul_dbh);
31ccf6a2
 	}
30986225
 
 	free_all_udomains();
31ccf6a2
 
 	/* free callbacks list */
 	destroy_ulcb_list();
 }
 
87c5d45a
 /*! \brief
  * Callback to handle the SIP replies
  */
 static int ul_sip_reply_received(sip_msg_t *msg)
 {
 	if(ul_ka_mode == 0) {
 		return 1;
 	}
 	ul_ka_reply_received(msg);
 	return 1;
 }
31ccf6a2
 
adfa93a7
 /*! \brief
c642e504
  * Core timer handler
  */
 static void ul_core_timer(unsigned int ticks, void* param)
 {
 	if (synchronize_all_udomains(0, 1) != 0) {
 		LM_ERR("synchronizing cache failed\n");
 	}
 }
 
 /*! \brief
  * Local timer handler
31ccf6a2
  */
c642e504
 static void ul_local_timer(unsigned int ticks, void* param)
31ccf6a2
 {
c642e504
 	if (synchronize_all_udomains((int)(long)param, ul_timer_procs) != 0) {
de7fe5e9
 		LM_ERR("synchronizing cache failed\n");
31ccf6a2
 	}
 }
30986225
 
93b5d2e5
 /*! \brief
  * DB dlean timer handler
  */
 static void ul_db_clean_timer(unsigned int ticks, void* param)
 {
 	ul_db_clean_udomains();
 }
 
16679e6d
 /*! \brief
  * preload module parameter handler
  */
 static int ul_preload_param(modparam_t type, void* val)
 {
 	if(val==NULL)
 	{
 		LM_ERR("invalid parameter\n");
 		goto error;
 	}
 	if(ul_preload_index>=UL_PRELOAD_SIZE)
 	{
 		LM_ERR("too many preloaded tables\n");
 		goto error;
 	}
 	ul_preload_list[ul_preload_index] = (char*)val;
 	ul_preload_index++;
 	return 0;
 error:
 	return -1;
 }