use super::test_dialog_states::{create_invite_request, create_test_endpoint};
use crate::dialog::{dialog::DialogInner, server_dialog::ServerInviteDialog, DialogId};
use crate::sip::headers::*;
use crate::sip::{Header, Method, Request, SipMessage, StatusCode};
use crate::transaction::{
key::{TransactionKey, TransactionRole},
transaction::Transaction,
};
use crate::transport::{
channel::ChannelConnection, connection::TransportEvent, SipAddr, SipConnection,
};
use std::convert::TryFrom;
use std::sync::Arc;
use tokio::sync::mpsc::unbounded_channel;
use tokio::time::{timeout, Duration};
#[tokio::test]
async fn server_dialog_handles_prack_request() -> crate::Result<()> {
let endpoint = create_test_endpoint().await?;
let (state_sender, _state_receiver) = unbounded_channel();
let (tu_sender, _tu_receiver) = unbounded_channel();
let dialog_id = DialogId {
call_id: "test-call-prack".to_string(),
local_tag: "bob-tag".to_string(),
remote_tag: "alice-tag".to_string(),
};
let invite_req = create_invite_request(&dialog_id.remote_tag, "", &dialog_id.call_id);
let dialog_inner = DialogInner::new(
TransactionRole::Server,
dialog_id.clone(),
invite_req,
endpoint.inner.clone(),
state_sender,
None,
Some(crate::sip::Uri::try_from("sip:bob@bob.example.com:5060")?),
tu_sender,
)?;
let mut server_dialog = ServerInviteDialog {
inner: Arc::new(dialog_inner),
};
let prack_request = Request {
method: Method::PRack,
uri: crate::sip::Uri::try_from("sip:bob@example.com:5060")?,
headers: vec![
Via::new("SIP/2.0/UDP 198.51.100.1:5060;branch=z9hG4bKprack01").into(),
CSeq::new("2 PRACK").into(),
From::new(&format!(
"Alice <sip:alice@example.com>;tag={}",
dialog_id.remote_tag
))
.into(),
To::new(&format!(
"Bob <sip:bob@example.com>;tag={}",
dialog_id.local_tag
))
.into(),
CallId::new(&dialog_id.call_id).into(),
Header::Other("RAck".into(), "1 1 INVITE".into()),
Contact::new("<sip:alice@198.51.100.1:5060>").into(),
MaxForwards::new("70").into(),
Header::ContentLength((0u32).into()),
]
.into(),
version: crate::sip::Version::V2,
body: vec![],
};
let key = TransactionKey::from_request(&prack_request, TransactionRole::Server)?;
let (_, incoming_rx) = unbounded_channel();
let (transport_tx, mut transport_rx) = unbounded_channel();
let sip_addr: SipAddr = crate::sip::HostWithPort::try_from("127.0.0.1:5060")?.into();
let channel =
ChannelConnection::create_connection(incoming_rx, transport_tx, sip_addr.clone(), None)
.await?;
let connection = SipConnection::Channel(channel);
let mut tx =
Transaction::new_server(key, prack_request, endpoint.inner.clone(), Some(connection));
tx.destination = Some(sip_addr.clone());
server_dialog.handle(&mut tx).await?;
let event = timeout(Duration::from_secs(1), transport_rx.recv())
.await
.expect("timeout waiting for PRACK response")
.expect("transport event");
match event {
TransportEvent::Incoming(SipMessage::Response(resp), _, _) => {
assert_eq!(resp.status_code, StatusCode::OK);
}
other => panic!("unexpected transport event: {other:?}"),
}
Ok(())
}