Dear ALL:
I insert records to my usr_preferences as below:
In usr_preferences table: username domain attribute value ------------------------------------------------------------------------------------------------------------------- 1022 ser.xxx.net.tw donotdisturb n 1022 ser.xxx.net.tw voicemail n 1022 ser.xxx.net.tw anoncallrej n 1022 ser.xxx.net.tw callidblock n 1022 ser.xxx.net.tw callfwd sip:0939749xxx@ser.xxx.net.tw 1022 ser.xxx.net.tw fwdnoanswer sip:0939749xxx@ser.xxx.net.tw 1022 ser.xxx.net.tw fwdbusy sip:0939749xxx@ser.xxx.net.tw
In grp table: username domain grp --------------------------------------------------- 1022 ser.xxx.net.tw int 1011 ser.xxx.net.tw int
Now, I change my value to sip:0939749xxx@ser.xxx.net.tw. If its attribute is "callfwd", the call will be forward to my mobile phone(0939749xxx) using route(3) to PSTN. So the result is OK.
I delete the attribute "callfwd" in order to test "fwdnoanswer" function.
If UA 1011 make a call to UA 1022 and UA 1022 no answer, it should goto failure_route[1] and make a call to route(3) depending on its "uri" (phone number).
And I also find it runs to failure_route[1] and jump to route(3). But the connection will disconnect for a few seconds. And displays "408 Request Timeout" on my X-Pro Client. I find it jumps to another route(2) after disconnect.
I know I should not disturb you too much because of your works and your new best example cfg file for us. But can you please help me to discover what reason about it.
I think it should be the reason in my TM modules.
I am a Taiwanese and using a poor English.
Best Regard Charles
Error Logs lists below: ------------------------------------------------------------------------------------------------------ SER: Failure Route section failure_route(1) SER: fork to fwdnoanswer SER: No Answer Failure and Jump to route(3) SER: Demestic Call Off-Net section route(3) SER: Connecting to PSTN.... <=========== Connect to PSTN here!!!!. error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy PDT:prefix2domain: no prefix found in [1022] SER: SIP Call On-Net section route(2)
My ser.cfg list below: -------------------------------------------------------------------------------------------------------- debug=10 # debug level (cmd line: -dddddddddd) fork=yes log_stderror=no # (cmd line: -E)
listen=xxx.xxx.xxx.xxx alias=ser.xxx.net.tw alias=ser alias=xxx.xxx.xxx.xxx
check_via=no # (cmd. line: -v) dns=no # (cmd. line: -r) rev_dns=no # (cmd. line: -R) port=5060 children=4 fifo_mode=0666 fifo="/tmp/ser_fifo" fifo_db_url="mysql://ser:heslo@localhost/ser"
# ------------------ module loading ---------------------------------- # ----------------- setting module-specific parameters --------------- ----------(skip)
# -- mediaproxy params -- modparam("mediaproxy", "natping_interval", 30) modparam("mediaproxy", "sip_asymmetrics", "/usr/local/etc/ser/sip-asymmetric-clients") modparam("mediaproxy", "rtp_asymmetrics", "/usr/local/etc/ser/rtp-asymmetric-clients")
# -- usrloc params -- modparam("usrloc", "db_mode", 1) modparam("usrloc", "timer_interval", 60) modparam("usrloc", "desc_time_order", 1)
# -- auth params -- modparam("auth_db", "calculate_ha1", yes) modparam("auth_db", "password_column", "password")
# -- rr params -- # add value to ;lr param to make some broken UAs happy modparam("rr", "enable_full_lr", 1)
# -- db_url params -- modparam("acc|auth_db|domain|group|permissions|speeddial|uri_db|usrloc|pdt", "db_url", "mysql://ser:heslo@localhost/ser")
# -- use_domain params -- modparam("auth_db|group|registrar|speeddial|uri_db|usrloc", "use_domain", 0)
# -- permissions params -- modparam("permissions", "db_mode", 1) modparam("permissions", "trusted_table", "trusted")
# -- accounting params -- modparam("acc", "db_flag", 1) modparam("acc", "db_missed_flag", 1) modparam("acc", "log_fmt", "cdfimorstup") modparam("acc", "log_level", 1) modparam("acc", "failed_transactions", 1) modparam("acc", "report_cancels", 1) modparam("acc", "report_ack", 0)
# -- domain params -- modparam("domain", "db_mode", 1)
# ------------- exec parameters modparam("exec", "setvars", 1) modparam("exec", "time_to_kill", 10)
# -- registration params -- modparam("registrar", "nat_flag", 2) modparam("registrar", "min_expires", 60) modparam("registrar", "max_expires", 86400) modparam("registrar", "default_expires", 3600) modparam("registrar", "append_branches", 1)
# -- avp params -- modparam("avpops", "avp_url", "mysql://ser:heslo@localhost/ser") modparam("avpops", "avp_table", "usr_preferences") #modparam("avpops", "use_domain", "1") modparam("avpops", "uuid_column", "uuid") modparam("avpops", "username_column", "username") modparam("avpops", "domain_column", "domain") modparam("avpops", "attribute_column", "attribute") modparam("avpops", "value_column", "value") modparam("avpops", "type_column", "type") modparam("avpops", "avp_aliases", "voicemail=i:500;calltype=i:700;fwd_no_answer_type=i:701;fwd_busy_type=i:702") # To use more than one tables example #modparam("avpops", "db_scheme", "scheme1:table=subscriber;uuid_column=uuid;value_column=first_name")
# -- tm params -- modparam("tm", "fr_timer", 15) modparam("tm", "fr_inv_timer", 22) modparam("tm", "wt_timer", 5) modparam("tm", "fr_inv_timer_avp", "inv_timeout")
# -- pdt params -- modparam("pdt", "db_table", "prefix_domain") modparam("pdt", "prefix", "") modparam("pdt", "hsize_2pow", 2) modparam("pdt", "sync_time", 300) modparam("pdt", "clean_time", 600)
# -- logging params modparam("xlog", "buf_size", 8192)
# -- group params -- modparam("group", "table", "grp") modparam("group", "user_column", "username") modparam("group", "domain_column", "domain") modparam("group", "group_column", "grp")
# ------------------------- request routing logic -------------------
# main routing logic
route {
# ------------------------------------------------------------------------ # Sanity Check Section # ------------------------------------------------------------------------ if (!mf_process_maxfwd_header("10")) { sl_send_reply("483", "Too Many Hops"); break; };
if (msg:len > max_len) { sl_send_reply("513", "Message Overflow"); break; };
# ------------------------------------------------------------------------ # NOTIFY Keep-Alive Section # ------------------------------------------------------------------------ if ((method=="NOTIFY") && search("^Event: keep-alive")) { sl_send_reply("200", "OK"); break; };
# ------------------------------------------------------------------------ # OPTIONS Section # ------------------------------------------------------------------------ if (method=="OPTIONS") { options_reply(); break; };
# ------------------------------------------------------------------------ # NAT Test Section #1 # ------------------------------------------------------------------------ if (method=="REGISTER" && client_nat_test("3")) { fix_contact(); force_rport(); setflag(2); };
# ------------------------------------------------------------------------ # Registration Section # ------------------------------------------------------------------------ if (method=="REGISTER") {
# allow all requests from user 700 - the Click2Dial controller if (!isflagset(14)) { if (!is_from_local()) { sl_send_reply("403", "Unknown Domain"); break; }; if (!www_authorize("", "subscriber")) { www_challenge("", "0"); break; }; if (!check_to()) { sl_send_reply("401", "Unauthorized"); break; };
# To - Use To username and (optionally) domain to check if (is_user_in("To", "demo-disabled")) { sl_send_reply("403", "Your evaluation period has expired"); break; };
# To - Use To username and (optionally) domain to check if (is_user_in("To", "disabled")) { sl_send_reply("403", "Your account has been disabled"); break; }; };
# snom sip phones use this header to start their # keep-alive mechanism for NAT bindings append_to_reply("P-NAT-Refresh: 15\r\n");
if (!save("location")) { sl_reply_error(); }; break; };
# ------------------------------------------------------------------------ # Accounting Section # 1 # # NOTE: We test for flag 14 because we do not want to record Click2Dial # entries # ------------------------------------------------------------------------ if ((method=="INVITE" || method=="BYE") && !isflagset(14)) { setflag(1); };
# ------------------------------------------------------------------------ # NAT Tear-Down Section # ------------------------------------------------------------------------ if ((method == "BYE" || method == "CANCEL")) { end_media_session(); };
# ------------------------------------------------------------------------ # Record Route Section # # we record-route all messages -- to make sure that subsequent messages # will go through our proxy; that's particularly good if upstream and # downstream entities use different transport protocol # ------------------------------------------------------------------------ if (!method=="REGISTER") { record_route(); };
# ------------------------------------------------------------------------ # Loose Route Section # # Grant route routing if route headers present # ------------------------------------------------------------------------ if (loose_route()) { route(2); break; };
prefix2domain();
# ------------------------------------------------------------------------ # NAT Test Section #1 # ------------------------------------------------------------------------ if (client_nat_test("3") && !search("^Record-Route:")) { force_rport(); fix_contact(); };
# ------------------------------------------------------------------------ # PSTN Section # ------------------------------------------------------------------------ if (method=="INVITE") { ## Deny PSTN to 0204 and 095 on Tawan if ((uri=~"^sip:0204[0-9]*@") || (uri=~"^sip:095[0-9]*@")) { sl_send_reply("503", "Service Unavailable"); break; }; };
# ------------------------------------------------------------------------ # Alias Routing Section # ------------------------------------------------------------------------ lookup("aliases"); if (!uri==myself) { route(2); break; };
# ------------------------------------------------------------------------ # Load ACL Section # ------------------------------------------------------------------------ if (method=="INVITE" && !isflagset(14)) { xlog("L_ERR", "Time:[%Tf] Method:<%rm> r-uri:<%ru>\n"); xlog("L_ERR", "IP:<%is> From:<%fu> To:<%tu> %ct\n"); if (is_user_in("Request-URI", "voicemail")) { setflag(31); }; if (is_from_local() || is_uri_host_local()) {
# Check user from grp table if (is_user_in("From", "int")) { log(1, "SER: a INT user\n"); setflag(29); }; if (is_user_in("From", "free-pstn")) { log(1, "SER: a FREE-PSTN user\n"); setflag(28); }; if (avp_db_load("$from/username", "s:callidblock")) { if (avp_check("s:callidblock", "eq/y/i")) { setflag(25); }; }; }; if (avp_db_load("$ruri/username", "s:anoncallrej")) { if (avp_check("s:anoncallrej", "eq/y/i")) { log(1, "SER: a ANON-CALL-REJ user\n"); setflag(24); }; }; };
# ------------------------------------------------------------------------ # Anonymous Call Rejection Section # 24 # ------------------------------------------------------------------------ if (isflagset(24) && (method=="INVITE") && search("^(f|F)rom:.*(a|A)nonymous")) { route(8); break; };
# ------------------------------------------------------------------------ # Speed Dialing Section # ------------------------------------------------------------------------ if ((method=="INVITE") && (uri=~"^sip:[0-9]{2}@.*")) { sd_lookup("speed_dial"); };
# ------------------------------------------------------------------------ # 002 International Call Section # 29 # ------------------------------------------------------------------------ if (method=="INVITE" && uri=~"^sip:002[0-9]*@") { if (isflagset(29)) { log(1, "SER: an International Call route(6)\n"); route(6); } else { sl_send_reply("503", "Service Unavailable"); }; break; };
# ------------------------------------------------------------------------ # 0XXXXXXXXX Domestic Call Section # 29 # ------------------------------------------------------------------------ if (method=="INVITE" && uri=~"^sip:0[0-9]{9}@") { if (isflagset(29)) { log(1, "SER: a Domestic Call route(6)\n"); route(6); } else { sl_send_reply("503", "Service Unavailable"); }; break; };
# ------------------------------------------------------------------------ # URI Compare Section # # Here we compare the "from" and "to" to see if the caller is dialing # their own extension. If so then we route to voicemail(31) if needed # ------------------------------------------------------------------------ if (method=="INVITE") { avp_write("$from", "i:34"); if (avp_check("i:34", "eq/$ruri/i")) { if (isflagset(31)) { route(5); break; } else { sl_send_reply("486", "Busy"); break; }; }; };
# ------------------------------------------------------------------------ # Do Not Disturb Section # ------------------------------------------------------------------------ if (avp_db_load("$ruri/username", "s:donotdisturb")) { if (avp_check("s:donotdisturb", "eq/y/i")) { route(5); break; }; };
# ------------------------------------------------------------------------ # Blind Call Forwarding Section # ------------------------------------------------------------------------ if (method=="INVITE") { log(1, "SER: BLIND CALL FORWARDING\n"); # here we must store the current (aka original) R-URI because if # we set call forwarding and the forwarded number is busy then we # need to use this original R-URI to determine which voicemail # box we should go to if (isflagset(31)) { avp_write("$ruri", "$voicemail"); }; if (avp_db_load("$ruri/username", "s:callfwd")) { avp_pushto("$ruri", "s:callfwd");
# lookup the call fowarding number to see if it is a served # sip number or a PSTN number
# check forwarding number rules log(1, "SER: Check Forwarding Number Rules\n"); route(1);
if (avp_check("$calltype", "eq/-/i")) { log(1, "SER: 503 Service Unavailable 1\n"); sl_send_reply("503", "Service Unavailable"); break; };
# test for domestic PSTN gateway if (avp_check("$calltype", "eq/dom/i")) { log(1, "SER: Start a domestic PSTN call route(3)\n"); route(3); break; };
# test for international PSTN gateway if (avp_check("$calltype", "eq/int/i")) { log(1, "SER: Start an international PSTN call route(6)\n"); route(6); break; }; }; };
# ------------------------------------------------------------------------ # Call Routing Section # ------------------------------------------------------------------------ if (!lookup("location")) {
# if flag 31 (ie voicemail) is set and we made it here this means # the user's phone is not registered anywhere. We'll forward to # voicemail after this block because we need to check the call # forward settings first if (isflagset(31)) { # flag 19 means the user has voicemail but is not online # so we need to remember to send to voicemail if call # forwarding is not enabled setflag(19); };
if (method=="INVITE") { if (does_uri_exist()) { # subscriber record found, but they're offline log(1, "SER: Temporarily Unavailable\n"); sl_send_reply("480", "Temporarily Unavailable"); break; };
if (uri=~"^sip:0[0-9]{9}@") { # Send to PSTN Gateway if (isflagset(28) || (is_user_in("From", "int")) || (is_user_in("From", "free-pstn"))) { log(1, "SER: Start a PSTN call\n"); route(3); } else { log(1, "SER: 503 Service Unavailable 2\n"); sl_send_reply("503", "Service Unavailable"); }; break; }; sl_send_reply("404", "User Not Found"); break; }; };
# ------------------------------------------------------------------------ # Call Forwarding Section # ------------------------------------------------------------------------ if (method=="INVITE") {
# save R-URI in a temp AVP for later use avp_write("$ruri", "i:99");
# only load the forward no answer option if voice mail is not enabled if (!isflagset(31)) { if (avp_db_load("$ruri/username", "s:fwdnoanswer")) { route(1); }; }; if (avp_db_load("$ruri/username", "s:fwdbusy")) { route(1); }; avp_pushto("$ruri", "i:99"); }; if (isflagset(19)) { # send to voicemail route(5); } else { route(2); }; }
route[1] {
# Here we have route checks for all the call forwarding stuff. # The return values are passed as AVP $calltype as follows: # # "-" = R-URI is not allowed # "dom" = R-RURI is a domestic call # "int" = R-RURI is an international call # "sip" = R-RURI is a sip call
avp_write("sip", "$calltype");
# Call rejected if ((uri=~"^sip:0204[0-9]*@") || (uri=~"^sip:095[0-9]*@") || (uri=~"^sip:[0-9]{3}@")) { break; }; log(1, "SER: Look aliases\n"); lookup("aliases");
log(1, "SER: Look location\n"); if (!lookup("location")) { if (uri=~"^sip:0[0-9]{9}@") { # test for domestic PSTN number if (isflagset(28)) { log(1, "SER isflagset 28 (domestic)\n"); avp_write("dom", "$calltype"); }; } else if (uri=~"^sip:002[0-9]*@") { # test for international PSTN number if (isflagset(29)) { log(1, "SER isflagset 29 (int)\n"); avp_write("int", "$calltype"); }; }; break; }; log(1, "SER isflagset (sip)\n"); avp_write("sip", "$calltype"); }
route[2] { log(1, "SER: SIP Call On-Net section route(2)\n"); if ((method=="INVITE") && !allow_trusted()) { if (!proxy_authorize("", "subscriber")) { proxy_challenge("", "0"); break; } else if (!check_from()) { log(1, "Spoofed SIP call attempt"); sl_send_reply("403", "Use From=ID"); break; } else if (!(is_from_local() || is_uri_host_local())) { sl_send_reply("403", "Please register to use our service"); break; }; }; if (uri=~"[@:](192.168.|10.|172.(1[6-9]|2[0-9]|3[0-1]).)" && !search("^Route:")){ sl_send_reply("479", "We don't forward to private IP addresses"); break; }; if (isflagset(25)) { replace("^From:(.*)>" , "From: "Anonymous" sip:someone@anonymous.invalid"); }; if (method=="INVITE" || method=="ACK") { use_media_proxy(); }; t_on_failure("1"); t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
route[3] { log(1, "SER: Demestic Call Off-Net section route(3)\n");
# All Domestic Calls Go To CISCO 5300 if (method=="INVITE") { if (!proxy_authorize("", "subscriber")) { proxy_challenge("", "0"); break; } else if (!check_from()) { log(1, "Spoofed SIP call attempt"); sl_send_reply("403", "Use From=ID"); break; } else if (!(is_from_local() || is_uri_host_local())) { sl_send_reply("403", "Please register to use our service"); break; }; # enable caller id blocking for PSTN calls if (isflagset(25)) { append_rpid_hf(); }; }; # SIP->PSTN calls get 45 seconds to timeout log(1, "SER: Connecting to PSTN.....\n"); avp_write("i:45", "inv_timeout"); rewritehost("xxx.xxx.xxx.243"); if (uri=~"[@:](192.168.|10.|172.(1[6-9]|2[0-9]|3[0-1]).)" && !search("^Route:")){ sl_send_reply("479", "We don't forward to private IP addresses"); break; }; if (method=="INVITE" || method=="ACK") { use_media_proxy(); }; if (isflagset(31)) { t_on_failure("1"); }; t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
route[4] { ------------------(skip) }
route[5] { --------------------(skip) }
route[6] { log(1, "SER: International Call Off-Net section route(6)\n");
# All International Calls Go To CISCO 5300 if (method=="INVITE") { if (!proxy_authorize("", "subscriber")) { proxy_challenge("", "0"); break; } else if (!check_from()) { log(1, "Spoofed SIP call attempt"); sl_send_reply("403", "Use From=ID"); break; } else if (!(is_from_local() || is_uri_host_local())) { sl_send_reply("403", "Please register to use our service"); break; }; # enable caller id blocking for PSTN calls if (isflagset(25)) { append_rpid_hf(); }; }; # SIP->PSTN calls get 45 seconds to timeout avp_write("i:45", "inv_timeout"); rewritehost("xxx.xxx.xxx.243"); if (uri=~"[@:](192.168.|10.|172.(1[6-9]|2[0-9]|3[0-1]).)" && !search("^Route:")){ sl_send_reply("479", "We don't forward to private IP addresses"); break; }; if (method=="INVITE" || method=="ACK") { use_media_proxy(); }; t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
route[7] { -----(skip) }
route[8] { log(1, "SER: Anonymous Call Rejection section route(8)\n");
# anonymous call rejection announcment # # this path this executed for anonymous callers
if (method=="INVITE" || method=="ACK") { use_media_proxy(); }; rewriteuri("sip:698@99.99.99.100:5060"); t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
onreply_route[1] { # Not all 2xx messages have a content body so here we # make sure our Content-Length > 0 to avoid a parse error if (status=~"(180)|(183)|2[0-9][0-9]") { if (!search("^Content-Length:\ 0")) { use_media_proxy(); }; }; if (client_nat_test("1")) { fix_contact(); }; }
failure_route[1] { log(1, "SER: Failure Route section failure_route(1)\n");
# if caller hung up then don't sent to voicemail if (t_check_status("487")) { break; }; if (isflagset(26) && t_check_status("486")) { # forward busy is flag 26 if (avp_pushto("$ruri", "s:fwdbusy")) { log(1, "SER: fork to fwdbusy\n"); avp_delete("s:fwdbusy"); append_branch(); resetflag(26);
# test for domestic PSTN gateway if (uri=~"^sip:0[0-9]{9}@") { # if (avp_check("$fwd_busy_type", "eq/dom/i")) { # test for domestic PSTN gateway log(1, "SER: Busy Failure and Jump to route(3)\n"); route(3); } else if (uri=~"^sip:002[1-9][0-9]*@") { # } else if (avp_check("$fwd_busy_type", "eq/int/i")) { # test for international PSTN gateway log(1, "SER: Busy Failure and Jump to route(6)\n"); route(6); } else { # default to sip call log(1, "SER: Busy Failure and Jump to route(2)\n"); route(2); }; break; }; };
# here we can have either voicemail __OR__ forward no answer if (isflagset(27) && t_check_status("408")) { # forward no answer is flag 27 if (avp_pushto("$ruri", "s:fwdnoanswer")) { log(1, "SER: fork to fwdnoanswer\n"); avp_delete("s:fwdnoanswer"); append_branch(); resetflag(27);
if (uri=~"^sip:0[0-9]{9}@") { # if (avp_check("$fwd_no_answer_type", "eq/dom/i")) { # test for domestic PSTN gateway log(1, "SER: No Answer Failure and Jump to route(3)\n"); route(3); } else if (uri=~"^sip:002[1-9][0-9]*@") { # } else if (avp_check("$fwd_no_answer_type", "eq/int/i")) { # test for international PSTN gateway log(1, "SER: No Answer Failure and Jump to route(6)\n"); route(6); } else { # default to sip call log(1, "SER: No Answer Failure and Jump to route(2)\n"); route(2); }; break; }; } else if (isflagset(31) && avp_pushto("$ruri", "$voicemail")) { avp_delete("$voicemail"); log(1, "SER: No Answer Failure and Jump to route(4)\n"); route(4); break; }; }