pub struct DialogLayer {
pub endpoint: EndpointInnerRef,
pub inner: DialogLayerInnerRef,
}Expand description
SIP Dialog Layer
DialogLayer provides high-level dialog management functionality for SIP
applications. It handles dialog creation, lookup, and lifecycle management
while coordinating with the transaction layer.
§Key Responsibilities
- Creating and managing SIP dialogs
- Dialog identification and routing
- Dialog state tracking and cleanup
- Integration with transaction layer
- Sequence number management
§Usage Patterns
§Server-side Dialog Creation
use rsipstack::dialog::dialog_layer::DialogLayer;
use rsipstack::transaction::endpoint::EndpointInner;
use std::sync::Arc;
// Create dialog layer
let dialog_layer = DialogLayer::new(endpoint.clone());
// Handle incoming INVITE transaction
let server_dialog = dialog_layer.get_or_create_server_invite(
&transaction,
state_sender,
credential,
contact_uri
)?;
// Accept the call
server_dialog.accept(None, None)?;§Dialog Lookup and Routing
// Find existing dialog for incoming request
if let Some(mut dialog) = dialog_layer.match_dialog(&transaction) {
// Route to existing dialog
dialog.handle(&mut transaction).await?;
} else {
// Create new dialog or reject
}§Dialog Cleanup
// Remove completed dialog
dialog_layer.remove_dialog(&dialog_id);§Dialog Lifecycle
- Creation - Dialog created from incoming INVITE or outgoing request
- Early State - Dialog exists but not yet confirmed
- Confirmed - Dialog established with 2xx response and ACK
- Active - Dialog can exchange in-dialog requests
- Terminated - Dialog ended with BYE or error
- Cleanup - Dialog removed from layer
§Thread Safety
DialogLayer is thread-safe and can be shared across multiple tasks:
- Dialog lookup operations are concurrent
- Dialog creation is serialized when needed
- Automatic cleanup prevents memory leaks
Fields§
§endpoint: EndpointInnerRef§inner: DialogLayerInnerRefImplementations§
Source§impl DialogLayer
impl DialogLayer
pub fn new(endpoint: EndpointInnerRef) -> Self
pub fn get_or_create_server_invite( &self, tx: &Transaction, state_sender: DialogStateSender, credential: Option<Credential>, local_contact: Option<Uri>, ) -> Result<ServerInviteDialog>
pub fn get_or_create_server_subscription( &self, tx: &Transaction, state_sender: DialogStateSender, credential: Option<Credential>, local_contact: Option<Uri>, ) -> Result<ServerSubscriptionDialog>
pub fn get_or_create_server_publication( &self, tx: &Transaction, state_sender: DialogStateSender, credential: Option<Credential>, local_contact: Option<Uri>, ) -> Result<ServerPublicationDialog>
pub fn get_or_create_client_publication( &self, call_id: String, from_tag: String, to_tag: String, initial_request: Request, state_sender: DialogStateSender, credential: Option<Credential>, local_contact: Option<Uri>, ) -> Result<ClientPublicationDialog>
pub fn get_or_create_client_subscription( &self, call_id: String, from_tag: String, to_tag: String, initial_request: Request, state_sender: DialogStateSender, credential: Option<Credential>, local_contact: Option<Uri>, ) -> Result<ClientSubscriptionDialog>
pub fn increment_last_seq(&self) -> u32
pub fn len(&self) -> usize
pub fn all_dialog_ids(&self) -> Vec<String>
pub fn get_dialog(&self, id: &DialogId) -> Option<Dialog>
pub fn get_dialog_with(&self, id: &String) -> Option<Dialog>
Sourcepub fn get_client_dialog_by_call_id(
&self,
call_id: &str,
) -> Vec<ClientInviteDialog>
pub fn get_client_dialog_by_call_id( &self, call_id: &str, ) -> Vec<ClientInviteDialog>
Returns all client-side INVITE dialogs (UAC) that share the given Call-ID.
In a forking scenario, multiple client dialogs can exist for the same
Call-ID (same local From-tag, different remote To-tags). This helper
scans the internal dialog registry and returns all ClientInviteDialog
instances whose DialogId.call_id equals the provided call_id.
The returned vector may be empty if no matching client dialogs are found.
Sourcepub fn restore_from_snapshot(
&self,
snapshot: DialogSnapshot,
state_sender: DialogStateSender,
) -> Result<bool>
pub fn restore_from_snapshot( &self, snapshot: DialogSnapshot, state_sender: DialogStateSender, ) -> Result<bool>
Restore a dialog from persisted snapshot.
Restores only CONFIRMED snapshots. Non-confirmed snapshots are ignored (warn inside try_restore_from_snapshot).
Returns:
- Ok(true) => restored and inserted
- Ok(false) => skipped (already exists or not confirmed)
pub fn remove_dialog(&self, id: &DialogId)
pub fn match_dialog(&self, tx: &Transaction) -> Option<Dialog>
pub fn new_dialog_state_channel( &self, ) -> (DialogStateSender, DialogStateReceiver)
pub fn build_local_contact( &self, username: Option<String>, params: Option<Vec<Param>>, ) -> Result<Uri>
Source§impl DialogLayer
impl DialogLayer
Sourcepub fn make_invite_request(&self, opt: &InviteOption) -> Result<Request>
pub fn make_invite_request(&self, opt: &InviteOption) -> Result<Request>
Create an INVITE request from options
Constructs a properly formatted SIP INVITE request based on the provided options. This method handles all the required headers and parameters according to RFC 3261.
§Parameters
opt- INVITE options containing all necessary parameters
§Returns
Ok(Request)- Properly formatted INVITE requestErr(Error)- Failed to create request
§Generated Headers
The method automatically generates:
- Via header with branch parameter
- From header with tag parameter
- To header (without tag for initial request)
- Contact header
- Content-Type header
- CSeq header with incremented sequence number
- Call-ID header
§Examples
let request = dialog_layer.make_invite_request(&invite_option)?;
println!("Created INVITE to: {}", request.uri);Sourcepub async fn do_invite(
&self,
opt: InviteOption,
state_sender: DialogStateSender,
) -> Result<(ClientInviteDialog, Option<Response>)>
pub async fn do_invite( &self, opt: InviteOption, state_sender: DialogStateSender, ) -> Result<(ClientInviteDialog, Option<Response>)>
Send an INVITE request and create a client dialog
This is the main method for initiating outbound calls. It creates an INVITE request, sends it, and manages the resulting dialog. The method handles the complete INVITE transaction including authentication challenges and response processing.
§Parameters
opt- INVITE options containing all call parametersstate_sender- Channel for receiving dialog state updates
§Returns
Ok((ClientInviteDialog, Option<Response>))- Created dialog and final responseErr(Error)- Failed to send INVITE or process responses
§Call Flow
- Creates INVITE request from options
- Creates client dialog and transaction
- Sends INVITE request
- Processes responses (1xx, 2xx, 3xx-6xx)
- Handles authentication challenges if needed
- Returns established dialog and final response
§Examples
§Basic Call Setup
let (dialog, response) = dialog_layer.do_invite(invite_option, state_sender).await?;
if let Some(resp) = response {
match resp.status_code {
rsip::StatusCode::OK => {
println!("Call answered!");
// Process SDP answer in resp.body
},
rsip::StatusCode::BusyHere => {
println!("Called party is busy");
},
_ => {
println!("Call failed: {}", resp.status_code);
}
}
}§Monitoring Dialog State
let (state_tx, mut state_rx) = tokio::sync::mpsc::unbounded_channel();
let (dialog, response) = dialog_layer.do_invite(invite_option, state_tx).await?;
// Monitor dialog state changes
tokio::spawn(async move {
while let Some(state) = state_rx.recv().await {
match state {
DialogState::Early(_, resp) => {
println!("Ringing: {}", resp.status_code);
},
DialogState::Confirmed(_,_) => {
println!("Call established");
},
DialogState::Terminated(_, code) => {
println!("Call ended: {:?}", code);
break;
},
_ => {}
}
}
});§Error Handling
The method can fail for various reasons:
- Network connectivity issues
- Authentication failures
- Invalid SIP URIs or headers
- Transaction timeouts
- Protocol violations
§Authentication
If credentials are provided in the options, the method will automatically handle 401/407 authentication challenges by resending the request with proper authentication headers.
Sourcepub fn do_invite_async(
self: &Arc<Self>,
opt: InviteOption,
state_sender: DialogStateSender,
) -> Result<(ClientInviteDialog, JoinHandle<InviteAsyncResult>)>
pub fn do_invite_async( self: &Arc<Self>, opt: InviteOption, state_sender: DialogStateSender, ) -> Result<(ClientInviteDialog, JoinHandle<InviteAsyncResult>)>
Registers the dialog under an early dialog ID while the INVITE is in progress. Once completed, the early entry is removed and, on 2xx response, the dialog is re-registered under the confirmed dialog ID. Returns a JoinHandle resolving to the final dialog ID and response.
pub fn create_client_invite_dialog( &self, opt: InviteOption, state_sender: DialogStateSender, ) -> Result<(ClientInviteDialog, Transaction)>
Auto Trait Implementations§
impl Freeze for DialogLayer
impl !RefUnwindSafe for DialogLayer
impl Send for DialogLayer
impl Sync for DialogLayer
impl Unpin for DialogLayer
impl !UnwindSafe for DialogLayer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> PipeAsRef for T
impl<T> PipeAsRef for T
Source§impl<T> PipeBorrow for T
impl<T> PipeBorrow for T
Source§impl<T> PipeDeref for T
impl<T> PipeDeref for T
Source§impl<T> PipeRef for T
impl<T> PipeRef for T
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&Self) -> R,
fn tap<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&Self) -> R,
Source§fn tap_dbg<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&Self) -> R,
fn tap_dbg<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&Self) -> R,
tap in debug builds, and does nothing in release builds.Source§fn tap_mut<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&mut Self) -> R,
fn tap_mut<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&mut Self) -> R,
Source§fn tap_mut_dbg<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&mut Self) -> R,
fn tap_mut_dbg<F, R>(self, func: F) -> Selfwhere
F: FnOnce(&mut Self) -> R,
tap_mut in debug builds, and does nothing in release builds.Source§impl<T, U> TapAsRef<U> for Twhere
U: ?Sized,
impl<T, U> TapAsRef<U> for Twhere
U: ?Sized,
Source§fn tap_ref<F, R>(self, func: F) -> Self
fn tap_ref<F, R>(self, func: F) -> Self
Source§fn tap_ref_dbg<F, R>(self, func: F) -> Self
fn tap_ref_dbg<F, R>(self, func: F) -> Self
tap_ref in debug builds, and does nothing in release builds.Source§fn tap_ref_mut<F, R>(self, func: F) -> Self
fn tap_ref_mut<F, R>(self, func: F) -> Self
Source§impl<T, U> TapBorrow<U> for Twhere
U: ?Sized,
impl<T, U> TapBorrow<U> for Twhere
U: ?Sized,
Source§fn tap_borrow<F, R>(self, func: F) -> Self
fn tap_borrow<F, R>(self, func: F) -> Self
Source§fn tap_borrow_dbg<F, R>(self, func: F) -> Self
fn tap_borrow_dbg<F, R>(self, func: F) -> Self
tap_borrow in debug builds, and does nothing in release builds.Source§fn tap_borrow_mut<F, R>(self, func: F) -> Self
fn tap_borrow_mut<F, R>(self, func: F) -> Self
Source§impl<T> TapDeref for T
impl<T> TapDeref for T
Source§fn tap_deref_dbg<F, R>(self, func: F) -> Self
fn tap_deref_dbg<F, R>(self, func: F) -> Self
tap_deref in debug builds, and does nothing in release builds.Source§fn tap_deref_mut<F, R>(self, func: F) -> Self
fn tap_deref_mut<F, R>(self, func: F) -> Self
self for modification.