Requests send with uac module's functions like uac_req_send() and remote registrations use the TM module, but don't actually do (DNS) failover when a destination is unreachable or sends a 503.
In the tm's uac.c, t_uac_prepare() function, i can already see that the dns handle is stored in a throwaway variable instead of in the transaction, but fixing the issue isn't as simple as just storing it in the transaction (print_uac_request_from_buf() needs a uas in the transaction).
Due to github not supporting attachments to issues, the sample config and debug log are inline.... :(
DNS entry: ``` $ host -t SRV _sip._udp.failover.test.speakup.nl _sip._udp.failover.test.speakup.nl has SRV record 10 0 1111 try1.test.speakup.nl. _sip._udp.failover.test.speakup.nl has SRV record 100 0 2222 try2.test.speakup.nl. ```
Log snippet: ```syslog Jun 15 10:00:03 rio UACFailover[18178]: INFO: <script>: Sending OPTIONS request to sip:failover.test.speakup.nl Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: tm [uac.c:249]: t_uac_prepare(): DEBUG:tm:t_uac: next_hop=sip:failover.test.speakup.nl Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:537]: _dns_hash_find(): (_sip._udp.failover.test.speakup.nl(34), 33), h=825 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [resolve.c:937]: get_record(): skipping 8 NS (p=0x9ea284, end=0x9ea3e9) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [resolve.c:952]: get_record(): parsing 9 ARs (p=0x9ea335, end=0x9ea3e9) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:1741]: dns_get_related(): (0x7f225233eb38 (_sip._udp.failover.test.speakup.nl, 33), 33, *0x7f2257baf2b8) (0) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:840]: dns_cache_add_unsafe(): adding _sip._udp.failover.test.speakup.nl(34) 33 (flags=0) at 825 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:840]: dns_cache_add_unsafe(): adding try1.test.speakup.nl(20) 1 (flags=0) at 310 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:840]: dns_cache_add_unsafe(): adding try2.test.speakup.nl(20) 1 (flags=0) at 307 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:2336]: dns_srv_get_nxt_rr(): (0x7f225233eb38, 0, 0, 1597643831): selected 0/1 in grp. 0 (rand_w=0, rr=0x7f225233eba0 rd=0x7f225233ebb8 p=10 w=0 rsum=0) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:537]: _dns_hash_find(): (try1.test.speakup.nl(20), 1), h=310 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:2926]: dns_a_resolve(): (try1.test.speakup.nl, 0) returning 0 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:3169]: dns_srv_resolve_ip(): ("_sip._udp.failover.test.speakup.nl", 0, 0), ret=0, ip=192.168.1.245 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [dns_cache.c:3260]: dns_srv_sip_resolve(): (failover.test.speakup.nl, 0, 0), srv0, ret=0 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: tm [uac.c:150]: dlg2hash(): DEBUG: dlg2hash: 54501 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: tm [uac.c:351]: t_uac_prepare(): executing event_route[tm:local-request] Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/msg_parser.c:606]: parse_msg(): SIP Request: Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/msg_parser.c:608]: parse_msg(): method: <OPTIONS> Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/msg_parser.c:610]: parse_msg(): uri: sip:failover.test.speakup.nl Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/msg_parser.c:612]: parse_msg(): version: <SIP/2.0> Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/parse_via.c:1254]: parse_via_param(): Found param type 232, <branch> = <z9hG4bK5e4d.47adbbf5000000000000000000000000.0>; state=16 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/parse_via.c:2642]: parse_via(): end of header reached, state=5 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/msg_parser.c:496]: parse_headers(): parse_headers: Via found, flags=2 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/msg_parser.c:498]: parse_headers(): parse_headers: this is the first via Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/parse_addr_spec.c:894]: parse_addr_spec(): end of header reached, state=10 Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/msg_parser.c:173]: get_hdr_field(): DEBUG: get_hdr_field: <To> [22]; uri=[sip:to.example.com] Jun 15 10:00:03 rio UACFailover[18178]: [97B blob data] Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [parser/msg_parser.c:153]: get_hdr_field(): get_hdr_field: cseq <CSeq>: <10> <OPTIONS> Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: pv [pv_core.c:376]: pv_get_xto_attr(): no Tag parameter Jun 15 10:00:03 rio UACFailover[18178]: INFO: <script>: [udp:172.28.4.128:6789] [10 OPTIONS] Request (cid: 6cd531e47cc63e20-18178@172.28.4.128 Branch: -1 ToTag: <null> len:382) To sip:failover.test.speakup.nl via sip:failover.test.speakup.nl Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [usr_avp.c:631]: destroy_avp_list(): destroying list (nil) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [usr_avp.c:631]: destroy_avp_list(): destroying list (nil) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [usr_avp.c:631]: destroy_avp_list(): destroying list (nil) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [usr_avp.c:631]: destroy_avp_list(): destroying list (nil) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [usr_avp.c:631]: destroy_avp_list(): destroying list (nil) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [usr_avp.c:631]: destroy_avp_list(): destroying list (nil) Jun 15 10:00:03 rio UACFailover[18178]: DEBUG: <core> [xavp.c:446]: xavp_destroy_list(): destroying xavp list (nil)
Jun 15 10:00:05 rio UACFailover[18176]: DEBUG: tm [t_reply.c:1230]: t_should_relay_response(): ->>>>>>>>> T_code=0, new_code=408 Jun 15 10:00:05 rio UACFailover[18176]: WARNING: tm [t_reply.c:957]: run_failure_handlers(): Warning: run_failure_handlers: no UAC support (1, 0) Jun 15 10:00:05 rio UACFailover[18176]: DEBUG: tm [t_reply.c:2016]: local_reply(): DEBUG: local_reply: branch=0, save=0, winner=0 Jun 15 10:00:05 rio UACFailover[18176]: DEBUG: tm [t_reply.c:2053]: local_reply(): DEBUG: local transaction completed ```
Sample config: ```python #------------------ # Flags #------------------
debug=3 memdbg=5 mem_summary=5
#fork=no # This option should not be present to enable forking but disable daemonize, also -D commandline parameter is needed log_stderror=no sip_warning=no
listen=172.28.4.128 port=6789 children=2 shm_mem_size=64
log_name="UACFailover"
check_via=no # (cmd. line: -v) dns=no # (cmd. line: -r) rev_dns=no # (cmd. line: -R) dns_use_search_list=no use_dns_failover=yes dns_srv_lb=yes disable_tcp=yes
mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/"
loadmodule "pv.so" loadmodule "tm.so" loadmodule "tmx.so" loadmodule "sl.so" loadmodule "xlog.so" loadmodule "rr.so" loadmodule "uac.so" loadmodule "rtimer.so"
# ----------------------------------------------------------------- # Module settings # -----------------------------------------------------------------
modparam("pv", "varset", "server=s:LOGNAME")
modparam("tm", "auto_inv_100", 0) # Time until provisional response (eg "100 Trying") is received modparam("tm", "fr_timer", 2000) # Time to await final response on INVITE per branch (eg per branch ring time) modparam("tm", "fr_inv_timer", 10000) # Time to await final response on INVITE (eg ring time) modparam("tm", "max_inv_lifetime", 20000) modparam("tm", "restart_fr_on_each_reply", 0) modparam("tm", "failure_reply_mode", 3)
modparam("rtimer", "timer", "name=uac;interval=10;mode=1;") modparam("rtimer", "exec", "timer=uac;route=TIMER")
route { xlog("L_NOTICE", "[$pr:$si:$sp] [$cs $rm] Request. (cid: $ci <$fu> => <$ru> len: $ml)");
drop(); }
event_route[tm:local-request] { xlog("L_INFO", " [$pr:$si:$sp] [$cs $rm] Request (cid: $ci Branch: $T_branch_idx ToTag: $tt len:$ml) To <$ru> via <$du>"); }
onreply_route { xlog("L_INFO", " [$pr:$si:$sp] [$cs $rm] Reply (cid: $ci Branch: $T_branch_idx Status: $rs $rr ToTag: $tt len:$ml)"); }
route[TIMER] { if not $var(done) == 1 { $var(done) = 1; $uac_req(method) = "OPTIONS"; $uac_req(ruri) = "sip:failover.test.speakup.nl"; $uac_req(furi) = "sip:from.example.com"; $uac_req(turi) = "sip:to.example.com"; xlog("L_INFO", "Sending $uac_req(method) request to $uac_req(ruri)"); uac_req_send(); } } ```
--- Reply to this email directly or view it on GitHub: https://github.com/kamailio/kamailio/issues/210