rvoip_dialog_core/api/server/sip_methods.rs
1//! Specialized SIP Methods for DialogServer
2//!
3//! This module provides specialized SIP method handling for various dialog operations
4//! including BYE, REFER, NOTIFY, UPDATE, and INFO methods.
5
6use tracing::{debug, info};
7
8use rvoip_sip_core::Method;
9use rvoip_transaction_core::TransactionKey;
10use crate::dialog::DialogId;
11use super::super::{ApiResult, ApiError};
12use super::core::DialogServer;
13
14/// Specialized SIP method implementations for DialogServer
15impl DialogServer {
16 /// Send a BYE request to terminate a dialog
17 ///
18 /// Sends a BYE request within the specified dialog to terminate the call.
19 ///
20 /// # Arguments
21 /// * `dialog_id` - The dialog to send BYE within
22 ///
23 /// # Returns
24 /// Transaction key for tracking the BYE request
25 pub async fn send_bye(&self, dialog_id: &DialogId) -> ApiResult<TransactionKey> {
26 info!("Sending BYE for dialog {}", dialog_id);
27
28 // Send BYE request through dialog manager
29 let transaction_key = self.dialog_manager.send_request(dialog_id, Method::Bye, None).await
30 .map_err(ApiError::from)?;
31
32 // Update statistics - call is ending
33 {
34 let mut stats = self.stats.write().await;
35 stats.active_dialogs = stats.active_dialogs.saturating_sub(1);
36 }
37
38 Ok(transaction_key)
39 }
40
41 /// Send a REFER request for call transfer
42 ///
43 /// Implements call transfer functionality according to RFC 3515.
44 ///
45 /// # Arguments
46 /// * `dialog_id` - The dialog to send REFER within
47 /// * `target_uri` - The URI to transfer the call to (Refer-To header)
48 /// * `refer_body` - Optional REFER request body
49 ///
50 /// # Returns
51 /// Transaction key for tracking the REFER request
52 pub async fn send_refer(
53 &self,
54 dialog_id: &DialogId,
55 target_uri: String,
56 refer_body: Option<String>
57 ) -> ApiResult<TransactionKey> {
58 debug!("Sending REFER for dialog {} to {}", dialog_id, target_uri);
59
60 // Build REFER request body with Refer-To header
61 let body = if let Some(custom_body) = refer_body {
62 Some(custom_body.into_bytes().into())
63 } else {
64 // Use target URI as default body or build proper REFER headers
65 Some(format!("Refer-To: {}", target_uri).into_bytes().into())
66 };
67
68 self.dialog_manager.send_request(dialog_id, Method::Refer, body).await
69 .map_err(ApiError::from)
70 }
71
72 /// Send a NOTIFY request for event notification
73 ///
74 /// Implements event notification according to RFC 6665.
75 ///
76 /// # Arguments
77 /// * `dialog_id` - The dialog to send NOTIFY within
78 /// * `event` - Event type (Event header value)
79 /// * `body` - Optional notification body
80 ///
81 /// # Returns
82 /// Transaction key for tracking the NOTIFY request
83 pub async fn send_notify(
84 &self,
85 dialog_id: &DialogId,
86 event: String,
87 body: Option<String>
88 ) -> ApiResult<TransactionKey> {
89 debug!("Sending NOTIFY for dialog {} with event {}", dialog_id, event);
90
91 let notify_body = body.map(|b| b.into_bytes().into());
92
93 self.dialog_manager.send_request(dialog_id, Method::Notify, notify_body).await
94 .map_err(ApiError::from)
95 }
96
97 /// Send an UPDATE request for session modification
98 ///
99 /// Implements session modification according to RFC 3311.
100 ///
101 /// # Arguments
102 /// * `dialog_id` - The dialog to send UPDATE within
103 /// * `sdp` - Optional SDP for session modification
104 ///
105 /// # Returns
106 /// Transaction key for tracking the UPDATE request
107 pub async fn send_update(
108 &self,
109 dialog_id: &DialogId,
110 sdp: Option<String>
111 ) -> ApiResult<TransactionKey> {
112 debug!("Sending UPDATE for dialog {}", dialog_id);
113
114 let update_body = sdp.map(|s| s.into_bytes().into());
115
116 self.dialog_manager.send_request(dialog_id, Method::Update, update_body).await
117 .map_err(ApiError::from)
118 }
119
120 /// Send an INFO request for application information
121 ///
122 /// Implements application-level information exchange according to RFC 6086.
123 ///
124 /// # Arguments
125 /// * `dialog_id` - The dialog to send INFO within
126 /// * `info_body` - Information payload
127 ///
128 /// # Returns
129 /// Transaction key for tracking the INFO request
130 pub async fn send_info(
131 &self,
132 dialog_id: &DialogId,
133 info_body: String
134 ) -> ApiResult<TransactionKey> {
135 debug!("Sending INFO for dialog {}", dialog_id);
136
137 let body = Some(info_body.into_bytes().into());
138
139 self.dialog_manager.send_request(dialog_id, Method::Info, body).await
140 .map_err(ApiError::from)
141 }
142}