rvoip_dialog_core/api/server/
mod.rs

1//! Dialog Server API
2//!
3//! This module provides a comprehensive server interface for SIP dialog management,
4//! designed for building robust SIP servers, proxies, and application servers that
5//! handle incoming calls, dialog state management, and advanced SIP operations.
6//!
7//! ## Overview
8//!
9//! The DialogServer is the primary interface for server-side SIP operations, providing
10//! a modular, scalable architecture that handles the complexities of SIP dialog management
11//! while offering powerful features for call handling, media coordination, and protocol
12//! extensions.
13//!
14//! ### Key Features
15//!
16//! - **Call Handling**: Accept, reject, and manage incoming calls with full control
17//! - **Dialog Management**: Complete SIP dialog lifecycle for server scenarios
18//! - **Session Integration**: Built-in coordination with session-core for media management
19//! - **Request/Response Handling**: Process incoming requests and generate compliant responses
20//! - **Auto-Response Modes**: Automatic handling of OPTIONS, REGISTER, and other methods
21//! - **Statistics & Monitoring**: Real-time metrics and performance tracking
22//! - **Modular Architecture**: Clean separation of concerns across focused submodules
23//!
24//! ## Architecture Overview
25//!
26//! The DialogServer is organized into focused submodules for maintainability:
27//!
28//! ```text
29//! ┌─────────────────────────────────────────┐
30//! │             DialogServer                │
31//! ├─────────────────────────────────────────┤
32//! │ Core           │ Server struct & config │  ← [`core`]
33//! │ Call Ops       │ Call lifecycle mgmt    │  ← [`call_operations`]
34//! │ Dialog Ops     │ Dialog management      │  ← [`dialog_operations`]
35//! │ Response       │ Response building      │  ← [`response_builder`]
36//! │ SIP Methods    │ Specialized handlers   │  ← [`sip_methods`]
37//! ├─────────────────────────────────────────┤
38//! │         DialogManager (shared)          │
39//! ├─────────────────────────────────────────┤
40//! │       TransactionManager                │
41//! ├─────────────────────────────────────────┤
42//! │        TransportManager                 │
43//! └─────────────────────────────────────────┘
44//! ```
45//!
46//! ## Quick Start
47//!
48//! ### Basic SIP Server
49//!
50//! ```rust,no_run
51//! use rvoip_dialog_core::api::{DialogServer, DialogApi, ServerConfig};
52//! use rvoip_dialog_core::events::SessionCoordinationEvent;
53//! use rvoip_transaction_core::TransactionManager;
54//! use tokio::sync::mpsc;
55//! use std::sync::Arc;
56//!
57//! #[tokio::main]
58//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
59//!     // Set up dependencies (transport setup omitted for brevity)
60//!     # let transport = unimplemented!(); // Mock transport
61//!     let tx_mgr = Arc::new(TransactionManager::new_sync(transport));
62//!     let config = ServerConfig::new("0.0.0.0:5060".parse()?)
63//!         .with_domain("sip.company.com")
64//!         .with_auto_options()
65//!         .with_auto_register();
66//!     
67//!     // Create and configure server
68//!     let server = DialogServer::with_dependencies(tx_mgr, config).await?;
69//!     
70//!     // Set up session coordination for call handling
71//!     let (session_tx, mut session_rx) = mpsc::channel(100);
72//!     server.set_session_coordinator(session_tx).await?;
73//!     
74//!     // Start the server
75//!     server.start().await?;
76//!     println!("✅ SIP server listening on 0.0.0.0:5060");
77//!     
78//!     // Handle incoming calls
79//!     tokio::spawn(async move {
80//!         while let Some(event) = session_rx.recv().await {
81//!             match event {
82//!                 SessionCoordinationEvent::IncomingCall { dialog_id, request, .. } => {
83//!                     println!("📞 Incoming call: {} from {}", 
84//!                         dialog_id, request.from().unwrap().uri());
85//!                     // Handle call - see examples below
86//!                 },
87//!                 _ => {}
88//!             }
89//!         }
90//!     });
91//!     
92//!     // Keep server running
93//!     tokio::signal::ctrl_c().await?;
94//!     server.stop().await?;
95//!     println!("✅ Server stopped gracefully");
96//!     
97//!     Ok(())
98//! }
99//! ```
100//!
101//! ## Usage Patterns
102//!
103//! ### Pattern 1: Simple Call Server
104//!
105//! For basic call handling with automatic responses:
106//!
107//! ```rust,no_run
108//! use rvoip_dialog_core::api::{DialogServer, DialogApi, ServerConfig};
109//! use rvoip_dialog_core::events::SessionCoordinationEvent;
110//! use rvoip_sip_core::StatusCode;
111//! use tokio::sync::mpsc;
112//!
113//! # async fn simple_server() -> Result<(), Box<dyn std::error::Error>> {
114//! # let (tx_mgr, config) = setup_dependencies().await?;
115//! let server = DialogServer::with_dependencies(tx_mgr, config).await?;
116//! 
117//! // Set up call handling
118//! let (session_tx, mut session_rx) = mpsc::channel(100);
119//! server.set_session_coordinator(session_tx).await?;
120//! server.start().await?;
121//! 
122//! // Simple call handler
123//! tokio::spawn(async move {
124//!     while let Some(event) = session_rx.recv().await {
125//!         match event {
126//!             SessionCoordinationEvent::IncomingCall { dialog_id, request, .. } => {
127//!                 // Accept calls using handle_invite with the actual request
128//!                 if let Ok(call) = server.handle_invite(request, "127.0.0.1:5060".parse().unwrap()).await {
129//!                     call.answer(Some("SDP answer".to_string())).await.ok();
130//!                     println!("Call {} auto-accepted", dialog_id);
131//!                 }
132//!             },
133//!             SessionCoordinationEvent::CallTerminated { dialog_id, .. } => {
134//!                 println!("Call {} ended", dialog_id);
135//!             },
136//!             _ => {}
137//!         }
138//!     }
139//! });
140//! # Ok(())
141//! # }
142//! # async fn setup_dependencies() -> Result<(std::sync::Arc<rvoip_transaction_core::TransactionManager>, rvoip_dialog_core::api::ServerConfig), std::io::Error> { unimplemented!() }
143//! ```
144//!
145//! ### Pattern 2: Advanced Call Processing
146//!
147//! For sophisticated call routing and processing:
148//!
149//! ```rust,no_run
150//! use rvoip_dialog_core::api::{DialogServer, DialogApi};
151//! use rvoip_dialog_core::events::SessionCoordinationEvent;
152//! use rvoip_sip_core::{StatusCode, Request};
153//! use std::collections::HashMap;
154//!
155//! # async fn advanced_server(server: DialogServer) -> Result<(), Box<dyn std::error::Error>> {
156//! let (session_tx, mut session_rx) = mpsc::channel(100);
157//! server.set_session_coordinator(session_tx).await?;
158//! server.start().await?;
159//!
160//! // Advanced call processing with routing logic
161//! tokio::spawn(async move {
162//!     let mut active_calls = HashMap::new();
163//!     
164//!     while let Some(event) = session_rx.recv().await {
165//!         match event {
166//!             SessionCoordinationEvent::IncomingCall { dialog_id, request, .. } => {
167//!                 let to_uri = request.to().unwrap().uri().to_string();
168//!                 
169//!                 // Route based on destination
170//!                 match route_call(&to_uri).await {
171//!                     CallRoute::Accept(sdp_answer) => {
172//!                         if let Ok(call) = server.handle_invite(request, "127.0.0.1:5060".parse().unwrap()).await {
173//!                             call.answer(Some(sdp_answer)).await.ok();
174//!                             active_calls.insert(dialog_id.clone(), CallInfo::new(to_uri));
175//!                             println!("✅ Call {} accepted and routed", dialog_id);
176//!                         }
177//!                     },
178//!                     CallRoute::Redirect(_new_target) => {
179//!                         // Handle redirect (simplified for doc test)
180//!                         println!("↪️ Call {} would be redirected", dialog_id);
181//!                     },
182//!                     CallRoute::Reject(_reason) => {
183//!                         // Handle rejection (simplified for doc test)
184//!                         println!("❌ Call {} would be rejected", dialog_id);
185//!                     }
186//!                 }
187//!             },
188//!             SessionCoordinationEvent::CallTerminated { dialog_id, .. } => {
189//!                 active_calls.remove(&dialog_id);
190//!                 println!("📞 Call {} terminated", dialog_id);
191//!             },
192//!             _ => {}
193//!         }
194//!     }
195//! });
196//! # Ok(())
197//! # }
198//! # enum CallRoute { Accept(String), Redirect(String), Reject(String) }
199//! # async fn route_call(to_uri: &str) -> CallRoute { CallRoute::Accept("SDP".to_string()) }
200//! # struct CallInfo;
201//! # impl CallInfo { fn new(uri: String) -> Self { Self } }
202//! # use tokio::sync::mpsc;
203//! ```
204//!
205//! ### Pattern 3: Protocol Extension Server
206//!
207//! For servers implementing custom SIP extensions:
208//!
209//! ```rust,no_run
210//! use rvoip_dialog_core::api::DialogServer;
211//! use rvoip_sip_core::{Method, StatusCode};
212//! use rvoip_dialog_core::dialog::DialogId;
213//!
214//! # async fn protocol_server(server: DialogServer) -> Result<(), Box<dyn std::error::Error>> {
215//! // Handle custom SIP methods and extensions
216//! 
217//! // Custom NOTIFY handler for presence
218//! async fn handle_notify(server: &DialogServer, dialog_id: &DialogId, body: Option<String>) -> Result<(), Box<dyn std::error::Error>> {
219//!     if let Some(presence_data) = body {
220//!         println!("📍 Presence update: {}", presence_data);
221//!         
222//!         // Process presence information
223//!         let presence_status = parse_presence(&presence_data)?;
224//!         update_presence_database(&dialog_id, presence_status).await?;
225//!         
226//!         // Acknowledgment would be sent via proper transaction handling
227//!         println!("✅ Presence processed for dialog {}", dialog_id);
228//!     }
229//!     Ok(())
230//! }
231//!
232//! // Custom INFO handler for application data
233//! async fn handle_info(server: &DialogServer, dialog_id: &DialogId, body: Option<String>) -> Result<(), Box<dyn std::error::Error>> {
234//!     if let Some(app_data) = body {
235//!         println!("📱 Application data: {}", app_data);
236//!         
237//!         // Process application-specific information
238//!         match parse_app_data(&app_data)? {
239//!             AppData::ScreenShare { session_id } => {
240//!                 setup_screen_share(dialog_id, &session_id).await?;
241//!                 println!("🖥️ Screen share initiated for {}", dialog_id);
242//!             },
243//!             AppData::FileTransfer { file_id, size } => {
244//!                 initiate_file_transfer(dialog_id, &file_id, size).await?;
245//!                 println!("📁 File transfer started for {}", dialog_id);
246//!             },
247//!             _ => {
248//!                 println!("❓ Unknown app data type for {}", dialog_id);
249//!             }
250//!         }
251//!     }
252//!     Ok(())
253//! }
254//! # Ok(())
255//! # }
256//! # fn parse_presence(data: &str) -> Result<String, Box<dyn std::error::Error>> { Ok("online".to_string()) }
257//! # async fn update_presence_database(dialog_id: &DialogId, status: String) -> Result<(), Box<dyn std::error::Error>> { Ok(()) }
258//! # enum AppData { ScreenShare { session_id: String }, FileTransfer { file_id: String, size: u64 } }
259//! # fn parse_app_data(data: &str) -> Result<AppData, Box<dyn std::error::Error>> { Ok(AppData::ScreenShare { session_id: "123".to_string() }) }
260//! # async fn setup_screen_share(dialog_id: &DialogId, session_id: &str) -> Result<(), Box<dyn std::error::Error>> { Ok(()) }
261//! # async fn initiate_file_transfer(dialog_id: &DialogId, file_id: &str, size: u64) -> Result<(), Box<dyn std::error::Error>> { Ok(()) }
262//! ```
263//!
264//! ## Configuration Patterns
265//!
266//! ### Production Server Configuration
267//!
268//! ```rust
269//! use rvoip_dialog_core::api::ServerConfig;
270//! use std::time::Duration;
271//!
272//! let config = ServerConfig::new("0.0.0.0:5060".parse().unwrap())
273//!     .with_domain("sip.production.com")
274//!     .with_auto_options()
275//!     .with_auto_register();
276//!
277//! // Customize for high-load production
278//! let mut prod_config = config;
279//! prod_config.dialog = prod_config.dialog
280//!     .with_timeout(Duration::from_secs(300))
281//!     .with_max_dialogs(100000)
282//!     .with_user_agent("ProductionSIP/1.0")
283//!     .without_auto_cleanup(); // Manual control for performance
284//! ```
285//!
286//! ### Development Server Configuration
287//!
288//! ```rust
289//! use rvoip_dialog_core::api::ServerConfig;
290//! use std::time::Duration;
291//!
292//! let dev_config = ServerConfig::new("127.0.0.1:5060".parse().unwrap())
293//!     .with_domain("localhost")
294//!     .with_auto_options();
295//!
296//! // Fast timeouts for development
297//! let mut test_config = dev_config;
298//! test_config.dialog = test_config.dialog
299//!     .with_timeout(Duration::from_secs(30))
300//!     .with_user_agent("DevSIP/1.0");
301//! ```
302//!
303//! ## Error Handling Strategies
304//!
305//! ```rust,no_run
306//! use rvoip_dialog_core::api::{DialogServer, ApiError};
307//! use rvoip_sip_core::StatusCode;
308//! use rvoip_dialog_core::dialog::DialogId;
309//!
310//! async fn robust_call_handler(server: &DialogServer, dialog_id: &DialogId) -> Result<(), Box<dyn std::error::Error>> {
311//!     // This example shows error handling patterns, but actual implementation would need proper request/transaction context
312//!     println!("🔄 Processing call for dialog {}", dialog_id);
313//!     
314//!     // In a real implementation, you would:
315//!     // 1. Get the original INVITE request from transaction context
316//!     // 2. Use handle_invite() with the actual request
317//!     // 3. Use proper transaction keys for responses
318//!     
319//!     match server.get_dialog_info(dialog_id).await {
320//!         Ok(dialog_info) => {
321//!             println!("✅ Dialog {} found: {} -> {}", dialog_id, dialog_info.local_uri, dialog_info.remote_uri);
322//!             // Handle successful dialog case
323//!         },
324//!         Err(ApiError::Dialog { message }) => {
325//!             eprintln!("Dialog error for {}: {}", dialog_id, message);
326//!             // Dialog not found - would send 481 Call/Transaction Does Not Exist in real scenario
327//!         },
328//!         Err(ApiError::Protocol { message }) => {
329//!             eprintln!("Protocol error for {}: {}", dialog_id, message);
330//!             // Protocol error - would send 400 Bad Request in real scenario
331//!         },
332//!         Err(e) => {
333//!             eprintln!("Internal error for {}: {}", dialog_id, e);
334//!             // Internal error - would send 500 Server Internal Error in real scenario
335//!         }
336//!     }
337//!     Ok(())
338//! }
339//! ```
340//!
341//! ## Integration Examples
342//!
343//! ### Media Server Integration
344//!
345//! ```rust,no_run
346//! use rvoip_dialog_core::api::{DialogServer, DialogApi};
347//! use rvoip_dialog_core::events::SessionCoordinationEvent;
348//! use tokio::sync::mpsc;
349//!
350//! # async fn media_integration() -> Result<(), Box<dyn std::error::Error>> {
351//! # let (tx_mgr, config) = setup_dependencies().await?;
352//! let server = DialogServer::with_dependencies(tx_mgr, config).await?;
353//! let (session_tx, mut session_rx) = mpsc::channel(100);
354//! server.set_session_coordinator(session_tx).await?;
355//! server.start().await?;
356//!
357//! tokio::spawn(async move {
358//!     while let Some(event) = session_rx.recv().await {
359//!         match event {
360//!             SessionCoordinationEvent::IncomingCall { dialog_id, request, .. } => {
361//!                 // Extract SDP offer from incoming INVITE
362//!                 if let Some(offer_sdp) = extract_sdp_from_request(&request) {
363//!                     // Set up media session
364//!                     match setup_media_session(offer_sdp).await {
365//!                         Ok(answer_sdp) => {
366//!                             // Accept call with SDP answer
367//!                             if let Ok(call) = server.handle_invite(request, "127.0.0.1:5060".parse().unwrap()).await {
368//!                                 call.answer(Some(answer_sdp)).await.ok();
369//!                                 println!("🎵 Media session established for {}", dialog_id);
370//!                             }
371//!                         },
372//!                         Err(e) => {
373//!                             eprintln!("❌ Media setup failed: {}", e);
374//!                             // Would reject call in real scenario with proper transaction handling
375//!                         }
376//!                     }
377//!                 }
378//!             },
379//!             SessionCoordinationEvent::CallTerminated { dialog_id, .. } => {
380//!                 // Clean up media resources
381//!                 cleanup_media_session(&dialog_id).await.ok();
382//!                 println!("🔇 Media session cleaned up for {}", dialog_id);
383//!             },
384//!             _ => {}
385//!         }
386//!     }
387//! });
388//! # Ok(())
389//! # }
390//! # use rvoip_sip_core::Request;
391//! # fn extract_sdp_from_request(request: &Request) -> Option<String> { Some("SDP".to_string()) }
392//! # async fn setup_media_session(offer: String) -> Result<String, Box<dyn std::error::Error + Send + Sync>> { Ok("answer".to_string()) }
393//! # async fn cleanup_media_session(dialog_id: &rvoip_dialog_core::dialog::DialogId) -> Result<(), Box<dyn std::error::Error + Send + Sync>> { Ok(()) }
394//! # async fn setup_dependencies() -> Result<(std::sync::Arc<rvoip_transaction_core::TransactionManager>, rvoip_dialog_core::api::ServerConfig), std::io::Error> { unimplemented!() }
395//! ```
396//!
397//! ### Load Balancer Integration
398//!
399//! ```rust,no_run
400//! use rvoip_dialog_core::api::{DialogServer, DialogApi};
401//! use rvoip_sip_core::StatusCode;
402//! use std::sync::atomic::{AtomicU64, Ordering};
403//! use std::sync::Arc;
404//!
405//! # async fn load_balancer_integration() -> Result<(), Box<dyn std::error::Error>> {
406//! # let (tx_mgr, config) = setup_dependencies().await?;
407//! let server = DialogServer::with_dependencies(tx_mgr, config).await?;
408//! let call_counter = Arc::new(AtomicU64::new(0));
409//! let max_calls = 1000; // Server capacity limit
410//!
411//! let (session_tx, mut session_rx) = tokio::sync::mpsc::channel(100);
412//! server.set_session_coordinator(session_tx).await?;
413//! server.start().await?;
414//!
415//! let counter_clone = call_counter.clone();
416//! tokio::spawn(async move {
417//!     while let Some(event) = session_rx.recv().await {
418//!         match event {
419//!             rvoip_dialog_core::events::SessionCoordinationEvent::IncomingCall { dialog_id, .. } => {
420//!                 let current_calls = counter_clone.load(Ordering::Relaxed);
421//!                 
422//!                 if current_calls >= max_calls {
423//!                     // Server at capacity - redirect to another server
424//!                     println!("📊 Server at capacity, would redirect call {}", dialog_id);
425//!                 } else {
426//!                     // Accept the call (simplified for doc test)
427//!                     println!("📞 Call {} would be accepted ({}/{})", dialog_id, current_calls + 1, max_calls);
428//!                     counter_clone.fetch_add(1, Ordering::Relaxed);
429//!                 }
430//!             },
431//!             rvoip_dialog_core::events::SessionCoordinationEvent::CallTerminated { dialog_id, .. } => {
432//!                 counter_clone.fetch_sub(1, Ordering::Relaxed);
433//!                 let remaining = counter_clone.load(Ordering::Relaxed);
434//!                 println!("📞 Call {} ended ({}/{})", dialog_id, remaining, max_calls);
435//!             },
436//!             _ => {}
437//!         }
438//!     }
439//! });
440//! # Ok(())
441//! # }
442//! # async fn setup_dependencies() -> Result<(std::sync::Arc<rvoip_transaction_core::TransactionManager>, rvoip_dialog_core::api::ServerConfig), std::io::Error> { unimplemented!() }
443//! ```
444//!
445//! ## Monitoring & Statistics
446//!
447//! ```rust,no_run
448//! use rvoip_dialog_core::api::{DialogServer, DialogApi};
449//! use tokio::time::{interval, Duration};
450//!
451//! # async fn monitoring_example(server: DialogServer) -> Result<(), Box<dyn std::error::Error>> {
452//! // Set up periodic monitoring
453//! let mut monitor_interval = interval(Duration::from_secs(60));
454//!
455//! tokio::spawn(async move {
456//!     loop {
457//!         monitor_interval.tick().await;
458//!         
459//!         let stats = server.get_stats().await;
460//!         println!("=== Server Statistics ===");
461//!         println!("Active dialogs: {}", stats.active_dialogs);
462//!         println!("Total dialogs: {}", stats.total_dialogs);
463//!         println!("Success rate: {:.1}%", 
464//!             100.0 * stats.successful_calls as f64 / (stats.successful_calls + stats.failed_calls) as f64);
465//!         println!("Average call duration: {:.1}s", stats.avg_call_duration);
466//!
467//!         // Health check
468//!         if stats.active_dialogs > 5000 {
469//!             println!("⚠️ High dialog count - consider scaling");
470//!         }
471//!         
472//!         // List active dialogs for debugging
473//!         let active_dialogs = server.list_active_dialogs().await;
474//!         if active_dialogs.len() > 100 {
475//!             println!("📋 {} active dialogs (showing first 5):", active_dialogs.len());
476//!             for dialog_id in active_dialogs.iter().take(5) {
477//!                 if let Ok(info) = server.get_dialog_info(dialog_id).await {
478//!                     println!("  Dialog {}: {} -> {} ({})", 
479//!                         dialog_id, info.local_uri, info.remote_uri, info.state);
480//!                 }
481//!             }
482//!         }
483//!     }
484//! });
485//! # Ok(())
486//! # }
487//! ```
488//!
489//! ## Best Practices
490//!
491//! 1. **Use Session Coordination**: Always set up session event handling for robust call management
492//! 2. **Configure Auto-Responses**: Enable auto-OPTIONS and auto-REGISTER for standard compliance
493//! 3. **Implement Proper Error Handling**: Use specific error types and appropriate SIP status codes
494//! 4. **Monitor Server Health**: Track statistics and implement alerting for high loads
495//! 5. **Scale Horizontally**: Use load balancing and capacity limits for production deployments
496//! 6. **Validate Configuration**: Always call `validate()` on configurations before use
497//! 7. **Clean Shutdown**: Implement graceful shutdown with proper resource cleanup
498//! 8. **Security Considerations**: Implement authentication, authorization, and rate limiting
499//!
500//! ## Thread Safety
501//!
502//! DialogServer is designed to be thread-safe and can handle concurrent operations:
503//!
504//! ```rust,no_run
505//! use rvoip_dialog_core::api::DialogServer;
506//! use std::sync::Arc;
507//!
508//! # async fn thread_safety(server: DialogServer) -> Result<(), Box<dyn std::error::Error>> {
509//! let server = Arc::new(server);
510//!
511//! // Spawn multiple tasks handling different aspects
512//! let server1 = server.clone();
513//! let call_handler = tokio::spawn(async move {
514//!     // Handle incoming calls
515//! });
516//!
517//! let server2 = server.clone();
518//! let monitoring_task = tokio::spawn(async move {
519//!     // Monitor server statistics
520//! });
521//!
522//! let server3 = server.clone();
523//! let protocol_handler = tokio::spawn(async move {
524//!     // Handle custom protocol extensions
525//! });
526//!
527//! // All tasks can safely use the server concurrently
528//! tokio::try_join!(call_handler, monitoring_task, protocol_handler)?;
529//! # Ok(())
530//! # }
531//! ```
532//!
533//! ## Submodules
534//!
535//! - [`core`]: Core server struct, constructors, and configuration management
536//! - [`call_operations`]: Call lifecycle management (handle, accept, reject, terminate)
537//! - [`dialog_operations`]: Dialog management operations (create, query, list, terminate)  
538//! - [`response_builder`]: Response building and sending functionality with SIP compliance
539//! - [`sip_methods`]: Specialized SIP method handlers (BYE, REFER, NOTIFY, UPDATE, INFO)
540
541pub mod core;
542pub mod call_operations;
543pub mod dialog_operations;
544pub mod response_builder;
545pub mod sip_methods;
546
547// Re-export the main types for external use
548pub use core::{DialogServer, ServerStats};