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;
};
}