use super::create_test_endpoint;
use crate::sip::{headers::*, Response, SipMessage, StatusCode};
use crate::transaction::{
key::{TransactionKey, TransactionRole},
transaction::{Transaction, TransactionEvent},
TransactionState,
};
#[tokio::test]
async fn test_multiple_provisional_responses() -> crate::Result<()> {
let endpoint = create_test_endpoint(Some("127.0.0.1:0")).await?;
let invite_req = crate::sip::Request {
method: crate::sip::Method::Invite,
uri: crate::sip::Uri::try_from("sip:test.example.com:5060").unwrap(),
headers: vec![
Via::new("SIP/2.0/UDP test.example.com:5060;branch=z9hG4bKnashds").into(),
CSeq::new("1 INVITE").into(),
From::new("Alice <sip:alice@example.com>;tag=1928301774").into(),
To::new("Bob <sip:bob@example.com>").into(),
CallId::new("a84b4c76e66710@pc33.atlanta.com").into(),
MaxForwards::new("70").into(),
]
.into(),
version: crate::sip::Version::V2,
body: Default::default(),
};
let key = TransactionKey::from_request(&invite_req, TransactionRole::Client)?;
let mut tx = Transaction::new_client(
key.clone(),
invite_req.clone(),
endpoint.inner.clone(),
None,
);
let resp1 = Response {
version: crate::sip::Version::V2,
status_code: StatusCode::SessionProgress, headers: vec![
Via::new("SIP/2.0/UDP test.example.com:5060;branch=z9hG4bKnashds").into(),
CSeq::new("1 INVITE").into(),
From::new("Alice <sip:alice@example.com>;tag=1928301774").into(),
To::new("Bob <sip:bob@example.com>;tag=asdf").into(),
CallId::new("a84b4c76e66710@pc33.atlanta.com").into(),
]
.into(),
body: vec![],
};
tx.tu_sender
.send(TransactionEvent::Received(
SipMessage::Response(resp1.clone()),
None,
))
.unwrap();
let received1 = tx.receive().await.expect("Should receive first 183");
if let SipMessage::Response(r) = received1 {
assert_eq!(r.status_code, StatusCode::SessionProgress);
} else {
panic!("Expected response");
}
assert_eq!(tx.state, TransactionState::Proceeding);
assert!(
tx.last_ack.is_none(),
"Should not send ACK for provisional response"
);
let resp2 = Response {
version: crate::sip::Version::V2,
status_code: StatusCode::SessionProgress, headers: vec![
Via::new("SIP/2.0/UDP test.example.com:5060;branch=z9hG4bKnashds").into(),
CSeq::new("1 INVITE").into(),
From::new("Alice <sip:alice@example.com>;tag=1928301774").into(),
To::new("Bob <sip:bob@example.com>;tag=asdf").into(),
CallId::new("a84b4c76e66710@pc33.atlanta.com").into(),
].into(),
body: b"v=0\r\no=- 2890844526 2890844526 IN IP4 127.0.0.1\r\ns=-\r\nc=IN IP4 127.0.0.1\r\nt=0 0\r\nm=audio 49170 RTP/AVP 0\r\na=rtpmap:0 PCMU/8000\r\n".to_vec(),
};
tx.tu_sender
.send(TransactionEvent::Received(
SipMessage::Response(resp2.clone()),
None,
))
.unwrap();
let received2 = tx
.receive()
.await
.expect("Should receive second 183 with SDP");
if let SipMessage::Response(r) = received2 {
assert_eq!(r.status_code, StatusCode::SessionProgress);
assert_eq!(r.body, resp2.body);
} else {
panic!("Expected response");
}
assert_eq!(tx.state, TransactionState::Proceeding);
assert!(
tx.last_ack.is_none(),
"Should not send ACK for provisional response"
);
tx.tu_sender
.send(TransactionEvent::Received(
SipMessage::Response(resp2.clone()),
None,
))
.unwrap();
let result = tokio::time::timeout(std::time::Duration::from_millis(100), tx.receive()).await;
assert!(result.is_err(), "Should have timed out (response ignored)");
Ok(())
}