rvoip_client_core/client/
builder.rs

1//! Client builder for creating SIP clients
2//! 
3//! This module provides a fluent builder interface for constructing SIP clients
4//! with comprehensive configuration options. The builder pattern allows for
5//! readable, flexible client configuration while providing sensible defaults.
6//! 
7//! # Architecture
8//! 
9//! The `ClientBuilder` uses the builder pattern to construct a `ClientManager`
10//! with all necessary configuration. It supports:
11//! 
12//! - Network configuration (local addresses, ports)
13//! - Media configuration (codecs, SRTP, echo cancellation)
14//! - SIP settings (user agent, domain)
15//! - Resource limits (concurrent calls, bandwidth)
16//! - Fluent sub-builders for complex configuration
17//! 
18//! # Examples
19//! 
20//! ## Basic Client Setup
21//! 
22//! ```rust
23//! use rvoip_client_core::ClientBuilder;
24//! 
25//! # tokio_test::block_on(async {
26//! let client = ClientBuilder::new()
27//!     .local_address("127.0.0.1:5060".parse().unwrap())
28//!     .domain("example.com")
29//!     .user_agent("MyApp/1.0")
30//!     .build()
31//!     .await
32//!     .expect("Failed to build client");
33//! # })
34//! ```
35//! 
36//! ## Advanced Media Configuration
37//! 
38//! ```rust
39//! use rvoip_client_core::{ClientBuilder, MediaPreset};
40//! 
41//! # tokio_test::block_on(async {
42//! let client = ClientBuilder::new()
43//!     .local_address("0.0.0.0:5060".parse().unwrap())
44//!     .media_address("192.168.1.100:7000".parse().unwrap())
45//!     .with_media(|m| m
46//!         .codecs(vec!["opus", "G722", "PCMU"])
47//!         .require_srtp(true)
48//!         .echo_cancellation(true)
49//!         .noise_suppression(true)
50//!         .max_bandwidth_kbps(256)
51//!         .rtp_ports(7000..8000)
52//!     )
53//!     .max_concurrent_calls(10)
54//!     .build()
55//!     .await
56//!     .expect("Failed to build client");
57//! # })
58//! ```
59
60use std::sync::Arc;
61use crate::{ClientConfig, ClientResult, client::ClientManager};
62use super::config::{MediaConfig, MediaPreset};
63use super::media_builder::MediaConfigBuilder;
64
65/// Fluent builder for creating SIP clients with comprehensive configuration
66/// 
67/// The `ClientBuilder` provides a chainable interface for constructing SIP clients
68/// with all necessary configuration options. It encapsulates the complexity of
69/// client setup while providing sensible defaults and validation.
70/// 
71/// # Design Principles
72/// 
73/// - **Fluent Interface**: All configuration methods return `Self` for chaining
74/// - **Sensible Defaults**: Works out-of-the-box with minimal configuration
75/// - **Type Safety**: Compile-time validation of configuration parameters
76/// - **Async Ready**: Built for async/await patterns with tokio integration
77/// - **Flexible Media**: Supports both simple and advanced media configuration
78/// 
79/// # Configuration Categories
80/// 
81/// ## Network Configuration
82/// - Local SIP and media addresses
83/// - Port ranges for RTP traffic
84/// - Domain and transport settings
85/// 
86/// ## Media Configuration  
87/// - Codec preferences and capabilities
88/// - Audio processing (echo cancellation, noise suppression)
89/// - Security (SRTP requirements)
90/// - Bandwidth and quality settings
91/// 
92/// ## SIP Configuration
93/// - User agent identification
94/// - Protocol compliance settings
95/// - Extension support
96/// 
97/// ## Resource Management
98/// - Concurrent call limits
99/// - Memory and CPU constraints
100/// - Network resource allocation
101/// 
102/// # Examples
103/// 
104/// ## Simple Desktop Client
105/// 
106/// ```rust
107/// use rvoip_client_core::ClientBuilder;
108/// 
109/// # tokio_test::block_on(async {
110/// let client = ClientBuilder::new()
111///     .local_address("127.0.0.1:5060".parse().unwrap())
112///     .domain("sip.example.com")
113///     .echo_cancellation(true)
114///     .build()
115///     .await.unwrap();
116/// # })
117/// ```
118/// 
119/// ## Enterprise Server Setup
120/// 
121/// ```rust
122/// use rvoip_client_core::{ClientBuilder, MediaPreset};
123/// 
124/// # tokio_test::block_on(async {
125/// let client = ClientBuilder::new()
126///     .local_address("0.0.0.0:5060".parse().unwrap())
127///     .media_address("192.168.1.100:0".parse().unwrap())
128///     .domain("enterprise.example.com")
129///     .user_agent("EnterpriseVoIP/2.1")
130///     .media_preset(MediaPreset::VoiceOptimized)
131///     .max_concurrent_calls(100)
132///     .rtp_ports(10000, 20000)
133///     .build()
134///     .await.unwrap();
135/// # })
136/// ```
137/// 
138/// ## WebRTC-Compatible Client
139/// 
140/// ```rust
141/// use rvoip_client_core::ClientBuilder;
142/// 
143/// # tokio_test::block_on(async {
144/// let client = ClientBuilder::new()
145///     .local_address("127.0.0.1:5060".parse().unwrap())
146///     .with_media(|m| m
147///         .codecs(vec!["opus", "G722"])
148///         .require_srtp(true)
149///         .echo_cancellation(true)
150///         .auto_gain_control(true)
151///         .noise_suppression(true)
152///     )
153///     .build()
154///     .await.unwrap();
155/// # })
156/// ```
157pub struct ClientBuilder {
158    config: ClientConfig,
159}
160
161impl ClientBuilder {
162    /// Create a new client builder with default configuration
163    /// 
164    /// Initializes a new `ClientBuilder` with sensible default values suitable
165    /// for most use cases. The defaults include:
166    /// 
167    /// - Local SIP address: `127.0.0.1:5060`
168    /// - Local media address: `127.0.0.1:0` (auto-assigned port)
169    /// - User agent: Generated from crate name and version
170    /// - Media configuration: Basic codecs with standard settings
171    /// - No domain specified (must be set for registration)
172    /// - Maximum concurrent calls: 10
173    /// 
174    /// # Returns
175    /// 
176    /// A new `ClientBuilder` instance ready for configuration chaining.
177    /// 
178    /// # Examples
179    /// 
180    /// ## Basic Initialization
181    /// 
182    /// ```rust
183    /// use rvoip_client_core::ClientBuilder;
184    /// 
185    /// let builder = ClientBuilder::new();
186    /// 
187    /// // Builder is ready for configuration
188    /// # tokio_test::block_on(async {
189    /// let client = builder
190    ///     .local_address("127.0.0.1:5060".parse().unwrap())
191    ///     .build()
192    ///     .await.unwrap();
193    /// # })
194    /// ```
195    /// 
196    /// ## Chained Configuration
197    /// 
198    /// ```rust
199    /// use rvoip_client_core::ClientBuilder;
200    /// 
201    /// # tokio_test::block_on(async {
202    /// let client = ClientBuilder::new()
203    ///     .local_address("0.0.0.0:5060".parse().unwrap())
204    ///     .domain("sip.example.com")
205    ///     .user_agent("CustomApp/1.0")
206    ///     .max_concurrent_calls(50)
207    ///     .build()
208    ///     .await.unwrap();
209    /// # })
210    /// ```
211    pub fn new() -> Self {
212        Self {
213            config: ClientConfig::default(),
214        }
215    }
216    
217    /// Set the local SIP address for binding the SIP transport
218    /// 
219    /// Configures the local socket address where the SIP client will bind to
220    /// listen for incoming SIP messages and send outgoing requests. This address
221    /// is used for all SIP protocol communication.
222    /// 
223    /// # Arguments
224    /// 
225    /// * `addr` - The socket address (IP and port) to bind for SIP communication
226    /// 
227    /// # Network Considerations
228    /// 
229    /// - **IP Address**: Use `0.0.0.0` to bind to all interfaces, or a specific IP for single-interface binding
230    /// - **Port**: Standard SIP port is 5060 (UDP/TCP) or 5061 (TLS)
231    /// - **Firewall**: Ensure the specified port is accessible for incoming connections
232    /// - **NAT**: Consider using STUN/TURN for NAT traversal in production environments
233    /// 
234    /// # Examples
235    /// 
236    /// ## Standard SIP Port
237    /// 
238    /// ```rust
239    /// use rvoip_client_core::ClientBuilder;
240    /// 
241    /// # tokio_test::block_on(async {
242    /// let client = ClientBuilder::new()
243    ///     .local_address("127.0.0.1:5060".parse().unwrap())
244    ///     .build()
245    ///     .await.unwrap();
246    /// # })
247    /// ```
248    /// 
249    /// ## All Interfaces Binding
250    /// 
251    /// ```rust
252    /// use rvoip_client_core::ClientBuilder;
253    /// 
254    /// # tokio_test::block_on(async {
255    /// let client = ClientBuilder::new()
256    ///     .local_address("0.0.0.0:5060".parse().unwrap())
257    ///     .domain("sip.provider.com")
258    ///     .build()
259    ///     .await.unwrap();
260    /// # })
261    /// ```
262    /// 
263    /// ## Custom Port
264    /// 
265    /// ```rust
266    /// use rvoip_client_core::ClientBuilder;
267    /// 
268    /// # tokio_test::block_on(async {
269    /// let client = ClientBuilder::new()
270    ///     .local_address("127.0.0.1:15060".parse().unwrap())
271    ///     .build()
272    ///     .await.unwrap();
273    /// # })
274    /// ```
275    pub fn local_address(mut self, addr: std::net::SocketAddr) -> Self {
276        self.config.local_sip_addr = addr;
277        self
278    }
279    
280    /// Set the local media address for RTP/RTCP traffic
281    /// 
282    /// Configures the local address where the client will bind for media traffic.
283    /// This address is used for RTP (Real-time Transport Protocol) audio streams
284    /// and RTCP (Real-time Control Protocol) feedback messages.
285    /// 
286    /// # Arguments
287    /// 
288    /// * `addr` - The socket address (IP and port) to bind for media communication
289    /// 
290    /// # Media Network Considerations
291    /// 
292    /// - **Separate from SIP**: Media traffic is independent of SIP signaling
293    /// - **Port Zero**: When set to port 0, uses automatic port allocation via GlobalPortAllocator
294    /// - **Firewall**: RTP requires a range of UDP ports to be accessible
295    /// - **Quality of Service**: Consider network QoS settings for media traffic
296    /// - **NAT Handling**: Media traffic often requires additional NAT traversal
297    /// 
298    /// # Examples
299    /// 
300    /// ## Auto-assigned Media Port
301    /// 
302    /// ```rust
303    /// use rvoip_client_core::ClientBuilder;
304    /// 
305    /// # tokio_test::block_on(async {
306    /// let client = ClientBuilder::new()
307    ///     .local_address("127.0.0.1:5060".parse().unwrap())
308    ///     .media_address("127.0.0.1:0".parse().unwrap()) // Port auto-assigned
309    ///     .build()
310    ///     .await.unwrap();
311    /// # })
312    /// ```
313    /// 
314    /// ## Specific Media Interface
315    /// 
316    /// ```rust
317    /// use rvoip_client_core::ClientBuilder;
318    /// 
319    /// # tokio_test::block_on(async {
320    /// let client = ClientBuilder::new()
321    ///     .local_address("127.0.0.1:5060".parse().unwrap())
322    ///     .media_address("127.0.0.1:7000".parse().unwrap())
323    ///     .rtp_ports(7000, 8000) // Define RTP port range
324    ///     .build()
325    ///     .await.unwrap();
326    /// # })
327    /// ```
328    /// 
329    /// ## Multi-homed Configuration
330    /// 
331    /// ```rust
332    /// use rvoip_client_core::ClientBuilder;
333    /// 
334    /// # tokio_test::block_on(async {
335    /// // SIP on one port, media on another
336    /// let client = ClientBuilder::new()
337    ///     .local_address("127.0.0.1:5060".parse().unwrap())
338    ///     .media_address("127.0.0.1:0".parse().unwrap())
339    ///     .build()
340    ///     .await.unwrap();
341    /// # })
342    /// ```
343    pub fn media_address(mut self, addr: std::net::SocketAddr) -> Self {
344        self.config.local_media_addr = addr;
345        self
346    }
347    
348    /// Set the User-Agent header value for SIP messages
349    /// 
350    /// Configures the User-Agent header that will be included in outgoing SIP
351    /// requests and responses. This header identifies the client software and
352    /// version to remote SIP endpoints and servers.
353    /// 
354    /// # Arguments
355    /// 
356    /// * `user_agent` - String identifying the client application and version
357    /// 
358    /// # SIP Protocol Considerations
359    /// 
360    /// - **RFC 3261 Compliance**: User-Agent header is recommended in SIP messages
361    /// - **Identification**: Helps with debugging and interoperability testing
362    /// - **Statistics**: SIP servers often collect User-Agent statistics
363    /// - **Format**: Typically follows "ProductName/Version" convention
364    /// 
365    /// # Examples
366    /// 
367    /// ## Application Identification
368    /// 
369    /// ```rust
370    /// use rvoip_client_core::ClientBuilder;
371    /// 
372    /// # tokio_test::block_on(async {
373    /// let client = ClientBuilder::new()
374    ///     .local_address("127.0.0.1:5060".parse().unwrap())
375    ///     .user_agent("MyVoIPApp/2.1.0")
376    ///     .build()
377    ///     .await.unwrap();
378    /// # })
379    /// ```
380    /// 
381    /// ## Platform-Specific Agent
382    /// 
383    /// ```rust
384    /// use rvoip_client_core::ClientBuilder;
385    /// 
386    /// # tokio_test::block_on(async {
387    /// let platform = std::env::consts::OS;
388    /// let user_agent = format!("EnterprisePhone/1.0 ({})", platform);
389    /// 
390    /// let client = ClientBuilder::new()
391    ///     .local_address("127.0.0.1:5060".parse().unwrap())
392    ///     .user_agent(user_agent)
393    ///     .build()
394    ///     .await.unwrap();
395    /// # })
396    /// ```
397    /// 
398    /// ## SDK Integration
399    /// 
400    /// ```rust
401    /// use rvoip_client_core::ClientBuilder;
402    /// 
403    /// # tokio_test::block_on(async {
404    /// let client = ClientBuilder::new()
405    ///     .local_address("127.0.0.1:5060".parse().unwrap())
406    ///     .user_agent("CustomerApp/3.2 rvoip-client-core/1.0")
407    ///     .build()
408    ///     .await.unwrap();
409    /// # })
410    /// ```
411    pub fn user_agent(mut self, user_agent: impl Into<String>) -> Self {
412        self.config.user_agent = user_agent.into();
413        self
414    }
415    
416    /// Set the SIP domain for registration and routing
417    /// 
418    /// Configures the SIP domain that this client belongs to. This domain is used
419    /// for SIP registration, request routing, and URI construction. It typically
420    /// corresponds to the SIP service provider's domain.
421    /// 
422    /// # Arguments
423    /// 
424    /// * `domain` - The SIP domain name (e.g., "sip.provider.com")
425    /// 
426    /// # SIP Domain Usage
427    /// 
428    /// - **Registration**: Used as the domain in REGISTER requests
429    /// - **URI Construction**: Forms the domain part of SIP URIs (sip:user@domain)
430    /// - **Routing**: Helps determine where to send outbound requests
431    /// - **Authentication**: Often tied to authentication realm
432    /// 
433    /// # Examples
434    /// 
435    /// ## Service Provider Domain
436    /// 
437    /// ```rust
438    /// use rvoip_client_core::ClientBuilder;
439    /// 
440    /// # tokio_test::block_on(async {
441    /// let client = ClientBuilder::new()
442    ///     .local_address("127.0.0.1:5060".parse().unwrap())
443    ///     .domain("sip.provider.com")
444    ///     .build()
445    ///     .await.unwrap();
446    /// # })
447    /// ```
448    /// 
449    /// ## Enterprise Domain
450    /// 
451    /// ```rust
452    /// use rvoip_client_core::ClientBuilder;
453    /// 
454    /// # tokio_test::block_on(async {
455    /// let client = ClientBuilder::new()
456    ///     .local_address("0.0.0.0:5060".parse().unwrap())
457    ///     .domain("pbx.company.com")
458    ///     .user_agent("CompanyPhone/1.0")
459    ///     .build()
460    ///     .await.unwrap();
461    /// # })
462    /// ```
463    /// 
464    /// ## Local Development
465    /// 
466    /// ```rust
467    /// use rvoip_client_core::ClientBuilder;
468    /// 
469    /// # tokio_test::block_on(async {
470    /// let client = ClientBuilder::new()
471    ///     .local_address("127.0.0.1:5060".parse().unwrap())
472    ///     .domain("localhost")
473    ///     .build()
474    ///     .await.unwrap();
475    /// # })
476    /// ```
477    pub fn domain(mut self, domain: impl Into<String>) -> Self {
478        self.config.domain = Some(domain.into());
479        self
480    }
481    
482    /// Set preferred audio codecs in priority order
483    /// 
484    /// Configures the list of preferred audio codecs for media negotiation.
485    /// Codecs are specified in order of preference, with the first codec being
486    /// the most preferred. During SDP negotiation, the client will attempt to
487    /// use codecs in the specified order.
488    /// 
489    /// # Arguments
490    /// 
491    /// * `codecs` - Iterator of codec names in preference order
492    /// 
493    /// # Codec Considerations
494    /// 
495    /// - **Quality vs Bandwidth**: Balance audio quality with network bandwidth
496    /// - **Compatibility**: Ensure codecs are supported by remote endpoints
497    /// - **Computational Load**: Consider CPU requirements for codec processing
498    /// - **Network Conditions**: Some codecs handle packet loss better than others
499    /// 
500    /// # Common Codecs
501    /// 
502    /// - **opus**: Modern, high-quality codec with excellent packet loss resilience
503    /// - **G722**: Wideband codec (7kHz) with good quality
504    /// - **PCMU/PCMA**: Standard narrowband codecs with universal compatibility
505    /// - **G729**: Low-bandwidth codec, good for limited networks
506    /// - **iLBC**: Designed for packet loss resilience
507    /// 
508    /// # Examples
509    /// 
510    /// ## High-Quality Configuration
511    /// 
512    /// ```rust
513    /// use rvoip_client_core::ClientBuilder;
514    /// 
515    /// # tokio_test::block_on(async {
516    /// let client = ClientBuilder::new()
517    ///     .local_address("127.0.0.1:5060".parse().unwrap())
518    ///     .codecs(vec!["opus", "G722", "PCMU"])
519    ///     .build()
520    ///     .await.unwrap();
521    /// # })
522    /// ```
523    /// 
524    /// ## Low-Bandwidth Configuration
525    /// 
526    /// ```rust
527    /// use rvoip_client_core::ClientBuilder;
528    /// 
529    /// # tokio_test::block_on(async {
530    /// let client = ClientBuilder::new()
531    ///     .local_address("127.0.0.1:5060".parse().unwrap())
532    ///     .codecs(vec!["G729", "iLBC", "PCMU"])
533    ///     .build()
534    ///     .await.unwrap();
535    /// # })
536    /// ```
537    /// 
538    /// ## Universal Compatibility
539    /// 
540    /// ```rust
541    /// use rvoip_client_core::ClientBuilder;
542    /// 
543    /// # tokio_test::block_on(async {
544    /// let client = ClientBuilder::new()
545    ///     .local_address("127.0.0.1:5060".parse().unwrap())
546    ///     .codecs(vec!["PCMU", "PCMA", "G722"])
547    ///     .build()
548    ///     .await.unwrap();
549    /// # })
550    /// ```
551    pub fn codecs<I, S>(mut self, codecs: I) -> Self 
552    where
553        I: IntoIterator<Item = S>,
554        S: Into<String>,
555    {
556        self.config.media.preferred_codecs = codecs.into_iter().map(Into::into).collect();
557        self
558    }
559    
560    /// Configure media settings using a fluent sub-builder interface
561    /// 
562    /// This method provides access to a comprehensive media configuration builder
563    /// that allows fine-grained control over audio processing, codecs, security,
564    /// and network settings. The closure receives a `MediaConfigBuilder` that
565    /// can be chained to configure multiple media options.
566    /// 
567    /// # Arguments
568    /// 
569    /// * `f` - Closure that configures media settings via `MediaConfigBuilder`
570    /// 
571    /// # Media Configuration Options
572    /// 
573    /// The sub-builder provides access to:
574    /// - **Codec Selection**: Preferred codecs and priority ordering
575    /// - **Audio Processing**: Echo cancellation, noise suppression, AGC
576    /// - **Security**: SRTP requirements and key management
577    /// - **Network**: Bandwidth limits, port ranges, DSCP marking
578    /// - **Quality**: Sample rates, frame sizes, packet times
579    /// 
580    /// # Examples
581    /// 
582    /// ## Professional Audio Setup
583    /// 
584    /// ```rust
585    /// use rvoip_client_core::ClientBuilder;
586    /// 
587    /// # tokio_test::block_on(async {
588    /// let client = ClientBuilder::new()
589    ///     .local_address("127.0.0.1:5060".parse().unwrap())
590    ///     .with_media(|m| m
591    ///         .codecs(vec!["opus", "G722", "PCMU"])
592    ///         .echo_cancellation(true)
593    ///         .noise_suppression(true)
594    ///         .auto_gain_control(true)
595    ///         .max_bandwidth_kbps(256)
596    ///         .ptime(20)
597    ///     )
598    ///     .build()
599    ///     .await.unwrap();
600    /// # })
601    /// ```
602    /// 
603    /// ## Secure Enterprise Configuration
604    /// 
605    /// ```rust
606    /// use rvoip_client_core::ClientBuilder;
607    /// 
608    /// # tokio_test::block_on(async {
609    /// let client = ClientBuilder::new()
610    ///     .local_address("0.0.0.0:5060".parse().unwrap())
611    ///     .with_media(|m| m
612    ///         .codecs(vec!["opus", "G722"])
613    ///         .require_srtp(true)
614    ///         .srtp_profiles(vec!["AES_CM_128_HMAC_SHA1_80"])
615    ///         .rtp_ports(10000..20000)
616    /// 
617    ///         .echo_cancellation(true)
618    ///     )
619    ///     .build()
620    ///     .await.unwrap();
621    /// # })
622    /// ```
623    /// 
624    /// ## Low-Bandwidth Mobile Setup
625    /// 
626    /// ```rust
627    /// use rvoip_client_core::ClientBuilder;
628    /// 
629    /// # tokio_test::block_on(async {
630    /// let client = ClientBuilder::new()
631    ///     .local_address("127.0.0.1:5060".parse().unwrap())
632    ///     .with_media(|m| m
633    ///         .codecs(vec!["opus", "iLBC", "G729"])
634    ///         .max_bandwidth_kbps(64)
635    ///         .ptime(40) // Larger packets for efficiency
636    ///         .echo_cancellation(true)
637    ///     )
638    ///     .build()
639    ///     .await.unwrap();
640    /// # })
641    /// ```
642    /// 
643    /// ## WebRTC-Style Configuration
644    /// 
645    /// ```rust
646    /// use rvoip_client_core::ClientBuilder;
647    /// 
648    /// # tokio_test::block_on(async {
649    /// let client = ClientBuilder::new()
650    ///     .local_address("127.0.0.1:5060".parse().unwrap())
651    ///     .with_media(|m| m
652    ///         .codecs(vec!["opus", "G722"])
653    ///         .require_srtp(true)
654    ///         .echo_cancellation(true)
655    ///         .noise_suppression(true)
656    ///         .auto_gain_control(true)
657    ///     )
658    ///     .build()
659    ///     .await.unwrap();
660    /// # })
661    /// ```
662    pub fn with_media<F>(mut self, f: F) -> Self 
663    where
664        F: FnOnce(MediaConfigBuilder) -> MediaConfigBuilder,
665    {
666        let builder = MediaConfigBuilder::new();
667        self.config.media = f(builder).build();
668        self
669    }
670    
671    /// Set media configuration directly
672    pub fn media_config(mut self, media: MediaConfig) -> Self {
673        self.config.media = media;
674        self
675    }
676    
677    /// Apply a predefined media configuration preset
678    /// 
679    /// Media presets provide quick configuration for common use cases by applying
680    /// a set of predefined media settings. This is convenient when you need
681    /// standard configurations without detailed customization.
682    /// 
683    /// # Arguments
684    /// 
685    /// * `preset` - The media preset to apply
686    /// 
687    /// # Available Presets
688    /// 
689    /// - **`VoiceOptimized`**: Optimized for voice calls with echo cancellation and noise suppression
690    /// - **`HighQuality`**: Premium audio quality with wideband codecs and advanced processing
691    /// - **`LowLatency`**: Minimal processing delay for real-time applications
692    /// - **`LowBandwidth`**: Optimized for limited network conditions
693    /// - **`Conference`**: Multi-party conferencing with audio mixing support
694    /// - **`WebRTCCompatible`**: Settings compatible with WebRTC endpoints
695    /// 
696    /// # Examples
697    /// 
698    /// ## Voice-Optimized Desktop Client
699    /// 
700    /// ```rust
701    /// use rvoip_client_core::{ClientBuilder, MediaPreset};
702    /// 
703    /// # tokio_test::block_on(async {
704    /// let client = ClientBuilder::new()
705    ///     .local_address("127.0.0.1:5060".parse().unwrap())
706    ///     .media_preset(MediaPreset::VoiceOptimized)
707    ///     .build()
708    ///     .await.unwrap();
709    /// # })
710    /// ```
711    /// 
712    /// ## Security-Focused System
713    /// 
714    /// ```rust
715    /// use rvoip_client_core::{ClientBuilder, MediaPreset};
716    /// 
717    /// # tokio_test::block_on(async {
718    /// let client = ClientBuilder::new()
719    ///     .local_address("127.0.0.1:5060".parse().unwrap())
720    ///     .media_preset(MediaPreset::Secure)
721    ///     .domain("premium.voip.com")
722    ///     .build()
723    ///     .await
724    ///     .unwrap();
725    /// # })
726    /// ```
727    /// 
728    /// ## Legacy-Compatible Application
729    /// 
730    /// ```rust
731    /// use rvoip_client_core::{ClientBuilder, MediaPreset};
732    /// 
733    /// # tokio_test::block_on(async {
734    /// let client = ClientBuilder::new()
735    ///     .local_address("127.0.0.1:18060".parse().unwrap())
736    ///     .media_preset(MediaPreset::Legacy)
737    ///     .max_concurrent_calls(50)
738    ///     .build()
739    ///     .await
740    ///     .unwrap();
741    /// # })
742    /// ```
743    /// 
744    /// ## Mobile/Limited Bandwidth
745    /// 
746    /// ```rust
747    /// use rvoip_client_core::{ClientBuilder, MediaPreset};
748    /// 
749    /// # tokio_test::block_on(async {
750    /// let client = ClientBuilder::new()
751    ///     .local_address("127.0.0.1:5060".parse().unwrap())
752    ///     .media_preset(MediaPreset::LowBandwidth)
753    ///     .build()
754    ///     .await
755    ///     .unwrap();
756    /// # })
757    /// ```
758    pub fn media_preset(mut self, preset: MediaPreset) -> Self {
759        self.config.media = MediaConfig::from_preset(preset);
760        self
761    }
762    
763    /// Enable or disable acoustic echo cancellation (AEC)
764    /// 
765    /// Acoustic echo cancellation removes the echo of your own voice that
766    /// can occur when the remote party's audio is played through speakers
767    /// instead of headphones. This is essential for hands-free operation.
768    /// 
769    /// # Arguments
770    /// 
771    /// * `enabled` - Whether to enable echo cancellation processing
772    /// 
773    /// # Use Cases
774    /// 
775    /// - **Hands-free calling**: Essential when using speakers instead of headphones
776    /// - **Conference rooms**: Critical for room-based conferencing systems
777    /// - **Desktop applications**: Improves user experience in office environments
778    /// - **Mobile devices**: Important for speakerphone functionality
779    /// 
780    /// # Performance Considerations
781    /// 
782    /// - **CPU Usage**: Echo cancellation requires additional processing power
783    /// - **Latency**: May introduce small amounts of audio delay
784    /// - **Quality**: Generally improves overall call quality significantly
785    /// 
786    /// # Examples
787    /// 
788    /// ```rust
789    /// use rvoip_client_core::ClientBuilder;
790    /// 
791    /// # tokio_test::block_on(async {
792    /// // Enable for desktop/conference use
793    /// let client = ClientBuilder::new()
794    ///     .local_address("127.0.0.1:5060".parse().unwrap())
795    ///     .echo_cancellation(true)
796    ///     .build()
797    ///     .await.unwrap();
798    /// # })
799    /// ```
800    pub fn echo_cancellation(mut self, enabled: bool) -> Self {
801        self.config.media.echo_cancellation = enabled;
802        self
803    }
804    
805    /// Require or allow SRTP (Secure Real-time Transport Protocol)
806    /// 
807    /// SRTP provides encryption and authentication for RTP media streams.
808    /// When required, the client will only establish calls that support
809    /// encrypted media, rejecting unencrypted connections.
810    /// 
811    /// # Arguments
812    /// 
813    /// * `required` - Whether SRTP is mandatory for all media streams
814    /// 
815    /// # Security Considerations
816    /// 
817    /// - **Data Protection**: Encrypts audio streams end-to-end
818    /// - **Integrity**: Protects against media tampering and injection
819    /// - **Compliance**: May be required for regulatory compliance
820    /// - **Performance**: Adds minimal computational overhead
821    /// 
822    /// # Compatibility
823    /// 
824    /// - **WebRTC**: SRTP is mandatory in WebRTC implementations
825    /// - **Legacy Systems**: Some older SIP devices may not support SRTP
826    /// - **Enterprise**: Most modern enterprise systems support SRTP
827    /// 
828    /// # Examples
829    /// 
830    /// ## Security-First Configuration
831    /// 
832    /// ```rust
833    /// use rvoip_client_core::ClientBuilder;
834    /// 
835    /// # tokio_test::block_on(async {
836    /// let client = ClientBuilder::new()
837    ///     .local_address("127.0.0.1:5060".parse().unwrap())
838    ///     .require_srtp(true)
839    ///     .domain("secure.voip.com")
840    ///     .build()
841    ///     .await.unwrap();
842    /// # })
843    /// ```
844    /// 
845    /// ## Flexible Security (SRTP preferred but not required)
846    /// 
847    /// ```rust
848    /// use rvoip_client_core::ClientBuilder;
849    /// 
850    /// # tokio_test::block_on(async {
851    /// let client = ClientBuilder::new()
852    ///     .local_address("127.0.0.1:5060".parse().unwrap())
853    ///     .require_srtp(false) // Allow fallback to RTP
854    ///     .build()
855    ///     .await.unwrap();
856    /// # })
857    /// ```
858    pub fn require_srtp(mut self, required: bool) -> Self {
859        self.config.media.require_srtp = required;
860        self
861    }
862    
863    /// Set the UDP port range for RTP media traffic
864    /// 
865    /// Configures the range of UDP ports that will be used for RTP and RTCP
866    /// media streams. The client will allocate ports within this range for
867    /// each active call's media streams.
868    /// 
869    /// # Arguments
870    /// 
871    /// * `start` - First port in the range (inclusive)
872    /// * `end` - Last port in the range (inclusive)
873    /// 
874    /// # Port Planning Considerations
875    /// 
876    /// - **Concurrent Calls**: Each call typically uses 2 ports (RTP + RTCP)
877    /// - **Firewall Configuration**: All ports in range must be accessible
878    /// - **Range Size**: Should accommodate maximum expected simultaneous calls
879    /// - **Standard Ranges**: Many systems use 10000-20000 or 16384-32767
880    /// 
881    /// # Examples
882    /// 
883    /// ## Standard Enterprise Range
884    /// 
885    /// ```rust
886    /// use rvoip_client_core::ClientBuilder;
887    /// 
888    /// # tokio_test::block_on(async {
889    /// let client = ClientBuilder::new()
890    ///     .local_address("0.0.0.0:5060".parse().unwrap())
891    ///     .rtp_ports(10000, 20000) // 10,000 ports for ~5,000 calls
892    ///     .max_concurrent_calls(1000)
893    ///     .build()
894    ///     .await.unwrap();
895    /// # })
896    /// ```
897    /// 
898    /// ## Small Office Configuration
899    /// 
900    /// ```rust
901    /// use rvoip_client_core::ClientBuilder;
902    /// 
903    /// # tokio_test::block_on(async {
904    /// let client = ClientBuilder::new()
905    ///     .local_address("127.0.0.1:5060".parse().unwrap())
906    ///     .rtp_ports(7000, 7100) // 100 ports for ~50 calls
907    ///     .max_concurrent_calls(25)
908    ///     .build()
909    ///     .await.unwrap();
910    /// # })
911    /// ```
912    /// 
913    /// ## High-Density Server
914    /// 
915    /// ```rust
916    /// use rvoip_client_core::ClientBuilder;
917    /// 
918    /// # tokio_test::block_on(async {
919    /// let client = ClientBuilder::new()
920    ///     .local_address("0.0.0.0:5060".parse().unwrap())
921    ///     .rtp_ports(16384, 32767) // ~16k ports for high capacity
922    ///     .max_concurrent_calls(5000)
923    ///     .build()
924    ///     .await.unwrap();
925    /// # })
926    /// ```
927    pub fn rtp_ports(mut self, start: u16, end: u16) -> Self {
928        self.config.media.rtp_port_start = start;
929        self.config.media.rtp_port_end = end;
930        self
931    }
932    
933    /// Set the maximum number of concurrent calls
934    /// 
935    /// Limits the number of simultaneous active calls that the client can handle.
936    /// This prevents resource exhaustion and ensures predictable performance
937    /// under load. New call attempts beyond this limit will be rejected.
938    /// 
939    /// # Arguments
940    /// 
941    /// * `max` - Maximum number of concurrent calls allowed
942    /// 
943    /// # Resource Planning
944    /// 
945    /// Consider the following resources when setting limits:
946    /// - **CPU**: Audio processing scales with concurrent calls
947    /// - **Memory**: Each call maintains state and buffers
948    /// - **Network**: Bandwidth requirements multiply with call count
949    /// - **Ports**: Each call requires RTP/RTCP port pairs
950    /// 
951    /// # Examples
952    /// 
953    /// ## Desktop Client
954    /// 
955    /// ```rust
956    /// use rvoip_client_core::ClientBuilder;
957    /// 
958    /// # tokio_test::block_on(async {
959    /// let client = ClientBuilder::new()
960    ///     .local_address("127.0.0.1:5060".parse().unwrap())
961    ///     .max_concurrent_calls(5) // Typical for desktop use
962    ///     .build()
963    ///     .await.unwrap();
964    /// # })
965    /// ```
966    /// 
967    /// ## Small Business Server
968    /// 
969    /// ```rust
970    /// use rvoip_client_core::ClientBuilder;
971    /// 
972    /// # tokio_test::block_on(async {
973    /// let client = ClientBuilder::new()
974    ///     .local_address("0.0.0.0:5060".parse().unwrap())
975    ///     .max_concurrent_calls(100)
976    ///     .rtp_ports(10000, 10500) // Adequate port range
977    ///     .build()
978    ///     .await.unwrap();
979    /// # })
980    /// ```
981    /// 
982    /// ## High-Capacity System
983    /// 
984    /// ```rust
985    /// use rvoip_client_core::ClientBuilder;
986    /// 
987    /// # tokio_test::block_on(async {
988    /// let client = ClientBuilder::new()
989    ///     .local_address("0.0.0.0:5060".parse().unwrap())
990    ///     .max_concurrent_calls(10000)
991    ///     .rtp_ports(10000, 40000) // Large port range
992    ///     .with_media(|m| m
993    ///         .codecs(vec!["G729", "PCMU"]) // Low-bandwidth codecs
994    ///         .max_bandwidth_kbps(64)
995    ///     )
996    ///     .build()
997    ///     .await.unwrap();
998    /// # })
999    /// ```
1000    pub fn max_concurrent_calls(mut self, max: usize) -> Self {
1001        self.config.max_concurrent_calls = max;
1002        self
1003    }
1004    
1005    /// Build and initialize the SIP client
1006    /// 
1007    /// Consumes the builder and creates a fully configured `ClientManager` instance.
1008    /// This method performs all necessary initialization including network binding,
1009    /// media system setup, and internal component initialization.
1010    /// 
1011    /// # Returns
1012    /// 
1013    /// Returns a `ClientResult<Arc<ClientManager>>` which will be:
1014    /// - `Ok(client)` on successful initialization
1015    /// - `Err(error)` if initialization fails for any reason
1016    /// 
1017    /// # Initialization Process
1018    /// 
1019    /// The build process performs several critical steps:
1020    /// 1. **Configuration Validation**: Verifies all settings are valid and consistent
1021    /// 2. **Network Binding**: Binds to specified SIP and media addresses
1022    /// 3. **Media System Init**: Initializes audio processing and codec subsystems
1023    /// 4. **Component Startup**: Starts internal services and background tasks
1024    /// 5. **Resource Allocation**: Reserves ports, memory, and other resources
1025    /// 
1026    /// # Error Conditions
1027    /// 
1028    /// The build process can fail for various reasons:
1029    /// - **Network Errors**: Port already in use, invalid addresses, permission denied
1030    /// - **Resource Limits**: Insufficient system resources, file descriptor limits
1031    /// - **Configuration Errors**: Invalid settings, unsupported codec combinations
1032    /// - **System Errors**: Audio device access, network interface issues
1033    /// 
1034    /// # Examples
1035    /// 
1036    /// ## Basic Client Creation
1037    /// 
1038    /// ```rust
1039    /// use rvoip_client_core::ClientBuilder;
1040    /// 
1041    /// # tokio_test::block_on(async {
1042    /// let client = ClientBuilder::new()
1043    ///     .local_address("127.0.0.1:5060".parse().unwrap())
1044    ///     .build()
1045    ///     .await.unwrap();
1046    /// 
1047    /// // Client is ready for use
1048    /// println!("Client initialized successfully");
1049    /// # })
1050    /// ```
1051    /// 
1052    /// ## Error Handling
1053    /// 
1054    /// ```rust
1055    /// use rvoip_client_core::ClientBuilder;
1056    /// 
1057    /// # tokio_test::block_on(async {
1058    /// match ClientBuilder::new()
1059    ///     .local_address("127.0.0.1:5060".parse().unwrap())
1060    ///     .domain("sip.provider.com")
1061    ///     .build()
1062    ///     .await
1063    /// {
1064    ///     Ok(client) => {
1065    ///         println!("Client ready for SIP operations");
1066    ///         // Use client...
1067    ///     }
1068    ///     Err(error) => {
1069    ///         eprintln!("Failed to initialize client: {}", error);
1070    ///         // Handle initialization failure...
1071    ///     }
1072    /// }
1073    /// # })
1074    /// ```
1075    /// 
1076    /// ## Production Configuration
1077    /// 
1078    /// ```rust
1079    /// use rvoip_client_core::{ClientBuilder, MediaPreset};
1080    /// 
1081    /// # tokio_test::block_on(async {
1082    /// let client = ClientBuilder::new()
1083    ///     .local_address("0.0.0.0:5060".parse().unwrap())
1084    ///     .media_address("192.168.1.100:0".parse().unwrap())
1085    ///     .domain("enterprise.company.com")
1086    ///     .user_agent("CompanyPhone/3.1.0")
1087    ///     .media_preset(MediaPreset::VoiceOptimized)
1088    ///     .max_concurrent_calls(50)
1089    ///     .rtp_ports(10000, 20000)
1090    ///     .require_srtp(true)
1091    ///     .build()
1092    ///     .await.unwrap();
1093    /// 
1094    /// println!("Enterprise client initialized and ready");
1095    /// # })
1096    /// ```
1097    /// 
1098    /// # Thread Safety
1099    /// 
1100    /// The returned `ClientManager` is wrapped in an `Arc` for safe sharing
1101    /// across threads and async tasks. All client operations are thread-safe.
1102    /// 
1103    /// # Resource Management
1104    /// 
1105    /// The client automatically manages its resources and will clean up
1106    /// properly when dropped. For graceful shutdown, use the client's
1107    /// shutdown methods before dropping.
1108    pub async fn build(mut self) -> ClientResult<Arc<ClientManager>> {
1109        // If media address has default IP (127.0.0.1), update to match SIP IP but keep port
1110        let default_media_addr: std::net::SocketAddr = "127.0.0.1:0".parse().unwrap();
1111        if self.config.local_media_addr.ip() == default_media_addr.ip() {
1112            let sip_ip = self.config.local_sip_addr.ip();
1113            let media_port = self.config.local_media_addr.port(); // Keep existing port (0 = auto)
1114            self.config.local_media_addr = format!("{}:{}", sip_ip, media_port).parse().unwrap();
1115        }
1116        ClientManager::new(self.config).await
1117    }
1118}
1119
1120/// Default implementation for ClientBuilder
1121/// 
1122/// Creates a new `ClientBuilder` with default configuration settings.
1123/// This is equivalent to calling `ClientBuilder::new()`.
1124/// 
1125/// # Examples
1126/// 
1127/// ```rust
1128/// use rvoip_client_core::ClientBuilder;
1129/// 
1130/// // These are equivalent:
1131/// let builder1 = ClientBuilder::new();
1132/// let builder2 = ClientBuilder::default();
1133/// 
1134/// # tokio_test::block_on(async {
1135/// let client = ClientBuilder::default()
1136///     .local_address("127.0.0.1:5060".parse().unwrap())
1137///     .build()
1138///     .await.unwrap();
1139/// # })
1140/// ```
1141impl Default for ClientBuilder {
1142    fn default() -> Self {
1143        Self::new()
1144    }
1145}