You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/uid_avp_db/doc/avp_dialogs.cfg

329 lines
8.2 KiB

debug=3
memdbg=5
server_signature=0
sip_warning=0
check_via=yes;
dns=no;
rev_dns=no;
children=4;
tcp_children=4;
tcp_max_connections=2048;
port=5060
loadmodule "/home/kubartv/SER/lib/ser/modules/sl.so";
#loadmodule "/home/kubartv/SER/lib/ser/modules/maxfwd.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/tm.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/rr.so";
#loadmodule "/home/kubartv/SER/lib/ser/modules/xmlrpc.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/mysql.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/domain.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/uri_db.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/avp.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/avp_db.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/usrloc.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/registrar.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/xprint.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/eval.so";
loadmodule "/home/kubartv/SER/lib/ser/modules/gflags.so"
#modparam("maxfwd", "max_limit", 70);
modparam("usrloc", "db_mode", 1);
modparam("usrloc|avp_db", "db_url", "mysql://ser:heslo@127.0.0.1/ser")
modparam("avp_db", "attr_group", "id=dlg,flag=dialog_flag,table=dlg_attrs,key_column=dlg_id");
modparam("gflags", "load_global_attrs", 1);
avpflags dialog_flag;
route["create_dialog"] {
# sets attributes needed by dialog (stored when processing reply)
$dlg_caller = @contact;
$dlg_caller_cseq = @cseq.num;
$dlg_status = "new";
$dlg_init_method = @cseq.method;
$dir = "caller2callee";
t_on_reply("dialog_creation_reply");
return 1;
}
onreply_route["dialog_creation_reply"] {
xplog("L_ERR", "dialog creation reply (%rs, %@cseq.method) [%@from.tag, %@to.tag]\n");
$res = @msg.response.code;
xplog("L_ERR", " ... response: %$res\n");
if ((!@to.tag) || (@to.tag=="")) {
# don't create dialog from response without to tag
break;
}
if ($res < 101) {
xplog("L_ERR", " ... I won't create dialog from 100 response.\n");
break;
}
del_attr("$id"); # xlset_attr works strange when the attribute already exists
xlset_attr("$id", "call-id:%@call_id caller_tag:%@from.tag callee_tag:%@to.tag");
if ($res > 299) {
xplog("L_ERR", " ... dialog terminated\n");
remove_extra_attrs("dlg", "$id");
break;
}
xplog("L_ERR", " ... creating dialog '%$id'\n");
# generate dialog id
lock_extra_attrs("dlg", "$id");
# TODO: try to load the dialog (early dialog may exist)?
# update dialog data
if (($dlg_status == "new") && ($res < 200)) {
# early response may arrive after final one
$dlg_callee = @contact;
$dlg_status = "early";
xplog("L_ERR", " ... creating early dialog\n");
}
if ($res >= 200) {
$dlg_callee = @contact;
$dlg_status = "confirmed";
$dlg_confirmed_at = @sys.now.local;
xplog("L_ERR", " ... confirming dialog\n");
}
route("save_dialog");
}
route["save_dialog"] {
if ($dlg_status == "destroyed") {
xplog("L_ERR", " ... destroying dialog %$id\n");
# use this if you want to delete destroyed dialogs:
# remove_extra_attrs("dlg", "$id");
# else if you want leave them in DB (with the time of termination)
$dlg_destroyed_at = @sys.now.local;
# set flag for attributes with name beggining with dlg_
setavpflag("$f./^dlg_/", "dialog_flag");
save_extra_attrs("dlg", "$id");
}
else {
# set flag for attributes with name beggining with dlg_
setavpflag("$f./^dlg_/", "dialog_flag");
save_extra_attrs("dlg", "$id");
}
unlock_extra_attrs("dlg", "$id");
}
route["load_dialog_data"] {
lock_extra_attrs("dlg", "$id");
del_attr("$dlg_init_method"); # used as flag of succesful read of data
# delete all used dlg attrs (because load_extra_attrs doesn't delete them itself before adding)
del_attr("$dlg_init_method");
del_attr("$dlg_caller");
del_attr("$dlg_callee");
del_attr("$dlg_caller_cseq");
del_attr("$dlg_callee_cseq");
del_attr("$dlg_status");
load_extra_attrs("dlg", "$id");
if (!$dlg_init_method) {
# dialog was not loaded
unlock_extra_attrs("dlg", "$id");
return -1;
}
return 1;
}
route["load_dialog"] {
# tries to load dialog according tags and callid
# try to load dialog
del_attr("$id"); # xlset_attr works strange when the attribute already exists
xlset_attr("$id", "call-id:%@call_id caller_tag:%@from.tag callee_tag:%@to.tag");
if (route("load_dialog_data")) {
$dir = "caller2callee";
return 1;
}
# try to load dialog in other direction
del_attr("$id"); # xlset_attr works strange when the attribute already exists
xlset_attr("$id", "call-id:%@call_id caller_tag:%@to.tag callee_tag:%@from.tag");
if (route("load_dialog_data")) {
$dir = "callee2caller";
return 1;
}
$id = "error";
return -1;
}
route["update_dialog_reply"] {
if ((@cseq.method == "INVITE") || (@cseq.method == "UPDATE")) {
# target refresh for INVITE dialogs
if ($dir == "caller2calle") { # if request from caller
$dlg_callee = @contact; # update callee's contact (response!)
}
else {
$dlg_caller = @contact;
}
}
if (@cseq.method=="BYE") {
$dlg_status = "destroyed"; # will be removed in save_dialog
}
}
route["update_dialog"] {
if ((@cseq.method == "INVITE") || (@cseq.method == "UPDATE")) {
# target refresh for INVITE dialogs
if ($dir == "caller2calle") { # if request from caller
$dlg_caller = @contact; # update caller's contact (request!)
}
else {
$dlg_callee = @contact;
}
}
if ($dir == "caller2callee") { # if request from caller
# TODO: verify CSeq before modifying and return 500 if lower than last one
$dlg_caller_cseq = @cseq.num;
}
else {
# TODO: verify CSeq before modifying and return 500 if lower than last one
$dlg_callee_cseq = @cseq.num;
}
if (method=="BYE") {
$dlg_status = "pre-destroyed"; # to see that BYE already went through
}
return 1;
}
route["trace_dialog"] {
xplog("L_ERR", " ... dialog '%$id'\n");
xplog("L_ERR", " -> initial method: %$dlg_init_method\n");
xplog("L_ERR", " -> request dir: %$dir\n");
xplog("L_ERR", " -> caller: %$dlg_caller\n");
xplog("L_ERR", " -> caller's CSeq: %$dlg_caller_cseq\n");
xplog("L_ERR", " -> callee: %$dlg_callee\n");
xplog("L_ERR", " -> callee's CSeq: %$dlg_callee_cseq\n");
xplog("L_ERR", " -> status: %$dlg_status\n");
return 1;
}
onreply_route["dialog_reply"] {
if ($id) {
xplog("L_ERR", "In-dialog reply (%rs, %@cseq.method) [%@to.tag, %@from.tag]\n");
if (!route("load_dialog")) {
xplog("L_ERR", "Can't load dialog data\n");
}
else {
route("update_dialog_reply");
route("trace_dialog");
route("save_dialog");
}
}
}
route {
if (method=="SUBSCRIBE") {
# here we support only INVITE/BYE dialogs
sl_reply("400", "Unsupported");
break;
}
if (!lookup_domain("$td", "@to.uri.host")) {
sl_send_reply("404", "Domain Not Found");
break;
}
if (!lookup_user("To")) {
sl_send_reply("404", "Unknown user");
break;
}
if (method=="REGISTER") {
save("location");
break;
};
xplog("L_ERR", "----> processing request %@cseq.method\n");
if (!lookup_domain("$fd", "@from.uri.host")) {
sl_send_reply("404", "From domain Not Found");
break;
}
if (!lookup_user("From")) {
sl_send_reply("404", "Unknown user in From");
break;
}
if (method != "REGISTER") record_route();
# dialog needs transactions
if (!t_newtran()) {
sl_send_reply("500", "Can not start transaction");
drop;
}
# dialog creation/loading
if (!@to.tag || (@to.tag == "")) {
# initial request or non-dialog message
if (method=="INVITE") {
route("create_dialog");
# we don't save the dialog here because AVPs will be set
# when reply comes and the dialog will be stored then
}
else {
xplog("L_ERR", "Non-dialog message: %@cseq\n");
}
}
else {
# message within dialog
if (route("load_dialog")) {
route("update_dialog");
route("trace_dialog");
route("save_dialog");
t_on_reply("dialog_reply");
}
else {
xplog("L_ERR", "Message within unknown dialog: %@cseq, to_tag=%@to.tag from_tag=%@from.tag\n");
}
}
if (loose_route()) {
route(1);
break;
}
if (!lookup("location")) {
t_reply("404", "Not Found");
break;
};
route(1);
}
route[1]
{
xplog("L_ERR", "<---- request %@cseq.method processed\n");
# send it out now; use stateful forwarding as it works reliably
# even for UDP2TCP
if (!t_relay()) {
sl_reply_error();
};
}