rvoip_client_core/client/manager.rs
1use std::sync::Arc;
2use std::collections::HashMap;
3use tokio::sync::{RwLock, Mutex};
4use dashmap::DashMap;
5use uuid::Uuid;
6
7// Import session-core APIs - UPDATED to use new API structure
8use rvoip_session_core::api::{
9 SessionCoordinator,
10 SessionManagerBuilder,
11 SessionManagerConfig,
12 SessionControl,
13 MediaControl,
14 SipClient,
15 MediaConfig as SessionMediaConfig,
16 types::SessionId,
17 handlers::CallHandler,
18};
19
20// Import client-core types
21use crate::{
22 ClientConfig, ClientResult, ClientError,
23 call::{CallId, CallInfo},
24 registration::{RegistrationConfig, RegistrationInfo},
25 events::{ClientEventHandler, ClientEvent},
26};
27
28// Import types from our types module
29use super::types::*;
30use super::events::ClientCallHandler;
31use super::recovery::{retry_with_backoff, RetryConfig, ErrorContext};
32use super::config::MediaConfig;
33
34/// High-level SIP client manager that coordinates all client operations
35///
36/// The `ClientManager` is the primary entry point for VoIP client functionality.
37/// It provides a high-level, async API for SIP registration, call management,
38/// and media control while delegating to session-core for the underlying
39/// SIP protocol implementation.
40///
41/// # Architecture
42///
43/// ```text
44/// ┌─────────────────────────┐
45/// │ Application Layer │
46/// └───────────┬─────────────┘
47/// │
48/// ┌───────────▼─────────────┐
49/// │ ClientManager │ ◄── This Layer
50/// │ ┌─────────────────────┐ │
51/// │ │ Registration Mgmt │ │ • SIP REGISTER handling
52/// │ │ Call Management │ │ • Event coordination
53/// │ │ Media Integration │ │ • State management
54/// │ │ Event Broadcasting │ │ • Error handling
55/// │ └─────────────────────┘ │
56/// └───────────┬─────────────┘
57/// │
58/// ┌───────────▼─────────────┐
59/// │ session-core │
60/// │ SessionCoordinator │
61/// └─────────────────────────┘
62/// ```
63///
64/// # Core Features
65///
66/// ## Registration Management
67/// - **SIP Registration**: Register with SIP servers using REGISTER requests
68/// - **Authentication**: Handle digest authentication challenges
69/// - **Refresh**: Automatic and manual registration refresh
70/// - **Multiple Registrations**: Support multiple simultaneous registrations
71///
72/// ## Call Management
73/// - **Outbound Calls**: Initiate calls to SIP URIs or phone numbers
74/// - **Inbound Calls**: Accept incoming calls with proper SDP negotiation
75/// - **Call Control**: Hold, resume, transfer, and hangup operations
76/// - **DTMF**: Send dual-tone multi-frequency signals during calls
77///
78/// ## Media Integration
79/// - **Codec Support**: Multiple audio codecs (G.711, G.729, Opus)
80/// - **Quality Control**: Real-time media quality monitoring
81/// - **Echo Cancellation**: Built-in acoustic echo cancellation
82/// - **Noise Suppression**: Advanced noise reduction algorithms
83///
84/// ## Event System
85/// - **Real-time Events**: Registration, call, and media events
86/// - **Broadcast Channel**: Multi-consumer event distribution
87/// - **Typed Events**: Strongly-typed event structures
88/// - **Priority Levels**: Event prioritization for handling
89///
90/// # Usage Examples
91///
92/// ## Basic Client Setup
93///
94/// ```rust
95/// use rvoip_client_core::{ClientManager, ClientConfig};
96/// use std::net::SocketAddr;
97///
98/// async fn basic_setup() -> Result<(), Box<dyn std::error::Error>> {
99/// // Create client configuration
100/// let config = ClientConfig::new()
101/// .with_sip_addr("127.0.0.1:5060".parse()?);
102///
103/// // Create and start client manager
104/// let client = ClientManager::new(config).await?;
105/// client.start().await?;
106///
107/// println!("✅ SIP client started successfully");
108///
109/// // Clean shutdown
110/// client.stop().await?;
111/// Ok(())
112/// }
113/// ```
114///
115/// ## Registration and Call Flow
116///
117/// ```rust
118/// use rvoip_client_core::{ClientManager, ClientConfig, RegistrationConfig};
119/// use std::time::Duration;
120///
121/// async fn registration_flow() -> Result<(), Box<dyn std::error::Error>> {
122/// let config = ClientConfig::new()
123/// .with_sip_addr("127.0.0.1:5061".parse()?);
124///
125/// let client = ClientManager::new(config).await?;
126/// client.start().await?;
127///
128/// // Register with SIP server
129 /// let reg_config = RegistrationConfig {
130 /// server_uri: "sip:192.168.1.100:5060".to_string(),
131 /// from_uri: "sip:alice@example.com".to_string(),
132 /// contact_uri: "sip:alice@127.0.0.1:5061".to_string(),
133 /// expires: 3600,
134 /// username: None,
135 /// password: None,
136 /// realm: None,
137 /// };
138///
139/// let registration_id = client.register(reg_config).await?;
140/// println!("✅ Registered with ID: {}", registration_id);
141///
142/// // Make a call (would be implemented in calls.rs)
143/// // let call_id = client.make_call("sip:bob@example.com").await?;
144///
145/// // Clean up
146/// client.unregister(registration_id).await?;
147/// client.stop().await?;
148/// Ok(())
149/// }
150/// ```
151///
152/// ## Event Monitoring
153///
154/// ```rust
155/// use rvoip_client_core::{ClientManager, ClientConfig, ClientEvent};
156/// use tokio::time::{timeout, Duration};
157///
158/// async fn event_monitoring() -> Result<(), Box<dyn std::error::Error>> {
159/// let config = ClientConfig::new()
160/// .with_sip_addr("127.0.0.1:5062".parse()?);
161///
162/// let client = ClientManager::new(config).await?;
163/// client.start().await?;
164///
165/// // Subscribe to events
166/// let mut event_rx = client.subscribe_events();
167///
168/// // Monitor events for a short time
169/// let event_task = tokio::spawn(async move {
170/// let mut event_count = 0;
171/// while event_count < 3 {
172 /// if let Ok(event) = timeout(Duration::from_millis(100), event_rx.recv()).await {
173 /// match event {
174 /// Ok(ClientEvent::RegistrationStatusChanged { info, .. }) => {
175 /// println!("📋 Registration event: {} -> {:?}",
176 /// info.user_uri, info.status);
177 /// }
178 /// Ok(ClientEvent::CallStateChanged { info, .. }) => {
179 /// println!("📞 Call event: {} -> {:?}",
180 /// info.call_id, info.new_state);
181 /// }
182 /// Ok(ClientEvent::MediaEvent { info, .. }) => {
183 /// println!("🎵 Media event: Call {} event occurred",
184 /// info.call_id);
185 /// }
186 /// Ok(ClientEvent::IncomingCall { .. }) |
187 /// Ok(ClientEvent::ClientError { .. }) |
188 /// Ok(ClientEvent::NetworkEvent { .. }) => {
189 /// // Handle other events as needed
190 /// }
191 /// Err(_) => break,
192 /// }
193/// event_count += 1;
194/// } else {
195/// break; // Timeout
196/// }
197/// }
198/// });
199///
200/// // Wait for event monitoring to complete
201/// let _ = event_task.await;
202///
203/// client.stop().await?;
204/// Ok(())
205/// }
206/// ```
207pub struct ClientManager {
208 /// Session coordinator from session-core
209 pub(crate) coordinator: Arc<SessionCoordinator>,
210
211 /// Local SIP address (bound)
212 pub(crate) local_sip_addr: std::net::SocketAddr,
213
214 /// Media configuration
215 pub(crate) media_config: MediaConfig,
216
217 /// Whether the client is running
218 pub(crate) is_running: Arc<RwLock<bool>>,
219
220 /// Statistics
221 pub(crate) stats: Arc<Mutex<ClientStats>>,
222
223 /// Active registrations
224 pub(crate) registrations: Arc<RwLock<HashMap<Uuid, RegistrationInfo>>>,
225
226 /// Call/Session mapping (CallId -> SessionId)
227 pub(crate) session_mapping: Arc<DashMap<CallId, SessionId>>,
228
229 /// Call info storage
230 pub(crate) call_info: Arc<DashMap<CallId, CallInfo>>,
231
232 /// Call handler
233 pub(crate) call_handler: Arc<ClientCallHandler>,
234
235 /// Event broadcast channel
236 pub(crate) event_tx: tokio::sync::broadcast::Sender<ClientEvent>,
237
238 /// Tracks which calls have audio frame subscription set up
239 pub(crate) audio_setup_calls: Arc<DashMap<CallId, bool>>,
240
241 /// Handle to the audio setup task
242 audio_setup_task: Arc<Mutex<Option<tokio::task::JoinHandle<()>>>>,
243
244}
245
246impl ClientManager {
247 /// Create a new client manager with the given configuration
248 ///
249 /// This method initializes a new `ClientManager` instance with the provided
250 /// configuration. It sets up the underlying session coordinator, event system,
251 /// call mapping structures, and media configuration.
252 ///
253 /// # Arguments
254 ///
255 /// * `config` - The client configuration specifying SIP addresses, media settings,
256 /// codec preferences, and other operational parameters
257 ///
258 /// # Returns
259 ///
260 /// Returns an `Arc<ClientManager>` wrapped in a `ClientResult`. The Arc allows
261 /// the manager to be shared across multiple async tasks safely.
262 ///
263 /// # Errors
264 ///
265 /// * `ClientError::InternalError` - If the session coordinator cannot be created
266 /// due to invalid configuration or system resource constraints
267 ///
268 /// # Examples
269 ///
270 /// ## Basic Client Creation
271 ///
272 /// ```rust
273 /// use rvoip_client_core::{ClientManager, ClientConfig};
274 ///
275 /// async fn create_basic_client() -> Result<(), Box<dyn std::error::Error>> {
276 /// let config = ClientConfig::new()
277 /// .with_sip_addr("127.0.0.1:5060".parse()?);
278 ///
279 /// let client = ClientManager::new(config).await?;
280 /// println!("✅ Client created successfully");
281 ///
282 /// // Client is ready but not started yet
283 /// assert!(!client.is_running().await);
284 ///
285 /// Ok(())
286 /// }
287 /// ```
288 ///
289 /// ## Client with Custom Media Configuration
290 ///
291 /// ```rust
292 /// use rvoip_client_core::{ClientManager, ClientConfig, MediaConfig, MediaPreset};
293 ///
294 /// async fn create_custom_media_client() -> Result<(), Box<dyn std::error::Error>> {
295 /// use rvoip_client_core::client::config::MediaPreset;
296 /// let mut media_config = MediaConfig::from_preset(MediaPreset::VoiceOptimized);
297 /// media_config.echo_cancellation = true;
298 /// media_config.noise_suppression = true;
299 /// media_config.rtp_port_start = 10000;
300 /// media_config.rtp_port_end = 20000;
301 ///
302 /// let config = ClientConfig::new()
303 /// .with_sip_addr("127.0.0.1:5061".parse()?)
304 /// .with_media(media_config);
305 ///
306 /// let client = ClientManager::new(config).await?;
307 ///
308 /// // Verify media configuration was applied
309 /// let applied_config = client.get_media_config();
310 /// assert!(applied_config.echo_cancellation);
311 /// assert!(applied_config.noise_suppression);
312 /// assert_eq!(applied_config.rtp_port_start, 10000);
313 /// assert_eq!(applied_config.rtp_port_end, 20000);
314 ///
315 /// println!("✅ Custom media client created");
316 /// Ok(())
317 /// }
318 /// ```
319 ///
320 /// ## Enterprise Client Setup
321 ///
322 /// ```rust
323 /// use rvoip_client_core::{ClientManager, ClientConfig, MediaConfig};
324 ///
325 /// async fn create_enterprise_client() -> Result<(), Box<dyn std::error::Error>> {
326 /// use rvoip_client_core::client::config::MediaPreset;
327 /// let mut media_config = MediaConfig::from_preset(MediaPreset::Secure);
328 /// media_config.max_bandwidth_kbps = Some(128); // 128 kbps max
329 /// media_config.preferred_ptime = Some(20); // 20ms packet time
330 ///
331 /// let config = ClientConfig::new()
332 /// .with_sip_addr("0.0.0.0:5060".parse()?) // Bind to all interfaces
333 /// .with_media_addr("0.0.0.0:0".parse()?) // Dynamic media port
334 /// .with_media(media_config);
335 ///
336 /// let client = ClientManager::new(config).await?;
337 ///
338 /// println!("✅ Enterprise client ready for production");
339 /// Ok(())
340 /// }
341 /// ```
342 ///
343 /// ## Error Handling
344 ///
345 /// ```rust
346 /// use rvoip_client_core::{ClientManager, ClientConfig, ClientError};
347 ///
348 /// async fn handle_creation_errors() -> Result<(), Box<dyn std::error::Error>> {
349 /// // Try to create client with potentially problematic config
350 /// let config = ClientConfig::new()
351 /// .with_sip_addr("127.0.0.1:5062".parse()?);
352 ///
353 /// match ClientManager::new(config).await {
354 /// Ok(client) => {
355 /// println!("✅ Client created successfully");
356 /// // Use client...
357 /// }
358 /// Err(ClientError::InternalError { message }) => {
359 /// println!("❌ Failed to create client: {}", message);
360 /// // Handle error (retry, use different config, etc.)
361 /// }
362 /// Err(e) => {
363 /// println!("❌ Unexpected error: {}", e);
364 /// }
365 /// }
366 ///
367 /// Ok(())
368 /// }
369 /// ```
370 ///
371 /// ## Multi-Client Architecture
372 ///
373 /// ```rust
374 /// use rvoip_client_core::{ClientManager, ClientConfig};
375 /// use std::sync::Arc;
376 ///
377 /// async fn multi_client_setup() -> Result<(), Box<dyn std::error::Error>> {
378 /// // Create multiple clients for different purposes
379 /// let client1_config = ClientConfig::new()
380 /// .with_sip_addr("127.0.0.1:5060".parse()?);
381 /// let client1 = ClientManager::new(client1_config).await?;
382 ///
383 /// let client2_config = ClientConfig::new()
384 /// .with_sip_addr("127.0.0.1:5061".parse()?);
385 /// let client2 = ClientManager::new(client2_config).await?;
386 ///
387 /// // Clients can be shared across tasks
388 /// let client1_clone = Arc::clone(&client1);
389 /// let task1 = tokio::spawn(async move {
390 /// // Use client1_clone in this task
391 /// println!("Task 1 using client on port 5060");
392 /// });
393 ///
394 /// let client2_clone = Arc::clone(&client2);
395 /// let task2 = tokio::spawn(async move {
396 /// // Use client2_clone in this task
397 /// println!("Task 2 using client on port 5061");
398 /// });
399 ///
400 /// // Wait for tasks to complete
401 /// let _ = tokio::try_join!(task1, task2)?;
402 ///
403 /// println!("✅ Multi-client setup complete");
404 /// Ok(())
405 /// }
406 /// ```
407 ///
408 /// # Implementation Notes
409 ///
410 /// The constructor performs several key initialization steps:
411 ///
412 /// 1. **Session Coordinator Setup**: Creates the underlying session-core coordinator
413 /// with media preferences and SIP configuration
414 /// 2. **Event System**: Initializes broadcast channels for real-time events
415 /// 3. **Call Mapping**: Sets up concurrent data structures for call tracking
416 /// 4. **Media Configuration**: Applies codec preferences and quality settings
417 /// 5. **Handler Registration**: Registers the call handler for SIP events
418 ///
419 /// The returned `Arc<ClientManager>` enables safe sharing across async tasks
420 /// and ensures proper cleanup through RAII patterns.
421 pub async fn new(config: ClientConfig) -> ClientResult<Arc<Self>> {
422 // Create call/session mapping
423 let call_mapping = Arc::new(DashMap::new());
424 let session_mapping = Arc::new(DashMap::new());
425 let call_info = Arc::new(DashMap::new());
426 let incoming_calls = Arc::new(DashMap::new());
427
428 // Create event broadcast channel
429 let (event_tx, _) = tokio::sync::broadcast::channel(256);
430
431 // Create channel for call establishment notifications
432 let (call_established_tx, call_established_rx) = tokio::sync::mpsc::unbounded_channel();
433
434 // Create call handler
435 let call_handler = Arc::new(ClientCallHandler::new(
436 call_mapping.clone(),
437 session_mapping.clone(),
438 call_info.clone(),
439 incoming_calls.clone(),
440 ).with_event_tx(event_tx.clone())
441 .with_call_established_tx(call_established_tx));
442
443
444
445 // Build session coordinator with media preferences
446 // The media preferences will be used by session-core's SDP negotiator
447 // to generate offers/answers based on the configured codecs
448 let session_media_config = SessionMediaConfig {
449 preferred_codecs: config.media.preferred_codecs.clone(),
450 port_range: Some((config.media.rtp_port_start, config.media.rtp_port_end)),
451 quality_monitoring: true,
452 dtmf_support: config.media.dtmf_enabled,
453 echo_cancellation: config.media.echo_cancellation,
454 noise_suppression: config.media.noise_suppression,
455 auto_gain_control: config.media.auto_gain_control,
456 max_bandwidth_kbps: config.media.max_bandwidth_kbps,
457 preferred_ptime: config.media.preferred_ptime,
458 custom_sdp_attributes: config.media.custom_sdp_attributes.clone(),
459 };
460
461 // Note: If media port is 0, it signals automatic allocation
462 // The actual port will be allocated by session-core when creating media sessions
463 // This is the proper layered approach that respects the architecture
464
465 // Create session manager using session-core builder with media preferences
466 let coordinator = SessionManagerBuilder::new()
467 .with_local_address(&format!("sip:client@{}", config.local_sip_addr.ip()))
468 .with_sip_port(config.local_sip_addr.port())
469 .with_local_bind_addr(config.local_sip_addr) // Add this line to propagate bind address
470 .with_media_ports(config.media.rtp_port_start, config.media.rtp_port_end)
471 .with_media_config(session_media_config) // Pass media preferences to session-core
472 .with_handler(call_handler.clone() as Arc<dyn CallHandler>)
473 .enable_sip_client() // Enable SIP client features for REGISTER support
474 .build()
475 .await
476 .map_err(|e| ClientError::InternalError {
477 message: format!("Failed to create session coordinator: {}", e)
478 })?;
479
480
481
482 let mut stats = ClientStats {
483 is_running: false,
484 local_sip_addr: config.local_sip_addr,
485 local_media_addr: config.local_media_addr,
486 total_calls: 0,
487 connected_calls: 0,
488 total_registrations: 0,
489 active_registrations: 0,
490 };
491
492
493
494 let audio_setup_calls = Arc::new(DashMap::new());
495
496 // Create the client manager
497 let client = Arc::new(Self {
498 coordinator,
499 local_sip_addr: config.local_sip_addr,
500 media_config: config.media.clone(),
501 is_running: Arc::new(RwLock::new(false)),
502 stats: Arc::new(Mutex::new(stats)),
503 registrations: Arc::new(RwLock::new(HashMap::new())),
504 session_mapping,
505 call_info,
506 call_handler,
507 event_tx,
508 audio_setup_calls,
509 audio_setup_task: Arc::new(Mutex::new(None)),
510 });
511
512 // Spawn task to handle call establishment notifications
513 let client_clone = client.clone();
514 let mut call_established_rx = call_established_rx;
515 let audio_setup_task = tokio::spawn(async move {
516 while let Some(call_id) = call_established_rx.recv().await {
517 // Set up audio for the established call
518 if let Err(e) = client_clone.setup_call_audio(&call_id).await {
519 tracing::warn!("Failed to set up audio for established call {}: {}", call_id, e);
520 }
521 }
522 });
523
524 // Store the task handle
525 *client.audio_setup_task.lock().await = Some(audio_setup_task);
526
527 Ok(client)
528 }
529
530 /// Set the event handler for client events
531 ///
532 /// This method registers an application-provided event handler that will receive
533 /// notifications for all client events including registration changes, call status
534 /// updates, and media quality notifications. The handler is called asynchronously
535 /// and should not block for extended periods.
536 ///
537 /// # Arguments
538 ///
539 /// * `handler` - An implementation of the `ClientEventHandler` trait wrapped in an `Arc`
540 /// for thread-safe sharing across the event system
541 ///
542 /// # Examples
543 ///
544 /// ## Basic Event Handler
545 ///
546 /// ```rust
547 /// use rvoip_client_core::{
548 /// ClientManager, ClientConfig, ClientEventHandler,
549 /// events::{CallStatusInfo, RegistrationStatusInfo, MediaEventInfo, IncomingCallInfo, CallAction}
550 /// };
551 /// use async_trait::async_trait;
552 /// use std::sync::Arc;
553 ///
554 /// struct MyEventHandler;
555 ///
556 /// #[async_trait]
557 /// impl ClientEventHandler for MyEventHandler {
558 /// async fn on_incoming_call(&self, _info: IncomingCallInfo) -> CallAction {
559 /// CallAction::Accept
560 /// }
561 ///
562 /// async fn on_call_state_changed(&self, info: CallStatusInfo) {
563 /// println!("📞 Call {} changed to {:?}", info.call_id, info.new_state);
564 /// }
565 ///
566 /// async fn on_registration_status_changed(&self, info: RegistrationStatusInfo) {
567 /// println!("📋 Registration {} changed to {:?}", info.user_uri, info.status);
568 /// }
569 ///
570 /// async fn on_media_event(&self, info: MediaEventInfo) {
571 /// println!("🎵 Media event for call {}: {:?}", info.call_id, info.event_type);
572 /// }
573 /// }
574 ///
575 /// async fn setup_event_handler() -> Result<(), Box<dyn std::error::Error>> {
576 /// let config = ClientConfig::new()
577 /// .with_sip_addr("127.0.0.1:5063".parse()?);
578 ///
579 /// let client = ClientManager::new(config).await?;
580 ///
581 /// // Register our event handler
582 /// let handler = Arc::new(MyEventHandler);
583 /// client.set_event_handler(handler).await;
584 ///
585 /// client.start().await?;
586 /// println!("✅ Event handler registered and client started");
587 ///
588 /// client.stop().await?;
589 /// Ok(())
590 /// }
591 /// ```
592 ///
593 /// ## Stateful Event Handler
594 ///
595 /// ```rust
596 /// use rvoip_client_core::{
597 /// ClientManager, ClientConfig, ClientEventHandler,
598 /// events::{CallStatusInfo, RegistrationStatusInfo, MediaEventInfo, IncomingCallInfo, CallAction}
599 /// };
600 /// use async_trait::async_trait;
601 /// use std::sync::{Arc, Mutex};
602 /// use std::collections::HashMap;
603 ///
604 /// struct StatefulEventHandler {
605 /// call_states: Mutex<HashMap<String, String>>,
606 /// event_count: Mutex<u64>,
607 /// }
608 ///
609 /// impl StatefulEventHandler {
610 /// fn new() -> Self {
611 /// Self {
612 /// call_states: Mutex::new(HashMap::new()),
613 /// event_count: Mutex::new(0),
614 /// }
615 /// }
616 /// }
617 ///
618 /// #[async_trait]
619 /// impl ClientEventHandler for StatefulEventHandler {
620 /// async fn on_incoming_call(&self, _info: IncomingCallInfo) -> CallAction {
621 /// CallAction::Accept
622 /// }
623 ///
624 /// async fn on_call_state_changed(&self, info: CallStatusInfo) {
625 /// // Update state tracking
626 /// let mut states = self.call_states.lock().unwrap();
627 /// states.insert(info.call_id.to_string(), format!("{:?}", info.new_state));
628 ///
629 /// let mut count = self.event_count.lock().unwrap();
630 /// *count += 1;
631 ///
632 /// println!("📞 Call event #{}: {} -> {:?}", *count, info.call_id, info.new_state);
633 /// }
634 ///
635 /// async fn on_registration_status_changed(&self, info: RegistrationStatusInfo) {
636 /// println!("📋 Registration: {} -> {:?}", info.user_uri, info.status);
637 /// }
638 ///
639 /// async fn on_media_event(&self, info: MediaEventInfo) {
640 /// println!("🎵 Media: Call {} -> {:?}", info.call_id, info.event_type);
641 /// }
642 /// }
643 ///
644 /// async fn stateful_handler() -> Result<(), Box<dyn std::error::Error>> {
645 /// let config = ClientConfig::new()
646 /// .with_sip_addr("127.0.0.1:5064".parse()?);
647 ///
648 /// let client = ClientManager::new(config).await?;
649 ///
650 /// // Create stateful handler
651 /// let handler = Arc::new(StatefulEventHandler::new());
652 /// client.set_event_handler(handler.clone()).await;
653 ///
654 /// client.start().await?;
655 ///
656 /// // Handler is now tracking events
657 /// println!("✅ Stateful event handler active");
658 ///
659 /// client.stop().await?;
660 /// Ok(())
661 /// }
662 /// ```
663 ///
664 /// ## Logging Event Handler
665 ///
666 /// ```rust
667 /// use rvoip_client_core::{
668 /// ClientManager, ClientConfig, ClientEventHandler,
669 /// events::{CallStatusInfo, RegistrationStatusInfo, MediaEventInfo, IncomingCallInfo, CallAction}
670 /// };
671 /// use async_trait::async_trait;
672 /// use std::sync::Arc;
673 /// use chrono::Utc;
674 ///
675 /// struct LoggingEventHandler {
676 /// component_name: String,
677 /// }
678 ///
679 /// impl LoggingEventHandler {
680 /// fn new(name: &str) -> Self {
681 /// Self {
682 /// component_name: name.to_string(),
683 /// }
684 /// }
685 /// }
686 ///
687 /// #[async_trait]
688 /// impl ClientEventHandler for LoggingEventHandler {
689 /// async fn on_incoming_call(&self, _info: IncomingCallInfo) -> CallAction {
690 /// CallAction::Accept
691 /// }
692 ///
693 /// async fn on_call_state_changed(&self, info: CallStatusInfo) {
694 /// tracing::info!(
695 /// component = %self.component_name,
696 /// call_id = %info.call_id,
697 /// previous_state = ?info.previous_state,
698 /// new_state = ?info.new_state,
699 /// timestamp = %info.timestamp,
700 /// "Call status changed"
701 /// );
702 /// }
703 ///
704 /// async fn on_registration_status_changed(&self, info: RegistrationStatusInfo) {
705 /// tracing::info!(
706 /// component = %self.component_name,
707 /// user_uri = %info.user_uri,
708 /// status = ?info.status,
709 /// server = %info.server_uri,
710 /// "Registration status changed"
711 /// );
712 /// }
713 ///
714 /// async fn on_media_event(&self, info: MediaEventInfo) {
715 /// tracing::debug!(
716 /// component = %self.component_name,
717 /// call_id = %info.call_id,
718 /// event_type = ?info.event_type,
719 /// "Media event occurred"
720 /// );
721 /// }
722 /// }
723 ///
724 /// async fn logging_handler() -> Result<(), Box<dyn std::error::Error>> {
725 /// let config = ClientConfig::new()
726 /// .with_sip_addr("127.0.0.1:5065".parse()?);
727 ///
728 /// let client = ClientManager::new(config).await?;
729 ///
730 /// // Create logging handler
731 /// let handler = Arc::new(LoggingEventHandler::new("MyVoIPApp"));
732 /// client.set_event_handler(handler).await;
733 ///
734 /// client.start().await?;
735 /// println!("✅ Logging event handler registered");
736 ///
737 /// client.stop().await?;
738 /// Ok(())
739 /// }
740 /// ```
741 ///
742 /// ## Event Handler Replacement
743 ///
744 /// ```rust
745 /// use rvoip_client_core::{
746 /// ClientManager, ClientConfig, ClientEventHandler,
747 /// events::{CallStatusInfo, RegistrationStatusInfo, MediaEventInfo, IncomingCallInfo, CallAction}
748 /// };
749 /// use async_trait::async_trait;
750 /// use std::sync::Arc;
751 ///
752 /// struct Handler1;
753 /// struct Handler2;
754 ///
755 /// #[async_trait]
756 /// impl ClientEventHandler for Handler1 {
757 /// async fn on_incoming_call(&self, _info: IncomingCallInfo) -> CallAction {
758 /// CallAction::Accept
759 /// }
760 /// async fn on_call_state_changed(&self, info: CallStatusInfo) {
761 /// println!("Handler1: Call {} -> {:?}", info.call_id, info.new_state);
762 /// }
763 /// async fn on_registration_status_changed(&self, _info: RegistrationStatusInfo) {}
764 /// async fn on_media_event(&self, _info: MediaEventInfo) {}
765 /// }
766 ///
767 /// #[async_trait]
768 /// impl ClientEventHandler for Handler2 {
769 /// async fn on_incoming_call(&self, _info: IncomingCallInfo) -> CallAction {
770 /// CallAction::Accept
771 /// }
772 /// async fn on_call_state_changed(&self, info: CallStatusInfo) {
773 /// println!("Handler2: Call {} -> {:?}", info.call_id, info.new_state);
774 /// }
775 /// async fn on_registration_status_changed(&self, _info: RegistrationStatusInfo) {}
776 /// async fn on_media_event(&self, _info: MediaEventInfo) {}
777 /// }
778 ///
779 /// async fn handler_replacement() -> Result<(), Box<dyn std::error::Error>> {
780 /// let config = ClientConfig::new()
781 /// .with_sip_addr("127.0.0.1:5066".parse()?);
782 ///
783 /// let client = ClientManager::new(config).await?;
784 /// client.start().await?;
785 ///
786 /// // Set initial handler
787 /// let handler1 = Arc::new(Handler1);
788 /// client.set_event_handler(handler1).await;
789 /// println!("✅ Handler1 registered");
790 ///
791 /// // Replace with different handler
792 /// let handler2 = Arc::new(Handler2);
793 /// client.set_event_handler(handler2).await;
794 /// println!("✅ Handler2 replaced Handler1");
795 ///
796 /// client.stop().await?;
797 /// Ok(())
798 /// }
799 /// ```
800 ///
801 /// # Implementation Notes
802 ///
803 /// - **Thread Safety**: The handler is stored in an Arc<RwLock> for safe concurrent access
804 /// - **Async Execution**: All handler methods are called asynchronously
805 /// - **No Blocking**: Handlers should avoid blocking operations to prevent event queue backup
806 /// - **Error Handling**: Handler errors are logged but don't affect client operation
807 /// - **Replacement**: Setting a new handler replaces the previous one
808 ///
809 /// # Best Practices
810 ///
811 /// 1. **Keep handlers lightweight** - Avoid heavy computation in event callbacks
812 /// 2. **Use async patterns** - Leverage tokio for concurrent event processing
813 /// 3. **Handle errors gracefully** - Don't panic in event handlers
814 /// 4. **Consider batching** - For high-frequency events, consider batching updates
815 /// 5. **State management** - Use appropriate synchronization for handler state
816 pub async fn set_event_handler(&self, handler: Arc<dyn ClientEventHandler>) {
817 self.call_handler.set_event_handler(handler).await;
818 }
819
820 /// Start the client manager
821 ///
822 /// This method starts the client manager, initializing the underlying SIP transport,
823 /// binding to network addresses, and beginning event processing. The client must be
824 /// started before it can handle registrations, calls, or other SIP operations.
825 ///
826 /// # Returns
827 ///
828 /// Returns `Ok(())` if the client started successfully.
829 ///
830 /// # Errors
831 ///
832 /// * `ClientError::InternalError` - If the session coordinator fails to start
833 /// (e.g., port already in use, network unavailable)
834 ///
835 /// # Examples
836 ///
837 /// ## Basic Start/Stop Cycle
838 ///
839 /// ```rust
840 /// use rvoip_client_core::{ClientManager, ClientConfig};
841 ///
842 /// async fn start_stop_cycle() -> Result<(), Box<dyn std::error::Error>> {
843 /// let config = ClientConfig::new()
844 /// .with_sip_addr("127.0.0.1:5067".parse()?);
845 ///
846 /// let client = ClientManager::new(config).await?;
847 ///
848 /// // Initially not running
849 /// assert!(!client.is_running().await);
850 ///
851 /// // Start the client
852 /// client.start().await?;
853 /// assert!(client.is_running().await);
854 /// println!("✅ Client started successfully");
855 ///
856 /// // Stop the client
857 /// client.stop().await?;
858 /// assert!(!client.is_running().await);
859 /// println!("✅ Client stopped successfully");
860 ///
861 /// Ok(())
862 /// }
863 /// ```
864 ///
865 /// ## Error Handling on Start
866 ///
867 /// ```rust
868 /// use rvoip_client_core::{ClientManager, ClientConfig, ClientError};
869 ///
870 /// async fn handle_start_errors() -> Result<(), Box<dyn std::error::Error>> {
871 /// let config = ClientConfig::new()
872 /// .with_sip_addr("127.0.0.1:5068".parse()?);
873 ///
874 /// let client = ClientManager::new(config).await?;
875 ///
876 /// match client.start().await {
877 /// Ok(()) => {
878 /// println!("✅ Client started successfully");
879 /// client.stop().await?;
880 /// }
881 /// Err(ClientError::InternalError { message }) => {
882 /// println!("❌ Failed to start client: {}", message);
883 /// // Handle the error (retry with different port, etc.)
884 /// }
885 /// Err(e) => {
886 /// println!("❌ Unexpected error: {}", e);
887 /// }
888 /// }
889 ///
890 /// Ok(())
891 /// }
892 /// ```
893 ///
894 /// ## Multiple Start Attempts
895 ///
896 /// ```rust
897 /// use rvoip_client_core::{ClientManager, ClientConfig};
898 ///
899 /// async fn multiple_start_safe() -> Result<(), Box<dyn std::error::Error>> {
900 /// let config = ClientConfig::new()
901 /// .with_sip_addr("127.0.0.1:5069".parse()?);
902 ///
903 /// let client = ClientManager::new(config).await?;
904 ///
905 /// // Start the client
906 /// client.start().await?;
907 /// println!("✅ First start successful");
908 ///
909 /// // Multiple starts should be safe (idempotent)
910 /// client.start().await?;
911 /// println!("✅ Second start (should be no-op)");
912 ///
913 /// assert!(client.is_running().await);
914 ///
915 /// client.stop().await?;
916 /// Ok(())
917 /// }
918 /// ```
919 pub async fn start(&self) -> ClientResult<()> {
920 // Start the session coordinator using SessionControl trait
921 SessionControl::start(&self.coordinator)
922 .await
923 .map_err(|e| ClientError::InternalError {
924 message: format!("Failed to start session coordinator: {}", e)
925 })?;
926
927 *self.is_running.write().await = true;
928
929 // Update stats with actual bound addresses
930 let actual_addr = SessionControl::get_bound_address(&self.coordinator);
931 let mut stats = self.stats.lock().await;
932 stats.is_running = true;
933 stats.local_sip_addr = actual_addr;
934
935 tracing::info!("ClientManager started on {}", actual_addr);
936 Ok(())
937 }
938
939 /// Stop the client manager
940 ///
941 /// This method gracefully shuts down the client manager, terminating all active
942 /// calls, cleaning up network resources, and stopping event processing. Any active
943 /// registrations will be automatically unregistered.
944 ///
945 /// # Returns
946 ///
947 /// Returns `Ok(())` if the client stopped successfully.
948 ///
949 /// # Errors
950 ///
951 /// * `ClientError::InternalError` - If the session coordinator fails to stop cleanly
952 ///
953 /// # Examples
954 ///
955 /// ## Graceful Shutdown
956 ///
957 /// ```rust
958 /// use rvoip_client_core::{ClientManager, ClientConfig};
959 ///
960 /// async fn graceful_shutdown() -> Result<(), Box<dyn std::error::Error>> {
961 /// let config = ClientConfig::new()
962 /// .with_sip_addr("127.0.0.1:5070".parse()?);
963 ///
964 /// let client = ClientManager::new(config).await?;
965 /// client.start().await?;
966 ///
967 /// // Do some work...
968 /// println!("Client running...");
969 ///
970 /// // Graceful shutdown
971 /// client.stop().await?;
972 /// assert!(!client.is_running().await);
973 /// println!("✅ Client stopped gracefully");
974 ///
975 /// Ok(())
976 /// }
977 /// ```
978 ///
979 /// ## Error Handling on Stop
980 ///
981 /// ```rust
982 /// use rvoip_client_core::{ClientManager, ClientConfig, ClientError};
983 ///
984 /// async fn handle_stop_errors() -> Result<(), Box<dyn std::error::Error>> {
985 /// let config = ClientConfig::new()
986 /// .with_sip_addr("127.0.0.1:5071".parse()?);
987 ///
988 /// let client = ClientManager::new(config).await?;
989 /// client.start().await?;
990 ///
991 /// match client.stop().await {
992 /// Ok(()) => {
993 /// println!("✅ Client stopped successfully");
994 /// }
995 /// Err(ClientError::InternalError { message }) => {
996 /// println!("⚠️ Stop had issues: {}", message);
997 /// // Resources may still be partially cleaned up
998 /// }
999 /// Err(e) => {
1000 /// println!("❌ Unexpected error during stop: {}", e);
1001 /// }
1002 /// }
1003 ///
1004 /// Ok(())
1005 /// }
1006 /// ```
1007 ///
1008 /// ## Multiple Stop Attempts
1009 ///
1010 /// ```rust
1011 /// use rvoip_client_core::{ClientManager, ClientConfig};
1012 ///
1013 /// async fn multiple_stop_safe() -> Result<(), Box<dyn std::error::Error>> {
1014 /// let config = ClientConfig::new()
1015 /// .with_sip_addr("127.0.0.1:5072".parse()?);
1016 ///
1017 /// let client = ClientManager::new(config).await?;
1018 /// client.start().await?;
1019 ///
1020 /// // Stop the client
1021 /// client.stop().await?;
1022 /// println!("✅ First stop successful");
1023 ///
1024 /// // Multiple stops should be safe (idempotent)
1025 /// client.stop().await?;
1026 /// println!("✅ Second stop (should be no-op)");
1027 ///
1028 /// assert!(!client.is_running().await);
1029 ///
1030 /// Ok(())
1031 /// }
1032 /// ```
1033 pub async fn stop(&self) -> ClientResult<()> {
1034 // Cancel the audio setup task if it's running
1035 if let Some(task) = self.audio_setup_task.lock().await.take() {
1036 task.abort();
1037 }
1038
1039 SessionControl::stop(&self.coordinator)
1040 .await
1041 .map_err(|e| ClientError::InternalError {
1042 message: format!("Failed to stop session coordinator: {}", e)
1043 })?;
1044
1045 *self.is_running.write().await = false;
1046
1047 let mut stats = self.stats.lock().await;
1048 stats.is_running = false;
1049
1050 tracing::info!("ClientManager stopped");
1051 Ok(())
1052 }
1053
1054 /// Register with a SIP server
1055 ///
1056 /// This method registers the client with a SIP server using the REGISTER method.
1057 /// Registration allows the client to receive incoming calls and establishes its
1058 /// presence on the SIP network. The method handles authentication challenges
1059 /// automatically and includes retry logic for network issues.
1060 ///
1061 /// # Arguments
1062 ///
1063 /// * `config` - Registration configuration including server URI, user credentials,
1064 /// and expiration settings
1065 ///
1066 /// # Returns
1067 ///
1068 /// Returns a `Uuid` that uniquely identifies this registration for future operations.
1069 ///
1070 /// # Errors
1071 ///
1072 /// * `ClientError::AuthenticationFailed` - Invalid credentials or auth challenge failed
1073 /// * `ClientError::RegistrationFailed` - Server rejected registration (403, etc.)
1074 /// * `ClientError::NetworkError` - Network timeout or connectivity issues
1075 ///
1076 /// # Examples
1077 ///
1078 /// ## Basic Registration
1079 ///
1080 /// ```rust
1081 /// use rvoip_client_core::{ClientManager, ClientConfig, RegistrationConfig};
1082 ///
1083 /// async fn basic_registration() -> Result<(), Box<dyn std::error::Error>> {
1084 /// let config = ClientConfig::new()
1085 /// .with_sip_addr("127.0.0.1:5073".parse()?);
1086 ///
1087 /// let client = ClientManager::new(config).await?;
1088 /// client.start().await?;
1089 ///
1090 /// let reg_config = RegistrationConfig {
1091 /// server_uri: "sip:sip.example.com:5060".to_string(),
1092 /// from_uri: "sip:alice@example.com".to_string(),
1093 /// contact_uri: "sip:alice@127.0.0.1:5073".to_string(),
1094 /// expires: 3600,
1095 /// username: None,
1096 /// password: None,
1097 /// realm: None,
1098 /// };
1099 ///
1100 /// let reg_id = client.register(reg_config).await?;
1101 /// println!("✅ Registered with ID: {}", reg_id);
1102 ///
1103 /// client.unregister(reg_id).await?;
1104 /// client.stop().await?;
1105 /// Ok(())
1106 /// }
1107 /// ```
1108 ///
1109 /// ## Registration with Authentication
1110 ///
1111 /// ```rust
1112 /// use rvoip_client_core::{ClientManager, ClientConfig, RegistrationConfig};
1113 ///
1114 /// async fn authenticated_registration() -> Result<(), Box<dyn std::error::Error>> {
1115 /// let config = ClientConfig::new()
1116 /// .with_sip_addr("127.0.0.1:5074".parse()?);
1117 ///
1118 /// let client = ClientManager::new(config).await?;
1119 /// client.start().await?;
1120 ///
1121 /// let reg_config = RegistrationConfig {
1122 /// server_uri: "sip:pbx.company.com".to_string(),
1123 /// from_uri: "sip:user@company.com".to_string(),
1124 /// contact_uri: "sip:user@127.0.0.1:5074".to_string(),
1125 /// expires: 1800, // 30 minutes
1126 /// username: Some("user".to_string()),
1127 /// password: Some("password123".to_string()),
1128 /// realm: Some("company.com".to_string()),
1129 /// };
1130 ///
1131 /// match client.register(reg_config).await {
1132 /// Ok(reg_id) => {
1133 /// println!("✅ Authenticated registration successful: {}", reg_id);
1134 /// client.unregister(reg_id).await?;
1135 /// }
1136 /// Err(e) => {
1137 /// println!("❌ Registration failed: {}", e);
1138 /// }
1139 /// }
1140 ///
1141 /// client.stop().await?;
1142 /// Ok(())
1143 /// }
1144 /// ```
1145 ///
1146 /// ## Multiple Registrations
1147 ///
1148 /// ```rust
1149 /// use rvoip_client_core::{ClientManager, ClientConfig, RegistrationConfig};
1150 ///
1151 /// async fn multiple_registrations() -> Result<(), Box<dyn std::error::Error>> {
1152 /// let config = ClientConfig::new()
1153 /// .with_sip_addr("127.0.0.1:5075".parse()?);
1154 ///
1155 /// let client = ClientManager::new(config).await?;
1156 /// client.start().await?;
1157 ///
1158 /// // Register with multiple servers
1159 /// let reg1_config = RegistrationConfig {
1160 /// server_uri: "sip:server1.com".to_string(),
1161 /// from_uri: "sip:alice@server1.com".to_string(),
1162 /// contact_uri: "sip:alice@127.0.0.1:5075".to_string(),
1163 /// expires: 3600,
1164 /// username: None,
1165 /// password: None,
1166 /// realm: None,
1167 /// };
1168 ///
1169 /// let reg2_config = RegistrationConfig {
1170 /// server_uri: "sip:server2.com".to_string(),
1171 /// from_uri: "sip:alice@server2.com".to_string(),
1172 /// contact_uri: "sip:alice@127.0.0.1:5075".to_string(),
1173 /// expires: 3600,
1174 /// username: None,
1175 /// password: None,
1176 /// realm: None,
1177 /// };
1178 ///
1179 /// let reg1_id = client.register(reg1_config).await?;
1180 /// let reg2_id = client.register(reg2_config).await?;
1181 ///
1182 /// println!("✅ Registered with {} servers", 2);
1183 ///
1184 /// // Check all registrations
1185 /// let all_regs = client.get_all_registrations().await;
1186 /// assert_eq!(all_regs.len(), 2);
1187 ///
1188 /// // Clean up
1189 /// client.unregister(reg1_id).await?;
1190 /// client.unregister(reg2_id).await?;
1191 /// client.stop().await?;
1192 /// Ok(())
1193 /// }
1194 /// ```
1195 pub async fn register(&self, config: RegistrationConfig) -> ClientResult<Uuid> {
1196 // Use SipClient trait to register with retry logic for network errors
1197 let registration_handle = retry_with_backoff(
1198 "sip_registration",
1199 RetryConfig::slow(), // Use slower retry for registration
1200 || async {
1201 SipClient::register(
1202 &self.coordinator,
1203 &config.server_uri,
1204 &config.from_uri,
1205 &config.contact_uri,
1206 config.expires,
1207 )
1208 .await
1209 .map_err(|e| {
1210 // Categorize the error properly based on response
1211 let error_msg = e.to_string();
1212 if error_msg.contains("401") || error_msg.contains("407") {
1213 ClientError::AuthenticationFailed {
1214 reason: format!("Authentication required: {}", e)
1215 }
1216 } else if error_msg.contains("timeout") {
1217 ClientError::NetworkError {
1218 reason: format!("Registration timeout: {}", e)
1219 }
1220 } else if error_msg.contains("403") {
1221 ClientError::RegistrationFailed {
1222 reason: format!("Registration forbidden: {}", e)
1223 }
1224 } else {
1225 ClientError::RegistrationFailed {
1226 reason: format!("Registration failed: {}", e)
1227 }
1228 }
1229 })
1230 }
1231 )
1232 .await
1233 .with_context(|| format!("Failed to register {} with {}", config.from_uri, config.server_uri))?;
1234
1235 // Create registration info
1236 let reg_id = Uuid::new_v4();
1237 let registration_info = RegistrationInfo {
1238 id: reg_id,
1239 server_uri: config.server_uri.clone(),
1240 from_uri: config.from_uri.clone(),
1241 contact_uri: config.contact_uri.clone(),
1242 expires: config.expires,
1243 status: crate::registration::RegistrationStatus::Active,
1244 registration_time: chrono::Utc::now(),
1245 refresh_time: None,
1246 handle: Some(registration_handle),
1247 };
1248
1249 // Store registration
1250 self.registrations.write().await.insert(reg_id, registration_info);
1251
1252 // Update stats
1253 let mut stats = self.stats.lock().await;
1254 stats.total_registrations += 1;
1255 stats.active_registrations += 1;
1256
1257 // Broadcast registration event
1258 let _ = self.event_tx.send(ClientEvent::RegistrationStatusChanged {
1259 info: crate::events::RegistrationStatusInfo {
1260 registration_id: reg_id,
1261 server_uri: config.server_uri.clone(),
1262 user_uri: config.from_uri.clone(),
1263 status: crate::registration::RegistrationStatus::Active,
1264 reason: Some("Registration successful".to_string()),
1265 timestamp: chrono::Utc::now(),
1266 },
1267 priority: crate::events::EventPriority::Normal,
1268 });
1269
1270 tracing::info!("Registered {} with server {}", config.from_uri, config.server_uri);
1271 Ok(reg_id)
1272 }
1273
1274 /// Unregister from a SIP server
1275 ///
1276 /// This method removes a registration from a SIP server by sending a REGISTER
1277 /// request with expires=0. This gracefully removes the client's presence from
1278 /// the server and stops receiving incoming calls for that registration.
1279 ///
1280 /// # Arguments
1281 ///
1282 /// * `reg_id` - The UUID of the registration to remove
1283 ///
1284 /// # Returns
1285 ///
1286 /// Returns `Ok(())` if the unregistration was successful.
1287 ///
1288 /// # Errors
1289 ///
1290 /// * `ClientError::InvalidConfiguration` - If the registration ID is not found
1291 /// * `ClientError::InternalError` - If the unregistration request fails
1292 ///
1293 /// # Examples
1294 ///
1295 /// ```rust
1296 /// use rvoip_client_core::{ClientManager, ClientConfig, RegistrationConfig};
1297 ///
1298 /// async fn unregister_example() -> Result<(), Box<dyn std::error::Error>> {
1299 /// let config = ClientConfig::new()
1300 /// .with_sip_addr("127.0.0.1:5079".parse()?);
1301 ///
1302 /// let client = ClientManager::new(config).await?;
1303 /// client.start().await?;
1304 ///
1305 /// let reg_config = RegistrationConfig {
1306 /// server_uri: "sip:server.example.com".to_string(),
1307 /// from_uri: "sip:alice@example.com".to_string(),
1308 /// contact_uri: "sip:alice@127.0.0.1:5079".to_string(),
1309 /// expires: 3600,
1310 /// username: None,
1311 /// password: None,
1312 /// realm: None,
1313 /// };
1314 ///
1315 /// let reg_id = client.register(reg_config).await?;
1316 /// println!("✅ Registered with ID: {}", reg_id);
1317 ///
1318 /// // Unregister
1319 /// client.unregister(reg_id).await?;
1320 /// println!("✅ Successfully unregistered");
1321 ///
1322 /// client.stop().await?;
1323 /// Ok(())
1324 /// }
1325 /// ```
1326 pub async fn unregister(&self, reg_id: Uuid) -> ClientResult<()> {
1327 let mut registrations = self.registrations.write().await;
1328
1329 if let Some(registration_info) = registrations.get_mut(®_id) {
1330 // To unregister, send REGISTER with expires=0
1331 if let Some(handle) = ®istration_info.handle {
1332 SipClient::register(
1333 &self.coordinator,
1334 &handle.registrar_uri,
1335 ®istration_info.from_uri,
1336 &handle.contact_uri,
1337 0, // expires=0 means unregister
1338 )
1339 .await
1340 .map_err(|e| ClientError::InternalError {
1341 message: format!("Failed to unregister: {}", e)
1342 })?;
1343 }
1344
1345 // Update status
1346 registration_info.status = crate::registration::RegistrationStatus::Cancelled;
1347 registration_info.handle = None;
1348
1349 // Update stats
1350 let mut stats = self.stats.lock().await;
1351 if stats.active_registrations > 0 {
1352 stats.active_registrations -= 1;
1353 }
1354
1355 tracing::info!("Unregistered {}", registration_info.from_uri);
1356 Ok(())
1357 } else {
1358 Err(ClientError::InvalidConfiguration {
1359 field: "registration_id".to_string(),
1360 reason: "Registration not found".to_string()
1361 })
1362 }
1363 }
1364
1365 /// Get registration information
1366 ///
1367 /// Retrieves detailed information about a specific registration including
1368 /// status, timestamps, and server details.
1369 ///
1370 /// # Arguments
1371 ///
1372 /// * `reg_id` - The UUID of the registration to retrieve
1373 ///
1374 /// # Returns
1375 ///
1376 /// Returns the `RegistrationInfo` struct containing all registration details.
1377 ///
1378 /// # Errors
1379 ///
1380 /// * `ClientError::InvalidConfiguration` - If the registration ID is not found
1381 ///
1382 /// # Examples
1383 ///
1384 /// ```rust
1385 /// use rvoip_client_core::{ClientManager, ClientConfig, RegistrationConfig};
1386 ///
1387 /// async fn get_registration_info() -> Result<(), Box<dyn std::error::Error>> {
1388 /// let config = ClientConfig::new()
1389 /// .with_sip_addr("127.0.0.1:5080".parse()?);
1390 ///
1391 /// let client = ClientManager::new(config).await?;
1392 /// client.start().await?;
1393 ///
1394 /// let reg_config = RegistrationConfig {
1395 /// server_uri: "sip:server.example.com".to_string(),
1396 /// from_uri: "sip:user@example.com".to_string(),
1397 /// contact_uri: "sip:user@127.0.0.1:5080".to_string(),
1398 /// expires: 1800,
1399 /// username: None,
1400 /// password: None,
1401 /// realm: None,
1402 /// };
1403 ///
1404 /// let reg_id = client.register(reg_config).await?;
1405 ///
1406 /// // Get registration details
1407 /// let reg_info = client.get_registration(reg_id).await?;
1408 /// println!("Registration status: {:?}", reg_info.status);
1409 /// println!("Server: {}", reg_info.server_uri);
1410 /// println!("User: {}", reg_info.from_uri);
1411 /// println!("Expires: {} seconds", reg_info.expires);
1412 ///
1413 /// client.unregister(reg_id).await?;
1414 /// client.stop().await?;
1415 /// Ok(())
1416 /// }
1417 /// ```
1418 pub async fn get_registration(&self, reg_id: Uuid) -> ClientResult<crate::registration::RegistrationInfo> {
1419 let registrations = self.registrations.read().await;
1420 registrations.get(®_id)
1421 .cloned()
1422 .ok_or(ClientError::InvalidConfiguration {
1423 field: "registration_id".to_string(),
1424 reason: "Registration not found".to_string()
1425 })
1426 }
1427
1428 /// Get all active registrations
1429 ///
1430 /// Returns a list of all currently active registrations. This includes only
1431 /// registrations with status `Active`, filtering out expired or cancelled ones.
1432 ///
1433 /// # Returns
1434 ///
1435 /// Returns a `Vec<RegistrationInfo>` containing all active registrations.
1436 ///
1437 /// # Examples
1438 ///
1439 /// ```rust
1440 /// use rvoip_client_core::{ClientManager, ClientConfig, RegistrationConfig};
1441 ///
1442 /// async fn list_registrations() -> Result<(), Box<dyn std::error::Error>> {
1443 /// let config = ClientConfig::new()
1444 /// .with_sip_addr("127.0.0.1:5081".parse()?);
1445 ///
1446 /// let client = ClientManager::new(config).await?;
1447 /// client.start().await?;
1448 ///
1449 /// // Create multiple registrations
1450 /// let reg1_config = RegistrationConfig {
1451 /// server_uri: "sip:server1.com".to_string(),
1452 /// from_uri: "sip:alice@server1.com".to_string(),
1453 /// contact_uri: "sip:alice@127.0.0.1:5081".to_string(),
1454 /// expires: 3600,
1455 /// username: None,
1456 /// password: None,
1457 /// realm: None,
1458 /// };
1459 ///
1460 /// let reg2_config = RegistrationConfig {
1461 /// server_uri: "sip:server2.com".to_string(),
1462 /// from_uri: "sip:alice@server2.com".to_string(),
1463 /// contact_uri: "sip:alice@127.0.0.1:5081".to_string(),
1464 /// expires: 1800,
1465 /// username: None,
1466 /// password: None,
1467 /// realm: None,
1468 /// };
1469 ///
1470 /// let _reg1_id = client.register(reg1_config).await?;
1471 /// let _reg2_id = client.register(reg2_config).await?;
1472 ///
1473 /// // List all active registrations
1474 /// let active_regs = client.get_all_registrations().await;
1475 /// println!("Active registrations: {}", active_regs.len());
1476 ///
1477 /// for reg in active_regs {
1478 /// println!("- {} at {}", reg.from_uri, reg.server_uri);
1479 /// }
1480 ///
1481 /// client.stop().await?;
1482 /// Ok(())
1483 /// }
1484 /// ```
1485 pub async fn get_all_registrations(&self) -> Vec<crate::registration::RegistrationInfo> {
1486 let registrations = self.registrations.read().await;
1487 registrations.values()
1488 .filter(|r| r.status == crate::registration::RegistrationStatus::Active)
1489 .cloned()
1490 .collect()
1491 }
1492
1493 /// Refresh a registration
1494 ///
1495 /// Manually refreshes a registration by sending a new REGISTER request with
1496 /// the same parameters. This is useful for extending registration lifetime
1497 /// before expiration or after network connectivity issues.
1498 ///
1499 /// # Arguments
1500 ///
1501 /// * `reg_id` - The UUID of the registration to refresh
1502 ///
1503 /// # Returns
1504 ///
1505 /// Returns `Ok(())` if the registration was successfully refreshed.
1506 ///
1507 /// # Errors
1508 ///
1509 /// * `ClientError::InvalidConfiguration` - If the registration ID is not found
1510 /// * `ClientError::InternalError` - If the refresh request fails
1511 ///
1512 /// # Examples
1513 ///
1514 /// ```rust
1515 /// use rvoip_client_core::{ClientManager, ClientConfig, RegistrationConfig};
1516 ///
1517 /// async fn refresh_registration_example() -> Result<(), Box<dyn std::error::Error>> {
1518 /// let config = ClientConfig::new()
1519 /// .with_sip_addr("127.0.0.1:5082".parse()?);
1520 ///
1521 /// let client = ClientManager::new(config).await?;
1522 /// client.start().await?;
1523 ///
1524 /// let reg_config = RegistrationConfig {
1525 /// server_uri: "sip:server.example.com".to_string(),
1526 /// from_uri: "sip:user@example.com".to_string(),
1527 /// contact_uri: "sip:user@127.0.0.1:5082".to_string(),
1528 /// expires: 300, // Short expiration for demo
1529 /// username: None,
1530 /// password: None,
1531 /// realm: None,
1532 /// };
1533 ///
1534 /// let reg_id = client.register(reg_config).await?;
1535 /// println!("✅ Initial registration completed");
1536 ///
1537 /// // Refresh the registration
1538 /// client.refresh_registration(reg_id).await?;
1539 /// println!("✅ Registration refreshed successfully");
1540 ///
1541 /// // Check registration info
1542 /// if let Ok(reg_info) = client.get_registration(reg_id).await {
1543 /// if let Some(refresh_time) = reg_info.refresh_time {
1544 /// println!("Last refreshed: {}", refresh_time);
1545 /// }
1546 /// }
1547 ///
1548 /// client.unregister(reg_id).await?;
1549 /// client.stop().await?;
1550 /// Ok(())
1551 /// }
1552 /// ```
1553 pub async fn refresh_registration(&self, reg_id: Uuid) -> ClientResult<()> {
1554 // Get registration data
1555 let (registrar_uri, from_uri, contact_uri, expires) = {
1556 let registrations = self.registrations.read().await;
1557
1558 if let Some(registration_info) = registrations.get(®_id) {
1559 if let Some(handle) = ®istration_info.handle {
1560 (
1561 handle.registrar_uri.clone(),
1562 registration_info.from_uri.clone(),
1563 handle.contact_uri.clone(),
1564 registration_info.expires,
1565 )
1566 } else {
1567 return Err(ClientError::InvalidConfiguration {
1568 field: "registration".to_string(),
1569 reason: "Registration has no handle".to_string()
1570 });
1571 }
1572 } else {
1573 return Err(ClientError::InvalidConfiguration {
1574 field: "registration_id".to_string(),
1575 reason: "Registration not found".to_string()
1576 });
1577 }
1578 };
1579
1580 // Re-register with the same parameters
1581 let new_handle = SipClient::register(
1582 &self.coordinator,
1583 ®istrar_uri,
1584 &from_uri,
1585 &contact_uri,
1586 expires,
1587 )
1588 .await
1589 .map_err(|e| ClientError::InternalError {
1590 message: format!("Failed to refresh registration: {}", e)
1591 })?;
1592
1593 // Update registration with new handle
1594 let mut registrations = self.registrations.write().await;
1595 if let Some(reg) = registrations.get_mut(®_id) {
1596 reg.handle = Some(new_handle);
1597 reg.refresh_time = Some(chrono::Utc::now());
1598 }
1599
1600 tracing::info!("Refreshed registration for {}", from_uri);
1601 Ok(())
1602 }
1603
1604 /// Clear expired registrations
1605 ///
1606 /// Removes all registrations with `Expired` status from the internal storage.
1607 /// This is a maintenance operation that cleans up stale registration entries
1608 /// and updates statistics accordingly.
1609 ///
1610 /// # Examples
1611 ///
1612 /// ```rust
1613 /// use rvoip_client_core::{ClientManager, ClientConfig};
1614 ///
1615 /// async fn cleanup_registrations() -> Result<(), Box<dyn std::error::Error>> {
1616 /// let config = ClientConfig::new()
1617 /// .with_sip_addr("127.0.0.1:5083".parse()?);
1618 ///
1619 /// let client = ClientManager::new(config).await?;
1620 /// client.start().await?;
1621 ///
1622 /// // In a real application, you might have some expired registrations
1623 /// // This method would clean them up
1624 /// client.clear_expired_registrations().await;
1625 /// println!("✅ Expired registrations cleaned up");
1626 ///
1627 /// // Check remaining active registrations
1628 /// let active_count = client.get_all_registrations().await.len();
1629 /// println!("Active registrations remaining: {}", active_count);
1630 ///
1631 /// client.stop().await?;
1632 /// Ok(())
1633 /// }
1634 /// ```
1635 pub async fn clear_expired_registrations(&self) {
1636 let mut registrations = self.registrations.write().await;
1637 let mut to_remove = Vec::new();
1638
1639 for (id, reg) in registrations.iter() {
1640 if reg.status == crate::registration::RegistrationStatus::Expired {
1641 to_remove.push(*id);
1642 }
1643 }
1644
1645 for id in to_remove {
1646 registrations.remove(&id);
1647
1648 // Update stats
1649 let mut stats = self.stats.lock().await;
1650 if stats.active_registrations > 0 {
1651 stats.active_registrations -= 1;
1652 }
1653 }
1654 }
1655
1656 // ===== CONVENIENCE METHODS FOR EXAMPLES =====
1657
1658 /// Convenience method: Register with simple parameters (for examples)
1659 ///
1660 /// This is a simplified registration method that takes basic parameters and
1661 /// constructs a complete `RegistrationConfig` automatically. It's designed
1662 /// for quick testing and simple use cases.
1663 ///
1664 /// # Arguments
1665 ///
1666 /// * `agent_uri` - The SIP URI for this agent (e.g., "sip:alice@example.com")
1667 /// * `server_addr` - The SIP server address and port
1668 /// * `duration` - How long the registration should last
1669 ///
1670 /// # Returns
1671 ///
1672 /// Returns `Ok(())` if registration was successful.
1673 ///
1674 /// # Examples
1675 ///
1676 /// ```rust
1677 /// use rvoip_client_core::{ClientManager, ClientConfig};
1678 /// use std::time::Duration;
1679 ///
1680 /// async fn simple_register() -> Result<(), Box<dyn std::error::Error>> {
1681 /// let config = ClientConfig::new()
1682 /// .with_sip_addr("127.0.0.1:5084".parse()?);
1683 ///
1684 /// let client = ClientManager::new(config).await?;
1685 /// client.start().await?;
1686 ///
1687 /// let server_addr = "192.168.1.100:5060".parse()?;
1688 /// let duration = Duration::from_secs(3600); // 1 hour
1689 ///
1690 /// // Simple registration
1691 /// client.register_simple(
1692 /// "sip:testuser@example.com",
1693 /// &server_addr,
1694 /// duration
1695 /// ).await?;
1696 ///
1697 /// println!("✅ Simple registration completed");
1698 ///
1699 /// // Cleanup using the simple unregister method
1700 /// client.unregister_simple(
1701 /// "sip:testuser@example.com",
1702 /// &server_addr
1703 /// ).await?;
1704 ///
1705 /// client.stop().await?;
1706 /// Ok(())
1707 /// }
1708 /// ```
1709 pub async fn register_simple(
1710 &self,
1711 agent_uri: &str,
1712 server_addr: &std::net::SocketAddr,
1713 duration: std::time::Duration
1714 ) -> ClientResult<()> {
1715 let config = RegistrationConfig {
1716 server_uri: format!("sip:{}", server_addr),
1717 from_uri: agent_uri.to_string(),
1718 contact_uri: format!("sip:{}:{}", self.local_sip_addr.ip(), self.local_sip_addr.port()),
1719 expires: duration.as_secs() as u32,
1720 username: None,
1721 password: None,
1722 realm: None,
1723 };
1724
1725 self.register(config).await?;
1726 Ok(())
1727 }
1728
1729 /// Convenience method: Unregister with simple parameters (for examples)
1730 ///
1731 /// This method finds and unregisters a registration that matches the given
1732 /// agent URI and server address. It's the counterpart to `register_simple()`
1733 /// and provides an easy way to clean up simple registrations.
1734 ///
1735 /// # Arguments
1736 ///
1737 /// * `agent_uri` - The SIP URI that was registered
1738 /// * `server_addr` - The SIP server address that was used
1739 ///
1740 /// # Returns
1741 ///
1742 /// Returns `Ok(())` if unregistration was successful.
1743 ///
1744 /// # Errors
1745 ///
1746 /// * `ClientError::InvalidConfiguration` - If no matching registration is found
1747 ///
1748 /// # Examples
1749 ///
1750 /// ```rust
1751 /// use rvoip_client_core::{ClientManager, ClientConfig};
1752 /// use std::time::Duration;
1753 ///
1754 /// async fn simple_unregister() -> Result<(), Box<dyn std::error::Error>> {
1755 /// let config = ClientConfig::new()
1756 /// .with_sip_addr("127.0.0.1:5085".parse()?);
1757 ///
1758 /// let client = ClientManager::new(config).await?;
1759 /// client.start().await?;
1760 ///
1761 /// let agent_uri = "sip:testuser@example.com";
1762 /// let server_addr = "192.168.1.100:5060".parse()?;
1763 ///
1764 /// // Register first
1765 /// client.register_simple(
1766 /// agent_uri,
1767 /// &server_addr,
1768 /// Duration::from_secs(3600)
1769 /// ).await?;
1770 ///
1771 /// println!("✅ Registration completed");
1772 ///
1773 /// // Now unregister using the same parameters
1774 /// client.unregister_simple(agent_uri, &server_addr).await?;
1775 /// println!("✅ Unregistration completed");
1776 ///
1777 /// // Verify no active registrations remain
1778 /// let active_regs = client.get_all_registrations().await;
1779 /// assert_eq!(active_regs.len(), 0);
1780 ///
1781 /// client.stop().await?;
1782 /// Ok(())
1783 /// }
1784 /// ```
1785 pub async fn unregister_simple(
1786 &self,
1787 agent_uri: &str,
1788 server_addr: &std::net::SocketAddr
1789 ) -> ClientResult<()> {
1790 // Find the registration matching these parameters
1791 let registrations = self.registrations.read().await;
1792 let reg_id = registrations.iter()
1793 .find(|(_, reg)| {
1794 reg.from_uri == agent_uri &&
1795 reg.server_uri == format!("sip:{}", server_addr)
1796 })
1797 .map(|(id, _)| *id);
1798 drop(registrations);
1799
1800 if let Some(id) = reg_id {
1801 self.unregister(id).await
1802 } else {
1803 Err(ClientError::InvalidConfiguration {
1804 field: "registration".to_string(),
1805 reason: "No matching registration found".to_string()
1806 })
1807 }
1808 }
1809
1810 /// Subscribe to client events
1811 ///
1812 /// Creates a new receiver for the client event broadcast channel. Multiple
1813 /// subscribers can listen to the same events simultaneously.
1814 ///
1815 /// # Returns
1816 ///
1817 /// Returns a `broadcast::Receiver<ClientEvent>` for receiving real-time events.
1818 ///
1819 /// # Examples
1820 ///
1821 /// ```rust
1822 /// use rvoip_client_core::{ClientManager, ClientConfig, ClientEvent};
1823 /// use tokio::time::{timeout, Duration};
1824 ///
1825 /// async fn event_subscription() -> Result<(), Box<dyn std::error::Error>> {
1826 /// let config = ClientConfig::new()
1827 /// .with_sip_addr("127.0.0.1:5076".parse()?);
1828 ///
1829 /// let client = ClientManager::new(config).await?;
1830 /// let mut events = client.subscribe_events();
1831 ///
1832 /// client.start().await?;
1833 ///
1834 /// // Listen for events (with timeout for doc test)
1835 /// if let Ok(Ok(event)) = timeout(Duration::from_millis(10), events.recv()).await {
1836 /// match event {
1837 /// ClientEvent::CallStateChanged { info, .. } => {
1838 /// println!("Call event: {:?}", info.new_state);
1839 /// }
1840 /// ClientEvent::RegistrationStatusChanged { info, .. } => {
1841 /// println!("Registration event: {:?}", info.status);
1842 /// }
1843 /// ClientEvent::MediaEvent { info, .. } => {
1844 /// println!("Media event for call: {}", info.call_id);
1845 /// }
1846 /// ClientEvent::IncomingCall { .. } |
1847 /// ClientEvent::ClientError { .. } |
1848 /// ClientEvent::NetworkEvent { .. } => {
1849 /// // Handle other events as needed
1850 /// }
1851 /// }
1852 /// }
1853 ///
1854 /// client.stop().await?;
1855 /// Ok(())
1856 /// }
1857 /// ```
1858 pub fn subscribe_events(&self) -> tokio::sync::broadcast::Receiver<ClientEvent> {
1859 self.event_tx.subscribe()
1860 }
1861
1862 /// Check if the client is running
1863 ///
1864 /// Returns the current running state of the client manager. A client must be
1865 /// started before it can handle SIP operations.
1866 ///
1867 /// # Returns
1868 ///
1869 /// Returns `true` if the client is currently running, `false` otherwise.
1870 ///
1871 /// # Examples
1872 ///
1873 /// ```rust
1874 /// use rvoip_client_core::{ClientManager, ClientConfig};
1875 ///
1876 /// async fn check_running_state() -> Result<(), Box<dyn std::error::Error>> {
1877 /// let config = ClientConfig::new()
1878 /// .with_sip_addr("127.0.0.1:5077".parse()?);
1879 ///
1880 /// let client = ClientManager::new(config).await?;
1881 ///
1882 /// // Initially not running
1883 /// assert!(!client.is_running().await);
1884 ///
1885 /// // Start and check
1886 /// client.start().await?;
1887 /// assert!(client.is_running().await);
1888 ///
1889 /// // Stop and check
1890 /// client.stop().await?;
1891 /// assert!(!client.is_running().await);
1892 ///
1893 /// Ok(())
1894 /// }
1895 /// ```
1896 pub async fn is_running(&self) -> bool {
1897 *self.is_running.read().await
1898 }
1899
1900 /// Get the media configuration
1901 ///
1902 /// Returns a reference to the current media configuration being used by the client.
1903 /// This includes codec preferences, quality settings, and network parameters.
1904 ///
1905 /// # Returns
1906 ///
1907 /// Returns a reference to the `MediaConfig` used during client initialization.
1908 ///
1909 /// # Examples
1910 ///
1911 /// ```rust
1912 /// use rvoip_client_core::{ClientManager, ClientConfig, MediaConfig, MediaPreset};
1913 ///
1914 /// async fn check_media_config() -> Result<(), Box<dyn std::error::Error>> {
1915 /// use rvoip_client_core::client::config::MediaPreset;
1916 /// let mut media_config = MediaConfig::from_preset(MediaPreset::VoiceOptimized);
1917 /// media_config.echo_cancellation = true;
1918 /// media_config.max_bandwidth_kbps = Some(128);
1919 ///
1920 /// let config = ClientConfig::new()
1921 /// .with_sip_addr("127.0.0.1:5078".parse()?)
1922 /// .with_media(media_config);
1923 ///
1924 /// let client = ClientManager::new(config).await?;
1925 ///
1926 /// // Check applied configuration
1927 /// let applied_config = client.get_media_config();
1928 /// assert!(applied_config.echo_cancellation);
1929 /// assert_eq!(applied_config.max_bandwidth_kbps, Some(128));
1930 ///
1931 /// println!("Echo cancellation: {}", applied_config.echo_cancellation);
1932 /// println!("Noise suppression: {}", applied_config.noise_suppression);
1933 /// println!("RTP port range: {}-{}",
1934 /// applied_config.rtp_port_start, applied_config.rtp_port_end);
1935 ///
1936 /// Ok(())
1937 /// }
1938 /// ```
1939 pub fn get_media_config(&self) -> &MediaConfig {
1940 &self.media_config
1941 }
1942
1943 // ===== PRIORITY 3.2: CALL CONTROL OPERATIONS =====
1944 // Call control operations have been moved to controls.rs
1945
1946 // ===== PRIORITY 4.1: ENHANCED MEDIA INTEGRATION =====
1947 // Media operations have been moved to media.rs
1948
1949 /// Set up audio frame subscription for a call
1950 ///
1951 /// This internal method is called when a call becomes established to automatically
1952 /// set up audio frame subscription, enabling audio to flow for the call.
1953 pub(crate) async fn setup_call_audio(&self, call_id: &CallId) -> ClientResult<()> {
1954 // Get the session ID for this call
1955 if let Some(session_id_entry) = self.session_mapping.get(call_id) {
1956 let session_id = session_id_entry.clone();
1957
1958 // Subscribe to audio frames from this session
1959 match MediaControl::subscribe_to_audio_frames(&self.coordinator, &session_id).await {
1960 Ok(audio_subscriber) => {
1961 // Mark that audio is set up for this call
1962 self.audio_setup_calls.insert(*call_id, true);
1963
1964 // Audio subscriber is now available for the application to use
1965 // The application (e.g., sip-client) can integrate with audio-core
1966 // to connect this subscriber to speakers and set up microphone capture
1967 tracing::info!("Audio frame subscription ready for call {}", call_id);
1968 tracing::info!("To enable audio, integrate with audio-core in your application");
1969
1970 // For now, just drop the subscriber as we can't use audio-core directly
1971 // due to circular dependency issues
1972 drop(audio_subscriber);
1973
1974 // TODO: In the future, this is where we would connect to audio-core
1975 // to route audio frames to the appropriate audio device.
1976 // For now, the audio frames are available via the subscriber.
1977
1978 tracing::info!("Set up audio frame subscription for call {}", call_id);
1979 Ok(())
1980 }
1981 Err(e) => {
1982 // Log the error but don't fail the call - audio might still work
1983 // through other means or this might be a non-audio call
1984 tracing::warn!("Failed to set up audio frame subscription for call {}: {}", call_id, e);
1985 Err(ClientError::MediaError {
1986 details: format!("Failed to subscribe to audio frames: {}", e)
1987 })
1988 }
1989 }
1990 } else {
1991 Err(ClientError::CallNotFound { call_id: *call_id })
1992 }
1993 }
1994}
1995
1996impl Drop for ClientManager {
1997 fn drop(&mut self) {
1998 // Check if still running using try_read to avoid blocking
1999 if let Ok(is_running) = self.is_running.try_read() {
2000 if *is_running {
2001 tracing::warn!("ClientManager dropped while still running! Call stop() before dropping to ensure proper cleanup.");
2002 }
2003 }
2004 }
2005}
2006
2007