diff --git a/src/dialog/client_dialog.rs b/src/dialog/client_dialog.rs index 588a11e..782cc41 100644 --- a/src/dialog/client_dialog.rs +++ b/src/dialog/client_dialog.rs @@ -471,20 +471,17 @@ impl ClientInviteDialog { /// /// # Parameters /// - /// * `refer_to` - The URI to refer to (Refer-To header value) + /// * `refer_to` - The full Refer-To header value. `Uri` inputs are serialized as ``. /// * `headers` - Optional additional headers /// * `body` - Optional message body pub async fn refer( &self, - refer_to: crate::sip::Uri, + refer_to: impl Into, headers: Option>, body: Option>, ) -> Result> { let mut headers = headers.unwrap_or_default(); - headers.push(crate::sip::Header::Other( - "Refer-To".into(), - format!("<{}>", refer_to), - )); + headers.push(crate::sip::Header::ReferTo(refer_to.into())); self.request(crate::sip::Method::Refer, Some(headers), body) .await } diff --git a/src/dialog/dialog.rs b/src/dialog/dialog.rs index ee591fb..0ed9556 100644 --- a/src/dialog/dialog.rs +++ b/src/dialog/dialog.rs @@ -1429,7 +1429,7 @@ impl Dialog { pub async fn refer( &self, - refer_to: crate::sip::Uri, + refer_to: impl Into, headers: Option>, body: Option>, ) -> Result> { diff --git a/src/dialog/publication.rs b/src/dialog/publication.rs index de3d93b..f1800d2 100644 --- a/src/dialog/publication.rs +++ b/src/dialog/publication.rs @@ -96,14 +96,12 @@ impl ClientPublicationDialog { pub async fn refer( &self, - refer_to: crate::sip::Uri, + refer_to: impl Into, headers: Option>, body: Option>, ) -> Result> { let mut headers = headers.unwrap_or_default(); - headers.push(crate::sip::Header::ReferTo( - format!("<{}>", refer_to).into(), - )); + headers.push(crate::sip::Header::ReferTo(refer_to.into())); self.request(crate::sip::Method::Refer, Some(headers), body) .await } @@ -229,14 +227,12 @@ impl ServerPublicationDialog { pub async fn refer( &self, - refer_to: crate::sip::Uri, + refer_to: impl Into, headers: Option>, body: Option>, ) -> Result> { let mut headers = headers.unwrap_or_default(); - headers.push(crate::sip::Header::ReferTo( - format!("<{}>", refer_to).into(), - )); + headers.push(crate::sip::Header::ReferTo(refer_to.into())); self.request(crate::sip::Method::Refer, Some(headers), body) .await } diff --git a/src/dialog/server_dialog.rs b/src/dialog/server_dialog.rs index a7c7dff..9761dd7 100644 --- a/src/dialog/server_dialog.rs +++ b/src/dialog/server_dialog.rs @@ -552,15 +552,12 @@ impl ServerInviteDialog { /// Send a REFER request pub async fn refer( &self, - refer_to: crate::sip::Uri, + refer_to: impl Into, headers: Option>, body: Option>, ) -> Result> { let mut headers = headers.unwrap_or_default(); - headers.push(crate::sip::Header::Other( - "Refer-To".into(), - format!("<{}>", refer_to), - )); + headers.push(crate::sip::Header::ReferTo(refer_to.into())); self.request(crate::sip::Method::Refer, Some(headers), body) .await } diff --git a/src/dialog/subscription.rs b/src/dialog/subscription.rs index 998a8bf..d992b46 100644 --- a/src/dialog/subscription.rs +++ b/src/dialog/subscription.rs @@ -58,14 +58,12 @@ impl ClientSubscriptionDialog { pub async fn refer( &self, - refer_to: crate::sip::Uri, + refer_to: impl Into, headers: Option>, body: Option>, ) -> Result> { let mut headers = headers.unwrap_or_default(); - headers.push(crate::sip::Header::ReferTo( - format!("<{}>", refer_to).into(), - )); + headers.push(crate::sip::Header::ReferTo(refer_to.into())); self.request(crate::sip::Method::Refer, Some(headers), body) .await } @@ -193,14 +191,12 @@ impl ServerSubscriptionDialog { pub async fn refer( &self, - refer_to: crate::sip::Uri, + refer_to: impl Into, headers: Option>, body: Option>, ) -> Result> { let mut headers = headers.unwrap_or_default(); - headers.push(crate::sip::Header::ReferTo( - format!("<{}>", refer_to).into(), - )); + headers.push(crate::sip::Header::ReferTo(refer_to.into())); self.request(crate::sip::Method::Refer, Some(headers), body) .await } diff --git a/src/dialog/tests/mod.rs b/src/dialog/tests/mod.rs index 73e646f..bdec1f8 100644 --- a/src/dialog/tests/mod.rs +++ b/src/dialog/tests/mod.rs @@ -3,5 +3,6 @@ mod test_client_dialog; mod test_dialog_layer; mod test_dialog_states; mod test_prack; +mod test_refer; mod test_server_dialog; mod test_sub_pub; diff --git a/src/dialog/tests/test_refer.rs b/src/dialog/tests/test_refer.rs new file mode 100644 index 0000000..84993e2 --- /dev/null +++ b/src/dialog/tests/test_refer.rs @@ -0,0 +1,54 @@ +use std::sync::Arc; + +use tokio::sync::mpsc::unbounded_channel; + +use crate::dialog::{client_dialog::ClientInviteDialog, dialog::DialogInner, DialogId}; +use crate::sip::{ReferTo, Uri}; +use crate::transaction::key::TransactionRole; + +use super::test_dialog_states::{create_invite_request, create_test_endpoint}; + +#[test] +fn test_refer_to_from_uri_preserves_existing_uri_behavior() -> crate::Result<()> { + let refer_to = ReferTo::from(Uri::try_from("sip:carol@restsend.com")?); + assert_eq!(refer_to.value(), ""); + Ok(()) +} + +#[tokio::test] +async fn test_client_dialog_refer_accepts_name_addr_values() -> crate::Result<()> { + let endpoint = create_test_endpoint().await?; + let (state_sender, _) = unbounded_channel(); + + let dialog_id = DialogId { + call_id: "refer-name-addr".to_string(), + local_tag: "alice-tag".to_string(), + remote_tag: "bob-tag".to_string(), + }; + + let invite_req = create_invite_request("alice-tag", "bob-tag", "refer-name-addr"); + let (tu_sender, _tu_receiver) = unbounded_channel(); + + let dialog_inner = DialogInner::new( + TransactionRole::Client, + dialog_id, + invite_req, + endpoint.inner.clone(), + state_sender, + None, + Some(Uri::try_from("sip:alice@alice.example.com:5060")?), + tu_sender, + )?; + + let client_dialog = ClientInviteDialog { + inner: Arc::new(dialog_inner), + }; + + std::mem::drop(client_dialog.refer( + "\"Display Name\" ", + None, + None, + )); + + Ok(()) +} diff --git a/src/sip/headers/untyped.rs b/src/sip/headers/untyped.rs index b1a7ab2..ae13cd1 100644 --- a/src/sip/headers/untyped.rs +++ b/src/sip/headers/untyped.rs @@ -173,6 +173,12 @@ untyped_header!(Privacy, "Privacy", Header::Privacy); untyped_header!(Path, "Path", Header::Path); untyped_header!(Identity, "Identity", Header::Identity); +impl std::convert::From for ReferTo { + fn from(uri: crate::sip::Uri) -> Self { + Self(format!("<{}>", uri)) + } +} + #[derive(Debug, PartialEq, Eq, Clone, Default)] pub struct CallId(pub String); impl CallId {