use super::dialog::{DialogInnerRef, DialogState, TerminatedReason, TransactionHandle};
use super::DialogId;
use crate::sip::{Header, Method, StatusCode};
use crate::transaction::transaction::Transaction;
use crate::Result;
use tokio_util::sync::CancellationToken;
#[derive(Clone)]
pub struct ClientSubscriptionDialog {
pub(super) inner: DialogInnerRef,
}
impl ClientSubscriptionDialog {
pub fn id(&self) -> DialogId {
self.inner.id.lock().clone()
}
pub fn state(&self) -> DialogState {
self.inner.state.lock().clone()
}
pub fn cancel_token(&self) -> &CancellationToken {
&self.inner.cancel_token
}
pub async fn subscribe(
&self,
headers: Option<Vec<Header>>,
body: Option<Vec<u8>>,
) -> Result<Option<crate::sip::Response>> {
self.request(Method::Subscribe, headers, body).await
}
pub async fn unsubscribe(&self) -> Result<()> {
self.unsubscribe_with_headers(None).await
}
pub async fn unsubscribe_with_headers(&self, headers: Option<Vec<Header>>) -> Result<()> {
let mut headers = headers.unwrap_or_default();
headers.push(Header::Expires(0.into()));
self.request(Method::Subscribe, Some(headers), None).await?;
self.inner
.transition(DialogState::Terminated(self.id(), TerminatedReason::UacBye))?;
Ok(())
}
pub async fn request(
&self,
method: crate::sip::Method,
headers: Option<Vec<crate::sip::Header>>,
body: Option<Vec<u8>>,
) -> Result<Option<crate::sip::Response>> {
let request = self
.inner
.make_request(method, None, None, None, headers, body)?;
self.inner.do_request(request).await
}
pub async fn refer(
&self,
refer_to: crate::sip::Uri,
headers: Option<Vec<crate::sip::Header>>,
body: Option<Vec<u8>>,
) -> Result<Option<crate::sip::Response>> {
let mut headers = headers.unwrap_or_default();
headers.push(crate::sip::Header::ReferTo(
format!("<{}>", refer_to).into(),
));
self.request(crate::sip::Method::Refer, Some(headers), body)
.await
}
pub async fn message(
&self,
headers: Option<Vec<crate::sip::Header>>,
body: Option<Vec<u8>>,
) -> Result<Option<crate::sip::Response>> {
self.request(crate::sip::Method::Message, headers, body)
.await
}
pub async fn handle(&mut self, tx: &mut Transaction) -> Result<()> {
match tx.original.method {
Method::Notify => {
let (handle, rx) = TransactionHandle::new();
self.inner.transition(DialogState::Notify(
self.id(),
tx.original.clone(),
handle,
))?;
self.inner.process_transaction_handle(tx, rx).await
}
Method::Refer => {
let (handle, rx) = TransactionHandle::new();
self.inner.transition(DialogState::Refer(
self.id(),
tx.original.clone(),
handle,
))?;
self.inner.process_transaction_handle(tx, rx).await
}
Method::Message => {
let (handle, rx) = TransactionHandle::new();
self.inner.transition(DialogState::Message(
self.id(),
tx.original.clone(),
handle,
))?;
self.inner.process_transaction_handle(tx, rx).await
}
_ => Ok(()),
}
}
}
#[derive(Clone)]
pub struct ServerSubscriptionDialog {
pub(super) inner: DialogInnerRef,
}
impl ServerSubscriptionDialog {
pub fn id(&self) -> DialogId {
self.inner.id.lock().clone()
}
pub fn state(&self) -> DialogState {
self.inner.state.lock().clone()
}
pub fn cancel_token(&self) -> &CancellationToken {
&self.inner.cancel_token
}
pub fn accept(&self, headers: Option<Vec<Header>>, body: Option<Vec<u8>>) -> Result<()> {
let resp = self.inner.make_response(
&self.inner.initial_request.lock(),
StatusCode::OK,
headers,
body,
);
use crate::transaction::transaction::TransactionEvent;
self.inner
.tu_sender
.send(TransactionEvent::Respond(resp.clone()))?;
self.inner
.transition(DialogState::Confirmed(self.id(), resp))?;
Ok(())
}
pub async fn notify(
&self,
headers: Option<Vec<Header>>,
body: Option<Vec<u8>>,
) -> Result<Option<crate::sip::Response>> {
if !self.inner.is_confirmed() {
return Ok(None);
}
let request =
self.inner
.make_request(crate::sip::Method::Notify, None, None, None, headers, body)?;
self.inner.do_request(request).await
}
pub async fn unsubscribe(&self) -> Result<()> {
self.unsubscribe_with_headers(None).await
}
pub async fn unsubscribe_with_headers(&self, headers: Option<Vec<Header>>) -> Result<()> {
let mut headers = headers.unwrap_or_default();
headers.push(Header::Expires(0.into()));
self.request(Method::Subscribe, Some(headers), None).await?;
self.inner
.transition(DialogState::Terminated(self.id(), TerminatedReason::UasBye))?;
Ok(())
}
pub async fn request(
&self,
method: crate::sip::Method,
headers: Option<Vec<crate::sip::Header>>,
body: Option<Vec<u8>>,
) -> Result<Option<crate::sip::Response>> {
if !self.inner.is_confirmed() {
return Ok(None);
}
let request = self
.inner
.make_request(method, None, None, None, headers, body)?;
self.inner.do_request(request).await
}
pub async fn refer(
&self,
refer_to: crate::sip::Uri,
headers: Option<Vec<crate::sip::Header>>,
body: Option<Vec<u8>>,
) -> Result<Option<crate::sip::Response>> {
let mut headers = headers.unwrap_or_default();
headers.push(crate::sip::Header::ReferTo(
format!("<{}>", refer_to).into(),
));
self.request(crate::sip::Method::Refer, Some(headers), body)
.await
}
pub async fn message(
&self,
headers: Option<Vec<crate::sip::Header>>,
body: Option<Vec<u8>>,
) -> Result<Option<crate::sip::Response>> {
self.request(crate::sip::Method::Message, headers, body)
.await
}
pub async fn handle(&mut self, tx: &mut Transaction) -> Result<()> {
match tx.original.method {
Method::Subscribe => {
let (handle, rx) = TransactionHandle::new();
self.inner.transition(DialogState::Updated(
self.id(),
tx.original.clone(),
handle,
))?;
self.inner.process_transaction_handle(tx, rx).await
}
Method::Refer => {
let (handle, rx) = TransactionHandle::new();
self.inner.transition(DialogState::Refer(
self.id(),
tx.original.clone(),
handle,
))?;
self.inner.process_transaction_handle(tx, rx).await
}
Method::Message => {
let (handle, rx) = TransactionHandle::new();
self.inner.transition(DialogState::Message(
self.id(),
tx.original.clone(),
handle,
))?;
self.inner.process_transaction_handle(tx, rx).await
}
_ => Ok(()),
}
}
}