###################################################################### ## Core Parameters ###################################################################### # chroot= # group="opensips" # user="opensips" # dbversion_table= disable_core_dump=no max_while_loops=100 maxbuffer=262144 memdump=3 memlog=2 # open_files_limit=2048 server_signature=no server_header="Server: OpenSIPS" user_agent_header="User-Agent: OpenSIPS" ###################################################################### ## Core Fork Parameters ###################################################################### fork=yes children=8 tcp_children=8 ###################################################################### ## Core Logging Parameters ###################################################################### debug=3 sip_warning=0 log_stderror=no log_facility=LOG_LOCAL0 log_name="opensips" ###################################################################### ## Aliases ###################################################################### auto_aliases=yes alias=localhost alias=localhost.localdomain ###################################################################### ## Connectivity ###################################################################### #listen=udp:eth0:5060 listen=udp:eth0:5060 listen=tcp:eth0:5060 listen=udp:eth0:7000 listen=tcp:eth0:7000 #listen=udp:eth0:7000 #listen=tcp:eth0:7000 # listen=udp:eth1:5060 tos=IPTOS_LOWDELAY # advertised_address=174.129.131.38 # advertised_port=5060 mcast_loopback=no mcast_ttl=1 mhomed=0 # tcp_accept_aliases tcp_connect_timeout=3 tcp_connection_lifetime=120 tcp_max_connections=2048 # tcp_poll_method=select ###################################################################### ## DNS ###################################################################### dns=no dns_retr_time=1 dns_retr_no=3 # dns_servers_no=2 dns_try_ipv6=no disable_dns_blacklist=yes disable_dns_failover=no dns_use_search_list=no rev_dns=no ###################################################################### ## SIP ###################################################################### check_via=0 #! disable_503_translation=no disable_stateless_fwd=no disable_tcp=no # disable_tls=no #! reply_to_via=1 ###################################################################### ## TLS ###################################################################### # disable_tls=no # listen=tls:your_IP:5061 # tls_verify_server=1 # tls_verify_client=1 # tls_require_client_certificate=0 # tls_method=TLSv1 # tls_certificate="/usr/local/etc/opensips/tls/user/user-cert.pem" # tls_private_key="/usr/local/etc/opensips/tls/user/user-privkey.pem" # tls_ca_list="/usr/local/etc/opensips/tls/user/user-calist.pem" ###################################################################### ## Destination Blacklist ###################################################################### # dst_blacklist=gw:{( tcp , 192.168.2.100 , 5060 , "" ),( any , 192.168.2.101 , 0 , "" )} # dst_blacklist=net_filter2:{ !( any , 192.168.30.0/255.255.255.0 , 0 , "" )} ###################################################################### ## Attribute Value Pairs ###################################################################### # avp_aliases="uuid=I:660;email=s:email_addr;fwd=i:753" ###################################################################### ## Module Loading ###################################################################### mpath="/usr/local/lib64/opensips/modules/" loadmodule "db_mysql.so" loadmodule "localcache.so" loadmodule "signaling.so" loadmodule "sl.so" loadmodule "tm.so" loadmodule "dialog.so" loadmodule "maxfwd.so" loadmodule "rr.so" loadmodule "path.so" loadmodule "uri.so" loadmodule "textops.so" loadmodule "usrloc.so" loadmodule "nathelper.so" loadmodule "nat_traversal.so" loadmodule "uac_redirect.so" loadmodule "dispatcher.so" loadmodule "mi_fifo.so" # loadmodule "mi_datagram.so" ###################################################################### ## Localcache Module Parameters ###################################################################### modparam("localcache", "cache_table_size", 10) modparam("localcache", "cache_clean_period", 120) ###################################################################### ## Stateless UA Module Parameters ###################################################################### modparam("sl", "enable_stats", 1) ###################################################################### ## SIP Transaction UA Module Parameters ###################################################################### modparam("tm", "fr_timer", 2) modparam("tm", "fr_inv_timer", 120) # modparam("tm", "wt_timer", 5) # modparam("tm", "delete_timer", 2) # modparam("tm", "T1_timer", 500) # modparam("tm", "T2_timer", 4000) # modparam("tm", "ruri_matching", 1) # modparam("tm", "via1_matching", 1) # modparam("tm", "unix_tx_timeout", 2) # modparam("tm", "restart_fr_on_each_reply", 1) modparam("tm", "fr_timer_avp", "$avp(final_reply_timer)") # modparam("tm", "fr_inv_timer_avp", "$avp(25)") # modparam("tm", "tw_append", # "test: ua=$hdr(User-Agent) ;avp=$avp(i:10);$rb;time=$Ts") modparam("tm", "pass_provisional_replies", 1) # modparam("tm", "syn_branch", 1) # modparam("tm", "onreply_avp_mode", 0) # modparam("tm", "disable_6xx_block", 0) # modparam("tm", "enable_stats", 1) # modparam("tm", "minor_branch_flag", 3) ###################################################################### ## Max Forward Module Parameters ###################################################################### modparam("maxfwd", "max_limit", 30) ###################################################################### ## Record Route Module Parameters ###################################################################### #modparam("rr", "enable_full_lr", 1) modparam("rr", "append_fromtag", 1) modparam("rr", "enable_double_rr", 0) modparam("rr", "add_username", 0) ###################################################################### ## Path Module Parameters ###################################################################### modparam("path", "use_received", 1) ###################################################################### ## URI Module Parameters ###################################################################### # modparam("uri", "aaa_url", "radius:/etc/radiusclient-ng/radiusclient.conf") modparam("uri", "use_sip_uri_host", 0) modparam("uri", "use_uri_table", 0) modparam("uri", "service_type", 10) modparam("uri", "use_domain", 1) modparam("uri", "use_uri_table", 0) # modparam("uri", "db_url", "mysql://username:password@localhost/opensips") # modparam("uri", "db_table", "uri") # modparam("uri", "user_column", "username") # modparam("uri", "domain_column", "domain") # modparam("uri", "uriuser_column", "uri_user") ###################################################################### ## User Location Module Parameters ###################################################################### modparam("usrloc", "nat_bflag", 6) modparam("usrloc", "use_domain", 1) modparam("usrloc", "desc_time_order", 0) modparam("usrloc", "timer_interval", 60) modparam("usrloc", "matching_mode", 0) modparam("usrloc", "cseq_delay", 20) modparam("usrloc", "hash_size", 9) modparam("usrloc", "db_mode", 0) # modparam("usrloc", "db_url", "dbdriver://username:password@dbhost/dbname") #modparam("usrloc", "fetch_rows", 2000) modparam("usrloc", "user_column", "username") modparam("usrloc", "domain_column", "domain") modparam("usrloc", "contact_column", "contact") modparam("usrloc", "expires_column", "expires") modparam("usrloc", "q_column", "q") modparam("usrloc", "callid_column", "callid") modparam("usrloc", "cseq_column", "cseq") modparam("usrloc", "methods_column", "methods") modparam("usrloc", "flags_column", "flags") modparam("usrloc", "cflags_column", "cflags") modparam("usrloc", "user_agent_column", "user_agent") modparam("usrloc", "received_column", "received") modparam("usrloc", "socket_column", "socket") modparam("usrloc", "path_column", "path") ###################################################################### ## Nathelper Module Parameters ###################################################################### # modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:7890") # modparam("nathelper", "natping_interval", 30) # modparam("nathelper", "ping_nated_only", 1) # modparam("nathelper", "natping_processes", 3) # modparam("nathelper", "sipping_bflag", 7) # modparam("nathelper", "sipping_from", "sip:[email protected]") # modparam("nathelper", "sipping_method", "INFO") ###################################################################### ## NAT Traversal Module Parameters ###################################################################### modparam("nat_traversal", "keepalive_interval", 60) modparam("nat_traversal", "keepalive_method", "OPTIONS") modparam("nat_traversal", "keepalive_from", "sip:[email protected]:5060") modparam("nat_traversal", "keepalive_state_file", "/tmp/opensips_keepalive_state") ###################################################################### ## UAC Redirect Module Parameters ###################################################################### modparam("uac_redirect", "default_filter", "accept") # modparam("uac_redirect", "deny_filter", NULL) # modparam("uac_redirect", "accept_filter", NULL) # modparam("uac_redirect", "acc_function", "acc_log_request") # modparam("uac_redirect", "acc_db_table", "acc") ###################################################################### ## Dispatcher Module Parameters ###################################################################### #modparam("dispatcher", "list_file", "/etc/opensips/dispatcher.list") modparam("dispatcher", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") modparam("dispatcher", "flags", 2) modparam("dispatcher", "use_default", 0) modparam("dispatcher", "force_dst", 1) modparam("dispatcher", "dst_avp", "$avp(271)") modparam("dispatcher", "attrs_avp", "$avp(272)") modparam("dispatcher", "grp_avp", "$avp(273)") modparam("dispatcher", "cnt_avp", "$avp(274)") modparam("dispatcher", "hash_pvar", "$avp(273)") # modparam("dispatcher", "setid_pvar", "$var(setid)") modparam("dispatcher", "ds_ping_method", "OPTIONS") modparam("dispatcher", "ds_ping_from", "sip:[email protected]:5060") modparam("dispatcher", "ds_ping_interval", 10) # modparam("dispatcher", "ds_ping_sock", "udp:ext.ip.addr:5060") modparam("dispatcher", "ds_probing_threshhold", 3) modparam("dispatcher", "ds_probing_mode", 1) modparam("dispatcher", "options_reply_codes", "501,403,404,400,200") ###################################################################### ## MI-FIFO Module Parameters ###################################################################### modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") ###################################################################### ## MI-Datagram Module Parameters ###################################################################### # modparam("mi_datagram", "socket_name", "udp:127.0.0.1:8889") # modparam("mi_datagram", "children_count", 1) # modparam("mi_datagram", "unix_socket_mode", 0600) # modparam("mi_datagram", "unix_socket_group", "root") # modparam("mi_datagram", "unix_socket_user", "root") # modparam("mi_datagram", "socket_timeout", 2000) # modparam("mi_datagram", "reply_indent", "\t") ###################################################################### ## XLog Module Parameters ###################################################################### # modparam("xlog", "buf_size", 4096) # modparam("xlog", "force_color", 0) ###################################################################### ## Multiple Module Parameters ###################################################################### ###################################################################### ## Main Request Routing ###################################################################### route { # log the basic info regarding this call xlog("L_INFO", "$ci|start|recieved $oP request $rm $ou"); xlog("L_INFO", "$ci|log|source $si:$sp"); xlog("L_INFO", "$ci|log|from $fu"); xlog("L_INFO", "$ci|log|to $tu"); # check that hop cound for this request and make sure it is under 10 # to prevent endless loops if (!mf_process_maxfwd_header("10")) { xlog("L_WARN", "$ci|end|to many hops"); sl_send_reply("483", "We refuse to process this endless imbroglio"); exit; } # this check detemines if the opensips has routed the request to itself, # this happens because the server is the destination of the request but # we mangle it to send it else where. When that mangeling fails and we # still relay it then it just comes right back to us... if (src_ip==myself) { xlog("L_WARN", "$ci|end|sourced from this server"); exit; } # currently we dont support subscribe so to keep the noise down # just end the request here. For options just end the request here as well. if (is_method("OPTIONS")) { xlog("L_NOTICE", "$ci|end|unsupported method"); sl_send_reply("503", "Rawr!!"); exit; } # if the source IP/port are in one of the server dispatch lists # then this request originated from one of our media servers, mark it # as such by setting flag 26 if (ds_is_in_list("$si", "", "1")) { xlog("L_INFO", "$ci|log|originated from internal sources"); # Flag 26 marks the source as a on-net server setflag(26); setbflag(26); } # if the request source IP/port was not in any dispatcher lists # this this originated outside our equipment (carrier, client, ect) else { xlog("L_INFO", "$ci|log|originated from external sources"); } # if the to header has a tag attached then it implies this request # has been processed by us before (IE: a media server has added # its tag on the to header in prior messages) if (has_totag()) { # sequential request within a dialog should # take the path determined by record-routing if (loose_route()) { append_hf("P-hint: rr-enforced\r\n"); # if we have locked this call to a media server then # maintain that association if (cache_fetch("local", "$ci", $avp(55))) { if (is_method("BYE")) { # remove the association between the call-id and the media server (if one) # but leave the contact user and server to support transfers cache_remove("local", "$ci"); xlog("L_INFO", "$ci|log|cleaned up call id from cache"); } else if (isflagset(26)) { cache_store("local", "$tU", "$avp(55)", 3600); xlog("L_INFO", "$ci|log|maintaining associated $tU with media server $avp(55)"); } else if ($ct.fields(uri)) { cache_store("local", "$(ct.fields(uri){uri.user})", "$avp(55)", 3600); xlog("L_INFO", "$ci|log|maintaining associated $(ct.fields(uri){uri.user}) with media server $avp(55)"); } cache_store("local", "$ci", "$avp(55)", 3600); } xlog("L_INFO", "$ci|log|forwarding based on the route set"); if (isflagset(26)) { route(internal_to_external_relay); } else { route(external_to_internal_relay); } exit(); } else if ( is_method("ACK") ) { if ( t_check_trans() ) { # non loose-route, but stateful ACK; must be an ACK after # a 487 or e.g. 404 from upstream server xlog("L_INFO", "$ci|log|in dialog request belongs to a known transaction"); route(logged_relay); } else { # ACK without matching transaction -> # ignore and discard xlog("L_NOTICE", "$ci|end|no matching transaction"); } exit(); } else if ( is_method("NOTIFY") ) { route(logged_relay); exit(); } # request with a to tag that cant be routed loosly and is not an ACK # ignor eand discard xlog("L_WARN", "$ci|end|could not route in dialog"); sl_send_reply("486", "PC Load Letter"); exit(); } # if the request is to cancel a transaction process it now if (is_method("CANCEL")) { # If this cancel is part of a transaction # then pass it along to concerned parties if (t_check_trans()) { xlog("L_INFO", "$ci|log|request belogs to a known transaction"); route(logged_relay); } # if the cancel does not belong to a known transaction or a # request that has not progressed outside this server dont relay it else { xlog("L_NOTICE", "$ci|end|no matching transaction"); } # remove the association between the call-id and the media server (if one) # but leave the contact user and server to support transfers cache_remove("local", "$ci"); xlog("L_INFO", "$ci|log|cleaned up call id from cache"); exit; } # If this is a retransmission it will break/stop the script # and do standard processing of the message t_check_trans(); # Except for an ACK no request should have a route set with no to tag, this would # indicate that the intial request has the Route headers and is likely someone trying # to get us to send the request were they want if (loose_route()) { if (!is_method("ACK")) { xlog("L_WARN", "$ci|end|initial request contained a preloaded route set"); sl_send_reply("403", "The only winning move it not to play"); exit; } } # If the request is a register we will pass it along but we need # to add the path header (along with the received IP/port info) if (is_method("REGISTER")) { # if we fail to add the path header then dont let it # register because it will cause issues later... if (!add_path_received()) { xlog("L_ERR", "$ci|log|unable to add path"); sl_send_reply("503", "Internal path befuddlement"); # remove the association between the call-id and the media server (if one) # but leave the contact user and server to support transfers cache_remove("local", "$ci"); xlog("L_INFO", "$ci|end|cleaned up call id from cache"); exit; } xlog("L_INFO", "$ci|log|added path"); } # for all initial request (not having been processed above in the has_totag) # that are not a register or message add this sever to the route set on the # request so subsequent messages come through this server if (!is_method("REGISTER|MESSAGE")) { # Record the route that this request has taken # so we remain in the signaling path record_route(); xlog("L_INFO", "$ci|log|added this server to the route set"); } # if the request is from a media server send it out if (isflagset(26)) { route(internal_to_external_relay); exit(); } # if the request is not from a media server it must be for one, # there is much work to do! # load a list of currently active media servers # if no media server could be set with ds_select_domain then there are no # active servers, no need to conitnue if (!ds_select_domain("1", "4")) { xlog("L_ERR", "$ci|end|no servers avaliable"); sl_send_reply("480", "The cake is a lie!"); exit; } if (cache_fetch("local", "$ou", $avp(55))) { xlog("L_INFO", "$ci|log|request $ou is associated with media server $avp(55)"); cache_remove("local", "$ou"); cache_store("local", "$ci", "$avp(55)", 3600); } # if the request is not from our media severs but has a call-id in localcache # then change the routing to go to the server previously associated with it. else if (cache_fetch("local", "$ci", $avp(55))) { cache_store("local", "$ci", "$avp(55)", 3600); xlog("L_INFO", "$ci|log|call-id is associated with media server $avp(55)"); } # if the request is not from our media severs but has a contact uri in localcache # then change the routing to go to the server previously associated with it. else if ($ct.fields(uri) && cache_fetch("local", "$(ct.fields(uri){uri.user})", $avp(55))) { cache_store("local", "$(ct.fields(uri){uri.user})", "$avp(55)", 3600); xlog("L_INFO", "$ci|log|contact $(ct.fields(uri){uri.user}) is associated with media server $avp(55)"); } # if the request is not from our media servers and no associations in localcache # then use the distribute list as is else { xlog("L_INFO", "$ci|log|routing call to arbitrary media server $rd:$rp"); } # if the dispatcher list (in 271) does not start with # the request domain/port that we are sending this call # to, re-order the list so that it does if($avp(55) && $(avp(271)[0]) != $avp(55)) { # create a index var for our loop (arrays are start at 0 and this is a count) $var(i) = $avp(274) - 1; # loop over the dispatcher list while($var(i) > 0) { # if this element in the dispatch list is the same # as the call destination if($(avp(271)[$var(i)]) == $avp(55)) { # replace it with the first element of the list $(avp(271)[$(var(i))]) = $(avp(271)[0]); # break out of the loop $var(i) = -1; } $var(i) = $var(i) - 1; } # handles the case were we only have two servers # and the one that we are locked to has failed if ($var(i) >= 0) { xlog("L_INFO", "$ci|log|associated media server is inactive, moving to $rd"); if ($ct.fields(uri) && cache_fetch("local", "$ci", $avp(56))) { cache_store("local", "$(ct.fields(uri){uri.user})", "sip:$rd:$rp", 3600); xlog("L_INFO", "$ci|log|associated contact $(ct.fields(uri){uri.user}) with media server sip:$rd:$rp"); } # update the callid cache cache_store("local", "$ci", "sip:$rd:$rp", 3600); } # the server we are locked to is in the active server list from then # dispatcher so re-arrange the list to try it first else { xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to keep associated server first"); # set the first element of the list to the destination $(avp(271)[0]) = $avp(55); # set the domain for this request (server IP to route to) $rd = $(avp(55){uri.host}); # set the port for this request (server IP to route to) $rp = $(avp(55){uri.port}); } } route(external_to_internal_relay); } route[external_to_internal_relay] { # 1. correct any nat issues # 2. remove any X-AUTH-IP headers so we will be the only one to set it # 3. set the X-AUTH-IP header for freeswitch ACLs # 4. set the final reply timer to two seconds, so we failover faster # 5. arm a logging branch for replies # 6. arm a failure branch that will try another one of our media servers when possible route("nat_test_and_correct"); remove_hf("X-AUTH-IP"); append_hf("X-AUTH-IP: $si\r\n"); xlog("L_INFO", "$ci|log|X-AUTH-IP: $si"); $avp(final_reply_timer) = 2; t_on_reply("internal_reply"); t_on_failure("internal_fault"); route("logged_relay"); exit; } route[internal_to_external_relay] { # if the request is from a media server then assume it is going somewhere # outside our control and give that equipment longer to respond. # Also arm a branch to log the replies $avp(final_reply_timer) = 6; t_on_reply("external_reply"); route("logged_relay"); exit; } route[logged_relay] { # try to send the request on its way, if it fails send back a # stateless error to the requestor if (t_relay()) { xlog("L_INFO", "$ci|pass|$rd:$rp"); } else { xlog("L_ERR", "$ci|end|unable to relay message"); sl_reply_error(); } } route[nat_test_and_correct] { # 1. Contact header field is searched for occurrence of RFC1918 addresses # if (nat_uac_test("1")) # { # xlog("L_INFO", "$ci|log|contact header field contains a RFC1918 address"); # # fix_contact(); # } # 2 - the "received" test is used: address in Via is compared against source IP address of signaling if (nat_uac_test("2")) { xlog("L_INFO", "$ci|log|address in Via differs from source IP"); # adds the rport parameter to the first Via header force_rport(); fix_contact(); } # if the request has a body see if it needs NAT corrections as well, # this check looks at: # 8. SDP is searched for occurrence of RFC1918 addresses if (has_body("application/sdp") && nat_uac_test("8")) { xlog("L_INFO", "$ci|log|SDP contains a RFC1918 address"); # alters the SDP information in order to facilitate NAT traversal. # 2. rewrite media IP address (c=) with source IP # 8. rewrite IP from origin description (o=) with source IP fix_nated_sdp("10"); } } onreply_route[external_reply] { # this branch handles replies that are comming from equipment # outside our control xlog("L_INFO", "$ci|start|recieved external reply $rs $rr"); xlog("L_INFO", "$ci|log|source $si:$sp"); # This ensures that if a endpoint recieves a call they can properly # transfer that call # TODO: this will track calls made to carriers when we start sending carrier # traffic through opensips # Target: A endpoint answering a call made from one of our media # servers should lock that endpoint to the server if (t_check_status("200") && is_method("INVITE") && $(fd{ip.isip}) && ds_is_in_list("$fd", "", "1")) { $var(d) = $(fu{uri.host}); if ($(fu{uri.port}) == 0) { $var(p) = 5060; } else { $var(p) = $(fu{uri.port}); } if ($ct.fields(uri)) { cache_store("local", "$(ct.fields(uri){uri.user})", "sip:$var(d):$var(p)", 3600); xlog("L_INFO", "$ci|log|associated $(ct.fields(uri){uri.user}) with media server sip:$var(d):$var(p)"); } cache_store("local", "$ci", "sip:$var(d):$var(p)", 3600); xlog("L_INFO", "$ci|log|associated call-id with media server sip:$var(d):$var(p)"); } if (is_method("BYE")) { # remove the association between the call-id and the media server (if one) # but leave the contact user and server to support transfers cache_remove("local", "$ci"); xlog("L_INFO", "$ci|log|cleaned up call id from cache"); } route("nat_test_and_correct"); xlog("L_INFO", "$ci|pass|$(< request >si):$(< request >sp)"); # if the reply is not dropped (only provisional replies can be), # it will be injected and processed by the transaction engine. } onreply_route[internal_reply] { # this branch handles replies that are comming from our media server if(t_local_replied("last")) { xlog("L_INFO", "$ci|start|recieved local internal reply $T_reply_code $rr"); } else { xlog("L_INFO", "$ci|start|recieved internal reply $T_reply_code $rr"); xlog("L_INFO", "$ci|log|source $si:$sp"); } # Ensure that if we challenge an endpoint its response is not round-robin'd # We have to do it in the reply so we have the correct call id # Target: Endpoint intiated a request that was challenged, lock that # call id to the challenging server so it recieves the reply if (t_check_status("(407)|(401)") && $(si{ip.isip}) && ds_is_in_list("$si", "", "1")) { cache_store("local", "$ci", "sip:$si:$sp", 3600); xlog("L_INFO", "$ci|log|associated call-id with media server sip:$si:$sp"); } if (is_method("BYE")) { # remove the association between the call-id and the media server (if one) # but leave the contact user and server to support transfers cache_store("local", "$ci", "sip:$si:$sp", 360); xlog("L_INFO", "$ci|log|cleaned up call id from cache"); } if ($rs < 300 ) { xlog("L_INFO", "$ci|pass|$(si):$(< request >sp)"); } # if the reply is not dropped (only provisional replies can be), # it will be injected and processed by the transaction engine. } failure_route[internal_fault] { # this branch handles failures (>=300) to our media servers, # which we can sometimes overcome by routing to another server # if the failure cause was due to the transaction being # cancelled then we are complete if (t_was_cancelled()) { xlog("L_INFO", "$ci|log|transaction was cancelled"); # remove the association between the call-id and the media server (if one) # but leave the contact user and server to support transfers cache_remove("local", "$ci"); xlog("L_INFO", "$ci|end|cleaned up call id from cache"); exit; } # if the failure case was soemthing that we should recover # from then try to find a new media server if (t_check_status("(401)|(407)|(403)")) { xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $rr"); } else if (t_check_status("402")) { send_reply("486", "More money please"); exit(); } else if (t_check_status("(4[0-9][0-9])|(5[0-9][0-9])")) { xlog("L_INFO", "$ci|start|received failure reply $T_reply_code $rr"); if (cache_fetch("local", "$ci-failure", $avp(55))) { $avp(55) = $(avp(55){s.int}); } else { $avp(55) = 0; } xlog("L_INFO", "$ci|log|attempting retry $avp(55) of failed request"); # try to find a new media server to send the call to if($avp(55) < 3 && ds_next_domain()) { xlog("L_INFO", "$ci|log|routing call to next media server $rd:$rp"); # store the new callid association cache_store("local", "$ci", "sip:$rd:$rp", 3600); # if the request has a contact and is an INVITE then store the new # association if ($ct.fields(uri) && is_method("INVITE")) { cache_store("local", "$(ct.fields(uri){uri.user})", "sip:$rd:$rp", 3600); xlog("L_INFO", "$ci|log|associated contact $(ct.fields(uri){uri.user}) with media server sip:$rd:$rp"); } # reset the final reply timer $avp(final_reply_timer) = 2; t_on_reply("internal_reply"); t_on_failure("internal_fault"); xlog("L_INFO", "$ci|pass|$rd:$rp"); # relay the request to the new media server t_relay(); $avp(55) = $avp(55) + 1; cache_store("local", "$ci-failure", "$avp(55)", 60); exit(); } else { cache_remove("local", "$ci-failure"); xlog("L_ERR", "$ci|log|no other media servers avaliable"); } } else if (t_check_status("302")) { if( $(hdr(X-Redirect-Server)) && $(< reply >ct.fields(uri)) ) { $var(redirect_host) = $(< reply >hdr(X-Redirect-Server){uri.host}); $var(redirect_port) = $(< reply >hdr(X-Redirect-Server){uri.port}); cache_store("local", "$(< reply >ct.fields(uri))", "sip:$var(redirect_host):$var(redirect_port)", 60); xlog("L_INFO", "$ci|log|stored redirect mapping for $(< reply >ct.fields(uri)) to sip:$var(redirect_host):$var(redirect_port)"); xlog("L_INFO", "$ci|log|stored redirect mapping for $(< reply >ct.fields(uri)) to sip:$var(redirect_host):$var(redirect_port)"); remove_hf("X-Redirect-Server"); } } else { xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $rr"); } if (!t_check_status("(407)|(401)|(302)")) { # remove the association between the call-id and the media server (if one) # but leave the contact user and server to support transfers cache_remove("local", "$ci"); xlog("L_INFO", "$ci|log|cleaned up call id from cache"); } xlog("L_INFO", "$ci|pass|$(< request >si):$(< request >sp)"); # if no new branch is generated or no reply is forced over, by default, # the winning reply will be sent back to UAC. } |