mirror of https://github.com/sipwise/kamailio.git
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.
329 lines
8.2 KiB
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();
|
|
};
|
|
}
|
|
|