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
00054 #include <stdio.h>
00055 #include "ul_mod.h"
00056 #include "../../sr_module.h"
00057 #include "../../dprint.h"
00058 #include "../../rpc_lookup.h"
00059 #include "../../timer.h"
00060 #include "../../timer_proc.h"
00061 #include "../../globals.h"
00062 #include "../../ut.h"
00063 #include "../../lib/srutils/sruid.h"
00064 #include "dlist.h"
00065 #include "udomain.h"
00066 #include "urecord.h"
00067 #include "ucontact.h"
00068 #include "ul_mi.h"
00069 #include "ul_rpc.h"
00070 #include "ul_callback.h"
00071 #include "usrloc.h"
00072
00073 MODULE_VERSION
00074
00075 #define RUID_COL "ruid"
00076 #define USER_COL "username"
00077 #define DOMAIN_COL "domain"
00078 #define CONTACT_COL "contact"
00079 #define EXPIRES_COL "expires"
00080 #define Q_COL "q"
00081 #define CALLID_COL "callid"
00082 #define CSEQ_COL "cseq"
00083 #define FLAGS_COL "flags"
00084 #define CFLAGS_COL "cflags"
00085 #define USER_AGENT_COL "user_agent"
00086 #define RECEIVED_COL "received"
00087 #define PATH_COL "path"
00088 #define SOCK_COL "socket"
00089 #define METHODS_COL "methods"
00090 #define INSTANCE_COL "instance"
00091 #define REG_ID_COL "reg_id"
00092 #define LAST_MOD_COL "last_modified"
00093
00094 static int mod_init(void);
00095 static void destroy(void);
00096 static void ul_core_timer(unsigned int ticks, void* param);
00097 static void ul_local_timer(unsigned int ticks, void* param);
00098 static int child_init(int rank);
00099 static int mi_child_init(void);
00100
00101 #define UL_PRELOAD_SIZE 8
00102 static char* ul_preload_list[UL_PRELOAD_SIZE];
00103 static int ul_preload_index = 0;
00104 static int ul_preload_param(modparam_t type, void* val);
00105
00106 extern int bind_usrloc(usrloc_api_t* api);
00107 extern int ul_locks_no;
00108 int ul_db_update_as_insert = 0;
00109 int ul_timer_procs = 0;
00110
00111
00112 sruid_t _ul_sruid;
00113
00114
00115
00116
00117
00118 str ruid_col = str_init(RUID_COL);
00119 str user_col = str_init(USER_COL);
00120 str domain_col = str_init(DOMAIN_COL);
00121 str contact_col = str_init(CONTACT_COL);
00122 str expires_col = str_init(EXPIRES_COL);
00123 str q_col = str_init(Q_COL);
00124 str callid_col = str_init(CALLID_COL);
00125 str cseq_col = str_init(CSEQ_COL);
00126 str flags_col = str_init(FLAGS_COL);
00127 str cflags_col = str_init(CFLAGS_COL);
00128 str user_agent_col = str_init(USER_AGENT_COL);
00129 str received_col = str_init(RECEIVED_COL);
00130 str path_col = str_init(PATH_COL);
00131 str sock_col = str_init(SOCK_COL);
00132 str methods_col = str_init(METHODS_COL);
00133 str instance_col = str_init(INSTANCE_COL);
00134 str reg_id_col = str_init(REG_ID_COL);
00135 str last_mod_col = str_init(LAST_MOD_COL);
00136 str db_url = str_init(DEFAULT_DB_URL);
00137 int timer_interval = 60;
00138 int db_mode = 0;
00139 int use_domain = 0;
00140 int desc_time_order = 0;
00142 int ul_fetch_rows = 2000;
00143 int ul_hash_size = 9;
00144
00145
00146 unsigned int nat_bflag = (unsigned int)-1;
00147 unsigned int init_flag = 0;
00148
00149 db1_con_t* ul_dbh = 0;
00150 db_func_t ul_dbf;
00151
00152
00153
00157 static cmd_export_t cmds[] = {
00158 {"ul_bind_usrloc", (cmd_function)bind_usrloc, 1, 0, 0, 0},
00159 {0, 0, 0, 0, 0, 0}
00160 };
00161
00162
00166 static param_export_t params[] = {
00167 {"ruid_column", STR_PARAM, &ruid_col.s },
00168 {"user_column", STR_PARAM, &user_col.s },
00169 {"domain_column", STR_PARAM, &domain_col.s },
00170 {"contact_column", STR_PARAM, &contact_col.s },
00171 {"expires_column", STR_PARAM, &expires_col.s },
00172 {"q_column", STR_PARAM, &q_col.s },
00173 {"callid_column", STR_PARAM, &callid_col.s },
00174 {"cseq_column", STR_PARAM, &cseq_col.s },
00175 {"flags_column", STR_PARAM, &flags_col.s },
00176 {"cflags_column", STR_PARAM, &cflags_col.s },
00177 {"db_url", STR_PARAM, &db_url.s },
00178 {"timer_interval", INT_PARAM, &timer_interval },
00179 {"db_mode", INT_PARAM, &db_mode },
00180 {"use_domain", INT_PARAM, &use_domain },
00181 {"desc_time_order", INT_PARAM, &desc_time_order },
00182 {"user_agent_column", STR_PARAM, &user_agent_col.s},
00183 {"received_column", STR_PARAM, &received_col.s },
00184 {"path_column", STR_PARAM, &path_col.s },
00185 {"socket_column", STR_PARAM, &sock_col.s },
00186 {"methods_column", STR_PARAM, &methods_col.s },
00187 {"instance_column", STR_PARAM, &instance_col.s },
00188 {"reg_id_column", STR_PARAM, ®_id_col.s },
00189 {"matching_mode", INT_PARAM, &matching_mode },
00190 {"cseq_delay", INT_PARAM, &cseq_delay },
00191 {"fetch_rows", INT_PARAM, &ul_fetch_rows },
00192 {"hash_size", INT_PARAM, &ul_hash_size },
00193 {"nat_bflag", INT_PARAM, &nat_bflag },
00194 {"preload", STR_PARAM|USE_FUNC_PARAM, (void*)ul_preload_param},
00195 {"db_update_as_insert", INT_PARAM, &ul_db_update_as_insert},
00196 {"timer_procs", INT_PARAM, &ul_timer_procs},
00197 {0, 0, 0}
00198 };
00199
00200
00201 stat_export_t mod_stats[] = {
00202 {"registered_users" , STAT_IS_FUNC, (stat_var**)get_number_of_users },
00203 {0,0,0}
00204 };
00205
00206
00207 static mi_export_t mi_cmds[] = {
00208 { MI_USRLOC_RM, mi_usrloc_rm_aor, 0, 0,
00209 mi_child_init },
00210 { MI_USRLOC_RM_CONTACT, mi_usrloc_rm_contact, 0, 0,
00211 mi_child_init },
00212 { MI_USRLOC_DUMP, mi_usrloc_dump, 0, 0,
00213 0 },
00214 { MI_USRLOC_FLUSH, mi_usrloc_flush, MI_NO_INPUT_FLAG, 0,
00215 mi_child_init },
00216 { MI_USRLOC_ADD, mi_usrloc_add, 0, 0,
00217 mi_child_init },
00218 { MI_USRLOC_SHOW_CONTACT, mi_usrloc_show_contact, 0, 0,
00219 mi_child_init },
00220 { 0, 0, 0, 0, 0}
00221 };
00222
00223
00224 struct module_exports exports = {
00225 "usrloc",
00226 DEFAULT_DLFLAGS,
00227 cmds,
00228 params,
00229 mod_stats,
00230 mi_cmds,
00231 0,
00232 0,
00233 mod_init,
00234 0,
00235 destroy,
00236 child_init
00237 };
00238
00239
00243 static int mod_init(void)
00244 {
00245 int i;
00246 udomain_t* d;
00247
00248 if(sruid_init(&_ul_sruid, '-', "ulcx", SRUID_INC)<0)
00249 return -1;
00250
00251 #ifdef STATISTICS
00252
00253 if (register_module_stats( exports.name, mod_stats)!=0 ) {
00254 LM_ERR("failed to register core statistics\n");
00255 return -1;
00256 }
00257 #endif
00258
00259 if(register_mi_mod(exports.name, mi_cmds)!=0)
00260 {
00261 LM_ERR("failed to register MI commands\n");
00262 return -1;
00263 }
00264
00265 if (rpc_register_array(ul_rpc)!=0)
00266 {
00267 LM_ERR("failed to register RPC commands\n");
00268 return -1;
00269 }
00270
00271
00272 ruid_col.len = strlen(ruid_col.s);
00273 user_col.len = strlen(user_col.s);
00274 domain_col.len = strlen(domain_col.s);
00275 contact_col.len = strlen(contact_col.s);
00276 expires_col.len = strlen(expires_col.s);
00277 q_col.len = strlen(q_col.s);
00278 callid_col.len = strlen(callid_col.s);
00279 cseq_col.len = strlen(cseq_col.s);
00280 flags_col.len = strlen(flags_col.s);
00281 cflags_col.len = strlen(cflags_col.s);
00282 user_agent_col.len = strlen(user_agent_col.s);
00283 received_col.len = strlen(received_col.s);
00284 path_col.len = strlen(path_col.s);
00285 sock_col.len = strlen(sock_col.s);
00286 methods_col.len = strlen(methods_col.s);
00287 instance_col.len = strlen(instance_col.s);
00288 reg_id_col.len = strlen(reg_id_col.s);
00289 last_mod_col.len = strlen(last_mod_col.s);
00290 db_url.len = strlen(db_url.s);
00291
00292 if(ul_hash_size<=1)
00293 ul_hash_size = 512;
00294 else
00295 ul_hash_size = 1<<ul_hash_size;
00296 ul_locks_no = ul_hash_size;
00297
00298
00299 switch (matching_mode) {
00300 case CONTACT_ONLY:
00301 case CONTACT_CALLID:
00302 case CONTACT_PATH:
00303 break;
00304 default:
00305 LM_ERR("invalid matching mode %d\n", matching_mode);
00306 }
00307
00308 if(ul_init_locks()!=0)
00309 {
00310 LM_ERR("locks array initialization failed\n");
00311 return -1;
00312 }
00313
00314
00315 if(ul_timer_procs<=0)
00316 register_timer(ul_core_timer, 0, timer_interval);
00317 else
00318 register_sync_timers(ul_timer_procs);
00319
00320
00321 if ( init_ulcb_list() < 0) {
00322 LM_ERR("usrloc/callbacks initialization failed\n");
00323 return -1;
00324 }
00325
00326
00327 if (db_mode != NO_DB) {
00328 if (db_bind_mod(&db_url, &ul_dbf) < 0) {
00329 LM_ERR("failed to bind database module\n");
00330 return -1;
00331 }
00332 if (!DB_CAPABILITY(ul_dbf, DB_CAP_ALL)) {
00333 LM_ERR("database module does not implement all functions"
00334 " needed by the module\n");
00335 return -1;
00336 }
00337 if(ul_fetch_rows<=0) {
00338 LM_ERR("invalid fetch_rows number '%d'\n", ul_fetch_rows);
00339 return -1;
00340 }
00341 }
00342
00343 if (nat_bflag==(unsigned int)-1) {
00344 nat_bflag = 0;
00345 } else if ( nat_bflag>=8*sizeof(nat_bflag) ) {
00346 LM_ERR("bflag index (%d) too big!\n", nat_bflag);
00347 return -1;
00348 } else {
00349 nat_bflag = 1<<nat_bflag;
00350 }
00351
00352 for(i=0; i<ul_preload_index; i++) {
00353 if(register_udomain((const char*)ul_preload_list[i], &d)<0) {
00354 LM_ERR("cannot register preloaded table %s\n", ul_preload_list[i]);
00355 return -1;
00356 }
00357 }
00358 init_flag = 1;
00359
00360 return 0;
00361 }
00362
00363
00364 static int child_init(int _rank)
00365 {
00366 dlist_t* ptr;
00367 int i;
00368
00369 if(_rank==PROC_MAIN && ul_timer_procs>0)
00370 {
00371 for(i=0; i<ul_timer_procs; i++)
00372 {
00373 if(fork_sync_timer(PROC_TIMER, "USRLOC Timer", 1 ,
00374 ul_local_timer, (void*)(long)i, timer_interval )<0) {
00375 LM_ERR("failed to start timer routine as process\n");
00376 return -1;
00377 }
00378 }
00379 }
00380
00381
00382 switch (db_mode) {
00383 case NO_DB:
00384 return 0;
00385 case DB_ONLY:
00386 case WRITE_THROUGH:
00387
00388
00389 if (_rank<=0 && _rank!=PROC_TIMER && _rank!=PROC_MAIN)
00390 return 0;
00391 break;
00392 case WRITE_BACK:
00393
00394
00395 if (_rank!=PROC_TIMER && _rank!=PROC_MAIN && _rank!=1)
00396 return 0;
00397 break;
00398 }
00399
00400 ul_dbh = ul_dbf.init(&db_url);
00401 if (!ul_dbh) {
00402 LM_ERR("child(%d): failed to connect to database\n", _rank);
00403 return -1;
00404 }
00405
00406 if (_rank==PROC_SIPINIT && db_mode!= DB_ONLY) {
00407
00408 for( ptr=root ; ptr ; ptr=ptr->next) {
00409 if (preload_udomain(ul_dbh, ptr->d) < 0) {
00410 LM_ERR("child(%d): failed to preload domain '%.*s'\n",
00411 _rank, ptr->name.len, ZSW(ptr->name.s));
00412 return -1;
00413 }
00414 }
00415 }
00416
00417 return 0;
00418 }
00419
00420
00421
00422 static int mi_child_init(void)
00423 {
00424 static int done = 0;
00425
00426 if (done)
00427 return 0;
00428
00429 if (db_mode != NO_DB) {
00430 ul_dbh = ul_dbf.init(&db_url);
00431 if (!ul_dbh) {
00432 LM_ERR("failed to connect to database\n");
00433 return -1;
00434 }
00435 }
00436 done = 1;
00437
00438 return 0;
00439 }
00440
00441
00445 static void destroy(void)
00446 {
00447
00448 if (ul_dbh) {
00449 ul_unlock_locks();
00450 if (synchronize_all_udomains(0, 1) != 0) {
00451 LM_ERR("flushing cache failed\n");
00452 }
00453 ul_dbf.close(ul_dbh);
00454 }
00455
00456 free_all_udomains();
00457 ul_destroy_locks();
00458
00459
00460 destroy_ulcb_list();
00461 }
00462
00463
00467 static void ul_core_timer(unsigned int ticks, void* param)
00468 {
00469 if (synchronize_all_udomains(0, 1) != 0) {
00470 LM_ERR("synchronizing cache failed\n");
00471 }
00472 }
00473
00477 static void ul_local_timer(unsigned int ticks, void* param)
00478 {
00479 if (synchronize_all_udomains((int)(long)param, ul_timer_procs) != 0) {
00480 LM_ERR("synchronizing cache failed\n");
00481 }
00482 }
00483
00487 static int ul_preload_param(modparam_t type, void* val)
00488 {
00489 if(val==NULL)
00490 {
00491 LM_ERR("invalid parameter\n");
00492 goto error;
00493 }
00494 if(ul_preload_index>=UL_PRELOAD_SIZE)
00495 {
00496 LM_ERR("too many preloaded tables\n");
00497 goto error;
00498 }
00499 ul_preload_list[ul_preload_index] = (char*)val;
00500 ul_preload_index++;
00501 return 0;
00502 error:
00503 return -1;
00504 }