00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00055 #include <stdio.h>
00056 #include "p_usrloc_mod.h"
00057 #include "../../sr_module.h"
00058 #include "../../dprint.h"
00059 #include "../../rpc_lookup.h"
00060 #include "../../timer_proc.h"
00061 #include "../../globals.h"
00062 #include "../../ut.h"
00063 #include "udomain.h"
00064 #include "urecord.h"
00065 #include "ucontact.h"
00066 #include "ul_mi.h"
00067 #include "../usrloc/ul_callback.h"
00068 #include "ul_db_api.h"
00069 #include "ul_db_watch.h"
00070 #include "ul_check.h"
00071 #include "ul_db.h"
00072 #include "ul_db_layer.h"
00073 #include "dlist.h"
00074
00075 MODULE_VERSION
00076
00077 #define USER_COL "username"
00078 #define DOMAIN_COL "domain"
00079 #define CONTACT_COL "contact"
00080 #define EXPIRES_COL "expires"
00081 #define Q_COL "q"
00082 #define CALLID_COL "callid"
00083 #define CSEQ_COL "cseq"
00084 #define FLAGS_COL "flags"
00085 #define CFLAGS_COL "cflags"
00086 #define USER_AGENT_COL "user_agent"
00087 #define RECEIVED_COL "received"
00088 #define PATH_COL "path"
00089 #define SOCK_COL "socket"
00090 #define METHODS_COL "methods"
00091 #define LAST_MOD_COL "last_modified"
00092
00093 static int mod_init(void);
00094 static void destroy(void);
00095 static int child_init(int rank);
00096 static int mi_child_init(void);
00097 static int mi_child_loc_nr_init(void);
00098 extern int bind_usrloc(usrloc_api_t* api);
00099 extern int ul_locks_no;
00100
00101
00102
00103
00138 str user_col = str_init(USER_COL);
00139 str domain_col = str_init(DOMAIN_COL);
00140 str contact_col = str_init(CONTACT_COL);
00141 str expires_col = str_init(EXPIRES_COL);
00142 str q_col = str_init(Q_COL);
00143 str callid_col = str_init(CALLID_COL);
00144 str cseq_col = str_init(CSEQ_COL);
00145 str flags_col = str_init(FLAGS_COL);
00146 str cflags_col = str_init(CFLAGS_COL);
00147 str user_agent_col = str_init(USER_AGENT_COL);
00148 str received_col = str_init(RECEIVED_COL);
00149 str path_col = str_init(PATH_COL);
00150 str sock_col = str_init(SOCK_COL);
00151 str methods_col = str_init(METHODS_COL);
00152 str last_mod_col = str_init(LAST_MOD_COL);
00153 int db_mode = 3;
00154 int use_domain = 0;
00155 int desc_time_order = 0;
00157 int ul_fetch_rows = 2000;
00158 int ul_hash_size = 9;
00159 str write_db_url = {DEFAULT_DB_URL, DEFAULT_DB_URL_LEN};
00160 str read_db_url = {DEFAULT_DB_URL, DEFAULT_DB_URL_LEN};
00161 str reg_table = {REG_TABLE, sizeof(REG_TABLE) -1};
00162 str id_col = {ID_COL, sizeof(ID_COL) - 1};
00163 str url_col = {URL_COL, sizeof(URL_COL) - 1};
00164 str num_col = {NUM_COL, sizeof(NUM_COL) - 1};
00165 str status_col = {STATUS_COL, sizeof(STATUS_COL) - 1};
00166 str failover_time_col = {FAILOVER_T_COL, sizeof(FAILOVER_T_COL) - 1};
00167 str spare_col = {SPARE_COL, sizeof(SPARE_COL) - 1};
00168 str error_col = {ERROR_COL, sizeof(ERROR_COL) - 1};
00169 str risk_group_col = {RISK_GROUP_COL, sizeof(RISK_GROUP_COL) - 1};
00170 int expire_time = DEFAULT_EXPIRE;
00171 int db_error_threshold = DEFAULT_ERR_THRESHOLD;
00172 int failover_level = DEFAULT_FAILOVER_LEVEL;
00173 int retry_interval = DB_RETRY;
00174 int policy = DB_DEFAULT_POLICY;
00175 int db_write = 0;
00176 int db_master_write = 0;
00177 int alg_location = 0;
00178
00179 int db_use_transactions = 0;
00180 str db_transaction_level = {DB_DEFAULT_TRANSACTION_LEVEL, sizeof(DB_DEFAULT_TRANSACTION_LEVEL) -1};
00181 char * isolation_level;
00182 int connection_expires = DB_DEFAULT_CONNECTION_EXPIRES;
00183 int max_loc_nr = 0 ;
00184
00185
00186
00187 unsigned int nat_bflag = (unsigned int)-1;
00188 unsigned int init_flag = 0;
00189
00190 str default_db_url = str_init(DEFAULT_DB_URL);
00191 str default_db_type = str_init(DEFAULT_DB_TYPE);
00192 str domain_db = str_init(DEFAULT_DOMAIN_DB);
00193 int default_dbt = 0;
00194 int expire = 0;
00195
00196
00200 static cmd_export_t cmds[] = {
00201 {"ul_bind_usrloc", (cmd_function)bind_usrloc, 1, 0, 0, 0},
00202 {0, 0, 0, 0, 0, 0}
00203 };
00204
00205
00209 static param_export_t params[] = {
00210 {"user_column", STR_PARAM, &user_col.s },
00211 {"domain_column", STR_PARAM, &domain_col.s },
00212 {"contact_column", STR_PARAM, &contact_col.s },
00213 {"expires_column", STR_PARAM, &expires_col.s },
00214 {"q_column", STR_PARAM, &q_col.s },
00215 {"callid_column", STR_PARAM, &callid_col.s },
00216 {"cseq_column", STR_PARAM, &cseq_col.s },
00217 {"flags_column", STR_PARAM, &flags_col.s },
00218 {"cflags_column", STR_PARAM, &cflags_col.s },
00219 {"db_mode", INT_PARAM, &db_mode },
00220 {"use_domain", INT_PARAM, &use_domain },
00221 {"desc_time_order", INT_PARAM, &desc_time_order },
00222 {"user_agent_column", STR_PARAM, &user_agent_col.s},
00223 {"received_column", STR_PARAM, &received_col.s },
00224 {"path_column", STR_PARAM, &path_col.s },
00225 {"socket_column", STR_PARAM, &sock_col.s },
00226 {"methods_column", STR_PARAM, &methods_col.s },
00227 {"matching_mode", INT_PARAM, &matching_mode },
00228 {"cseq_delay", INT_PARAM, &cseq_delay },
00229 {"fetch_rows", INT_PARAM, &ul_fetch_rows },
00230 {"hash_size", INT_PARAM, &ul_hash_size },
00231 {"nat_bflag", INT_PARAM, &nat_bflag },
00232 {"default_db_url", STR_PARAM, &default_db_url.s },
00233 {"default_db_type", STR_PARAM, &default_db_type.s },
00234 {"domain_db", STR_PARAM, &domain_db.s },
00235 {"write_db_url", STR_PARAM, &write_db_url.s },
00236 {"read_db_url", STR_PARAM, &read_db_url.s },
00237 {"reg_db_table", STR_PARAM, ®_table.s },
00238 {"id_column", STR_PARAM, &id_col.s },
00239 {"num_column", STR_PARAM, &num_col.s },
00240 {"url_column", STR_PARAM, &url_col.s },
00241 {"status_column", STR_PARAM, &status_col.s },
00242 {"failover_time_column", STR_PARAM, &failover_time_col.s },
00243 {"spare_flag_column", STR_PARAM, &spare_col.s },
00244 {"error_column", STR_PARAM, &error_col.s },
00245 {"risk_group_column", STR_PARAM, &risk_group_col.s },
00246 {"expire_time", INT_PARAM, &expire_time },
00247 {"db_err_threshold", INT_PARAM, &db_error_threshold },
00248 {"failover_level", INT_PARAM, &failover_level },
00249 {"db_retry_interval", INT_PARAM, &retry_interval },
00250 {"db_use_transactions", INT_PARAM, &db_use_transactions },
00251 {"db_transaction_level", INT_PARAM, &db_transaction_level},
00252 {"write_on_db", INT_PARAM, &db_write },
00253 {"write_on_master_db", INT_PARAM, &db_master_write },
00254 {"connection_expires", INT_PARAM, &connection_expires },
00255 {"alg_location", INT_PARAM, &alg_location },
00256 {0, 0, 0}
00257 };
00258
00259
00260 stat_export_t mod_stats[] = {
00261 {"registered_users" , STAT_IS_FUNC, (stat_var**)get_number_of_users },
00262 {0,0,0}
00263 };
00264
00265
00266 static mi_export_t mi_cmds[] = {
00267 { MI_USRLOC_RM, mi_usrloc_rm_aor, 0, 0,
00268 mi_child_init },
00269 { MI_USRLOC_RM_CONTACT, mi_usrloc_rm_contact, 0, 0,
00270 mi_child_init },
00271 { MI_USRLOC_DUMP, mi_usrloc_dump, 0, 0,
00272 0 },
00273 { MI_USRLOC_FLUSH, mi_usrloc_flush, MI_NO_INPUT_FLAG, 0,
00274 mi_child_init },
00275 { MI_USRLOC_ADD, mi_usrloc_add, 0, 0,
00276 mi_child_init },
00277 { MI_USRLOC_SHOW_CONTACT, mi_usrloc_show_contact, 0, 0,
00278 mi_child_init },
00279 { "loc_refresh", mi_ul_db_refresh, MI_NO_INPUT_FLAG, 0, mi_child_init },
00280 { "loc_nr_refresh", mi_loc_nr_refresh, MI_NO_INPUT_FLAG, 0, mi_child_loc_nr_init },
00281 { 0, 0, 0, 0, 0}
00282 };
00283
00284
00285 struct module_exports exports = {
00286 "p_usrloc",
00287 DEFAULT_DLFLAGS,
00288 cmds,
00289 params,
00290 mod_stats,
00291 mi_cmds,
00292 0,
00293 0,
00294 mod_init,
00295 0,
00296 destroy,
00297 child_init
00298 };
00299
00300
00304 static int mod_init(void)
00305 {
00306 #ifdef STATISTICS
00307
00308 if (register_module_stats( exports.name, mod_stats)!=0 ) {
00309 LM_ERR("failed to register core statistics\n");
00310 return -1;
00311 }
00312 #endif
00313
00314 if(register_mi_mod(exports.name, mi_cmds)!=0)
00315 {
00316 LM_ERR("failed to register MI commands\n");
00317 return -1;
00318 }
00319
00320
00321
00322 user_col.len = strlen(user_col.s);
00323 domain_col.len = strlen(domain_col.s);
00324 contact_col.len = strlen(contact_col.s);
00325 expires_col.len = strlen(expires_col.s);
00326 q_col.len = strlen(q_col.s);
00327 callid_col.len = strlen(callid_col.s);
00328 cseq_col.len = strlen(cseq_col.s);
00329 flags_col.len = strlen(flags_col.s);
00330 cflags_col.len = strlen(cflags_col.s);
00331 user_agent_col.len = strlen(user_agent_col.s);
00332 received_col.len = strlen(received_col.s);
00333 path_col.len = strlen(path_col.s);
00334 sock_col.len = strlen(sock_col.s);
00335 methods_col.len = strlen(methods_col.s);
00336 last_mod_col.len = strlen(last_mod_col.s);
00337
00338 write_db_url.len = strlen (write_db_url.s);
00339 read_db_url.len = strlen (read_db_url.s);
00340 reg_table.len = strlen(reg_table.s);
00341 id_col.len = strlen(id_col.s);
00342 url_col.len = strlen(url_col.s);
00343 num_col.len = strlen(num_col.s);
00344 status_col.len = strlen(status_col.s);
00345 failover_time_col.len = strlen(failover_time_col.s);
00346 spare_col.len = strlen(spare_col.s);
00347 error_col.len = strlen(error_col.s);
00348 risk_group_col.len = strlen(risk_group_col.s);
00349 db_transaction_level.len = strlen(db_transaction_level.s);
00350
00351
00352 if(ul_hash_size<=1)
00353 ul_hash_size = 512;
00354 else
00355 ul_hash_size = 1<<ul_hash_size;
00356 ul_locks_no = ul_hash_size;
00357
00358
00359 switch (matching_mode) {
00360 case CONTACT_ONLY:
00361 case CONTACT_CALLID:
00362 case CONTACT_PATH:
00363 break;
00364 default:
00365 LM_ERR("invalid matching mode %d\n", matching_mode);
00366 }
00367
00368 if(ul_init_locks()!=0)
00369 {
00370 LM_ERR("locks array initialization failed\n");
00371 return -1;
00372 }
00373
00374
00375 if ( init_ulcb_list() < 0) {
00376 LM_ERR("usrloc/callbacks initialization failed\n");
00377 return -1;
00378 }
00379
00380 if (db_mode != DB_ONLY) {
00381 LM_ERR("DB_ONLY is the only mode possible for partitioned usrloc. Please set db_mode to 3");
00382 return -1;
00383 }
00384
00385
00386 if (db_mode != NO_DB) {
00387 if(!default_db_url.s || !strlen(default_db_url.s)){
00388 LM_ERR("must set default_db_url parameter\n");
00389 return -1;
00390 }
00391 default_db_url.len = strlen (default_db_url.s);
00392
00393 domain_db.len = strlen(domain_db.s);
00394 default_db_type.len = strlen(default_db_type.s);
00395 if(strcmp(DB_TYPE_CLUSTER_STR, default_db_type.s) == 0){
00396 default_dbt = DB_TYPE_CLUSTER;
00397 } else {
00398 default_dbt = DB_TYPE_SINGLE;
00399 }
00400
00401 if (ul_db_layer_init() < 0) {
00402 return -1;
00403 }
00404
00405 if(ul_fetch_rows<=0) {
00406 LM_ERR("invalid fetch_rows number '%d'\n", ul_fetch_rows);
00407 return -1;
00408 }
00409 }
00410
00411 if (nat_bflag==(unsigned int)-1) {
00412 nat_bflag = 0;
00413 } else if ( nat_bflag>=8*sizeof(nat_bflag) ) {
00414 LM_ERR("bflag index (%d) too big!\n", nat_bflag);
00415 return -1;
00416 } else {
00417 nat_bflag = 1<<nat_bflag;
00418 }
00419
00420 init_flag = 1;
00421
00422 if((isolation_level = pkg_malloc(strlen("SET TRANSACTION ISOLATION LEVEL ") + db_transaction_level.len + 1)) == NULL){
00423 LM_ERR("couldn't allocate private memory.\n");
00424 return -1;
00425 }
00426 sprintf(isolation_level, "SET TRANSACTION ISOLATION LEVEL %s", db_transaction_level.s);
00427 if(init_list() < 0) {
00428 LM_ERR("could not init check list.\n");
00429 return -1;
00430 }
00431 if(ul_db_init() < 0){
00432 LM_ERR("could not initialise databases.\n");
00433 return -1;
00434 }
00435 if(ul_db_watch_init() < 0){
00436 LM_ERR("could not init database watch environment.\n");
00437 return -1;
00438 }
00439 if(db_master_write){
00440
00441 register_dummy_timers(1);
00442 }
00443 return 0;
00444 }
00445
00446
00447 static int child_init(int _rank)
00448 {
00449 if(_rank==PROC_INIT) {
00450 if(init_db_check() < 0){
00451 LM_ERR("could not initialise database check.\n");
00452 return -1;
00453 }
00454 return 0;
00455 }
00456 if(ul_db_child_init() < 0){
00457 LM_ERR("could not initialise databases.\n");
00458 return -1;
00459 }
00460
00461
00462 return 0;
00463 }
00464
00465
00466
00467 static int mi_child_init(void)
00468 {
00469
00470 return ul_db_child_init();
00471 }
00472
00473
00477 static void destroy(void)
00478 {
00479
00480 ul_unlock_locks();
00481
00482 free_all_udomains();
00483 ul_destroy_locks();
00484
00485 destroy_ulcb_list();
00486
00487 ul_db_shutdown();
00488 destroy_list();
00489 ul_db_watch_destroy();
00490
00491 }
00492
00493
00494 static int mi_child_loc_nr_init(void)
00495 {
00496 if(ul_db_child_locnr_init() < 0){
00497 LM_ERR("could not retrive location number from database. Try to reinitialize the db handles\n");
00498 return -1;
00499 }
00500 return 0;
00501 }
00502
00503
00504 struct mi_root* mi_ul_db_refresh(struct mi_root* cmd_tree, void* param) {
00505 int ret;
00506 ret = set_must_refresh();
00507
00508 LM_INFO("sp-ul_db location databases were refreshed (%i elements).\n", ret);
00509
00510 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00511 }
00512
00513
00514 struct mi_root* mi_loc_nr_refresh(struct mi_root* cmd_tree, void* param) {
00515
00516 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00517 }