From 2826f12e997f9a37ba6221913e1d55a73c459994 Mon Sep 17 00:00:00 2001 From: Venky Date: Sun, 22 Mar 2026 14:10:16 -0700 Subject: [PATCH] fix: detect lr parameter with value as loose routing in ACK Some SIP proxies (e.g., Kamailio) send Record-Route with ;lr=on instead of bare ;lr. The rsip crate parses ;lr=on as Param::Other("lr", Some("on")) since Param::Lr only matches the valueless form (;lr with no =value). This causes make_ack to fall into the strict routing branch, putting the Record-Route URI as the Request-URI and the Contact as the Route header. The ACK is then sent to the Contact address (often an unreachable internal IP behind a load balancer) instead of through the Record-Route proxy. The remote side never receives the ACK and terminates the call with "ACK Timeout". The fix checks for both Param::Lr and Param::Other where the name is "lr" (case-insensitive), matching ;lr, ;lr=on, ;lr=true, etc. as loose routing per RFC 3261 Section 16.6. --- src/transaction/message.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transaction/message.rs b/src/transaction/message.rs index 6562e46..4f1a93c 100644 --- a/src/transaction/message.rs +++ b/src/transaction/message.rs @@ -302,12 +302,12 @@ impl EndpointInner { Vec::new() } [head, rest @ ..] => { - // loose rooting + // loose routing — also match ;lr= (e.g. ;lr=on from Kamailio/Plivo) if head .uri .params .iter() - .any(|param| matches!(param, rsip::Param::Lr)) + .any(|param| matches!(param, rsip::Param::Lr) || matches!(param, rsip::Param::Other(name, _) if name.to_string().eq_ignore_ascii_case("lr"))) { request_uri = remote_target_uri; route_set