123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- 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:[email protected]/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 (([email protected]) || (@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 ([email protected] || (@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();
- };
- }
|