rvoip_client_core/
registration.rs

1//! Registration management for SIP client
2//!
3//! This module provides registration information structures and configuration for
4//! SIP registration with registrar servers. All actual SIP registration operations
5//! are delegated to session-core.
6//!
7//! # Architecture
8//!
9//! PROPER LAYER SEPARATION:
10//! client-core -> session-core -> {transaction-core, media-core, sip-transport, sip-core}
11//!
12//! # Key Components
13//!
14//! - **RegistrationConfig** - Configuration for SIP registration
15//! - **RegistrationStatus** - Current state of a registration
16//! - **RegistrationInfo** - Complete registration details and metadata
17//! - **RegistrationStats** - Aggregate statistics about registrations
18//!
19//! # SIP Registration Process
20//!
21//! 1. **Configuration** - Define server, credentials, and parameters
22//! 2. **Registration** - Send REGISTER request to SIP server
23//! 3. **Authentication** - Handle authentication challenge if required
24//! 4. **Maintenance** - Periodically refresh registration before expiry
25//! 5. **Termination** - Unregister when shutting down
26//!
27//! # Usage Examples
28//!
29//! ## Creating Registration Configuration
30//!
31//! ```rust
32//! use rvoip_client_core::registration::RegistrationConfig;
33//!
34//! // Basic registration without authentication
35//! let config = RegistrationConfig::new(
36//!     "sip:registrar.example.com".to_string(),
37//!     "sip:alice@example.com".to_string(),
38//!     "sip:alice@192.168.1.100:5060".to_string(),
39//! );
40//!
41//! // Registration with authentication
42//! let auth_config = RegistrationConfig::new(
43//!     "sip:registrar.example.com".to_string(),
44//!     "sip:alice@example.com".to_string(),
45//!     "sip:alice@192.168.1.100:5060".to_string(),
46//! )
47//! .with_credentials("alice".to_string(), "secret123".to_string())
48//! .with_realm("example.com".to_string())
49//! .with_expires(1800); // 30 minutes
50//!
51//! assert_eq!(auth_config.expires, 1800);
52//! assert_eq!(auth_config.username, Some("alice".to_string()));
53//! ```
54//!
55//! ## Working with Registration Status
56//!
57//! ```rust
58//! use rvoip_client_core::registration::RegistrationStatus;
59//!
60//! let status = RegistrationStatus::Active;
61//! println!("Registration status: {}", status);
62//!
63//! assert_eq!(status, RegistrationStatus::Active);
64//! assert_ne!(status, RegistrationStatus::Failed);
65//! ```
66//!
67//! ## Creating Registration Information
68//!
69//! ```rust
70//! use rvoip_client_core::registration::{RegistrationInfo, RegistrationStatus};
71//! use chrono::Utc;
72//! use uuid::Uuid;
73//!
74//! let reg_info = RegistrationInfo {
75//!     id: Uuid::new_v4(),
76//!     server_uri: "sip:registrar.example.com".to_string(),
77//!     from_uri: "sip:alice@example.com".to_string(),
78//!     contact_uri: "sip:alice@192.168.1.100:5060".to_string(),
79//!     expires: 3600,
80//!     status: RegistrationStatus::Active,
81//!     registration_time: Utc::now(),
82//!     refresh_time: Some(Utc::now()),
83//!     handle: None,
84//! };
85//!
86//! assert_eq!(reg_info.status, RegistrationStatus::Active);
87//! assert_eq!(reg_info.expires, 3600);
88//! ```
89
90use serde::{Deserialize, Serialize};
91use uuid::Uuid;
92use chrono::{DateTime, Utc};
93use rvoip_session_core::api::RegistrationHandle;
94
95/// Registration configuration for SIP server registration
96/// 
97/// Contains all necessary parameters to register with a SIP registrar server,
98/// including server details, user identity, authentication credentials,
99/// and registration timing parameters.
100/// 
101/// # Examples
102/// 
103/// ```rust
104/// use rvoip_client_core::registration::RegistrationConfig;
105/// 
106/// let config = RegistrationConfig::new(
107///     "sip:registrar.example.com".to_string(),
108///     "sip:alice@example.com".to_string(), 
109///     "sip:alice@192.168.1.100:5060".to_string(),
110/// )
111/// .with_credentials("alice".to_string(), "password123".to_string())
112/// .with_expires(1800);
113/// 
114/// assert_eq!(config.server_uri, "sip:registrar.example.com");
115/// assert_eq!(config.username, Some("alice".to_string()));
116/// assert_eq!(config.expires, 1800);
117/// ```
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct RegistrationConfig {
120    /// SIP registrar server URI (e.g., "sip:registrar.example.com")
121    /// 
122    /// The URI of the SIP registrar server where this client will register.
123    /// This should include the scheme (sip: or sips:) and may include port.
124    pub server_uri: String,
125    
126    /// From URI representing the user identity (e.g., "sip:alice@example.com")
127    /// 
128    /// The SIP address that identifies this user. This appears in the From
129    /// header of REGISTER requests and represents the user's public identity.
130    pub from_uri: String,
131    
132    /// Contact URI for this client (e.g., "sip:alice@192.168.1.100:5060")
133    /// 
134    /// The SIP URI where this client can be reached for incoming calls.
135    /// Typically includes the client's current IP address and port.
136    pub contact_uri: String,
137    
138    /// Registration expiration time in seconds
139    /// 
140    /// How long the registration should remain valid. The client will
141    /// automatically refresh the registration before this time expires.
142    /// Common values: 3600 (1 hour), 1800 (30 minutes), 300 (5 minutes).
143    pub expires: u32,
144    
145    /// Authentication username (optional)
146    /// 
147    /// Username for SIP digest authentication. Required if the registrar
148    /// server requires authentication (most production servers do).
149    pub username: Option<String>,
150    
151    /// Authentication password (optional)
152    /// 
153    /// Password for SIP digest authentication. Should be kept secure
154    /// and not logged or displayed in plain text.
155    pub password: Option<String>,
156    
157    /// Authentication realm (optional)
158    /// 
159    /// Authentication realm provided by the server. Often the same as
160    /// the domain portion of the server URI. Usually provided by the
161    /// server in authentication challenges.
162    pub realm: Option<String>,
163}
164
165impl RegistrationConfig {
166    /// Create a new registration configuration with default settings
167    /// 
168    /// Creates a basic registration configuration with a default expiration
169    /// of 3600 seconds (1 hour) and no authentication credentials.
170    /// 
171    /// # Arguments
172    /// 
173    /// * `server_uri` - URI of the SIP registrar server
174    /// * `from_uri` - SIP URI representing the user identity
175    /// * `contact_uri` - SIP URI where this client can be reached
176    /// 
177    /// # Examples
178    /// 
179    /// ```rust
180    /// use rvoip_client_core::registration::RegistrationConfig;
181    /// 
182    /// let config = RegistrationConfig::new(
183    ///     "sip:registrar.example.com".to_string(),
184    ///     "sip:alice@example.com".to_string(),
185    ///     "sip:alice@192.168.1.100:5060".to_string(),
186    /// );
187    /// 
188    /// assert_eq!(config.expires, 3600); // Default 1 hour
189    /// assert_eq!(config.username, None); // No auth by default
190    /// ```
191    pub fn new(server_uri: String, from_uri: String, contact_uri: String) -> Self {
192        Self {
193            server_uri,
194            from_uri,
195            contact_uri,
196            expires: 3600, // Default to 1 hour
197            username: None,
198            password: None,
199            realm: None,
200        }
201    }
202    
203    /// Set authentication credentials for the registration
204    /// 
205    /// Configures username and password for SIP digest authentication.
206    /// Most production SIP servers require authentication.
207    /// 
208    /// # Arguments
209    /// 
210    /// * `username` - Authentication username
211    /// * `password` - Authentication password
212    /// 
213    /// # Examples
214    /// 
215    /// ```rust
216    /// use rvoip_client_core::registration::RegistrationConfig;
217    /// 
218    /// let config = RegistrationConfig::new(
219    ///     "sip:registrar.example.com".to_string(),
220    ///     "sip:alice@example.com".to_string(),
221    ///     "sip:alice@192.168.1.100:5060".to_string(),
222    /// )
223    /// .with_credentials("alice".to_string(), "secret123".to_string());
224    /// 
225    /// assert_eq!(config.username, Some("alice".to_string()));
226    /// assert_eq!(config.password, Some("secret123".to_string()));
227    /// ```
228    pub fn with_credentials(mut self, username: String, password: String) -> Self {
229        self.username = Some(username);
230        self.password = Some(password);
231        self
232    }
233    
234    /// Set the authentication realm for the registration
235    /// 
236    /// The realm is usually provided by the server during authentication
237    /// challenges, but can be set in advance if known.
238    /// 
239    /// # Arguments
240    /// 
241    /// * `realm` - Authentication realm (often the server domain)
242    /// 
243    /// # Examples
244    /// 
245    /// ```rust
246    /// use rvoip_client_core::registration::RegistrationConfig;
247    /// 
248    /// let config = RegistrationConfig::new(
249    ///     "sip:registrar.example.com".to_string(),
250    ///     "sip:alice@example.com".to_string(),
251    ///     "sip:alice@192.168.1.100:5060".to_string(),
252    /// )
253    /// .with_realm("example.com".to_string());
254    /// 
255    /// assert_eq!(config.realm, Some("example.com".to_string()));
256    /// ```
257    pub fn with_realm(mut self, realm: String) -> Self {
258        self.realm = Some(realm);
259        self
260    }
261    
262    /// Set the registration expiration time
263    /// 
264    /// Controls how long the registration remains valid before requiring
265    /// a refresh. Shorter times provide faster failover detection but
266    /// increase network traffic.
267    /// 
268    /// # Arguments
269    /// 
270    /// * `expires` - Expiration time in seconds
271    /// 
272    /// # Examples
273    /// 
274    /// ```rust
275    /// use rvoip_client_core::registration::RegistrationConfig;
276    /// 
277    /// let config = RegistrationConfig::new(
278    ///     "sip:registrar.example.com".to_string(),
279    ///     "sip:alice@example.com".to_string(),
280    ///     "sip:alice@192.168.1.100:5060".to_string(),
281    /// )
282    /// .with_expires(1800); // 30 minutes
283    /// 
284    /// assert_eq!(config.expires, 1800);
285    /// ```
286    pub fn with_expires(mut self, expires: u32) -> Self {
287        self.expires = expires;
288        self
289    }
290}
291
292/// Current status of a SIP registration
293/// 
294/// Represents the various states a registration can be in during its lifecycle,
295/// from initial setup through active registration to termination.
296/// 
297/// # State Transitions
298/// 
299/// Typical registration flow:
300/// `Pending` → `Active` → `Expired`/`Failed`/`Cancelled`
301/// 
302/// # Examples
303/// 
304/// ```rust
305/// use rvoip_client_core::registration::RegistrationStatus;
306/// 
307/// let status = RegistrationStatus::Active;
308/// println!("Status: {}", status); // Prints "Status: Active"
309/// 
310/// assert_eq!(status, RegistrationStatus::Active);
311/// assert_ne!(status, RegistrationStatus::Failed);
312/// ```
313#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
314pub enum RegistrationStatus {
315    /// Registration request has been sent but no response received yet
316    /// 
317    /// Initial state when a REGISTER request is sent to the server.
318    /// The client is waiting for the server's response.
319    Pending,
320    
321    /// Registration is active and valid
322    /// 
323    /// The server has accepted the registration and it's currently valid.
324    /// The client can receive incoming calls and the registration will
325    /// be refreshed automatically before expiration.
326    Active,
327    
328    /// Registration failed
329    /// 
330    /// The server rejected the registration request, typically due to
331    /// authentication failure, invalid credentials, or server error.
332    /// This is a terminal state that requires manual intervention.
333    Failed,
334    
335    /// Registration expired
336    /// 
337    /// The registration validity period has elapsed and the registration
338    /// is no longer active. This can happen if refresh attempts fail
339    /// or if the client is disconnected for too long.
340    Expired,
341    
342    /// Registration was cancelled by the client
343    /// 
344    /// The client explicitly unregistered by sending a REGISTER request
345    /// with Expires: 0. This is the normal way to end a registration.
346    Cancelled,
347}
348
349impl std::fmt::Display for RegistrationStatus {
350    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
351        match self {
352            RegistrationStatus::Pending => write!(f, "Pending"),
353            RegistrationStatus::Active => write!(f, "Active"),
354            RegistrationStatus::Failed => write!(f, "Failed"),
355            RegistrationStatus::Expired => write!(f, "Expired"),
356            RegistrationStatus::Cancelled => write!(f, "Cancelled"),
357        }
358    }
359}
360
361/// Comprehensive information about a SIP registration
362/// 
363/// Contains all details about a registration including configuration,
364/// current status, timing information, and technical handles.
365/// 
366/// # Examples
367/// 
368/// ```rust
369/// use rvoip_client_core::registration::{RegistrationInfo, RegistrationStatus};
370/// use chrono::Utc;
371/// use uuid::Uuid;
372/// 
373/// let reg_info = RegistrationInfo {
374///     id: Uuid::new_v4(),
375///     server_uri: "sip:registrar.example.com".to_string(),
376///     from_uri: "sip:alice@example.com".to_string(),
377///     contact_uri: "sip:alice@192.168.1.100:5060".to_string(),
378///     expires: 3600,
379///     status: RegistrationStatus::Active,
380///     registration_time: Utc::now(),
381///     refresh_time: Some(Utc::now()),
382///     handle: None,
383/// };
384/// 
385/// assert_eq!(reg_info.status, RegistrationStatus::Active);
386/// assert_eq!(reg_info.server_uri, "sip:registrar.example.com");
387/// ```
388#[derive(Debug, Clone)]
389pub struct RegistrationInfo {
390    /// Unique registration identifier assigned by the client
391    pub id: Uuid,
392    
393    /// SIP registrar server URI where this registration is active
394    pub server_uri: String,
395    
396    /// From URI representing the registered user identity
397    pub from_uri: String,
398    
399    /// Contact URI where this client can be reached for incoming calls
400    pub contact_uri: String,
401    
402    /// Registration expiration time in seconds from last refresh
403    pub expires: u32,
404    
405    /// Current status of this registration
406    pub status: RegistrationStatus,
407    
408    /// When the registration was initially created
409    pub registration_time: DateTime<Utc>,
410    
411    /// When the registration was last successfully refreshed (if applicable)
412    pub refresh_time: Option<DateTime<Utc>>,
413    
414    /// Internal handle to the session-core registration (if active)
415    pub handle: Option<RegistrationHandle>,
416}
417
418/// Statistics about SIP registrations in the system
419/// 
420/// Provides aggregate counts and metrics about registrations, useful for
421/// monitoring, debugging, and user interface displays.
422/// 
423/// # Examples
424/// 
425/// ```rust
426/// use rvoip_client_core::registration::RegistrationStats;
427/// 
428/// let stats = RegistrationStats {
429///     total_registrations: 5,
430///     active_registrations: 3,
431///     failed_registrations: 1,
432/// };
433/// 
434/// assert_eq!(stats.total_registrations, 5);
435/// assert_eq!(stats.active_registrations, 3);
436/// assert_eq!(stats.failed_registrations, 1);
437/// 
438/// // Calculate derived metrics
439/// let pending_registrations = stats.total_registrations - stats.active_registrations - stats.failed_registrations;
440/// assert_eq!(pending_registrations, 1);
441/// ```
442#[derive(Debug, Clone)]
443pub struct RegistrationStats {
444    /// Total number of registrations (all statuses)
445    pub total_registrations: usize,
446    /// Number of registrations in Active status
447    pub active_registrations: usize,
448    /// Number of registrations in Failed status
449    pub failed_registrations: usize,
450}