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}