Skip to content

Commit c8ef123

Browse files
committed
fix: enhance loose routing handling in SIP headers and URI parsing #110
1 parent dde8468 commit c8ef123

6 files changed

Lines changed: 52 additions & 12 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rsipstack"
3-
version = "0.5.1"
3+
version = "0.5.2"
44
edition = "2021"
55
description = "SIP Stack Rust library for building SIP applications"
66
license = "MIT"

src/sip/headers/typed/record_route.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::parse_helpers::parse_display_uri_params_str;
2-
use crate::sip::{uri::Param, Error, Header, Uri};
2+
use crate::sip::{uri::Param, uri::ParamsExt, Error, Header, Uri};
33

44
#[derive(Debug, PartialEq, Eq, Clone)]
55
pub struct RecordRoute {
@@ -62,7 +62,7 @@ impl RecordRoute {
6262
}
6363

6464
pub fn has_lr(&self) -> bool {
65-
self.uri.params.iter().any(|p| matches!(p, Param::Lr))
65+
self.uri.has_lr()
6666
}
6767
}
6868

@@ -145,6 +145,7 @@ mod tests {
145145

146146
#[test]
147147
fn record_route_with_transport() {
148+
use crate::sip::Param;
148149
use crate::sip::Transport;
149150
let rr = RecordRoute::parse("<sip:proxy.restsend.com;transport=tcp;lr>").unwrap();
150151
assert!(rr.has_lr());
@@ -154,4 +155,11 @@ mod tests {
154155
.iter()
155156
.any(|p| matches!(p, Param::Transport(Transport::Tcp))));
156157
}
158+
159+
#[test]
160+
fn record_route_lr_on_is_treated_as_loose_route() {
161+
let rr = RecordRoute::parse("<sip:proxy.restsend.com;lr=on>").unwrap();
162+
assert!(rr.has_lr());
163+
assert_eq!(rr.uri.to_string(), "sip:proxy.restsend.com;lr=on");
164+
}
157165
}

src/sip/headers/typed/route.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::parse_helpers::parse_display_uri_params_str;
2-
use crate::sip::{uri::Param, Error, Header, Uri};
2+
use crate::sip::{uri::Param, uri::ParamsExt, Error, Header, Uri};
33

44
#[derive(Debug, PartialEq, Eq, Clone)]
55
pub struct Route {
@@ -62,7 +62,7 @@ impl Route {
6262
}
6363

6464
pub fn has_lr(&self) -> bool {
65-
self.uri.params.iter().any(|p| matches!(p, Param::Lr))
65+
self.uri.has_lr()
6666
}
6767

6868
pub fn has_ob(&self) -> bool {
@@ -182,6 +182,7 @@ mod tests {
182182

183183
#[test]
184184
fn route_with_transport_param() {
185+
use crate::sip::uri::Param;
185186
use crate::sip::Transport;
186187
let r = Route::parse("<sip:proxy.restsend.com;transport=tcp;lr>").unwrap();
187188
assert!(r.has_lr());
@@ -191,4 +192,11 @@ mod tests {
191192
.iter()
192193
.any(|p| matches!(p, Param::Transport(Transport::Tcp))));
193194
}
195+
196+
#[test]
197+
fn route_lr_on_is_treated_as_loose_route() {
198+
let r = Route::parse("<sip:proxy.restsend.com;lr=on>").unwrap();
199+
assert!(r.has_lr());
200+
assert_eq!(r.uri.to_string(), "sip:proxy.restsend.com;lr=on");
201+
}
194202
}

src/sip/uri.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,12 @@ pub trait ParamsExt {
668668
})
669669
}
670670
fn has_lr(&self) -> bool {
671-
self.params().iter().any(|p| matches!(p, Param::Lr))
671+
self.params().iter().any(|p| {
672+
matches!(p, Param::Lr)
673+
|| matches!(p, Param::Other(name, Some(value))
674+
if name.value().eq_ignore_ascii_case("lr")
675+
&& value.value().eq_ignore_ascii_case("on"))
676+
})
672677
}
673678
fn expires(&self) -> Option<&str> {
674679
self.params().iter().find_map(|p| {
@@ -826,7 +831,7 @@ impl ParamsExt for Uri {
826831

827832
#[cfg(test)]
828833
mod tests {
829-
use super::{parse_uri, Host, Param, Scheme};
834+
use super::{parse_uri, Host, Param, ParamsExt, Scheme};
830835

831836
#[test]
832837
fn uri_param_value_keeps_colons_and_following_params() {
@@ -899,6 +904,13 @@ mod tests {
899904
assert_eq!(uri.to_string(), "sip:proxy.restsend.com;lr");
900905
}
901906

907+
#[test]
908+
fn uri_lr_on_is_treated_as_loose_route() {
909+
let uri = parse_uri("sip:proxy.restsend.com;lr=on").unwrap();
910+
assert!(uri.has_lr());
911+
assert_eq!(uri.to_string(), "sip:proxy.restsend.com;lr=on");
912+
}
913+
902914
#[test]
903915
fn uri_sips_scheme() {
904916
let uri = parse_uri("sips:alice@restsend.com").unwrap();

src/transaction/message.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::{endpoint::EndpointInner, make_call_id};
22
use crate::sip::{
33
prelude::{HeadersExt, ToTypedHeader},
44
typed::Route as TypedRoute,
5+
uri::ParamsExt,
56
Error, Header, Request, Response, StatusCode, UriWithParams,
67
};
78
use crate::sip::{CallId, Method};
@@ -297,11 +298,7 @@ impl EndpointInner {
297298
}
298299
[head, rest @ ..] => {
299300
// loose routing
300-
if head
301-
.params
302-
.iter()
303-
.any(|param| matches!(param, crate::sip::Param::Lr))
304-
{
301+
if head.has_lr() {
305302
request_uri = remote_target_uri;
306303
route_set
307304
} else {

src/transaction/tests/test_client.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ Content-Length: 0\r\n\r\n";
248248
let invite = make_invite_request("sip:bob@example.com")?;
249249
let ack = endpoint.inner.make_ack(&invite, &response)?;
250250

251+
let expected_uri = Uri::try_from("sip:uas@192.0.2.55:5080")?;
252+
assert_eq!(
253+
ack.uri, expected_uri,
254+
"lr=on must be treated as loose routing so ACK targets Contact",
255+
);
256+
251257
let routes: Vec<String> = ack
252258
.headers
253259
.iter()
@@ -264,6 +270,15 @@ Content-Length: 0\r\n\r\n";
264270
"ACK Route headers must preserve du parameter values with colons and keep following params"
265271
);
266272

273+
assert_eq!(
274+
routes,
275+
vec![
276+
"<sip:4.5.6.7:32222;lr=on;ftag=d4nwJ0jF>".to_string(),
277+
"<sip:2.2.2.2;lr=on;ftag=d4nwJ0jF;du=sip:1.2.3.4:5060;did=893.d6d1>".to_string(),
278+
],
279+
"lr=on route set must be handled as loose routing and keep reversed Record-Route order",
280+
);
281+
267282
Ok(())
268283
}
269284

0 commit comments

Comments
 (0)