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 #include <stdio.h>
00041 #include <string.h>
00042 #include <stdlib.h>
00043 #include <sys/time.h>
00044
00045 #include "../../sr_module.h"
00046 #include "../../db/db.h"
00047 #include "../../dprint.h"
00048 #include "../../error.h"
00049 #include "../../ut.h"
00050 #include "../../pvar.h"
00051 #include "../../mod_fix.h"
00052 #include "../../script_cb.h"
00053 #include "../../faked_msg.h"
00054 #include "../../mem/mem.h"
00055 #include "../../mi/mi.h"
00056 #include "../tm/tm_load.h"
00057 #include "../rr/api.h"
00058 #include "dlg_hash.h"
00059 #include "dlg_timer.h"
00060 #include "dlg_handlers.h"
00061 #include "dlg_load.h"
00062 #include "dlg_cb.h"
00063 #include "dlg_db_handler.h"
00064 #include "dlg_req_within.h"
00065 #include "dlg_profile.h"
00066 #include "dlg_var.h"
00067 #include "dlg_transfer.h"
00068
00069 MODULE_VERSION
00070
00071
00072 static int mod_init(void);
00073 static int child_init(int rank);
00074 static void mod_destroy(void);
00075
00076
00077 static int dlg_hash_size = 4096;
00078 static char* rr_param = "did";
00079 static int dlg_flag = -1;
00080 static str timeout_spec = {NULL, 0};
00081 static int default_timeout = 60 * 60 * 12;
00082 static int seq_match_mode = SEQ_MATCH_STRICT_ID;
00083 static char* profiles_wv_s = NULL;
00084 static char* profiles_nv_s = NULL;
00085 str dlg_extra_hdrs = {NULL,0};
00086 static int db_fetch_rows = 200;
00087
00088 str dlg_bridge_controller = {"sip:controller@kamailio.org", 27};
00089
00090
00091 int dlg_enable_stats = 1;
00092 int active_dlgs_cnt = 0;
00093 int early_dlgs_cnt = 0;
00094 stat_var *active_dlgs = 0;
00095 stat_var *processed_dlgs = 0;
00096 stat_var *expired_dlgs = 0;
00097 stat_var *failed_dlgs = 0;
00098 stat_var *early_dlgs = 0;
00099
00100 struct tm_binds d_tmb;
00101 struct rr_binds d_rrb;
00102 pv_spec_t timeout_avp;
00103
00104
00105 static str db_url = str_init(DEFAULT_DB_URL);
00106 static unsigned int db_update_period = DB_DEFAULT_UPDATE_PERIOD;
00107
00108 static int pv_get_dlg_count( struct sip_msg *msg, pv_param_t *param,
00109 pv_value_t *res);
00110
00111
00112 static int fixup_profile(void** param, int param_no);
00113 static int fixup_get_profile2(void** param, int param_no);
00114 static int fixup_get_profile3(void** param, int param_no);
00115 static int w_set_dlg_profile(struct sip_msg*, char*, char*);
00116 static int w_unset_dlg_profile(struct sip_msg*, char*, char*);
00117 static int w_is_in_profile(struct sip_msg*, char*, char*);
00118 static int w_get_profile_size(struct sip_msg*, char*, char*, char*);
00119 static int w_dlg_isflagset(struct sip_msg *msg, char *flag, str *s2);
00120 static int w_dlg_resetflag(struct sip_msg *msg, char *flag, str *s2);
00121 static int w_dlg_setflag(struct sip_msg *msg, char *flag, char *s2);
00122 static int w_dlg_manage(struct sip_msg*, char*, char*);
00123 static int w_dlg_bye(struct sip_msg*, char*, char*);
00124 static int w_dlg_refer(struct sip_msg*, char*, char*);
00125 static int w_dlg_bridge(struct sip_msg*, char*, char*, char*);
00126 static int fixup_dlg_bye(void** param, int param_no);
00127 static int fixup_dlg_refer(void** param, int param_no);
00128 static int fixup_dlg_bridge(void** param, int param_no);
00129 static int w_dlg_get(struct sip_msg*, char*, char*, char*);
00130
00131 static cmd_export_t cmds[]={
00132 {"dlg_manage", (cmd_function)w_dlg_manage, 0,0,
00133 0, REQUEST_ROUTE },
00134 {"set_dlg_profile", (cmd_function)w_set_dlg_profile, 1,fixup_profile,
00135 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00136 {"set_dlg_profile", (cmd_function)w_set_dlg_profile, 2,fixup_profile,
00137 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00138 {"unset_dlg_profile", (cmd_function)w_unset_dlg_profile, 1,fixup_profile,
00139 0, FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00140 {"unset_dlg_profile", (cmd_function)w_unset_dlg_profile, 2,fixup_profile,
00141 0, FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00142 {"is_in_profile", (cmd_function)w_is_in_profile, 1,fixup_profile,
00143 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00144 {"is_in_profile", (cmd_function)w_is_in_profile, 2,fixup_profile,
00145 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00146 {"get_profile_size",(cmd_function)w_get_profile_size, 2,fixup_get_profile2,
00147 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00148 {"get_profile_size",(cmd_function)w_get_profile_size, 3,fixup_get_profile3,
00149 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00150 {"dlg_setflag", (cmd_function)w_dlg_setflag, 1,fixup_igp_null,
00151 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00152 {"dlg_resetflag", (cmd_function)w_dlg_resetflag, 1,fixup_igp_null,
00153 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00154 {"dlg_isflagset", (cmd_function)w_dlg_isflagset, 1,fixup_igp_null,
00155 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00156 {"dlg_bye",(cmd_function)w_dlg_bye, 1,fixup_dlg_bye,
00157 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00158 {"dlg_refer",(cmd_function)w_dlg_refer, 2,fixup_dlg_refer,
00159 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00160 {"dlg_bridge",(cmd_function)w_dlg_bridge, 3,fixup_dlg_bridge,
00161 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00162 {"dlg_get",(cmd_function)w_dlg_get, 3,fixup_dlg_bridge,
00163 0, REQUEST_ROUTE| FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00164 {"load_dlg", (cmd_function)load_dlg, 0, 0, 0, 0},
00165 {0,0,0,0,0,0}
00166 };
00167
00168 static param_export_t mod_params[]={
00169 { "enable_stats", INT_PARAM, &dlg_enable_stats },
00170 { "hash_size", INT_PARAM, &dlg_hash_size },
00171 { "rr_param", STR_PARAM, &rr_param },
00172 { "dlg_flag", INT_PARAM, &dlg_flag },
00173 { "timeout_avp", STR_PARAM, &timeout_spec.s },
00174 { "default_timeout", INT_PARAM, &default_timeout },
00175 { "dlg_extra_hdrs", STR_PARAM, &dlg_extra_hdrs.s },
00176 { "dlg_match_mode", INT_PARAM, &seq_match_mode },
00177 { "db_url", STR_PARAM, &db_url.s },
00178 { "db_mode", INT_PARAM, &dlg_db_mode },
00179 { "table_name", STR_PARAM, &dialog_table_name },
00180 { "call_id_column", STR_PARAM, &call_id_column.s },
00181 { "from_uri_column", STR_PARAM, &from_uri_column.s },
00182 { "from_tag_column", STR_PARAM, &from_tag_column.s },
00183 { "to_uri_column", STR_PARAM, &to_uri_column.s },
00184 { "to_tag_column", STR_PARAM, &to_tag_column.s },
00185 { "h_id_column", STR_PARAM, &h_id_column.s },
00186 { "h_entry_column", STR_PARAM, &h_entry_column.s },
00187 { "state_column", STR_PARAM, &state_column.s },
00188 { "start_time_column", STR_PARAM, &start_time_column.s },
00189 { "timeout_column", STR_PARAM, &timeout_column.s },
00190 { "to_cseq_column", STR_PARAM, &to_cseq_column.s },
00191 { "from_cseq_column", STR_PARAM, &from_cseq_column.s },
00192 { "to_route_column", STR_PARAM, &to_route_column.s },
00193 { "from_route_column", STR_PARAM, &from_route_column.s },
00194 { "to_contact_column", STR_PARAM, &to_contact_column.s },
00195 { "from_contact_column", STR_PARAM, &from_contact_column.s },
00196 { "to_sock_column", STR_PARAM, &to_sock_column.s },
00197 { "from_sock_column", STR_PARAM, &from_sock_column.s },
00198 { "sflags_column", STR_PARAM, &sflags_column.s },
00199 { "toroute_column", STR_PARAM, &toroute_column.s },
00200 { "db_update_period", INT_PARAM, &db_update_period },
00201 { "db_fetch_rows", INT_PARAM, &db_fetch_rows },
00202 { "profiles_with_value", STR_PARAM, &profiles_wv_s },
00203 { "profiles_no_value", STR_PARAM, &profiles_nv_s },
00204 { "bridge_controller", STR_PARAM, &dlg_bridge_controller.s },
00205 { 0,0,0 }
00206 };
00207
00208
00209 static stat_export_t mod_stats[] = {
00210 {"active_dialogs" , STAT_NO_RESET, &active_dlgs },
00211 {"early_dialogs", STAT_NO_RESET, &early_dlgs },
00212 {"processed_dialogs" , 0, &processed_dlgs },
00213 {"expired_dialogs" , 0, &expired_dlgs },
00214 {"failed_dialogs", 0, &failed_dlgs },
00215 {0,0,0}
00216 };
00217
00218 struct mi_root * mi_dlg_bridge(struct mi_root *cmd_tree, void *param);
00219
00220 static mi_export_t mi_cmds[] = {
00221 { "dlg_list", mi_print_dlgs, 0, 0, 0},
00222 { "dlg_list_ctx", mi_print_dlgs_ctx, 0, 0, 0},
00223 { "dlg_end_dlg", mi_terminate_dlg, 0, 0, 0},
00224 { "profile_get_size", mi_get_profile, 0, 0, 0},
00225 { "profile_list_dlgs", mi_profile_list, 0, 0, 0},
00226 { "dlg_bridge", mi_dlg_bridge, 0, 0, 0},
00227 { 0, 0, 0, 0, 0}
00228 };
00229
00230
00231 static pv_export_t mod_items[] = {
00232 { {"DLG_count", sizeof("DLG_count")-1}, PVT_OTHER, pv_get_dlg_count, 0,
00233 0, 0, 0, 0 },
00234 { {"DLG_lifetime",sizeof("DLG_lifetime")-1}, PVT_OTHER, pv_get_dlg_lifetime, 0,
00235 0, 0, 0, 0 },
00236 { {"DLG_status", sizeof("DLG_status")-1}, PVT_OTHER, pv_get_dlg_status, 0,
00237 0, 0, 0, 0 },
00238 { {"dlg_ctx", sizeof("dlg_ctx")-1}, PVT_OTHER, pv_get_dlg_ctx,
00239 pv_set_dlg_ctx, pv_parse_dlg_ctx_name, 0, 0, 0 },
00240 { {"dlg", sizeof("dlg")-1}, PVT_OTHER, pv_get_dlg,
00241 0, pv_parse_dlg_name, 0, 0, 0 },
00242 { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
00243 };
00244
00245 struct module_exports exports= {
00246 "dialog",
00247 DEFAULT_DLFLAGS,
00248 cmds,
00249 mod_params,
00250 mod_stats,
00251 mi_cmds,
00252 mod_items,
00253 0,
00254 mod_init,
00255 0,
00256 mod_destroy,
00257 child_init
00258 };
00259
00260
00261 static int fixup_profile(void** param, int param_no)
00262 {
00263 struct dlg_profile_table *profile;
00264 pv_elem_t *model=NULL;
00265 str s;
00266
00267 s.s = (char*)(*param);
00268 s.len = strlen(s.s);
00269 if(s.len==0) {
00270 LM_ERR("param %d is empty string!\n", param_no);
00271 return E_CFG;
00272 }
00273
00274 if (param_no==1) {
00275 profile = search_dlg_profile( &s );
00276 if (profile==NULL) {
00277 LM_CRIT("profile <%s> not definited\n",s.s);
00278 return E_CFG;
00279 }
00280 pkg_free(*param);
00281 *param = (void*)profile;
00282 return 0;
00283 } else if (param_no==2) {
00284 if(pv_parse_format(&s ,&model) || model==NULL) {
00285 LM_ERR("wrong format [%s] for value param!\n", s.s);
00286 return E_CFG;
00287 }
00288 *param = (void*)model;
00289 }
00290 return 0;
00291 }
00292
00293
00294 static int fixup_get_profile2(void** param, int param_no)
00295 {
00296 pv_spec_t *sp;
00297 int ret;
00298
00299 if (param_no==1) {
00300 return fixup_profile(param, 1);
00301 } else if (param_no==2) {
00302 ret = fixup_pvar(param);
00303 if (ret<0) return ret;
00304 sp = (pv_spec_t*)(*param);
00305 if (sp->type!=PVT_AVP && sp->type!=PVT_SCRIPTVAR) {
00306 LM_ERR("return must be an AVP or SCRIPT VAR!\n");
00307 return E_SCRIPT;
00308 }
00309 }
00310 return 0;
00311 }
00312
00313
00314 static int fixup_get_profile3(void** param, int param_no)
00315 {
00316 if (param_no==1) {
00317 return fixup_profile(param, 1);
00318 } else if (param_no==2) {
00319 return fixup_profile(param, 2);
00320 } else if (param_no==3) {
00321 return fixup_get_profile2( param, 2);
00322 }
00323 return 0;
00324 }
00325
00326
00327
00328 int load_dlg( struct dlg_binds *dlgb )
00329 {
00330 dlgb->register_dlgcb = register_dlgcb;
00331 return 1;
00332 }
00333
00334
00335 static int pv_get_dlg_count(struct sip_msg *msg, pv_param_t *param,
00336 pv_value_t *res)
00337 {
00338 int n;
00339 int l;
00340 char *ch;
00341
00342 if(msg==NULL || res==NULL)
00343 return -1;
00344
00345 n = active_dlgs ? get_stat_val(active_dlgs) : 0;
00346 l = 0;
00347 ch = int2str( n, &l);
00348
00349 res->rs.s = ch;
00350 res->rs.len = l;
00351
00352 res->ri = n;
00353 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
00354
00355 return 0;
00356 }
00357
00358
00359 static int mod_init(void)
00360 {
00361 unsigned int n;
00362
00363 if(faked_msg_init()<0)
00364 return -1;
00365
00366 if (timeout_spec.s)
00367 timeout_spec.len = strlen(timeout_spec.s);
00368
00369 dlg_bridge_controller.len = strlen(dlg_bridge_controller.s);
00370 db_url.len = strlen(db_url.s);
00371 call_id_column.len = strlen(call_id_column.s);
00372 from_uri_column.len = strlen(from_uri_column.s);
00373 from_tag_column.len = strlen(from_tag_column.s);
00374 to_uri_column.len = strlen(to_uri_column.s);
00375 to_tag_column.len = strlen(to_tag_column.s);
00376 h_id_column.len = strlen(h_id_column.s);
00377 h_entry_column.len = strlen(h_entry_column.s);
00378 state_column.len = strlen(state_column.s);
00379 start_time_column.len = strlen(start_time_column.s);
00380 timeout_column.len = strlen(timeout_column.s);
00381 to_cseq_column.len = strlen(to_cseq_column.s);
00382 from_cseq_column.len = strlen(from_cseq_column.s);
00383 to_route_column.len = strlen(to_route_column.s);
00384 from_route_column.len = strlen(from_route_column.s);
00385 to_contact_column.len = strlen(to_contact_column.s);
00386 from_contact_column.len = strlen(from_contact_column.s);
00387 to_sock_column.len = strlen(to_sock_column.s);
00388 from_sock_column.len = strlen(from_sock_column.s);
00389 sflags_column.len = strlen(sflags_column.s);
00390 toroute_column.len = strlen(toroute_column.s);
00391 dialog_table_name.len = strlen(dialog_table_name.s);
00392
00393
00394 if (dlg_flag==-1) {
00395 LM_ERR("no dlg flag set!!\n");
00396 return -1;
00397 } else if (dlg_flag>MAX_FLAG) {
00398 LM_ERR("invalid dlg flag %d!!\n",dlg_flag);
00399 return -1;
00400 }
00401
00402 if (rr_param==0 || rr_param[0]==0) {
00403 LM_ERR("empty rr_param!!\n");
00404 return -1;
00405 } else if (strlen(rr_param)>MAX_DLG_RR_PARAM_NAME) {
00406 LM_ERR("rr_param too long (max=%d)!!\n", MAX_DLG_RR_PARAM_NAME);
00407 return -1;
00408 }
00409
00410 if (timeout_spec.s) {
00411 if ( pv_parse_spec(&timeout_spec, &timeout_avp)==0
00412 && (timeout_avp.type!=PVT_AVP)){
00413 LM_ERR("malformed or non AVP timeout "
00414 "AVP definition in '%.*s'\n", timeout_spec.len,timeout_spec.s);
00415 return -1;
00416 }
00417 }
00418
00419 if (default_timeout<=0) {
00420 LM_ERR("0 default_timeout not accepted!!\n");
00421 return -1;
00422 }
00423
00424
00425 if (dlg_extra_hdrs.s)
00426 dlg_extra_hdrs.len = strlen(dlg_extra_hdrs.s);
00427
00428 if (seq_match_mode!=SEQ_MATCH_NO_ID &&
00429 seq_match_mode!=SEQ_MATCH_FALLBACK &&
00430 seq_match_mode!=SEQ_MATCH_STRICT_ID ) {
00431 LM_ERR("invalid value %d for seq_match_mode param!!\n",seq_match_mode);
00432 return -1;
00433 }
00434
00435
00436 if (dlg_enable_stats==0)
00437 exports.stats = 0;
00438
00439
00440 if (add_profile_definitions( profiles_nv_s, 0)!=0 ) {
00441 LM_ERR("failed to add profiles without value\n");
00442 return -1;
00443 }
00444 if (add_profile_definitions( profiles_wv_s, 1)!=0 ) {
00445 LM_ERR("failed to add profiles with value\n");
00446 return -1;
00447 }
00448
00449
00450 if (load_tm_api(&d_tmb)!=0) {
00451 LM_ERR("can't load TM API\n");
00452 return -1;
00453 }
00454
00455
00456 if (load_rr_api(&d_rrb)!=0) {
00457 LM_ERR("can't load RR API\n");
00458 return -1;
00459 }
00460
00461
00462
00463 if ( d_tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, dlg_onreq, 0, 0 ) <=0 ) {
00464 LM_ERR("cannot register TMCB_REQUEST_IN callback\n");
00465 return -1;
00466 }
00467
00468
00469 if ( d_rrb.register_rrcb( dlg_onroute, 0 ) <0 ) {
00470 LM_ERR("cannot register RR callback\n");
00471 return -1;
00472 }
00473
00474 if (register_script_cb( profile_cleanup, POST_SCRIPT_CB|REQ_TYPE_CB,0)<0) {
00475 LM_ERR("cannot regsiter script callback");
00476 return -1;
00477 }
00478 if (register_script_cb(dlg_cfg_cb,
00479 PRE_SCRIPT_CB|REQ_TYPE_CB,0)<0)
00480 {
00481 LM_ERR("cannot regsiter pre-script ctx callback\n");
00482 return -1;
00483 }
00484 if (register_script_cb(dlg_cfg_cb,
00485 POST_SCRIPT_CB|REQ_TYPE_CB,0)<0)
00486 {
00487 LM_ERR("cannot regsiter post-script ctx callback\n");
00488 return -1;
00489 }
00490
00491 if ( register_timer( dlg_timer_routine, 0, 1)<0 ) {
00492 LM_ERR("failed to register timer \n");
00493 return -1;
00494 }
00495
00496
00497 init_dlg_handlers( rr_param, dlg_flag,
00498 timeout_spec.s?&timeout_avp:0, default_timeout, seq_match_mode);
00499
00500
00501 if (init_dlg_timer(dlg_ontimeout)!=0) {
00502 LM_ERR("cannot init timer list\n");
00503 return -1;
00504 }
00505
00506
00507 for( n=0 ; n<(8*sizeof(n)) ; n++) {
00508 if (dlg_hash_size==(1<<n))
00509 break;
00510 if (dlg_hash_size<(1<<n)) {
00511 LM_WARN("hash_size is not a power "
00512 "of 2 as it should be -> rounding from %d to %d\n",
00513 dlg_hash_size, 1<<(n-1));
00514 dlg_hash_size = 1<<(n-1);
00515 }
00516 }
00517
00518 if ( init_dlg_table(dlg_hash_size)<0 ) {
00519 LM_ERR("failed to create hash table\n");
00520 return -1;
00521 }
00522
00523
00524 if (dlg_db_mode==DB_MODE_NONE) {
00525 db_url.s = 0; db_url.len = 0;
00526 } else {
00527 if (dlg_db_mode!=DB_MODE_REALTIME &&
00528 dlg_db_mode!=DB_MODE_DELAYED && dlg_db_mode!=DB_MODE_SHUTDOWN ) {
00529 LM_ERR("unsupported db_mode %d\n", dlg_db_mode);
00530 return -1;
00531 }
00532 if ( !db_url.s || db_url.len==0 ) {
00533 LM_ERR("db_url not configured for db_mode %d\n", dlg_db_mode);
00534 return -1;
00535 }
00536 if (init_dlg_db(&db_url, dlg_hash_size, db_update_period,db_fetch_rows)!=0) {
00537 LM_ERR("failed to initialize the DB support\n");
00538 return -1;
00539 }
00540 run_load_callbacks();
00541 }
00542
00543 destroy_dlg_callbacks( DLGCB_LOADED );
00544
00545 return 0;
00546 }
00547
00548
00549 static int child_init(int rank)
00550 {
00551 if (rank==1) {
00552 if_update_stat(dlg_enable_stats, active_dlgs, active_dlgs_cnt);
00553 if_update_stat(dlg_enable_stats, early_dlgs, early_dlgs_cnt);
00554 }
00555
00556 if ( (dlg_db_mode==DB_MODE_REALTIME && (rank>0 || rank==PROC_TIMER)) ||
00557 (dlg_db_mode==DB_MODE_SHUTDOWN && (rank==PROC_MAIN)) ||
00558 (dlg_db_mode==DB_MODE_DELAYED && (rank==PROC_MAIN || rank==PROC_TIMER ||
00559 rank>0) )){
00560 if ( dlg_connect_db(&db_url) ) {
00561 LM_ERR("failed to connect to database (rank=%d)\n",rank);
00562 return -1;
00563 }
00564 }
00565
00566
00567
00568 if (dlg_db_mode==DB_MODE_SHUTDOWN && rank!=PROC_MAIN)
00569 dlg_db_mode = DB_MODE_NONE;
00570
00571 return 0;
00572 }
00573
00574
00575 static void mod_destroy(void)
00576 {
00577 if(dlg_db_mode == DB_MODE_DELAYED || dlg_db_mode == DB_MODE_SHUTDOWN) {
00578 dialog_update_db(0, 0);
00579 destroy_dlg_db();
00580 }
00581
00582 dlg_db_mode = DB_MODE_NONE;
00583 destroy_dlg_table();
00584 destroy_dlg_timer();
00585 destroy_dlg_callbacks( DLGCB_CREATED|DLGCB_LOADED );
00586 destroy_dlg_handlers();
00587 destroy_dlg_profiles();
00588 }
00589
00590
00591
00592 static int w_set_dlg_profile(struct sip_msg *msg, char *profile, char *value)
00593 {
00594 pv_elem_t *pve;
00595 str val_s;
00596
00597 pve = (pv_elem_t *)value;
00598
00599 if (((struct dlg_profile_table*)profile)->has_value) {
00600 if ( pve==NULL || pv_printf_s(msg, pve, &val_s)!=0 ||
00601 val_s.len == 0 || val_s.s == NULL) {
00602 LM_WARN("cannot get string for value\n");
00603 return -1;
00604 }
00605 if ( set_dlg_profile( msg, &val_s,
00606 (struct dlg_profile_table*)profile) < 0 ) {
00607 LM_ERR("failed to set profile");
00608 return -1;
00609 }
00610 } else {
00611 if ( set_dlg_profile( msg, NULL,
00612 (struct dlg_profile_table*)profile) < 0 ) {
00613 LM_ERR("failed to set profile");
00614 return -1;
00615 }
00616 }
00617 return 1;
00618 }
00619
00620
00621
00622 static int w_unset_dlg_profile(struct sip_msg *msg, char *profile, char *value)
00623 {
00624 pv_elem_t *pve;
00625 str val_s;
00626
00627 pve = (pv_elem_t *)value;
00628
00629 if (((struct dlg_profile_table*)profile)->has_value) {
00630 if ( pve==NULL || pv_printf_s(msg, pve, &val_s)!=0 ||
00631 val_s.len == 0 || val_s.s == NULL) {
00632 LM_WARN("cannot get string for value\n");
00633 return -1;
00634 }
00635 if ( unset_dlg_profile( msg, &val_s,
00636 (struct dlg_profile_table*)profile) < 0 ) {
00637 LM_ERR("failed to unset profile");
00638 return -1;
00639 }
00640 } else {
00641 if ( unset_dlg_profile( msg, NULL,
00642 (struct dlg_profile_table*)profile) < 0 ) {
00643 LM_ERR("failed to unset profile");
00644 return -1;
00645 }
00646 }
00647 return 1;
00648 }
00649
00650
00651
00652 static int w_is_in_profile(struct sip_msg *msg, char *profile, char *value)
00653 {
00654 pv_elem_t *pve;
00655 str val_s;
00656
00657 pve = (pv_elem_t *)value;
00658
00659 if ( pve!=NULL && ((struct dlg_profile_table*)profile)->has_value) {
00660 if ( pv_printf_s(msg, pve, &val_s)!=0 ||
00661 val_s.len == 0 || val_s.s == NULL) {
00662 LM_WARN("cannot get string for value\n");
00663 return -1;
00664 }
00665 return is_dlg_in_profile( msg, (struct dlg_profile_table*)profile,
00666 &val_s);
00667 } else {
00668 return is_dlg_in_profile( msg, (struct dlg_profile_table*)profile,
00669 NULL);
00670 }
00671 }
00672
00673
00674 static int w_get_profile_size(struct sip_msg *msg, char *profile,
00675 char *value, char *result)
00676 {
00677 pv_elem_t *pve;
00678 str val_s;
00679 pv_spec_t *sp_dest;
00680 unsigned int size;
00681 pv_value_t val;
00682
00683 pve = (pv_elem_t *)value;
00684 sp_dest = (pv_spec_t *)result;
00685
00686 if ( pve!=NULL && ((struct dlg_profile_table*)profile)->has_value) {
00687 if ( pv_printf_s(msg, pve, &val_s)!=0 ||
00688 val_s.len == 0 || val_s.s == NULL) {
00689 LM_WARN("cannot get string for value\n");
00690 return -1;
00691 }
00692 size = get_profile_size( (struct dlg_profile_table*)profile ,&val_s );
00693 } else {
00694 size = get_profile_size( (struct dlg_profile_table*)profile, NULL );
00695 }
00696
00697 memset(&val, 0, sizeof(pv_value_t));
00698 val.flags = PV_VAL_INT|PV_TYPE_INT;
00699 val.ri = (int)size;
00700
00701 if(sp_dest->setf(msg, &sp_dest->pvp, (int)EQ_T, &val)<0)
00702 {
00703 LM_ERR("setting profile PV failed\n");
00704 return -1;
00705 }
00706
00707 return 1;
00708 }
00709
00710 static int w_dlg_setflag(struct sip_msg *msg, char *flag, char *s2)
00711 {
00712 struct dlg_cell *dlg;
00713 int val;
00714
00715 if(fixup_get_ivalue(msg, (gparam_p)flag, &val)!=0)
00716 {
00717 LM_ERR("no flag value\n");
00718 return -1;
00719 }
00720 if(val<0 || val>31)
00721 return -1;
00722 if ( (dlg=dlg_get_ctx_dialog())==NULL )
00723 return -1;
00724
00725 dlg->sflags |= 1<<val;
00726 return 1;
00727 }
00728
00729
00730 static int w_dlg_resetflag(struct sip_msg *msg, char *flag, str *s2)
00731 {
00732 struct dlg_cell *dlg;
00733 int val;
00734
00735 if(fixup_get_ivalue(msg, (gparam_p)flag, &val)!=0)
00736 {
00737 LM_ERR("no flag value\n");
00738 return -1;
00739 }
00740 if(val<0 || val>31)
00741 return -1;
00742
00743 if ( (dlg=dlg_get_ctx_dialog())==NULL )
00744 return -1;
00745
00746 dlg->sflags &= ~(1<<val);
00747 return 1;
00748 }
00749
00750
00751 static int w_dlg_isflagset(struct sip_msg *msg, char *flag, str *s2)
00752 {
00753 struct dlg_cell *dlg;
00754 int val;
00755
00756 if(fixup_get_ivalue(msg, (gparam_p)flag, &val)!=0)
00757 {
00758 LM_ERR("no flag value\n");
00759 return -1;
00760 }
00761 if(val<0 || val>31)
00762 return -1;
00763
00764 if ( (dlg=dlg_get_ctx_dialog())==NULL )
00765 return -1;
00766
00767 return (dlg->sflags&(1<<val))?1:-1;
00768 }
00769
00770 static int w_dlg_manage(struct sip_msg *msg, char *s1, char *s2)
00771 {
00772 str tag;
00773 int backup_mode;
00774
00775 if( (msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL )
00776 {
00777 LM_ERR("bad TO header\n");
00778 return -1;
00779 }
00780 tag = get_to(msg)->tag_value;
00781 if(tag.s!=0 && tag.len!=0)
00782 {
00783 backup_mode = seq_match_mode;
00784 seq_match_mode = SEQ_MATCH_NO_ID;
00785 dlg_onroute(msg, NULL, NULL);
00786 seq_match_mode = backup_mode;
00787 } else {
00788 if(dlg_new_dialog(msg, 0)!=0)
00789 return -1;
00790 }
00791 return 1;
00792 }
00793
00794 static int w_dlg_bye(struct sip_msg *msg, char *side, char *s2)
00795 {
00796 struct dlg_cell *dlg;
00797 int n;
00798
00799 dlg = dlg_get_ctx_dialog();
00800 if(dlg==NULL)
00801 return -1;
00802
00803 n = (int)(long)side;
00804 if(n==1)
00805 {
00806 if(dlg_bye(dlg, NULL, DLG_CALLER_LEG)!=0)
00807 return -1;
00808 return 1;
00809 } else if(n==2) {
00810 if(dlg_bye(dlg, NULL, DLG_CALLEE_LEG)!=0)
00811 return -1;
00812 return 1;
00813 } else {
00814 if(dlg_bye_all(dlg, NULL)!=0)
00815 return -1;
00816 return 1;
00817 }
00818 }
00819
00820 static int w_dlg_refer(struct sip_msg *msg, char *side, char *to)
00821 {
00822 struct dlg_cell *dlg;
00823 int n;
00824 str st = {0,0};
00825
00826 dlg = dlg_get_ctx_dialog();
00827 if(dlg==NULL)
00828 return -1;
00829
00830 n = (int)(long)side;
00831
00832 if(fixup_get_svalue(msg, (gparam_p)to, &st)!=0)
00833 {
00834 LM_ERR("unable to get To\n");
00835 return -1;
00836 }
00837 if(st.s==NULL || st.len == 0)
00838 {
00839 LM_ERR("invalid To parameter\n");
00840 return -1;
00841 }
00842 if(n==1)
00843 {
00844 if(dlg_transfer(dlg, &st, DLG_CALLER_LEG)!=0)
00845 return -1;
00846 } else {
00847 if(dlg_transfer(dlg, &st, DLG_CALLEE_LEG)!=0)
00848 return -1;
00849 }
00850 return 1;
00851 }
00852
00853 static int w_dlg_bridge(struct sip_msg *msg, char *from, char *to, char *op)
00854 {
00855 str sf = {0,0};
00856 str st = {0,0};
00857 str so = {0,0};
00858
00859 if(from==0 || to==0 || op==0)
00860 {
00861 LM_ERR("invalid parameters\n");
00862 return -1;
00863 }
00864
00865 if(fixup_get_svalue(msg, (gparam_p)from, &sf)!=0)
00866 {
00867 LM_ERR("unable to get From\n");
00868 return -1;
00869 }
00870 if(sf.s==NULL || sf.len == 0)
00871 {
00872 LM_ERR("invalid From parameter\n");
00873 return -1;
00874 }
00875 if(fixup_get_svalue(msg, (gparam_p)to, &st)!=0)
00876 {
00877 LM_ERR("unable to get To\n");
00878 return -1;
00879 }
00880 if(st.s==NULL || st.len == 0)
00881 {
00882 LM_ERR("invalid To parameter\n");
00883 return -1;
00884 }
00885 if(fixup_get_svalue(msg, (gparam_p)op, &so)!=0)
00886 {
00887 LM_ERR("unable to get OP\n");
00888 return -1;
00889 }
00890
00891 if(dlg_bridge(&sf, &st, &so)!=0)
00892 return -1;
00893 return 1;
00894 }
00895
00896
00897 static int fixup_dlg_bye(void** param, int param_no)
00898 {
00899 char *val;
00900 int n = 0;
00901
00902 if (param_no==1) {
00903 val = (char*)*param;
00904 if (strcasecmp(val,"all")==0) {
00905 n = 0;
00906 } else if (strcasecmp(val,"caller")==0) {
00907 n = 1;
00908 } else if (strcasecmp(val,"callee")==0) {
00909 n = 2;
00910 } else {
00911 LM_ERR("invalid param \"%s\"\n", val);
00912 return E_CFG;
00913 }
00914 pkg_free(*param);
00915 *param=(void*)(long)n;
00916 } else {
00917 LM_ERR("called with parameter != 1\n");
00918 return E_BUG;
00919 }
00920 return 0;
00921 }
00922
00923 static int fixup_dlg_refer(void** param, int param_no)
00924 {
00925 char *val;
00926 int n = 0;
00927
00928 if (param_no==1) {
00929 val = (char*)*param;
00930 if (strcasecmp(val,"caller")==0) {
00931 n = 1;
00932 } else if (strcasecmp(val,"callee")==0) {
00933 n = 2;
00934 } else {
00935 LM_ERR("invalid param \"%s\"\n", val);
00936 return E_CFG;
00937 }
00938 pkg_free(*param);
00939 *param=(void*)(long)n;
00940 } else if (param_no==2) {
00941 return fixup_spve_null(param, 1);
00942 } else {
00943 LM_ERR("called with parameter idx %d\n", param_no);
00944 return E_BUG;
00945 }
00946 return 0;
00947 }
00948
00949 static int fixup_dlg_bridge(void** param, int param_no)
00950 {
00951 if (param_no>=1 && param_no<=3) {
00952 return fixup_spve_null(param, 1);
00953 } else {
00954 LM_ERR("called with parameter idx %d\n", param_no);
00955 return E_BUG;
00956 }
00957 return 0;
00958 }
00959
00960 static int w_dlg_get(struct sip_msg *msg, char *ci, char *ft, char *tt)
00961 {
00962 struct dlg_cell *dlg = NULL;
00963 str sc = {0,0};
00964 str sf = {0,0};
00965 str st = {0,0};
00966 unsigned int dir = 0;
00967
00968 if(ci==0 || ft==0 || tt==0)
00969 {
00970 LM_ERR("invalid parameters\n");
00971 return -1;
00972 }
00973
00974 if(fixup_get_svalue(msg, (gparam_p)ci, &sc)!=0)
00975 {
00976 LM_ERR("unable to get Call-ID\n");
00977 return -1;
00978 }
00979 if(sc.s==NULL || sc.len == 0)
00980 {
00981 LM_ERR("invalid Call-ID parameter\n");
00982 return -1;
00983 }
00984 if(fixup_get_svalue(msg, (gparam_p)ft, &sf)!=0)
00985 {
00986 LM_ERR("unable to get From tag\n");
00987 return -1;
00988 }
00989 if(sf.s==NULL || sf.len == 0)
00990 {
00991 LM_ERR("invalid From tag parameter\n");
00992 return -1;
00993 }
00994 if(fixup_get_svalue(msg, (gparam_p)tt, &st)!=0)
00995 {
00996 LM_ERR("unable to get To Tag\n");
00997 return -1;
00998 }
00999 if(st.s==NULL || st.len == 0)
01000 {
01001 LM_ERR("invalid To tag parameter\n");
01002 return -1;
01003 }
01004
01005 dlg = get_dlg(&sc, &sf, &st, &dir);
01006 if(dlg==NULL)
01007 return -1;
01008 current_dlg_pointer = dlg;
01009 _dlg_ctx.dlg = dlg;
01010 _dlg_ctx.dir = dir;
01011 return 1;
01012 }
01013
01014 struct mi_root * mi_dlg_bridge(struct mi_root *cmd_tree, void *param)
01015 {
01016 str from = {0,0};
01017 str to = {0,0};
01018 str op = {0,0};
01019 struct mi_node* node;
01020
01021 node = cmd_tree->node.kids;
01022 if(node == NULL)
01023 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
01024 from = node->value;
01025 if(from.len<=0 || from.s==NULL)
01026 {
01027 LM_ERR("bad From value\n");
01028 return init_mi_tree( 500, "Bad From value", 14);
01029 }
01030
01031 node = node->next;
01032 if(node == NULL)
01033 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
01034 to = node->value;
01035 if(to.len<=0 || to.s == NULL)
01036 {
01037 return init_mi_tree(500, "Bad To value", 12);
01038 }
01039
01040 node= node->next;
01041 if(node != NULL)
01042 {
01043 op = node->value;
01044 if(op.len<=0 || op.s==NULL)
01045 {
01046 return init_mi_tree(500, "Bad OP value", 12);
01047 }
01048 }
01049
01050 if(dlg_bridge(&from, &to, &op)!=0)
01051 return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
01052
01053 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
01054 }
01055
01056