I would probably suggest adding a few things to non-dispatcher example.
For example, if your mediagateway reports busy (486) or not found (404) do you really want to try via the next media gateway???
By adding a handler to reset the failure handler when a provisional response (ie ringing 180 or progressing 183) is received then we should stop (perhaps) some failures hitting failure_route...
It would pay to test well with your gateways and different conditions (ie end point is busy, end point does not exist, end point does not answer etc...) and if need be exclude them from failure_route retries...
t_on_failure("1");
t_on_reply("1");
rewritehostport("gatewayip:gatewayport"); if (!t_relay()) { sl_reply_error(); }
onreply_route[1] { if( status =~ "18[0-9]" ) { t_on_failure("0"); } }
failure_route[1] { rewritehostport("backupip:backupport"); append_branch(); t_relay(); }
Example of stateful dispatcher with failover....
You need a file called 'dispatcher.list' with something like this in it...
1 sip:gateway1:5060 1 sip:gateway2:5060 1 sip:gateway3:5060
-- openser.cfg -- example with stateful dispatcher + failover (need OpenSER 1.1.x)
mpath = "/opt/openser/lib/openser/modules"
loadmodule "sl.so" loadmodule "tm.so" loadmodule "rr.so" loadmodule "maxfwd.so" loadmodule "xlog.so" loadmodule "dispatcher.so"
# ----------------- setting module-specific parameters ---------------
# -- tm parmas --
# how long to keep a transaction in memory after a final response to # catch things that are just lagged -- default is 5 secs modparam("tm", "wt_timer", 30)
# timer for response to a request modparam("tm", "fr_timer", 2)
# timer for final response after getting a provisional response # ie timer to get say a '200' after getting a '100 trying...' # NB -- this shouldn't need to be set so high, and is basically ignored # as 1) we cancel the failure_route on getting a provisional # 2) network timeouts will be less than this... modparam("tm", "fr_inv_timer", 120)
# -- rr params -- # add value to ;lr param to make some broken UAs happy modparam("rr", "enable_full_lr", 1)
# -- dispatcher params -- # we are in fallover mode... set flag=2 modparam("dispatcher", "flags", 2 )
# ------------------------- request routing logic -------------------
# main routing logic
route{ # initial sanity checks -- messages with # max_forwards==0, or excessively long requests if (!mf_process_maxfwd_header("10")) { xlog( "L_NOTICE", "[$Tf] RR: $ci -- Too Many Hops.\n" ); sl_send_reply("483","Too Many Hops"); exit; };
if (msg:len >= 2048 ) { xlog( "L_NOTICE", "[$Tf] RR: $ci -- Message too big.\n" ); sl_send_reply("513", "Message too big"); exit; };
if (loose_route()) { xlog( "L_NOTICE", "[$Tf] RR: $ci -- Loose Route $rm ($rd).\n" ); if (!t_relay()) { sl_reply_error(); }; return; };
if( method=="CANCEL" ){ if( t_check_trans() ){ xlog("L_NOTICE", "[$Tf] RR: $ci -- $rm Relay \n"); t_relay(); return; } else { xlog("L_WARN", "[$Tf] RR: $ci -- $rm HAS NO TRANSACTION\n" ); return; } }
# PSTN Gateways if( uri=~"^sip:0.........@" || uri=~"^sip:1[38]00......@" || uri=~"^sip:13....@" ) { route(1); return; } }
route[1] { # PSTN Routing - Alg4 == Round Robin
ds_select_domain("1","4");
xlog("L_NOTICE", "[$Tf] RR[1]: $ci -- [PSTN] $rm $fU -> $tU via $rd\n");
t_on_reply("1"); t_on_failure("2");
if( !t_relay() ){ xlog( "L_WARN", "[$Tf] RR[1]: $ci -- ERROR - Can not t_relay()\n" ); # perhaps we should do something here?? return; } return; }
onreply_route[1] {
# we are checking here for a progressing return... ie a 180 Ringing or # 183 session progress -- if this occurs we don't care from here on # about failures as a gateway is handling the call...
if( status =~ "18[0-9]" ) { xlog( "L_INFO", "[$Tf] ORR: $ci -- SIP-$rs Reset t_on_failure()\n"); t_on_failure("0"); } else { xlog( "L_INFO", "[$Tf] ORR: $ci -- $rs $rr\n" ); } }
failure_route[2] {
# If fr_timer expires t_check_status("408") is true, although $rs is <null> if( t_check_status("408") ){ xlog( "L_NOTICE", "[$Tf] FR: $ci -- TIMEOUT for Gateway $rd\n" ); } else { xlog( "L_NOTICE", "[$Tf] FR: $ci -- $rs reason $rr\n" ); }
# basically what we do is # 1. not worry about reasonable failures (ie busy, wrong number etc...) # 2. go to next destination gateway # 3. if no destination gateway then 503 (service unavailable)
# 403 -- typically ISDN network says 'not a valid number' etc.. if( t_check_status("403") ){ xlog("L_NOTICE", "[$Tf] FR: $ci -- SIP-$rs Forbidden -> ISDN Cause Code 1\n" ); return; }
# 408 -- timeout -- typically the end party has not answered # Since we cancel t_on_failure() on a provisional response we should not be # getting a 408 timeout from a gateway at this stage.. it will just "fall through" #if( t_check_status("408") ){ # xlog("L_NOTICE", "[$Tf] FR: $ci -- SIP-$rs Timeout\n" ); # return; #}
# 486 -- User Busy if( t_check_status("486") ){ xlog("L_NOTICE", "[$Tf] FR: $ci -- SIP-$rs Destination Busy\n" ); return; }
# 487 -- Request Cancelled (usually in response to a CANCEL transaction) if( t_check_status("487") ){ xlog("L_NOTICE", "[$Tf] FR: $ci -- SIP-$rs Request Cancelled\n" ); return; }
# ok... so at this stage we try the next gateway (unless we don't have one) # if no next gateway we bail... if( ds_next_domain() ){ t_on_reply("1"); t_on_failure("2"); xlog( "L_NOTICE", "[$Tf] FR: $ci Next gateway $fU -> $tU via $rd\n" ); if( !t_relay() ){ xlog( "L_WARN", "[$Tf] FR: $ci -- ERROR - Can not t_relay()\n" ); # perhaps we should do something here?? return; } return; } else { xlog( "L_WARN", "[$Tf] FR: $ci No more buscuits in the biscuit tin -> 503.\n" ); t_reply("503", "Service unavailable -- no more gateways" ); return; }
}