use std::sync::Arc;
use rvoip_sip_core::types::Method;
use crate::api::handle::CallId;
use crate::api::headers::{take_staged, BuilderHeaderState, SipRequestOptions};
use crate::api::unified::UnifiedCoordinator;
use crate::errors::Result;
use rvoip_sip_core::types::headers::{HeaderName, HeaderValue, TypedHeader};
pub struct ProvisionalBuilder {
coord: Arc<UnifiedCoordinator>,
call_id: CallId,
code: u16,
sdp: Option<String>,
require_100rel: bool,
state: BuilderHeaderState,
}
impl ProvisionalBuilder {
pub(crate) fn new(coord: Arc<UnifiedCoordinator>, call_id: CallId, code: u16) -> Self {
Self {
coord,
call_id,
code,
sdp: None,
require_100rel: false,
state: BuilderHeaderState::default(),
}
}
pub fn with_sdp(mut self, sdp: impl Into<String>) -> Self {
self.sdp = Some(sdp.into());
self
}
pub fn with_require_100rel(mut self, require: bool) -> Self {
self.require_100rel = require;
self
}
pub async fn send(mut self) -> Result<()> {
let mut extras = take_staged(&mut self.state);
if self.require_100rel {
extras.push(TypedHeader::Other(
HeaderName::Require,
HeaderValue::Raw(b"100rel".to_vec()),
));
}
if extras.is_empty() && (self.code == 183 || self.code == 180) {
return self.coord.send_early_media(&self.call_id, self.sdp).await;
}
self.coord
.dialog_adapter()
.send_response_with_options(&self.call_id, self.code, self.sdp, extras)
.await
}
}
impl SipRequestOptions for ProvisionalBuilder {
fn method(&self) -> Method {
Method::Invite
}
fn header_state_mut(&mut self) -> &mut BuilderHeaderState {
&mut self.state
}
fn header_state(&self) -> &BuilderHeaderState {
&self.state
}
}