Dear ALL:
I think it is a very good chance to study Paul's ser.cfg file. I use the 0.9.0 sample cfg and try to implement a call forward, busy forward, no answer forward function. But I got a 503 message when I use make a call from UA 1011 to UA 1022(registed on the same ser) with callforward to a PSTN .
But I have no voicemail option supported. So I must modify it.
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 0939749xxx@ser.xxx.net.tw 1022 ser.xxx.net.tw fwdnoanswer 0939749xxx@ser.xxx.net.tw 1022 ser.xxx.net.tw fwdbusy 0939749xxx@ser.xxx.net.tw
In grp table: username domain grp --------------------------------------------------- 1022 ser.xxx.net.tw int 1011 ser.xxx.net.tw int
I don't know where to defind the 'dom' and 'int' or '-' setting at DB table. What is its table name?
domain ==> ser.xxx.net.tw (the same as caller and machine)
When I test this call forward, a UA 1011 call to 1022. It It should be forward to a PSTN and use route(3) or route(6).
But when I do it, it seems failed at lookup("aliases") and lookup("location") function.
Log list below: --------------------------------------------------------------------------------------------------------- ser /usr/local/sbin/ser[9232]: SER: BLIND CALL FORWARDING ser /usr/local/sbin/ser[9232]: SER: Check Forwarding Number Rules ser /usr/local/sbin/ser[9232]: SER: Look aliases ser /usr/local/sbin/ser[9232]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9232]: extract_aor(): Error while parsing Address of Record ser /usr/local/sbin/ser[9232]: lookup(): Error while extracting address of record ser /usr/local/sbin/ser[9232]: SER: Look location ser /usr/local/sbin/ser[9232]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9232]: extract_aor(): Error while parsing Address of Record ser /usr/local/sbin/ser[9232]: lookup(): Error while extracting address of record ser /usr/local/sbin/ser[9232]: SER: 503 Service Unavailable ---------------------------------------------------------------------------------------------------------
If I delete the record callfwd of 1022 and want to test call noanswer forward. It seems can not forward to a PSTN number and jump to route(3) or route(6). It always keep the orginial rule and use route(2). Also the error message "error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy" always displays at log file whether the call is connected or failed call.
Log list below: ---------------------------------------------------------------------------------------------------------ser /usr/local/sbin/ser[9233]: SER: BLIND CALL FORWARDING ser /usr/local/sbin/ser[9233]: SER: Look aliases ser /usr/local/sbin/ser[9233]: SER: Look location ser /usr/local/sbin/ser[9233]: SER isflagset (sip) ser /usr/local/sbin/ser[9233]: SER: Look aliases ser /usr/local/sbin/ser[9233]: SER: Look location ser /usr/local/sbin/ser[9233]: SER isflagset (sip) ser /usr/local/sbin/ser[9233]: SER: SIP Call On-Net section route(2) ser /usr/local/sbin/ser[9233]: error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy ser /usr/local/sbin/ser[9231]: error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy ser /usr/local/sbin/ser[9231]: SER: SIP Call On-Net section route(2) ser /usr/local/sbin/ser[9234]: SER: Failure Route section failure_route(1) ser /usr/local/sbin/ser[9234]: SER: fork to fwdnoanswer ser /usr/local/sbin/ser[9234]: SER: No Answer Failure and Jump to route(2) ser /usr/local/sbin/ser[9234]: SER: SIP Call On-Net section route(2) ser /usr/local/sbin/ser[9234]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9234]: ERROR: parse_sip_msg_uri: bad uri 0939749xxx@ser.xxx.net.tw ser /usr/local/sbin/ser[9234]: error: mediaproxy/getDestinationDomain(): error parsing destination URI ser /usr/local/sbin/ser[9234]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9234]: ERROR: parse_sip_msg_uri: bad uri 0939749xxx@ser.xxx.net.tw ser /usr/local/sbin/ser[9234]: is_uri_host_local(): Error while parsing URI ser /usr/local/sbin/ser[9234]: error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy ser /usr/local/sbin/ser[9234]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9234]: ERROR: uri2proxy: bad_uri: 0939749xxx@ser.xxx.net.tw ser /usr/local/sbin/ser[9234]: ERROR: t_forward_nonack: failure to add branches ser /usr/local/sbin/ser[9234]: ERROR: w_t_relay (failure mode): forwarding failed ser /usr/local/sbin/ser[9234]: error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy ser /usr/local/sbin/ser[9234]: ERROR: sl_reply_error used: I'm terribly sorry, server error occurred (1/SL) ser /usr/local/sbin/ser[9231]: SER: SIP Call On-Net section route(2) ---------------------------------------------------------------------------------------------------------
My ser.cfg list below: --------------------------------------------------------------------------------------------------------- # # $Id: ser.cfg,v 1.25 2004/11/30 16:28:24 andrei Exp $ # # simple quick-start config script #
# ----------- global configuration parameters ------------------------
debug=10 # debug level (cmd line: -dddddddddd) fork=yes log_stderror=no # (cmd line: -E)
/* Uncomment these lines to enter debugging mode fork=no log_stderror=yes */
listen=99.99.99.99
alias=ser.xxx.net.tw alias=ser alias=99.99.99.99
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 ----------------------------------
# Uncomment this if you want to use SQL database loadmodule "/usr/local/lib/ser/modules/mysql.so" loadmodule "/usr/local/lib/ser/modules/sl.so" loadmodule "/usr/local/lib/ser/modules/tm.so" loadmodule "/usr/local/lib/ser/modules/rr.so" loadmodule "/usr/local/lib/ser/modules/maxfwd.so" loadmodule "/usr/local/lib/ser/modules/usrloc.so" loadmodule "/usr/local/lib/ser/modules/registrar.so" loadmodule "/usr/local/lib/ser/modules/textops.so" loadmodule "/usr/local/lib/ser/modules/auth.so" loadmodule "/usr/local/lib/ser/modules/auth_db.so" loadmodule "/usr/local/lib/ser/modules/exec.so" loadmodule "/usr/local/lib/ser/modules/avpops.so" loadmodule "/usr/local/lib/ser/modules/domain.so" loadmodule "/usr/local/lib/ser/modules/group.so" loadmodule "/usr/local/lib/ser/modules/uri.so" loadmodule "/usr/local/lib/ser/modules/uri_db.so" loadmodule "/usr/local/lib/ser/modules/permissions.so" loadmodule "/usr/local/lib/ser/modules/speeddial.so" loadmodule "/usr/local/lib/ser/modules/acc.so" loadmodule "/usr/local/lib/ser/modules/pdt.so" loadmodule "/usr/local/lib/ser/modules/options.so" loadmodule "/usr/local/lib/ser/modules/mediaproxy.so" loadmodule "/usr/local/lib/ser/modules/xlog.so"
# ----------------- setting module-specific parameters ---------------
# -- 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 -- # # 0 = disable # 1 = write-through # 2 = write-back # 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")
# -- speeddial params -- modparam("speeddial", "user_column", "username") modparam("speeddial", "domain_column", "domain") modparam("speeddial", "sd_user_column", "username_from_req_uri") modparam("speeddial", "sd_domain_column", "domain_from_req_uri") modparam("speeddial", "new_uri_column", "new_request_uri") modparam("speeddial", "domain_prefix", "tel")
# ------------------------- 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); };
# ------------------------------------------------------------------------ # Click2Dial Section # 14 # ------------------------------------------------------------------------ #if (src_ip=="99.99.99.99" && (search("^From: <sip:700@") || search("^To: <sip:700@"))) { # setflag(14); #};
# ------------------------------------------------------------------------ # 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; };
# ------------------------------------------------------------------------ # Message Waiting Indicator SUBSCRIBE Section # # Make sure all SUBSCRIBE messages with header "Event: message-summary" # are sent to the voicemail server # ------------------------------------------------------------------------ #if ((method=="SUBSCRIBE") && search("^Event: message-summary")) { # rewritehostport("99.99.99.100:5060"); # t_relay(); # break; #};
# ------------------------------------------------------------------------ # NAT Test Section #1 # ------------------------------------------------------------------------ if (client_nat_test("3") && !search("^Record-Route:")) { force_rport(); fix_contact(); };
# ------------------------------------------------------------------------ # Enhanced Voicemail Applications Section # # Access additional Asterisk applications at extension 701 and 702 # ------------------------------------------------------------------------ #if (uri=~"^sip:70[1|2]@") { # route(5); # break; #};
# ------------------------------------------------------------------------ # PSTN Section # ------------------------------------------------------------------------ # # This is an example of US phone call. # #if (method=="INVITE") { # if (uri=~"^sip:1[0-9]{10}@") { # strip(1); # }; # if ((uri=~"^sip:911@.*") || (uri=~"^sip:900[0-9]{7}@") || (uri=~"^sip:976[0-9]{7}@")) { # sl_send_reply("503", "Service Unavailable"); # break; # }; #}; if (method=="INVITE") { ## Deny PSTN to 0204 and 095 of Taiwan 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()) { #if (is_user_in("From", "411")) { # setflag(30); ## some call from directory service #};
# 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; };
# ------------------------------------------------------------------------ # 411 Directory Assistance Section # 30 # ------------------------------------------------------------------------ #if (method=="INVITE" && uri=~"^sip:411@.*") { # if (isflagset(30)) { # avp_write("$from", "i:34"); # avp_pushto("$ruri", "i:34"); # strip_tail(7); # subst_uri('/^sip:([0-9]+)@(.*)$/sip:\15551212@\2/i'); # avp_delete("i:34"); # route(3); # break; # }; # sl_send_reply("503", "Service Unavailable"); # break; #};
# ------------------------------------------------------------------------ # Speed Dialing Section # ------------------------------------------------------------------------ if ((method=="INVITE") && (uri=~"^sip:[0-9]{2}@.*")) { sd_lookup("speed_dial"); };
# ------------------------------------------------------------------------ # 011 International Call Section # 29 # ------------------------------------------------------------------------ #if (method=="INVITE" && uri=~"^sip:011[0-9]*@") { # if (isflagset(29)) { # route(6); # } else { # sl_send_reply("503", "Service Unavailable"); # }; # break; #};
# ------------------------------------------------------------------------ # 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; }; }; };
# ------------------------------------------------------------------------ # Call Block Section # ------------------------------------------------------------------------ #if (is_caller_blocked()) { # route(7); # 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\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)) { log(1, "SER: Start a PSTN call\n"); route(3); } else { log(1, "SER: 503 Service Unavailable\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_check("$calltype", "eq/-/i")) { if (avp_check("$calltype", "eq/dom/i")) { avp_write("dom", "$fwd_no_answer_type"); } else if (avp_check("$calltype", "eq/int/i")) { avp_write("int", "$fwd_no_answer_type"); } else { avp_write("sip", "$fwd_no_answer_type"); } setflag(27); }; }; }; if (avp_db_load("$ruri/username", "s:fwdbusy")) { route(1); if (!avp_check("$calltype", "eq/-/i")) { if (avp_check("$calltype", "eq/dom/i")) { avp_write("dom", "$fwd_busy_type"); } else if (avp_check("$calltype", "eq/int/i")) { avp_write("int", "$fwd_busy_type"); } else { avp_write("sip", "$fwd_busy_type"); } setflag(26); }; }; 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("-", "$calltype");
# US international call #if (uri=~"^sip:1[0-9]{10}@") { # strip(1); #};
# Call rejected #if ((uri=~"^sip:70[1|2]@") || (uri=~"^sip:411@.*") || # (uri=~"^sip:911@.*") || (uri=~"^sip:900[0-9]{7}@") || # (uri=~"^sip:976[0-9]{7}@")) { # break; #}; if ((uri=~"^sip:0204[0-9]*@") || (uri=~"^sip:095[0-9]*@") || (uri=~"^sip:[0-9]{3}@")) { break; }; # Error Message from this <================== ERROR 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:011[0-9]*@") { } 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 avp_write("i:45", "inv_timeout"); rewritehost("99.99.99.250"); 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] { log(1, "SER: Voice Mail section route(4)\n");
# voicemail route #1 # # this path this executed during these conditions: # # cond 1) the called number is in the location table # but the callee did not answer the phone # (ie, failover to voicemail)
if (isflagset(25)) { replace("^From:(.*)>" , "From: "Anonymous" sip:someone@anonymous.invalid"); }; rewritehostport("99.99.99.100:5060"); append_branch(); t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
route[5] { log(1, "SER: Voice Mail section route(5)\n");
# voicemail route #2 # # this path this executed during these conditions: # # cond 1) the called number is not in the location table # cond 2) the from_uri == to_uri (ie, caller==callee)
if (method=="INVITE" || method=="ACK") { use_media_proxy(); }; rewritehostport("99.99.99.100:5060"); t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
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("99.99.99.240"); 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] { log(1, "SER: Caller Blocked section route(7)\n");
# caller blocked announcment # # this path this executed if a caller has been blocked
if (method=="INVITE" || method=="ACK") { use_media_proxy(); }; rewriteuri("sip:699@99.99.99.100:5060"); t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
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 (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 (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 (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 (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; }; }
Dear ALL:
I think it is a very good chance to study Paul's ser.cfg file. I use the 0.9.0 sample cfg and try to implement a call forward, busy forward, no answer forward function. But I got a 503 message when I use make a call from UA 1011 to UA 1022(registed on the same ser) with callforward to a PSTN .
But I have no voicemail option supported. So I must modify it.
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 0939749xxx@ser.xxx.net.tw 1022 ser.xxx.net.tw fwdnoanswer 0939749xxx@ser.xxx.net.tw 1022 ser.xxx.net.tw fwdbusy 0939749xxx@ser.xxx.net.tw
In grp table: username domain grp --------------------------------------------------- 1022 ser.xxx.net.tw int 1011 ser.xxx.net.tw int
I don't know where to defind the 'dom' and 'int' or '-' setting at DB table. What is its table name?
domain ==> ser.xxx.net.tw (the same as caller and machine)
When I test this call forward, a UA 1011 call to 1022. It It should be forward to a PSTN and use route(3) or route(6).
But when I do it, it seems failed at lookup("aliases") and lookup("location") function.
Log list below: --------------------------------------------------------------------------------------------------------- ser /usr/local/sbin/ser[9232]: SER: BLIND CALL FORWARDING ser /usr/local/sbin/ser[9232]: SER: Check Forwarding Number Rules ser /usr/local/sbin/ser[9232]: SER: Look aliases ser /usr/local/sbin/ser[9232]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9232]: extract_aor(): Error while parsing Address of Record ser /usr/local/sbin/ser[9232]: lookup(): Error while extracting address of record ser /usr/local/sbin/ser[9232]: SER: Look location ser /usr/local/sbin/ser[9232]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9232]: extract_aor(): Error while parsing Address of Record ser /usr/local/sbin/ser[9232]: lookup(): Error while extracting address of record ser /usr/local/sbin/ser[9232]: SER: 503 Service Unavailable ---------------------------------------------------------------------------------------------------------
If I delete the record callfwd of 1022 and want to test call noanswer forward. It seems can not forward to a PSTN number and jump to route(3) or route(6). It always keep the orginial rule and use route(2). Also the error message "error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy" always displays at log file whether the call is connected or failed call.
Log list below: ---------------------------------------------------------------------------------------------------------ser /usr/local/sbin/ser[9233]: SER: BLIND CALL FORWARDING ser /usr/local/sbin/ser[9233]: SER: Look aliases ser /usr/local/sbin/ser[9233]: SER: Look location ser /usr/local/sbin/ser[9233]: SER isflagset (sip) ser /usr/local/sbin/ser[9233]: SER: Look aliases ser /usr/local/sbin/ser[9233]: SER: Look location ser /usr/local/sbin/ser[9233]: SER isflagset (sip) ser /usr/local/sbin/ser[9233]: SER: SIP Call On-Net section route(2) ser /usr/local/sbin/ser[9233]: error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy ser /usr/local/sbin/ser[9231]: error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy ser /usr/local/sbin/ser[9231]: SER: SIP Call On-Net section route(2) ser /usr/local/sbin/ser[9234]: SER: Failure Route section failure_route(1) ser /usr/local/sbin/ser[9234]: SER: fork to fwdnoanswer ser /usr/local/sbin/ser[9234]: SER: No Answer Failure and Jump to route(2) ser /usr/local/sbin/ser[9234]: SER: SIP Call On-Net section route(2) ser /usr/local/sbin/ser[9234]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9234]: ERROR: parse_sip_msg_uri: bad uri 0939749xxx@ser.xxx.net.tw ser /usr/local/sbin/ser[9234]: error: mediaproxy/getDestinationDomain(): error parsing destination URI ser /usr/local/sbin/ser[9234]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9234]: ERROR: parse_sip_msg_uri: bad uri 0939749xxx@ser.xxx.net.tw ser /usr/local/sbin/ser[9234]: is_uri_host_local(): Error while parsing URI ser /usr/local/sbin/ser[9234]: error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy ser /usr/local/sbin/ser[9234]: ERROR: parse_uri: bad uri, state 0 parsed: <0939> (4) / 0939749xxx@ser.xxx.net.tw (27) ser /usr/local/sbin/ser[9234]: ERROR: uri2proxy: bad_uri: 0939749xxx@ser.xxx.net.tw ser /usr/local/sbin/ser[9234]: ERROR: t_forward_nonack: failure to add branches ser /usr/local/sbin/ser[9234]: ERROR: w_t_relay (failure mode): forwarding failed ser /usr/local/sbin/ser[9234]: error: mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy ser /usr/local/sbin/ser[9234]: ERROR: sl_reply_error used: I'm terribly sorry, server error occurred (1/SL) ser /usr/local/sbin/ser[9231]: 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=99.99.99.99
alias=ser.xxx.net.tw alias=ser alias=99.99.99.99
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 ---------------------------------- ..............(skip)
# ----------------- setting module-specific parameters ---------------
# -- 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")
# -- speeddial params -- modparam("speeddial", "user_column", "username") modparam("speeddial", "domain_column", "domain") modparam("speeddial", "sd_user_column", "username_from_req_uri") modparam("speeddial", "sd_domain_column", "domain_from_req_uri") modparam("speeddial", "new_uri_column", "new_request_uri") modparam("speeddial", "domain_prefix", "tel")
# ------------------------- 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; };
# ------------------------------------------------------------------------ # 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 of Taiwan 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\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)) { log(1, "SER: Start a PSTN call\n"); route(3); } else { log(1, "SER: 503 Service Unavailable\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_check("$calltype", "eq/-/i")) { if (avp_check("$calltype", "eq/dom/i")) { avp_write("dom", "$fwd_no_answer_type"); } else if (avp_check("$calltype", "eq/int/i")) { avp_write("int", "$fwd_no_answer_type"); } else { avp_write("sip", "$fwd_no_answer_type"); } setflag(27); }; }; }; if (avp_db_load("$ruri/username", "s:fwdbusy")) { route(1); if (!avp_check("$calltype", "eq/-/i")) { if (avp_check("$calltype", "eq/dom/i")) { avp_write("dom", "$fwd_busy_type"); } else if (avp_check("$calltype", "eq/int/i")) { avp_write("int", "$fwd_busy_type"); } else { avp_write("sip", "$fwd_busy_type"); } setflag(26); }; }; 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("-", "$calltype");
# US international call #if (uri=~"^sip:1[0-9]{10}@") { # strip(1); #};
# Call rejected #if ((uri=~"^sip:70[1|2]@") || (uri=~"^sip:411@.*") || # (uri=~"^sip:911@.*") || (uri=~"^sip:900[0-9]{7}@") || # (uri=~"^sip:976[0-9]{7}@")) { # break; #}; if ((uri=~"^sip:0204[0-9]*@") || (uri=~"^sip:095[0-9]*@") || (uri=~"^sip:[0-9]{3}@")) { break; }; # Error Message from this <================== ERROR 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:011[0-9]*@") { } 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 avp_write("i:45", "inv_timeout"); rewritehost("99.99.99.250"); 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] { log(1, "SER: Voice Mail section route(4)\n");
# voicemail route #1 # # this path this executed during these conditions: # # cond 1) the called number is in the location table # but the callee did not answer the phone # (ie, failover to voicemail)
if (isflagset(25)) { replace("^From:(.*)>" , "From: "Anonymous" sip:someone@anonymous.invalid"); }; rewritehostport("99.99.99.100:5060"); append_branch(); t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
route[5] { log(1, "SER: Voice Mail section route(5)\n");
# voicemail route #2 # # this path this executed during these conditions: # # cond 1) the called number is not in the location table # cond 2) the from_uri == to_uri (ie, caller==callee)
if (method=="INVITE" || method=="ACK") { use_media_proxy(); }; rewritehostport("99.99.99.100:5060"); t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
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("99.99.99.240"); 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] { log(1, "SER: Caller Blocked section route(7)\n");
# caller blocked announcment # # this path this executed if a caller has been blocked
if (method=="INVITE" || method=="ACK") { use_media_proxy(); }; rewriteuri("sip:699@99.99.99.100:5060"); t_on_reply("1"); if (!t_relay()) { if (method=="INVITE" || method=="ACK") { end_media_session(); }; sl_reply_error(); }; }
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 (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 (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 (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 (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; }; }
Charles,
One problem I see is that the value for the forwarded number is not a valid SIP URI.
The values stored in the usr_preferences table must look like this:
sip:4075551212@mycompany.com
As for you question about the "-", "dom", and "int" avp lines, these are not database related. Instead this is a bit of a hack. I use these three values as AVPs which get referenced in other route blocks. The reason I call this a hack is that it would be better to move this kind of validation to a custom C module.
Anyhow, the whole point of that route block is to validate the destination number that the user is trying to have forwarded to. For example, the user should not be allowed to forward to 911 or an international number (unless they are entitled to international dialing).
One more note: That ser.cfg that you're referencing is very unwieldy. I've since restructured the entire thing for simplicity reasons. This ser.cfg follows the very simple concepts shown in the default ser.cfg example.
I feel it is much better to follow a per-method-type approach. For example in the main route block I now have:
if (method=="BYE") { route(1); # BYE message handler } else if (method=="ACK") { route(2); # ACK message handler } else ....
I'm hoping to post my entire reworked ser.cfg to the mailing list this week and seek comments and feedback on establishing "best coding practices" for ser because as far as I know this hasn't been addressed. My hopes are that the next ser.cfg I post, would at a minimum, get the ball rolling on defining how best to code ser.cfg logic.
Regards, Paul
On Sun, 20 Feb 2005 12:23:32 +0800, Charles Wang lazy.charles@gmail.com wrote:
Dear ALL:
I think it is a very good chance to study Paul's ser.cfg file. I use the 0.9.0 sample cfg and try to implement a call forward, busy forward, no answer forward function. But I got a 503 message when I use make a call from UA 1011 to UA 1022(registed on the same ser) with callforward to a PSTN .
Alternatively, you can use: avp_pushto("$ruri/username", "s:callfwd"); to replace only the username part of the ruri. callfwd can then be set to 4075551212 only.
g-)
Java Rockx wrote:
Charles,
One problem I see is that the value for the forwarded number is not a valid SIP URI.
The values stored in the usr_preferences table must look like this:
sip:4075551212@mycompany.com
As for you question about the "-", "dom", and "int" avp lines, these are not database related. Instead this is a bit of a hack. I use these three values as AVPs which get referenced in other route blocks. The reason I call this a hack is that it would be better to move this kind of validation to a custom C module.
Anyhow, the whole point of that route block is to validate the destination number that the user is trying to have forwarded to. For example, the user should not be allowed to forward to 911 or an international number (unless they are entitled to international dialing).
One more note: That ser.cfg that you're referencing is very unwieldy. I've since restructured the entire thing for simplicity reasons. This ser.cfg follows the very simple concepts shown in the default ser.cfg example.
I feel it is much better to follow a per-method-type approach. For example in the main route block I now have:
if (method=="BYE") { route(1); # BYE message handler } else if (method=="ACK") { route(2); # ACK message handler } else ....
I'm hoping to post my entire reworked ser.cfg to the mailing list this week and seek comments and feedback on establishing "best coding practices" for ser because as far as I know this hasn't been addressed. My hopes are that the next ser.cfg I post, would at a minimum, get the ball rolling on defining how best to code ser.cfg logic.
Regards, Paul
On Sun, 20 Feb 2005 12:23:32 +0800, Charles Wang lazy.charles@gmail.com wrote:
Dear ALL:
I think it is a very good chance to study Paul's ser.cfg file. I use the 0.9.0 sample cfg and try to implement a call forward, busy forward, no answer forward function. But I got a 503 message when I use make a call from UA 1011 to UA 1022(registed on the same ser) with callforward to a PSTN .
Serusers mailing list serusers@lists.iptel.org http://lists.iptel.org/mailman/listinfo/serusers