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
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #include <stdio.h>
00055 #include "ul_mod.h"
00056 #include "../../sr_module.h"
00057 #include "../../dprint.h"
00058 #include "../../timer.h"
00059 #include "../../globals.h"
00060 #include "../../ut.h"
00061 #include "dlist.h"
00062 #include "udomain.h"
00063 #include "urecord.h"
00064 #include "ucontact.h"
00065 #include "ul_mi.h"
00066 #include "ul_callback.h"
00067 #include "usrloc.h"
00068
00069 MODULE_VERSION
00070
00071 #define USER_COL "username"
00072 #define DOMAIN_COL "domain"
00073 #define CONTACT_COL "contact"
00074 #define EXPIRES_COL "expires"
00075 #define Q_COL "q"
00076 #define CALLID_COL "callid"
00077 #define CSEQ_COL "cseq"
00078 #define FLAGS_COL "flags"
00079 #define CFLAGS_COL "cflags"
00080 #define USER_AGENT_COL "user_agent"
00081 #define RECEIVED_COL "received"
00082 #define PATH_COL "path"
00083 #define SOCK_COL "socket"
00084 #define METHODS_COL "methods"
00085 #define LAST_MOD_COL "last_modified"
00086
00087 static int mod_init(void);
00088 static void destroy(void);
00089 static void timer(unsigned int ticks, void* param);
00090 static int child_init(int rank);
00091 static int mi_child_init(void);
00092
00093 extern int bind_usrloc(usrloc_api_t* api);
00094 extern int ul_locks_no;
00095
00096
00097
00098
00099 str user_col = str_init(USER_COL);
00100 str domain_col = str_init(DOMAIN_COL);
00101 str contact_col = str_init(CONTACT_COL);
00102 str expires_col = str_init(EXPIRES_COL);
00103 str q_col = str_init(Q_COL);
00104 str callid_col = str_init(CALLID_COL);
00105 str cseq_col = str_init(CSEQ_COL);
00106 str flags_col = str_init(FLAGS_COL);
00107 str cflags_col = str_init(CFLAGS_COL);
00108 str user_agent_col = str_init(USER_AGENT_COL);
00109 str received_col = str_init(RECEIVED_COL);
00110 str path_col = str_init(PATH_COL);
00111 str sock_col = str_init(SOCK_COL);
00112 str methods_col = str_init(METHODS_COL);
00113 str last_mod_col = str_init(LAST_MOD_COL);
00114 str db_url = str_init(DEFAULT_DB_URL);
00115 int timer_interval = 60;
00116 int db_mode = 0;
00117 int use_domain = 0;
00118 int desc_time_order = 0;
00119
00120 int ul_fetch_rows = 2000;
00121 int ul_hash_size = 9;
00122
00123
00124 unsigned int nat_bflag = (unsigned int)-1;
00125 unsigned int init_flag = 0;
00126
00127 db_con_t* ul_dbh = 0;
00128 db_func_t ul_dbf;
00129
00130
00131
00132
00133
00134
00135 static cmd_export_t cmds[] = {
00136 {"ul_bind_usrloc", (cmd_function)bind_usrloc, 1, 0, 0, 0},
00137 {0, 0, 0, 0, 0, 0}
00138 };
00139
00140
00141
00142
00143
00144 static param_export_t params[] = {
00145 {"user_column", STR_PARAM, &user_col.s },
00146 {"domain_column", STR_PARAM, &domain_col.s },
00147 {"contact_column", STR_PARAM, &contact_col.s },
00148 {"expires_column", STR_PARAM, &expires_col.s },
00149 {"q_column", STR_PARAM, &q_col.s },
00150 {"callid_column", STR_PARAM, &callid_col.s },
00151 {"cseq_column", STR_PARAM, &cseq_col.s },
00152 {"flags_column", STR_PARAM, &flags_col.s },
00153 {"cflags_column", STR_PARAM, &cflags_col.s },
00154 {"db_url", STR_PARAM, &db_url.s },
00155 {"timer_interval", INT_PARAM, &timer_interval },
00156 {"db_mode", INT_PARAM, &db_mode },
00157 {"use_domain", INT_PARAM, &use_domain },
00158 {"desc_time_order", INT_PARAM, &desc_time_order },
00159 {"user_agent_column", STR_PARAM, &user_agent_col.s},
00160 {"received_column", STR_PARAM, &received_col.s },
00161 {"path_column", STR_PARAM, &path_col.s },
00162 {"socket_column", STR_PARAM, &sock_col.s },
00163 {"methods_column", STR_PARAM, &methods_col.s },
00164 {"matching_mode", INT_PARAM, &matching_mode },
00165 {"cseq_delay", INT_PARAM, &cseq_delay },
00166 {"fetch_rows", INT_PARAM, &ul_fetch_rows },
00167 {"hash_size", INT_PARAM, &ul_hash_size },
00168 {"nat_bflag", INT_PARAM, &nat_bflag },
00169 {0, 0, 0}
00170 };
00171
00172
00173 stat_export_t mod_stats[] = {
00174 {"registered_users" , STAT_IS_FUNC, (stat_var**)get_number_of_users },
00175 {0,0,0}
00176 };
00177
00178
00179 static mi_export_t mi_cmds[] = {
00180 { MI_USRLOC_RM, mi_usrloc_rm_aor, 0, 0,
00181 mi_child_init },
00182 { MI_USRLOC_RM_CONTACT, mi_usrloc_rm_contact, 0, 0,
00183 mi_child_init },
00184 { MI_USRLOC_DUMP, mi_usrloc_dump, 0, 0,
00185 0 },
00186 { MI_USRLOC_FLUSH, mi_usrloc_flush, MI_NO_INPUT_FLAG, 0,
00187 mi_child_init },
00188 { MI_USRLOC_ADD, mi_usrloc_add, 0, 0,
00189 mi_child_init },
00190 { MI_USRLOC_SHOW_CONTACT, mi_usrloc_show_contact, 0, 0,
00191 mi_child_init },
00192 { 0, 0, 0, 0, 0}
00193 };
00194
00195
00196 struct module_exports exports = {
00197 "usrloc",
00198 DEFAULT_DLFLAGS,
00199 cmds,
00200 params,
00201 mod_stats,
00202 mi_cmds,
00203 0,
00204 0,
00205 mod_init,
00206 0,
00207 destroy,
00208 child_init
00209 };
00210
00211
00212
00213
00214
00215 static int mod_init(void)
00216 {
00217
00218 user_col.len = strlen(user_col.s);
00219 domain_col.len = strlen(domain_col.s);
00220 contact_col.len = strlen(contact_col.s);
00221 expires_col.len = strlen(expires_col.s);
00222 q_col.len = strlen(q_col.s);
00223 callid_col.len = strlen(callid_col.s);
00224 cseq_col.len = strlen(cseq_col.s);
00225 flags_col.len = strlen(flags_col.s);
00226 cflags_col.len = strlen(cflags_col.s);
00227 user_agent_col.len = strlen(user_agent_col.s);
00228 received_col.len = strlen(received_col.s);
00229 path_col.len = strlen(path_col.s);
00230 sock_col.len = strlen(sock_col.s);
00231 methods_col.len = strlen(methods_col.s);
00232 last_mod_col.len = strlen(last_mod_col.s);
00233 db_url.len = strlen(db_url.s);
00234
00235 if(ul_hash_size<=1)
00236 ul_hash_size = 512;
00237 else
00238 ul_hash_size = 1<<ul_hash_size;
00239 ul_locks_no = ul_hash_size;
00240
00241
00242 switch (matching_mode) {
00243 case CONTACT_ONLY:
00244 case CONTACT_CALLID:
00245 break;
00246 default:
00247 LM_ERR("invalid matching mode %d\n", matching_mode);
00248 }
00249
00250 if(ul_init_locks()!=0)
00251 {
00252 LM_ERR("locks array initialization failed\n");
00253 return -1;
00254 }
00255
00256
00257 register_timer( timer, 0, timer_interval);
00258
00259
00260 if ( init_ulcb_list() < 0) {
00261 LM_ERR("usrloc/callbacks initialization failed\n");
00262 return -1;
00263 }
00264
00265
00266 if (db_mode != NO_DB) {
00267 if (db_bind_mod(&db_url, &ul_dbf) < 0) {
00268 LM_ERR("failed to bind database module\n");
00269 return -1;
00270 }
00271 if (!DB_CAPABILITY(ul_dbf, DB_CAP_ALL)) {
00272 LM_ERR("database module does not implement all functions"
00273 " needed by the module\n");
00274 return -1;
00275 }
00276 if(ul_fetch_rows<=0) {
00277 LM_ERR("invalid fetch_rows number '%d'\n", ul_fetch_rows);
00278 return -1;
00279 }
00280 }
00281
00282 if (nat_bflag==(unsigned int)-1) {
00283 nat_bflag = 0;
00284 } else if ( nat_bflag>=8*sizeof(nat_bflag) ) {
00285 LM_ERR("bflag index (%d) too big!\n", nat_bflag);
00286 return -1;
00287 } else {
00288 nat_bflag = 1<<nat_bflag;
00289 }
00290
00291 init_flag = 1;
00292
00293 return 0;
00294 }
00295
00296
00297 static int child_init(int _rank)
00298 {
00299 dlist_t* ptr;
00300
00301
00302 switch (db_mode) {
00303 case NO_DB:
00304 return 0;
00305 case DB_ONLY:
00306 case WRITE_THROUGH:
00307
00308
00309 if (_rank<=0 && _rank!=PROC_TIMER && _rank!=PROC_MAIN)
00310 return 0;
00311 break;
00312 case WRITE_BACK:
00313
00314
00315 if (_rank!=PROC_TIMER && _rank!=PROC_MAIN && _rank!=1)
00316 return 0;
00317 break;
00318 }
00319
00320 ul_dbh = ul_dbf.init(&db_url);
00321 if (!ul_dbh) {
00322 LM_ERR("child(%d): failed to connect to database\n", _rank);
00323 return -1;
00324 }
00325
00326 if (_rank==1 && db_mode!= DB_ONLY) {
00327
00328 for( ptr=root ; ptr ; ptr=ptr->next) {
00329 if (preload_udomain(ul_dbh, ptr->d) < 0) {
00330 LM_ERR("child(%d): failed to preload domain '%.*s'\n",
00331 _rank, ptr->name.len, ZSW(ptr->name.s));
00332 return -1;
00333 }
00334 }
00335 }
00336
00337 return 0;
00338 }
00339
00340
00341
00342 static int mi_child_init(void)
00343 {
00344 static int done = 0;
00345
00346 if (done)
00347 return 0;
00348
00349 if (db_mode != NO_DB) {
00350 ul_dbh = ul_dbf.init(&db_url);
00351 if (!ul_dbh) {
00352 LM_ERR("failed to connect to database\n");
00353 return -1;
00354 }
00355 }
00356 done = 1;
00357
00358 return 0;
00359 }
00360
00361
00362
00363
00364
00365 static void destroy(void)
00366 {
00367
00368 if (ul_dbh) {
00369 ul_unlock_locks();
00370 if (synchronize_all_udomains() != 0) {
00371 LM_ERR("flushing cache failed\n");
00372 }
00373 ul_dbf.close(ul_dbh);
00374 }
00375
00376 free_all_udomains();
00377 ul_destroy_locks();
00378
00379
00380 destroy_ulcb_list();
00381 }
00382
00383
00384
00385
00386
00387 static void timer(unsigned int ticks, void* param)
00388 {
00389 if (synchronize_all_udomains() != 0) {
00390 LM_ERR("synchronizing cache failed\n");
00391 }
00392 }
00393