rvoip_client_core/client/
config.rs

1//! Client configuration structures and presets
2//!
3//! This module provides comprehensive configuration structures for the VoIP client, including
4//! media settings, codec preferences, network parameters, and security options. It offers
5//! both fine-grained control and convenient presets for common use cases.
6//!
7//! # Key Components
8//!
9//! - **ClientConfig** - Main client configuration with network and session settings
10//! - **MediaConfig** - Media-specific settings including codecs and audio processing
11//! - **MediaPreset** - Predefined media configuration templates for common scenarios
12//!
13//! # Architecture
14//!
15//! ```text
16//! ┌─────────────────────────┐
17//! │    ClientConfig         │
18//! │ ┌─────────────────────┐ │
19//! │ │   Network Settings  │ │  • SIP & Media addresses
20//! │ │   Session Settings  │ │  • Timeouts & Limits
21//! │ │   MediaConfig      ─┼─┼─ • Codec preferences
22//! │ └─────────────────────┘ │  • Audio processing
23//! └─────────────────────────┘  • Security settings
24//! ```
25//!
26//! # Usage Examples
27//!
28//! ## Basic Client Configuration
29//!
30//! ```rust
31//! use rvoip_client_core::client::config::{ClientConfig, MediaPreset};
32//! use std::net::SocketAddr;
33//!
34//! let config = ClientConfig::new()
35//!     .with_sip_addr("127.0.0.1:5060".parse().unwrap())
36//!     .with_media_addr("127.0.0.1:0".parse().unwrap())
37//!     .with_user_agent("MyApp/1.0".to_string())
38//!     .with_max_calls(5);
39//!
40//! assert_eq!(config.max_concurrent_calls, 5);
41//! assert_eq!(config.user_agent, "MyApp/1.0");
42//! ```
43//!
44//! ## Advanced Media Configuration
45//!
46//! ```rust
47//! use rvoip_client_core::client::config::{ClientConfig, MediaConfig};
48//! use std::collections::HashMap;
49//!
50//! let mut custom_attributes = HashMap::new();
51//! custom_attributes.insert("a".to_string(), "sendrecv".to_string());
52//!
53//! let media_config = MediaConfig {
54//!     preferred_codecs: vec!["opus".to_string(), "G722".to_string()],
55//!     echo_cancellation: true,
56//!     noise_suppression: true,
57//!     auto_gain_control: true,
58//!     max_bandwidth_kbps: Some(128),
59//!     require_srtp: true,
60//!     srtp_profiles: vec!["AES_CM_128_HMAC_SHA1_80".to_string()],
61//!     rtp_port_start: 12000,
62//!     rtp_port_end: 15000,
63//!     preferred_ptime: Some(20),
64//!     custom_sdp_attributes: custom_attributes,
65//!     dtmf_enabled: true,
66//! };
67//!
68//! let config = ClientConfig::new().with_media(media_config);
69//! assert!(config.media.require_srtp);
70//! assert_eq!(config.media.rtp_port_start, 12000);
71//! ```
72//!
73//! ## Using Media Presets
74//!
75//! ```rust
76//! use rvoip_client_core::client::config::{ClientConfig, MediaPreset, MediaConfig};
77//!
78//! // Secure configuration for enterprise use
79//! let secure_config = ClientConfig::new()
80//!     .with_media_preset(MediaPreset::Secure)
81//!     .with_user_agent("Enterprise-Phone/1.0".to_string());
82//!
83//! assert!(secure_config.media.require_srtp);
84//! assert!(!secure_config.media.srtp_profiles.is_empty());
85//!
86//! // Low bandwidth configuration for mobile
87//! let mobile_config = ClientConfig::new()
88//!     .with_media_preset(MediaPreset::LowBandwidth);
89//!
90//! assert!(mobile_config.media.max_bandwidth_kbps.unwrap() <= 32);
91//!
92//! // Voice-optimized configuration
93//! let voice_config = MediaConfig::from_preset(MediaPreset::VoiceOptimized);
94//! assert!(voice_config.echo_cancellation);
95//! assert!(voice_config.noise_suppression);
96//! ```
97//!
98//! ## Configuration Validation
99//!
100//! ```rust
101//! use rvoip_client_core::client::config::ClientConfig;
102//!
103//! let config = ClientConfig::new()
104//!     .with_sip_addr("0.0.0.0:5060".parse().unwrap())
105//!     .with_media_addr("0.0.0.0:0".parse().unwrap())
106//!     .with_max_calls(100);
107//!
108//! // Validate configuration settings
109//! assert!(config.max_concurrent_calls > 0);
110//! assert!(config.session_timeout_secs > 0);
111//! assert!(config.media.rtp_port_start < config.media.rtp_port_end);
112//! assert!(config.enable_audio); // Default is true
113//! ```
114//!
115//! # Common Patterns
116//!
117//! ## Enterprise VoIP Setup
118//!
119//! ```rust
120//! use rvoip_client_core::client::config::{ClientConfig, MediaPreset};
121//!
122//! let enterprise_config = ClientConfig::new()
123//!     .with_sip_addr("192.168.1.100:5060".parse().unwrap())
124//!     .with_media_preset(MediaPreset::Secure)
125//!     .with_user_agent("CorporatePhone/2.1".to_string())
126//!     .with_max_calls(20);
127//!
128//! assert_eq!(enterprise_config.max_concurrent_calls, 20);
129//! ```
130//!
131//! ## Residential VoIP Setup
132//!
133//! ```rust
134//! use rvoip_client_core::client::config::{ClientConfig, MediaPreset};
135//!
136//! let home_config = ClientConfig::new()
137//!     .with_media_preset(MediaPreset::VoiceOptimized)
138//!     .with_max_calls(3);
139//!
140//! assert_eq!(home_config.max_concurrent_calls, 3);
141//! assert!(home_config.media.echo_cancellation);
142//! ```
143//!
144//! ## Mobile VoIP Setup
145//!
146//! ```rust
147//! use rvoip_client_core::client::config::{ClientConfig, MediaPreset};
148//!
149//! let mobile_config = ClientConfig::new()
150//!     .with_media_preset(MediaPreset::LowBandwidth)
151//!     .with_user_agent("MobileVoIP/1.0".to_string())
152//!     .with_max_calls(2);
153//!
154//! assert!(mobile_config.media.max_bandwidth_kbps.is_some());
155//! assert!(mobile_config.media.max_bandwidth_kbps.unwrap() <= 32);
156//! ```
157
158use std::net::SocketAddr;
159use std::collections::HashMap;
160use serde::{Deserialize, Serialize};
161
162/// Media configuration preferences
163/// 
164/// Defines comprehensive media-related settings including codec preferences, audio processing
165/// options, security requirements, network parameters, and SDP customization. This structure
166/// provides fine-grained control over all aspects of media handling in VoIP calls.
167/// 
168/// # Audio Processing Features
169/// 
170/// - **Echo Cancellation**: Removes acoustic echo during calls
171/// - **Noise Suppression**: Filters background noise from audio
172/// - **Auto Gain Control**: Automatically adjusts microphone levels
173/// - **DTMF Support**: Dual-tone multi-frequency signaling for dial tones
174/// 
175/// # Security Features
176/// 
177/// - **SRTP Encryption**: Secure Real-time Transport Protocol for media encryption
178/// - **Profile Selection**: Choose from multiple SRTP encryption profiles
179/// - **Mandatory Encryption**: Option to require SRTP for all calls
180/// 
181/// # Network Configuration
182/// 
183/// - **Port Range Control**: Specify RTP port ranges for NAT/firewall traversal
184/// - **Bandwidth Management**: Set maximum bandwidth limits
185/// - **Packetization Time**: Control audio packet timing for latency/quality trade-offs
186/// 
187/// # Examples
188/// 
189/// ## Basic Media Configuration
190/// 
191/// ```rust
192/// use rvoip_client_core::client::config::MediaConfig;
193/// use std::collections::HashMap;
194/// 
195/// let media_config = MediaConfig {
196///     preferred_codecs: vec!["opus".to_string(), "PCMU".to_string()],
197///     dtmf_enabled: true,
198///     echo_cancellation: true,
199///     noise_suppression: true,
200///     auto_gain_control: true,
201///     max_bandwidth_kbps: Some(128),
202///     require_srtp: false,
203///     srtp_profiles: vec![],
204///     rtp_port_start: 10000,
205///     rtp_port_end: 20000,
206///     preferred_ptime: Some(20),
207///     custom_sdp_attributes: HashMap::new(),
208/// };
209/// 
210/// assert_eq!(media_config.preferred_codecs[0], "opus");
211/// assert!(media_config.echo_cancellation);
212/// assert_eq!(media_config.max_bandwidth_kbps, Some(128));
213/// ```
214/// 
215/// ## Secure Media Configuration
216/// 
217/// ```rust
218/// use rvoip_client_core::client::config::MediaConfig;
219/// use std::collections::HashMap;
220/// 
221/// let secure_config = MediaConfig {
222///     preferred_codecs: vec!["opus".to_string(), "G722".to_string()],
223///     require_srtp: true,
224///     srtp_profiles: vec![
225///         "AES_CM_128_HMAC_SHA1_80".to_string(),
226///         "AES_CM_128_HMAC_SHA1_32".to_string(),
227///     ],
228///     dtmf_enabled: true,
229///     echo_cancellation: true,
230///     noise_suppression: true,
231///     auto_gain_control: true,
232///     max_bandwidth_kbps: Some(256),
233///     rtp_port_start: 16384,
234///     rtp_port_end: 32767,
235///     preferred_ptime: Some(20),
236///     custom_sdp_attributes: HashMap::new(),
237/// };
238/// 
239/// assert!(secure_config.require_srtp);
240/// assert_eq!(secure_config.srtp_profiles.len(), 2);
241/// assert!(secure_config.srtp_profiles.contains(&"AES_CM_128_HMAC_SHA1_80".to_string()));
242/// ```
243/// 
244/// ## Low Bandwidth Configuration
245/// 
246/// ```rust
247/// use rvoip_client_core::client::config::MediaConfig;
248/// use std::collections::HashMap;
249/// 
250/// let low_bandwidth_config = MediaConfig {
251///     preferred_codecs: vec!["G729".to_string(), "GSM".to_string()],
252///     max_bandwidth_kbps: Some(32),
253///     preferred_ptime: Some(30), // Larger packets for efficiency
254///     echo_cancellation: true,
255///     noise_suppression: true,
256///     auto_gain_control: true,
257///     dtmf_enabled: true,
258///     require_srtp: false,
259///     srtp_profiles: vec![],
260///     rtp_port_start: 10000,
261///     rtp_port_end: 20000,
262///     custom_sdp_attributes: HashMap::new(),
263/// };
264/// 
265/// assert_eq!(low_bandwidth_config.max_bandwidth_kbps, Some(32));
266/// assert_eq!(low_bandwidth_config.preferred_ptime, Some(30));
267/// assert!(low_bandwidth_config.preferred_codecs.contains(&"G729".to_string()));
268/// ```
269/// 
270/// ## Custom SDP Attributes
271/// 
272/// ```rust
273/// use rvoip_client_core::client::config::MediaConfig;
274/// use std::collections::HashMap;
275/// 
276/// let mut custom_attrs = HashMap::new();
277/// custom_attrs.insert("a".to_string(), "sendrecv".to_string());
278/// custom_attrs.insert("a".to_string(), "rtcp-mux".to_string());
279/// 
280/// let custom_config = MediaConfig {
281///     preferred_codecs: vec!["opus".to_string()],
282///     custom_sdp_attributes: custom_attrs,
283///     dtmf_enabled: true,
284///     echo_cancellation: true,
285///     noise_suppression: true,
286///     auto_gain_control: true,
287///     max_bandwidth_kbps: None,
288///     require_srtp: false,
289///     srtp_profiles: vec![],
290///     rtp_port_start: 10000,
291///     rtp_port_end: 20000,
292///     preferred_ptime: Some(20),
293/// };
294/// 
295/// assert!(!custom_config.custom_sdp_attributes.is_empty());
296/// ```
297#[derive(Debug, Clone, Serialize, Deserialize)]
298pub struct MediaConfig {
299    /// Preferred codecs in order of preference
300    pub preferred_codecs: Vec<String>,
301    
302    /// Whether DTMF (Dual-Tone Multi-Frequency) signaling is enabled
303    pub dtmf_enabled: bool,
304    /// Whether echo cancellation audio processing is enabled
305    pub echo_cancellation: bool,
306    /// Whether noise suppression audio processing is enabled
307    pub noise_suppression: bool,
308    /// Whether automatic gain control audio processing is enabled
309    pub auto_gain_control: bool,
310    
311    /// Maximum bandwidth in kilobits per second (None for unlimited)
312    pub max_bandwidth_kbps: Option<u32>,
313    
314    /// Whether SRTP (Secure RTP) encryption is required
315    pub require_srtp: bool,
316    /// List of supported SRTP encryption profiles
317    pub srtp_profiles: Vec<String>,
318    
319    /// Starting port number for RTP media streams
320    pub rtp_port_start: u16,
321    /// Ending port number for RTP media streams
322    pub rtp_port_end: u16,
323    
324    /// Preferred packetization time in milliseconds
325    pub preferred_ptime: Option<u8>,
326    
327    /// Additional custom SDP (Session Description Protocol) attributes
328    pub custom_sdp_attributes: HashMap<String, String>,
329}
330
331impl Default for MediaConfig {
332    fn default() -> Self {
333        Self {
334            preferred_codecs: vec!["opus".to_string(), "PCMU".to_string(), "PCMA".to_string()],
335            dtmf_enabled: true,
336            echo_cancellation: true,
337            noise_suppression: true,
338            auto_gain_control: true,
339            max_bandwidth_kbps: None,
340            require_srtp: false,
341            srtp_profiles: vec![],
342            rtp_port_start: 10000,
343            rtp_port_end: 20000,
344            preferred_ptime: Some(20),
345            custom_sdp_attributes: HashMap::new(),
346        }
347    }
348}
349
350/// Predefined media configuration presets for common use cases
351/// 
352/// These presets provide optimized configurations for different scenarios,
353/// allowing users to quickly configure appropriate settings without manual tuning.
354/// Each preset can be further customized after application.
355/// 
356/// # Preset Characteristics
357/// 
358/// | Preset | Primary Use | Codecs | Bandwidth | Security | Audio Processing |
359/// |--------|-------------|--------|-----------|----------|------------------|
360/// | VoiceOptimized | Phone calls | Opus, PCMU | Standard | None | Full (AEC, NS, AGC) |
361/// | MusicOptimized | Music streaming | Opus | High | None | Minimal |
362/// | LowBandwidth | Mobile/poor networks | G.729, GSM | Low | None | Full |
363/// | Secure | Enterprise | Default | Standard | SRTP | Full |
364/// | Legacy | Compatibility | G.711 | Standard | None | Minimal |
365/// 
366/// # Examples
367/// 
368/// ## Voice Calling (Recommended for Phone Calls)
369/// 
370/// ```rust
371/// use rvoip_client_core::client::config::{MediaPreset, MediaConfig};
372/// 
373/// let voice_config = MediaConfig::from_preset(MediaPreset::VoiceOptimized);
374/// 
375/// // Optimized for voice with full audio processing
376/// assert!(voice_config.echo_cancellation);
377/// assert!(voice_config.noise_suppression);
378/// assert!(voice_config.auto_gain_control);
379/// assert_eq!(voice_config.preferred_ptime, Some(20));
380/// assert!(voice_config.preferred_codecs.contains(&"opus".to_string()));
381/// ```
382/// 
383/// ## Music Streaming (High Quality Audio)
384/// 
385/// ```rust
386/// use rvoip_client_core::client::config::{MediaPreset, MediaConfig};
387/// 
388/// let music_config = MediaConfig::from_preset(MediaPreset::MusicOptimized);
389/// 
390/// // Optimized for music with minimal processing
391/// assert!(!music_config.echo_cancellation); // No echo cancellation for music
392/// assert!(!music_config.noise_suppression); // Preserve audio fidelity
393/// assert!(!music_config.auto_gain_control);  // No gain adjustment
394/// assert_eq!(music_config.max_bandwidth_kbps, Some(256)); // Higher bandwidth
395/// assert!(music_config.preferred_codecs.contains(&"opus".to_string()));
396/// ```
397/// 
398/// ## Low Bandwidth (Mobile/Constrained Networks)
399/// 
400/// ```rust
401/// use rvoip_client_core::client::config::{MediaPreset, MediaConfig};
402/// 
403/// let mobile_config = MediaConfig::from_preset(MediaPreset::LowBandwidth);
404/// 
405/// // Optimized for low bandwidth connections
406/// assert_eq!(mobile_config.max_bandwidth_kbps, Some(32));
407/// assert_eq!(mobile_config.preferred_ptime, Some(30)); // Larger packets
408/// assert!(mobile_config.preferred_codecs.iter().any(|c| c == "G.729"));
409/// assert!(mobile_config.echo_cancellation); // Still enabled for quality
410/// ```
411/// 
412/// ## Secure Communications (Enterprise)
413/// 
414/// ```rust
415/// use rvoip_client_core::client::config::{MediaPreset, MediaConfig};
416/// 
417/// let secure_config = MediaConfig::from_preset(MediaPreset::Secure);
418/// 
419/// // Requires encryption for all calls
420/// assert!(secure_config.require_srtp);
421/// assert!(!secure_config.srtp_profiles.is_empty());
422/// assert!(secure_config.srtp_profiles.contains(&"AES_CM_128_HMAC_SHA1_80".to_string()));
423/// assert!(secure_config.echo_cancellation); // Full audio processing
424/// ```
425/// 
426/// ## Legacy Compatibility (Older Systems)
427/// 
428/// ```rust
429/// use rvoip_client_core::client::config::{MediaPreset, MediaConfig};
430/// 
431/// let legacy_config = MediaConfig::from_preset(MediaPreset::Legacy);
432/// 
433/// // Compatible with older SIP systems
434/// assert!(legacy_config.preferred_codecs.contains(&"PCMU".to_string()));
435/// assert!(legacy_config.preferred_codecs.contains(&"PCMA".to_string()));
436/// assert!(!legacy_config.echo_cancellation); // Minimal processing
437/// assert!(!legacy_config.require_srtp); // No encryption requirement
438/// ```
439/// 
440/// ## Preset Comparison
441/// 
442/// ```rust
443/// use rvoip_client_core::client::config::{MediaPreset, MediaConfig};
444/// 
445/// let voice = MediaConfig::from_preset(MediaPreset::VoiceOptimized);
446/// let music = MediaConfig::from_preset(MediaPreset::MusicOptimized);
447/// let mobile = MediaConfig::from_preset(MediaPreset::LowBandwidth);
448/// 
449/// // Voice has audio processing, music doesn't
450/// assert!(voice.echo_cancellation);
451/// assert!(!music.echo_cancellation);
452/// 
453/// // Mobile has lower bandwidth than music
454/// assert!(mobile.max_bandwidth_kbps.unwrap() < music.max_bandwidth_kbps.unwrap());
455/// 
456/// // All have DTMF enabled by default
457/// assert!(voice.dtmf_enabled);
458/// assert!(music.dtmf_enabled);
459/// assert!(mobile.dtmf_enabled);
460/// ```
461#[derive(Debug, Clone, Copy, PartialEq, Eq)]
462pub enum MediaPreset {
463    /// Optimized for voice calls with full audio processing
464    /// 
465    /// **Use Case**: Standard phone calls, conferencing, customer service
466    /// 
467    /// **Features**:
468    /// - Opus and PCMU codecs for voice clarity
469    /// - Full audio processing (echo cancellation, noise suppression, AGC)
470    /// - 20ms packetization for low latency
471    /// - Standard bandwidth usage
472    /// 
473    /// **Best For**: Business phones, softphones, call centers
474    VoiceOptimized,
475    
476    /// Optimized for high-quality music streaming
477    /// 
478    /// **Use Case**: Music streaming, audio conferencing, broadcast
479    /// 
480    /// **Features**:
481    /// - Opus codec for high fidelity
482    /// - Minimal audio processing to preserve quality
483    /// - Higher bandwidth allocation (256 kbps)
484    /// - No echo cancellation or gain control
485    /// 
486    /// **Best For**: Music apps, audio streaming, podcast recording
487    MusicOptimized,
488    
489    /// Optimized for constrained bandwidth connections
490    /// 
491    /// **Use Case**: Mobile networks, satellite links, poor connectivity
492    /// 
493    /// **Features**:
494    /// - Low bitrate codecs (G.729, GSM)
495    /// - 32 kbps maximum bandwidth
496    /// - 30ms packetization for efficiency
497    /// - Audio processing enabled for quality
498    /// 
499    /// **Best For**: Mobile VoIP, rural networks, international calling
500    LowBandwidth,
501    
502    /// Requires SRTP encryption for secure communications
503    /// 
504    /// **Use Case**: Enterprise communications, sensitive data, compliance
505    /// 
506    /// **Features**:
507    /// - Mandatory SRTP encryption
508    /// - Multiple SRTP profiles supported
509    /// - Full audio processing enabled
510    /// - Standard codec selection
511    /// 
512    /// **Best For**: Corporate phones, government, healthcare, legal
513    Secure,
514    
515    /// Basic G.711 compatibility for legacy systems
516    /// 
517    /// **Use Case**: Interoperability with older PBX systems
518    /// 
519    /// **Features**:
520    /// - G.711 (PCMU/PCMA) codecs only
521    /// - Minimal audio processing
522    /// - No encryption requirements
523    /// - Maximum compatibility
524    /// 
525    /// **Best For**: Legacy PBX integration, older VoIP systems
526    Legacy,
527}
528
529impl MediaConfig {
530    /// Create a MediaConfig from a predefined preset
531    /// 
532    /// This convenience method creates a MediaConfig with optimized settings for
533    /// specific use cases. The resulting configuration can be further customized
534    /// by modifying individual fields after creation.
535    /// 
536    /// # Arguments
537    /// 
538    /// * `preset` - The MediaPreset to use as a template
539    /// 
540    /// # Returns
541    /// 
542    /// A MediaConfig configured for the specified use case
543    /// 
544    /// # Examples
545    /// 
546    /// ## Voice-Optimized Configuration
547    /// 
548    /// ```rust
549    /// use rvoip_client_core::client::config::{MediaConfig, MediaPreset};
550    /// 
551    /// let config = MediaConfig::from_preset(MediaPreset::VoiceOptimized);
552    /// 
553    /// // Verify voice optimization settings
554    /// assert!(config.echo_cancellation);
555    /// assert!(config.noise_suppression);
556    /// assert!(config.auto_gain_control);
557    /// assert_eq!(config.preferred_ptime, Some(20));
558    /// assert!(config.preferred_codecs.contains(&"opus".to_string()));
559    /// ```
560    /// 
561    /// ## Secure Configuration for Enterprise
562    /// 
563    /// ```rust
564    /// use rvoip_client_core::client::config::{MediaConfig, MediaPreset};
565    /// 
566    /// let mut config = MediaConfig::from_preset(MediaPreset::Secure);
567    /// 
568    /// // Verify security settings
569    /// assert!(config.require_srtp);
570    /// assert!(!config.srtp_profiles.is_empty());
571    /// 
572    /// // Customize for specific enterprise needs
573    /// config.preferred_codecs = vec!["opus".to_string(), "G722".to_string()];
574    /// config.max_bandwidth_kbps = Some(128);
575    /// 
576    /// assert_eq!(config.preferred_codecs.len(), 2);
577    /// ```
578    /// 
579    /// ## Mobile-Optimized Configuration
580    /// 
581    /// ```rust
582    /// use rvoip_client_core::client::config::{MediaConfig, MediaPreset};
583    /// 
584    /// let config = MediaConfig::from_preset(MediaPreset::LowBandwidth);
585    /// 
586    /// // Verify mobile optimization
587    /// assert_eq!(config.max_bandwidth_kbps, Some(32));
588    /// assert_eq!(config.preferred_ptime, Some(30)); // Efficient packetization
589    /// assert!(config.preferred_codecs.iter().any(|c| c == "G.729"));
590    /// ```
591    /// 
592    /// ## Customizing After Preset Application
593    /// 
594    /// ```rust
595    /// use rvoip_client_core::client::config::{MediaConfig, MediaPreset};
596    /// use std::collections::HashMap;
597    /// 
598    /// let mut config = MediaConfig::from_preset(MediaPreset::VoiceOptimized);
599    /// 
600    /// // Add custom SDP attributes
601    /// let mut custom_attrs = HashMap::new();
602    /// custom_attrs.insert("a".to_string(), "rtcp-mux".to_string());
603    /// config.custom_sdp_attributes = custom_attrs;
604    /// 
605    /// // Adjust port range for firewall
606    /// config.rtp_port_start = 16384;
607    /// config.rtp_port_end = 32767;
608    /// 
609    /// // Verify customizations
610    /// assert!(!config.custom_sdp_attributes.is_empty());
611    /// assert_eq!(config.rtp_port_start, 16384);
612    /// ```
613    pub fn from_preset(preset: MediaPreset) -> Self {
614        match preset {
615            MediaPreset::VoiceOptimized => Self {
616                preferred_codecs: vec!["opus".to_string(), "PCMU".to_string()],
617                echo_cancellation: true,
618                noise_suppression: true,
619                auto_gain_control: true,
620                preferred_ptime: Some(20),
621                ..Default::default()
622            },
623            MediaPreset::MusicOptimized => Self {
624                preferred_codecs: vec!["opus".to_string()],
625                echo_cancellation: false,
626                noise_suppression: false,
627                auto_gain_control: false,
628                max_bandwidth_kbps: Some(256),
629                ..Default::default()
630            },
631            MediaPreset::LowBandwidth => Self {
632                preferred_codecs: vec!["G.729".to_string(), "GSM".to_string(), "PCMU".to_string()],
633                max_bandwidth_kbps: Some(32),
634                preferred_ptime: Some(30),
635                ..Default::default()
636            },
637            MediaPreset::Secure => Self {
638                require_srtp: true,
639                srtp_profiles: vec![
640                    "AES_CM_128_HMAC_SHA1_80".to_string(),
641                    "AES_CM_128_HMAC_SHA1_32".to_string(),
642                ],
643                ..Default::default()
644            },
645            MediaPreset::Legacy => Self {
646                preferred_codecs: vec!["PCMU".to_string(), "PCMA".to_string()],
647                dtmf_enabled: true,
648                echo_cancellation: false,
649                noise_suppression: false,
650                auto_gain_control: false,
651                ..Default::default()
652            },
653        }
654    }
655}
656
657/// Comprehensive configuration for the SIP client
658/// 
659/// This structure contains all the configuration needed to set up and run a VoIP client,
660/// including network settings, media configuration, session parameters, and feature flags.
661/// It uses the builder pattern for easy configuration and provides sensible defaults.
662/// 
663/// # Configuration Categories
664/// 
665/// ## Network Configuration
666/// - **SIP Address**: Local address for SIP signaling
667/// - **Media Address**: Local address for RTP media streams
668/// - **Domain**: Optional SIP domain for routing
669/// 
670/// ## Session Management
671/// - **Concurrent Calls**: Maximum number of simultaneous calls
672/// - **Timeouts**: Session and registration timeout values
673/// - **User Agent**: Client identification string
674/// 
675/// ## Media Settings
676/// - **Audio/Video**: Enable/disable media types
677/// - **MediaConfig**: Detailed codec and processing settings
678/// 
679/// # Examples
680/// 
681/// ## Basic Configuration
682/// 
683/// ```rust
684/// use rvoip_client_core::client::config::ClientConfig;
685/// 
686/// let config = ClientConfig::new()
687///     .with_sip_addr("127.0.0.1:5060".parse().unwrap())
688///     .with_user_agent("MyApp/1.0".to_string())
689///     .with_max_calls(5);
690/// 
691/// assert_eq!(config.max_concurrent_calls, 5);
692/// assert_eq!(config.user_agent, "MyApp/1.0");
693/// assert!(config.enable_audio);
694/// ```
695/// 
696/// ## Enterprise Configuration
697/// 
698/// ```rust
699/// use rvoip_client_core::client::config::{ClientConfig, MediaPreset};
700/// 
701/// let enterprise_config = ClientConfig::new()
702///     .with_sip_addr("192.168.1.100:5060".parse().unwrap())
703///     .with_media_addr("192.168.1.100:0".parse().unwrap())
704///     .with_user_agent("EnterprisePhone/2.1".to_string())
705///     .with_media_preset(MediaPreset::Secure)
706///     .with_max_calls(20);
707/// 
708/// assert_eq!(enterprise_config.max_concurrent_calls, 20);
709/// assert!(enterprise_config.media.require_srtp);
710/// assert_eq!(enterprise_config.local_sip_addr.ip().to_string(), "192.168.1.100");
711/// ```
712/// 
713/// ## Mobile Configuration
714/// 
715/// ```rust
716/// use rvoip_client_core::client::config::{ClientConfig, MediaPreset};
717/// 
718/// let mobile_config = ClientConfig::new()
719///     .with_media_preset(MediaPreset::LowBandwidth)
720///     .with_user_agent("MobileVoIP/1.0".to_string())
721///     .with_max_calls(2);
722/// 
723/// assert_eq!(mobile_config.max_concurrent_calls, 2);
724/// assert_eq!(mobile_config.media.max_bandwidth_kbps, Some(32));
725/// assert!(mobile_config.media.preferred_codecs.iter().any(|c| c == "G.729"));
726/// ```
727/// 
728/// ## Custom Media Configuration
729/// 
730/// ```rust
731/// use rvoip_client_core::client::config::{ClientConfig, MediaConfig};
732/// use std::collections::HashMap;
733/// 
734/// let custom_media = MediaConfig {
735///     preferred_codecs: vec!["opus".to_string(), "G722".to_string()],
736///     echo_cancellation: true,
737///     noise_suppression: true,
738///     auto_gain_control: false, // Disable AGC
739///     max_bandwidth_kbps: Some(128),
740///     require_srtp: true,
741///     srtp_profiles: vec!["AES_CM_128_HMAC_SHA1_80".to_string()],
742///     rtp_port_start: 16384,
743///     rtp_port_end: 32767,
744///     preferred_ptime: Some(20),
745///     custom_sdp_attributes: HashMap::new(),
746///     dtmf_enabled: true,
747/// };
748/// 
749/// let config = ClientConfig::new()
750///     .with_media(custom_media)
751///     .with_user_agent("CustomApp/1.0".to_string());
752/// 
753/// assert!(!config.media.auto_gain_control);
754/// assert!(config.media.require_srtp);
755/// assert_eq!(config.media.rtp_port_start, 16384);
756/// ```
757/// 
758/// ## Configuration Validation
759/// 
760/// ```rust
761/// use rvoip_client_core::client::config::ClientConfig;
762/// 
763/// let config = ClientConfig::new()
764///     .with_sip_addr("0.0.0.0:5060".parse().unwrap())
765///     .with_media_addr("0.0.0.0:0".parse().unwrap());
766/// 
767/// // Verify default settings
768/// assert!(config.max_concurrent_calls > 0);
769/// assert!(config.session_timeout_secs > 0);
770/// assert!(config.enable_audio);
771/// assert!(!config.enable_video); // Default: video disabled
772/// assert!(config.domain.is_none()); // Default: no domain
773/// 
774/// // Verify media defaults
775/// assert_eq!(config.media.rtp_port_start, 10000);
776/// assert_eq!(config.media.rtp_port_end, 20000);
777/// assert!(config.media.rtp_port_start < config.media.rtp_port_end);
778/// ```
779#[derive(Debug, Clone, Serialize, Deserialize)]
780pub struct ClientConfig {
781    /// Local SIP bind address
782    pub local_sip_addr: SocketAddr,
783    /// Local media bind address  
784    pub local_media_addr: SocketAddr,
785    /// User agent string
786    pub user_agent: String,
787    /// Media configuration
788    pub media: MediaConfig,
789    /// Maximum number of concurrent calls
790    pub max_concurrent_calls: usize,
791    /// Session timeout in seconds
792    pub session_timeout_secs: u64,
793    /// Enable audio processing
794    pub enable_audio: bool,
795    /// Enable video processing (future)
796    pub enable_video: bool,
797    /// SIP domain (optional)
798    pub domain: Option<String>,
799}
800
801impl ClientConfig {
802    /// Create a new client configuration with sensible defaults
803    /// 
804    /// Initializes a ClientConfig with default values suitable for most applications.
805    /// The configuration can be customized using the builder pattern methods.
806    /// 
807    /// # Default Values
808    /// 
809    /// - **SIP Address**: `127.0.0.1:5060` (bind to localhost, standard SIP port)
810    /// - **Media Address**: `127.0.0.1:0` (port 0 = automatic allocation when media session is created)
811    /// - **User Agent**: `rvoip-client-core/0.1.0`
812    /// - **Max Calls**: 10 concurrent calls
813    /// - **Timeout**: 300 seconds (5 minutes)
814    /// - **Audio**: Enabled
815    /// - **Video**: Disabled
816    /// - **Media**: Default MediaConfig with standard codecs
817    /// 
818    /// # Returns
819    /// 
820    /// A new ClientConfig with default settings
821    /// 
822    /// # Examples
823    /// 
824    /// ## Basic Usage
825    /// 
826    /// ```rust
827    /// use rvoip_client_core::client::config::ClientConfig;
828    /// 
829    /// let config = ClientConfig::new();
830    /// 
831    /// // Verify defaults
832    /// assert_eq!(config.local_sip_addr.ip().to_string(), "127.0.0.1");
833    /// assert_eq!(config.local_sip_addr.port(), 5060); // Standard SIP port
834    /// assert_eq!(config.max_concurrent_calls, 10);
835    /// assert_eq!(config.session_timeout_secs, 300);
836    /// assert!(config.enable_audio);
837    /// assert!(!config.enable_video);
838    /// assert!(config.domain.is_none());
839    /// ```
840    /// 
841    /// ## Immediate Customization
842    /// 
843    /// ```rust
844    /// use rvoip_client_core::client::config::ClientConfig;
845    /// 
846    /// let config = ClientConfig::new()
847    ///     .with_sip_addr("192.168.1.100:5060".parse().unwrap())
848    ///     .with_user_agent("MyApp/1.0".to_string())
849    ///     .with_max_calls(5);
850    /// 
851    /// assert_eq!(config.local_sip_addr.ip().to_string(), "192.168.1.100");
852    /// assert_eq!(config.local_sip_addr.port(), 5060);
853    /// assert_eq!(config.user_agent, "MyApp/1.0");
854    /// assert_eq!(config.max_concurrent_calls, 5);
855    /// ```
856    pub fn new() -> Self {
857        Self {
858            local_sip_addr: "127.0.0.1:5060".parse().unwrap(),
859            local_media_addr: "127.0.0.1:0".parse().unwrap(), // Port 0 = automatic allocation via GlobalPortAllocator
860            user_agent: "rvoip-client-core/0.1.0".to_string(),
861            media: MediaConfig::default(),
862            max_concurrent_calls: 10,
863            session_timeout_secs: 300,
864            enable_audio: true,
865            enable_video: false,
866            domain: None,
867        }
868    }
869
870    /// Set the local SIP bind address for signaling
871    /// 
872    /// Configures the local address and port that the SIP client will bind to
873    /// for receiving SIP messages. Use `0.0.0.0` to bind to all interfaces
874    /// and port `0` to let the OS assign an available port.
875    /// 
876    /// # Arguments
877    /// 
878    /// * `addr` - The socket address to bind SIP signaling to
879    /// 
880    /// # Examples
881    /// 
882    /// ```rust
883    /// use rvoip_client_core::client::config::ClientConfig;
884    /// use std::net::SocketAddr;
885    /// 
886    /// // Bind to specific address and port
887    /// let config = ClientConfig::new()
888    ///     .with_sip_addr("192.168.1.100:5060".parse().unwrap());
889    /// 
890    /// assert_eq!(config.local_sip_addr.ip().to_string(), "192.168.1.100");
891    /// assert_eq!(config.local_sip_addr.port(), 5060);
892    /// 
893    /// // Bind to all interfaces with OS-assigned port
894    /// let config2 = ClientConfig::new()
895    ///     .with_sip_addr("0.0.0.0:0".parse().unwrap());
896    /// 
897    /// assert_eq!(config2.local_sip_addr.ip().to_string(), "0.0.0.0");
898    /// assert_eq!(config2.local_sip_addr.port(), 0);
899    /// ```
900    pub fn with_sip_addr(mut self, addr: SocketAddr) -> Self {
901        self.local_sip_addr = addr;
902        self
903    }
904
905    /// Set the local media bind address for RTP streams
906    /// 
907    /// Configures the local address that will be used for RTP media streams.
908    /// This is typically the same as the SIP address but can be different
909    /// for advanced network configurations.
910    /// 
911    /// # Arguments
912    /// 
913    /// * `addr` - The socket address to bind RTP media to
914    /// 
915    /// # Examples
916    /// 
917    /// ```rust
918    /// use rvoip_client_core::client::config::ClientConfig;
919    /// 
920    /// // Use same address for SIP and media
921    /// let addr = "192.168.1.100:0".parse().unwrap();
922    /// let config = ClientConfig::new()
923    ///     .with_sip_addr(addr)
924    ///     .with_media_addr(addr);
925    /// 
926    /// assert_eq!(config.local_sip_addr.ip(), config.local_media_addr.ip());
927    /// 
928    /// // Use different addresses (advanced networking)
929    /// let config2 = ClientConfig::new()
930    ///     .with_sip_addr("10.0.0.100:5060".parse().unwrap())
931    ///     .with_media_addr("192.168.1.100:0".parse().unwrap());
932    /// 
933    /// assert_ne!(config2.local_sip_addr.ip(), config2.local_media_addr.ip());
934    /// ```
935    pub fn with_media_addr(mut self, addr: SocketAddr) -> Self {
936        self.local_media_addr = addr;
937        self
938    }
939
940    /// Set the User-Agent string for SIP identification
941    /// 
942    /// The User-Agent header identifies the client software in SIP messages.
943    /// It's helpful for debugging and server-side logging.
944    /// 
945    /// # Arguments
946    /// 
947    /// * `user_agent` - String identifying the client application
948    /// 
949    /// # Examples
950    /// 
951    /// ```rust
952    /// use rvoip_client_core::client::config::ClientConfig;
953    /// 
954    /// let config = ClientConfig::new()
955    ///     .with_user_agent("MyVoIPApp/2.1.0".to_string());
956    /// 
957    /// assert_eq!(config.user_agent, "MyVoIPApp/2.1.0");
958    /// 
959    /// // Enterprise naming convention
960    /// let enterprise_config = ClientConfig::new()
961    ///     .with_user_agent("CorporatePhone/1.0 (Build 12345)".to_string());
962    /// 
963    /// assert!(enterprise_config.user_agent.contains("CorporatePhone"));
964    /// assert!(enterprise_config.user_agent.contains("Build"));
965    /// ```
966    pub fn with_user_agent(mut self, user_agent: String) -> Self {
967        self.user_agent = user_agent;
968        self
969    }
970
971    /// Set preferred audio codecs (convenience method)
972    /// 
973    /// This is a convenience method that sets the preferred codec list
974    /// in the media configuration. Codecs are tried in the order specified.
975    /// 
976    /// # Arguments
977    /// 
978    /// * `codecs` - Vector of codec names in order of preference
979    /// 
980    /// # Examples
981    /// 
982    /// ```rust
983    /// use rvoip_client_core::client::config::ClientConfig;
984    /// 
985    /// let config = ClientConfig::new()
986    ///     .with_codecs(vec![
987    ///         "opus".to_string(),
988    ///         "G722".to_string(),
989    ///         "PCMU".to_string()
990    ///     ]);
991    /// 
992    /// assert_eq!(config.media.preferred_codecs[0], "opus");
993    /// assert_eq!(config.media.preferred_codecs[1], "G722");
994    /// assert_eq!(config.media.preferred_codecs[2], "PCMU");
995    /// assert_eq!(config.media.preferred_codecs.len(), 3);
996    /// ```
997    pub fn with_codecs(mut self, codecs: Vec<String>) -> Self {
998        self.media.preferred_codecs = codecs;
999        self
1000    }
1001    
1002    /// Set complete media configuration
1003    /// 
1004    /// Replaces the entire media configuration with a custom MediaConfig.
1005    /// This provides full control over all media-related settings.
1006    /// 
1007    /// # Arguments
1008    /// 
1009    /// * `media` - Custom MediaConfig with desired settings
1010    /// 
1011    /// # Examples
1012    /// 
1013    /// ```rust
1014    /// use rvoip_client_core::client::config::{ClientConfig, MediaConfig};
1015    /// use std::collections::HashMap;
1016    /// 
1017    /// let custom_media = MediaConfig {
1018    ///     preferred_codecs: vec!["opus".to_string()],
1019    ///     echo_cancellation: false,
1020    ///     noise_suppression: true,
1021    ///     auto_gain_control: true,
1022    ///     max_bandwidth_kbps: Some(64),
1023    ///     require_srtp: true,
1024    ///     srtp_profiles: vec!["AES_CM_128_HMAC_SHA1_80".to_string()],
1025    ///     rtp_port_start: 20000,
1026    ///     rtp_port_end: 30000,
1027    ///     preferred_ptime: Some(40),
1028    ///     custom_sdp_attributes: HashMap::new(),
1029    ///     dtmf_enabled: true,
1030    /// };
1031    /// 
1032    /// let config = ClientConfig::new().with_media(custom_media);
1033    /// 
1034    /// assert!(!config.media.echo_cancellation);
1035    /// assert!(config.media.require_srtp);
1036    /// assert_eq!(config.media.max_bandwidth_kbps, Some(64));
1037    /// assert_eq!(config.media.rtp_port_start, 20000);
1038    /// ```
1039    pub fn with_media(mut self, media: MediaConfig) -> Self {
1040        self.media = media;
1041        self
1042    }
1043    
1044    /// Set media configuration using a preset
1045    /// 
1046    /// Applies a predefined media configuration optimized for specific use cases.
1047    /// This is a convenience method that replaces the current media config
1048    /// with one generated from the specified preset.
1049    /// 
1050    /// # Arguments
1051    /// 
1052    /// * `preset` - MediaPreset to use for configuration
1053    /// 
1054    /// # Examples
1055    /// 
1056    /// ```rust
1057    /// use rvoip_client_core::client::config::{ClientConfig, MediaPreset};
1058    /// 
1059    /// // Voice-optimized for phone calls
1060    /// let voice_config = ClientConfig::new()
1061    ///     .with_media_preset(MediaPreset::VoiceOptimized);
1062    /// 
1063    /// assert!(voice_config.media.echo_cancellation);
1064    /// assert!(voice_config.media.noise_suppression);
1065    /// 
1066    /// // Low bandwidth for mobile
1067    /// let mobile_config = ClientConfig::new()
1068    ///     .with_media_preset(MediaPreset::LowBandwidth);
1069    /// 
1070    /// assert_eq!(mobile_config.media.max_bandwidth_kbps, Some(32));
1071    /// 
1072    /// // Secure for enterprise
1073    /// let secure_config = ClientConfig::new()
1074    ///     .with_media_preset(MediaPreset::Secure);
1075    /// 
1076    /// assert!(secure_config.media.require_srtp);
1077    /// ```
1078    pub fn with_media_preset(mut self, preset: MediaPreset) -> Self {
1079        self.media = MediaConfig::from_preset(preset);
1080        self
1081    }
1082
1083    /// Set maximum number of concurrent calls
1084    /// 
1085    /// Configures the maximum number of calls that can be active simultaneously.
1086    /// This helps with resource management and prevents overloading the client.
1087    /// 
1088    /// # Arguments
1089    /// 
1090    /// * `max_calls` - Maximum number of concurrent calls (must be > 0)
1091    /// 
1092    /// # Examples
1093    /// 
1094    /// ```rust
1095    /// use rvoip_client_core::client::config::ClientConfig;
1096    /// 
1097    /// // Single-line phone
1098    /// let single_line = ClientConfig::new().with_max_calls(1);
1099    /// assert_eq!(single_line.max_concurrent_calls, 1);
1100    /// 
1101    /// // Small office setup
1102    /// let office_phone = ClientConfig::new().with_max_calls(5);
1103    /// assert_eq!(office_phone.max_concurrent_calls, 5);
1104    /// 
1105    /// // Call center agent
1106    /// let call_center = ClientConfig::new().with_max_calls(20);
1107    /// assert_eq!(call_center.max_concurrent_calls, 20);
1108    /// 
1109    /// // Enterprise server
1110    /// let enterprise = ClientConfig::new().with_max_calls(100);
1111    /// assert_eq!(enterprise.max_concurrent_calls, 100);
1112    /// ```
1113    pub fn with_max_calls(mut self, max_calls: usize) -> Self {
1114        self.max_concurrent_calls = max_calls;
1115        self
1116    }
1117    
1118    /// Get the preferred codecs list (backwards compatibility)
1119    /// 
1120    /// Returns a slice of the preferred codec names in order of preference.
1121    /// This is a convenience method that provides direct access to the
1122    /// codec list without going through the media configuration.
1123    /// 
1124    /// # Returns
1125    /// 
1126    /// A slice containing codec names in preference order
1127    /// 
1128    /// # Examples
1129    /// 
1130    /// ```rust
1131    /// use rvoip_client_core::client::config::ClientConfig;
1132    /// 
1133    /// let config = ClientConfig::new()
1134    ///     .with_codecs(vec![
1135    ///         "opus".to_string(),
1136    ///         "G722".to_string(),
1137    ///         "PCMU".to_string()
1138    ///     ]);
1139    /// 
1140    /// let codecs = config.preferred_codecs();
1141    /// assert_eq!(codecs.len(), 3);
1142    /// assert_eq!(codecs[0], "opus");
1143    /// assert_eq!(codecs[1], "G722");
1144    /// assert_eq!(codecs[2], "PCMU");
1145    /// 
1146    /// // Check for specific codec support
1147    /// assert!(codecs.contains(&"opus".to_string()));
1148    /// assert!(!codecs.contains(&"G729".to_string()));
1149    /// ```
1150    pub fn preferred_codecs(&self) -> &[String] {
1151        &self.media.preferred_codecs
1152    }
1153}
1154
1155impl Default for ClientConfig {
1156    fn default() -> Self {
1157        Self::new()
1158    }
1159}