rvoip_client_core/events.rs
1//! Event handling for client-core operations
2//!
3//! This module provides a comprehensive event system for VoIP client operations,
4//! including call events, media events, registration events, and error handling.
5//! The event system supports filtering, prioritization, and async handling.
6//!
7//! # Event Types
8//!
9//! - **Call Events** - Incoming calls, state changes, completion
10//! - **Media Events** - Audio start/stop, quality changes, DTMF
11//! - **Registration Events** - SIP registration status changes
12//! - **Network Events** - Connectivity changes
13//! - **Error Events** - Client errors and failures
14//!
15//! # Usage Examples
16//!
17//! ## Basic Event Handler
18//!
19//! ```rust
20//! use rvoip_client_core::events::{ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
21//! use async_trait::async_trait;
22//!
23//! struct MyEventHandler;
24//!
25//! #[async_trait]
26//! impl ClientEventHandler for MyEventHandler {
27//! async fn on_incoming_call(&self, call_info: IncomingCallInfo) -> CallAction {
28//! println!("Incoming call from: {}", call_info.caller_uri);
29//! CallAction::Accept
30//! }
31//!
32//! async fn on_call_state_changed(&self, status_info: CallStatusInfo) {
33//! println!("Call {:?} state changed to {:?}", status_info.call_id, status_info.new_state);
34//! }
35//!
36//! async fn on_registration_status_changed(&self, status_info: RegistrationStatusInfo) {
37//! println!("Registration status: {:?}", status_info.status);
38//! }
39//! }
40//! ```
41//!
42//! ## Event Filtering
43//!
44//! ```rust
45//! use rvoip_client_core::events::{EventFilter, EventPriority, MediaEventType};
46//! use std::collections::HashSet;
47//!
48//! // Create a filter for high-priority events only
49//! let filter = EventFilter {
50//! min_priority: Some(EventPriority::High),
51//! media_event_types: None,
52//! call_ids: None,
53//! call_states: None,
54//! registration_ids: None,
55//! };
56//!
57//! // Create a filter for specific media events
58//! let mut media_types = HashSet::new();
59//! media_types.insert(MediaEventType::AudioStarted);
60//! media_types.insert(MediaEventType::AudioStopped);
61//!
62//! let media_filter = EventFilter {
63//! media_event_types: Some(media_types),
64//! min_priority: None,
65//! call_ids: None,
66//! call_states: None,
67//! registration_ids: None,
68//! };
69//! ```
70//!
71//! ## Event Subscription
72//!
73//! ```rust
74//! use rvoip_client_core::events::{EventSubscription, EventFilter, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
75//! use async_trait::async_trait;
76//! use std::sync::Arc;
77//!
78//! struct TestHandler;
79//!
80//! #[async_trait]
81//! impl ClientEventHandler for TestHandler {
82//! async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
83//! CallAction::Accept
84//! }
85//! async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
86//! async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
87//! }
88//!
89//! let handler = Arc::new(TestHandler);
90//! let subscription = EventSubscription::all_events(handler);
91//! println!("Subscription ID: {}", subscription.id());
92//! ```
93
94use std::sync::Arc;
95use chrono::{DateTime, Utc};
96use serde::{Deserialize, Serialize};
97use async_trait::async_trait;
98use std::collections::HashSet;
99
100use crate::call::{CallId, CallState};
101
102/// Action to take for an incoming call
103///
104/// Determines how the client should respond to an incoming call invitation.
105/// This is returned by event handlers to control call behavior.
106///
107/// # Examples
108///
109/// ```rust
110/// use rvoip_client_core::events::CallAction;
111///
112/// let action = CallAction::Accept;
113/// assert_eq!(action, CallAction::Accept);
114/// ```
115#[derive(Debug, Clone, PartialEq, Eq)]
116pub enum CallAction {
117 /// Accept the incoming call and establish the connection
118 Accept,
119 /// Reject the incoming call (sends busy or decline response)
120 Reject,
121 /// Ignore the incoming call (let it ring without responding)
122 Ignore,
123}
124
125/// Information about an incoming call
126///
127/// Contains all available details about a call invitation, including
128/// caller information, call metadata, and timing information.
129///
130/// # Examples
131///
132/// ```rust
133/// use rvoip_client_core::events::IncomingCallInfo;
134/// use rvoip_client_core::call::CallId;
135/// use chrono::Utc;
136///
137/// let call_info = IncomingCallInfo {
138/// call_id: uuid::Uuid::new_v4(),
139/// caller_uri: "sip:alice@example.com".to_string(),
140/// callee_uri: "sip:bob@example.com".to_string(),
141/// caller_display_name: Some("Alice Smith".to_string()),
142/// subject: Some("Business call".to_string()),
143/// created_at: Utc::now(),
144/// };
145///
146/// assert_eq!(call_info.caller_uri, "sip:alice@example.com");
147/// ```
148#[derive(Debug, Clone)]
149pub struct IncomingCallInfo {
150 /// Unique call identifier assigned by the client
151 pub call_id: CallId,
152 /// SIP URI of the caller (e.g., "sip:alice@example.com")
153 pub caller_uri: String,
154 /// SIP URI of the callee/local user (e.g., "sip:bob@example.com")
155 pub callee_uri: String,
156 /// Display name of the caller, if provided in the SIP headers
157 pub caller_display_name: Option<String>,
158 /// Call subject or reason, if provided in the SIP headers
159 pub subject: Option<String>,
160 /// Timestamp when the call invitation was received
161 pub created_at: DateTime<Utc>,
162}
163
164/// Information about a call state change
165///
166/// Provides details about call state transitions, including the previous
167/// and new states, timing, and reasons for the change.
168///
169/// # Examples
170///
171/// ```rust
172/// use rvoip_client_core::events::CallStatusInfo;
173/// use rvoip_client_core::call::{CallId, CallState};
174/// use chrono::Utc;
175///
176/// let status_info = CallStatusInfo {
177/// call_id: uuid::Uuid::new_v4(),
178/// new_state: CallState::Connected,
179/// previous_state: Some(CallState::Ringing),
180/// reason: Some("Call answered".to_string()),
181/// timestamp: Utc::now(),
182/// };
183///
184/// assert_eq!(status_info.new_state, CallState::Connected);
185/// ```
186#[derive(Debug, Clone)]
187pub struct CallStatusInfo {
188 /// Call that changed state
189 pub call_id: CallId,
190 /// New call state after the transition
191 pub new_state: CallState,
192 /// Previous call state before the transition (if known)
193 pub previous_state: Option<CallState>,
194 /// Reason for the state change (e.g., "Call answered", "Network error")
195 pub reason: Option<String>,
196 /// When the state change occurred
197 pub timestamp: DateTime<Utc>,
198}
199
200/// Information about registration status changes
201///
202/// Contains details about SIP registration state changes, including
203/// server information, user details, and status transition data.
204///
205/// # Examples
206///
207/// ```rust
208/// use rvoip_client_core::events::RegistrationStatusInfo;
209/// use rvoip_client_core::registration::RegistrationStatus;
210/// use chrono::Utc;
211/// use uuid::Uuid;
212///
213/// let reg_info = RegistrationStatusInfo {
214/// registration_id: Uuid::new_v4(),
215/// server_uri: "sip:registrar.example.com".to_string(),
216/// user_uri: "sip:user@example.com".to_string(),
217/// status: RegistrationStatus::Active,
218/// reason: Some("Registration successful".to_string()),
219/// timestamp: Utc::now(),
220/// };
221///
222/// assert_eq!(reg_info.status, RegistrationStatus::Active);
223/// ```
224#[derive(Debug, Clone)]
225pub struct RegistrationStatusInfo {
226 /// Unique registration identifier
227 pub registration_id: uuid::Uuid,
228 /// SIP registrar server URI
229 pub server_uri: String,
230 /// User URI being registered with the server
231 pub user_uri: String,
232 /// Current registration status
233 pub status: crate::registration::RegistrationStatus,
234 /// Reason for the status change (e.g., "Registration expired")
235 pub reason: Option<String>,
236 /// When the status change occurred
237 pub timestamp: DateTime<Utc>,
238}
239
240/// Types of media events that can occur during calls
241///
242/// Categorizes different media-related events including audio control,
243/// session management, and quality monitoring events.
244///
245/// # Examples
246///
247/// ```rust
248/// use rvoip_client_core::events::MediaEventType;
249///
250/// let event = MediaEventType::AudioStarted;
251/// let mute_event = MediaEventType::MicrophoneStateChanged { muted: true };
252/// let quality_event = MediaEventType::QualityChanged { mos_score_x100: 425 }; // 4.25 MOS
253/// ```
254#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
255pub enum MediaEventType {
256 // Phase 4.1: Enhanced Media Integration
257 /// Microphone mute state changed
258 MicrophoneStateChanged {
259 /// Whether the microphone is now muted
260 muted: bool
261 },
262 /// Speaker mute state changed
263 SpeakerStateChanged {
264 /// Whether the speaker is now muted
265 muted: bool
266 },
267 /// Audio streaming started for a call
268 AudioStarted,
269 /// Audio streaming stopped for a call
270 AudioStopped,
271 /// Call hold state changed
272 HoldStateChanged {
273 /// Whether the call is now on hold
274 on_hold: bool
275 },
276 /// DTMF digits were sent during the call
277 DtmfSent {
278 /// The DTMF digits that were sent
279 digits: String
280 },
281 /// Call transfer was initiated
282 TransferInitiated {
283 /// Target URI for the transfer
284 target: String,
285 /// Type of transfer (e.g., "blind", "attended")
286 transfer_type: String
287 },
288
289 // Phase 4.2: Media Session Coordination
290 /// SDP offer was generated for media negotiation
291 SdpOfferGenerated {
292 /// Size of the SDP offer in bytes
293 sdp_size: usize
294 },
295 /// SDP answer was processed during media negotiation
296 SdpAnswerProcessed {
297 /// Size of the SDP answer in bytes
298 sdp_size: usize
299 },
300 /// Media session started successfully
301 MediaSessionStarted {
302 /// Unique identifier for the media session
303 media_session_id: String
304 },
305 /// Media session stopped
306 MediaSessionStopped,
307 /// Media session was updated/modified
308 MediaSessionUpdated {
309 /// Size of the updated SDP in bytes
310 sdp_size: usize
311 },
312
313 // Quality and monitoring events (using integers for Hash/Eq compatibility)
314 /// Call quality changed (MOS score)
315 QualityChanged {
316 /// MOS score * 100 (e.g., 425 = 4.25 MOS score)
317 mos_score_x100: u32
318 },
319 /// Packet loss detected
320 PacketLoss {
321 /// Packet loss percentage * 100 (e.g., 150 = 1.5%)
322 percentage_x100: u32
323 },
324 /// Jitter levels changed
325 JitterChanged {
326 /// Current jitter in milliseconds
327 jitter_ms: u32
328 },
329}
330
331/// Media event information
332///
333/// Contains detailed information about a media event, including timing,
334/// metadata, and the associated call.
335///
336/// # Examples
337///
338/// ```rust
339/// use rvoip_client_core::events::{MediaEventInfo, MediaEventType};
340/// use rvoip_client_core::call::CallId;
341/// use chrono::Utc;
342/// use std::collections::HashMap;
343///
344/// let mut metadata = HashMap::new();
345/// metadata.insert("codec".to_string(), "PCMU".to_string());
346///
347/// let media_event = MediaEventInfo {
348/// call_id: uuid::Uuid::new_v4(),
349/// event_type: MediaEventType::AudioStarted,
350/// timestamp: Utc::now(),
351/// metadata,
352/// };
353///
354/// assert_eq!(media_event.event_type, MediaEventType::AudioStarted);
355/// ```
356#[derive(Debug, Clone)]
357pub struct MediaEventInfo {
358 /// Call the media event relates to
359 pub call_id: CallId,
360 /// Type of media event that occurred
361 pub event_type: MediaEventType,
362 /// When the event occurred
363 pub timestamp: DateTime<Utc>,
364 /// Additional event metadata (codec info, quality details, etc.)
365 pub metadata: std::collections::HashMap<String, String>,
366}
367
368/// Event filtering options for selective subscription
369///
370/// Allows clients to subscribe only to specific types of events,
371/// reducing noise and improving performance for targeted use cases.
372///
373/// # Examples
374///
375/// ```rust
376/// use rvoip_client_core::events::{EventFilter, EventPriority};
377/// use rvoip_client_core::call::CallId;
378/// use std::collections::HashSet;
379///
380/// // Filter for high-priority events only
381/// let priority_filter = EventFilter {
382/// min_priority: Some(EventPriority::High),
383/// call_ids: None,
384/// call_states: None,
385/// media_event_types: None,
386/// registration_ids: None,
387/// };
388///
389/// // Filter for specific call
390/// let mut call_ids = HashSet::new();
391/// call_ids.insert(uuid::Uuid::new_v4());
392/// let call_filter = EventFilter {
393/// call_ids: Some(call_ids),
394/// min_priority: None,
395/// call_states: None,
396/// media_event_types: None,
397/// registration_ids: None,
398/// };
399/// ```
400#[derive(Debug, Clone, Default)]
401pub struct EventFilter {
402 /// Only receive events for specific calls (None = all calls)
403 pub call_ids: Option<HashSet<CallId>>,
404 /// Only receive specific types of call state changes (None = all states)
405 pub call_states: Option<HashSet<CallState>>,
406 /// Only receive specific types of media events (None = all media events)
407 pub media_event_types: Option<HashSet<MediaEventType>>,
408 /// Only receive events for specific registration IDs (None = all registrations)
409 pub registration_ids: Option<HashSet<uuid::Uuid>>,
410 /// Minimum event priority level (None = all priorities)
411 pub min_priority: Option<EventPriority>,
412}
413
414/// Event priority levels for filtering and handling
415///
416/// Allows classification of events by importance, enabling priority-based
417/// filtering and handling strategies.
418///
419/// # Examples
420///
421/// ```rust
422/// use rvoip_client_core::events::EventPriority;
423///
424/// assert!(EventPriority::Critical > EventPriority::High);
425/// assert!(EventPriority::High > EventPriority::Normal);
426/// assert!(EventPriority::Normal > EventPriority::Low);
427/// ```
428#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
429pub enum EventPriority {
430 /// Low priority events (quality updates, routine status changes)
431 Low,
432 /// Normal priority events (state changes, DTMF, media events)
433 Normal,
434 /// High priority events (incoming calls, registration changes)
435 High,
436 /// Critical priority events (failures, security issues, network problems)
437 Critical,
438}
439
440/// Comprehensive client event types
441///
442/// Unified event type that encompasses all possible events in the VoIP client,
443/// with associated priority levels for filtering and handling.
444///
445/// # Examples
446///
447/// ```rust
448/// use rvoip_client_core::events::{ClientEvent, IncomingCallInfo, EventPriority};
449/// use rvoip_client_core::call::CallId;
450/// use chrono::Utc;
451///
452/// let call_info = IncomingCallInfo {
453/// call_id: uuid::Uuid::new_v4(),
454/// caller_uri: "sip:caller@example.com".to_string(),
455/// callee_uri: "sip:callee@example.com".to_string(),
456/// caller_display_name: None,
457/// subject: None,
458/// created_at: Utc::now(),
459/// };
460///
461/// let event = ClientEvent::IncomingCall {
462/// info: call_info,
463/// priority: EventPriority::High,
464/// };
465///
466/// assert_eq!(event.priority(), EventPriority::High);
467/// ```
468#[derive(Debug, Clone)]
469pub enum ClientEvent {
470 /// Incoming call received from a remote party
471 IncomingCall {
472 /// Information about the incoming call
473 info: IncomingCallInfo,
474 /// Priority level of this event
475 priority: EventPriority,
476 },
477 /// Call state changed (connecting, connected, disconnected, etc.)
478 CallStateChanged {
479 /// Information about the state change
480 info: CallStatusInfo,
481 /// Priority of this event
482 priority: EventPriority,
483 },
484 /// Media event occurred (audio start/stop, quality change, etc.)
485 MediaEvent {
486 /// Information about the media event
487 info: MediaEventInfo,
488 /// Priority of this event
489 priority: EventPriority,
490 },
491 /// Registration status changed with SIP server
492 RegistrationStatusChanged {
493 /// Information about the registration change
494 info: RegistrationStatusInfo,
495 /// Priority of this event
496 priority: EventPriority,
497 },
498 /// Client error occurred
499 ClientError {
500 /// The error that occurred
501 error: crate::ClientError,
502 /// Call ID associated with the error (if any)
503 call_id: Option<CallId>,
504 /// Priority of this event
505 priority: EventPriority,
506 },
507 /// Network connectivity changed
508 NetworkEvent {
509 /// Whether the network is now connected
510 connected: bool,
511 /// Reason for the connectivity change (if known)
512 reason: Option<String>,
513 /// Priority of this event
514 priority: EventPriority,
515 },
516}
517
518impl ClientEvent {
519 /// Get the priority of this event
520 ///
521 /// Returns the priority level assigned to this event, which can be used
522 /// for filtering and prioritization in event handling systems.
523 ///
524 /// # Examples
525 ///
526 /// ```rust
527 /// use rvoip_client_core::events::{ClientEvent, EventPriority};
528 /// use rvoip_client_core::ClientError;
529 ///
530 /// let error_event = ClientEvent::ClientError {
531 /// error: ClientError::internal_error("Test error"),
532 /// call_id: None,
533 /// priority: EventPriority::High,
534 /// };
535 ///
536 /// assert_eq!(error_event.priority(), EventPriority::High);
537 /// ```
538 pub fn priority(&self) -> EventPriority {
539 match self {
540 ClientEvent::IncomingCall { priority, .. } => priority.clone(),
541 ClientEvent::CallStateChanged { priority, .. } => priority.clone(),
542 ClientEvent::MediaEvent { priority, .. } => priority.clone(),
543 ClientEvent::RegistrationStatusChanged { priority, .. } => priority.clone(),
544 ClientEvent::ClientError { priority, .. } => priority.clone(),
545 ClientEvent::NetworkEvent { priority, .. } => priority.clone(),
546 }
547 }
548
549 /// Get the call ID associated with this event (if any)
550 ///
551 /// Returns the call ID for events that are related to a specific call.
552 /// Not all events have an associated call ID (e.g., network events).
553 ///
554 /// # Examples
555 ///
556 /// ```rust
557 /// use rvoip_client_core::events::{ClientEvent, EventPriority};
558 ///
559 /// let network_event = ClientEvent::NetworkEvent {
560 /// connected: true,
561 /// reason: Some("Connection restored".to_string()),
562 /// priority: EventPriority::Normal,
563 /// };
564 ///
565 /// assert_eq!(network_event.call_id(), None);
566 /// ```
567 pub fn call_id(&self) -> Option<CallId> {
568 match self {
569 ClientEvent::IncomingCall { info, .. } => Some(info.call_id),
570 ClientEvent::CallStateChanged { info, .. } => Some(info.call_id),
571 ClientEvent::MediaEvent { info, .. } => Some(info.call_id),
572 ClientEvent::ClientError { call_id, .. } => *call_id,
573 _ => None,
574 }
575 }
576
577 /// Check if this event passes the given filter
578 ///
579 /// Tests whether this event matches the criteria specified in the filter.
580 /// This is used by the event system to determine which subscriptions
581 /// should receive this event.
582 ///
583 /// # Examples
584 ///
585 /// ```rust
586 /// use rvoip_client_core::events::{ClientEvent, EventFilter, EventPriority};
587 ///
588 /// let event = ClientEvent::NetworkEvent {
589 /// connected: true,
590 /// reason: None,
591 /// priority: EventPriority::Normal,
592 /// };
593 ///
594 /// let filter = EventFilter {
595 /// min_priority: Some(EventPriority::High),
596 /// call_ids: None,
597 /// call_states: None,
598 /// media_event_types: None,
599 /// registration_ids: None,
600 /// };
601 ///
602 /// // This normal priority event should not pass a high-priority filter
603 /// assert!(!event.passes_filter(&filter));
604 /// ```
605 pub fn passes_filter(&self, filter: &EventFilter) -> bool {
606 // Check priority filter
607 if let Some(min_priority) = &filter.min_priority {
608 if self.priority() < *min_priority {
609 return false;
610 }
611 }
612
613 // Check call ID filter
614 if let Some(call_ids) = &filter.call_ids {
615 if let Some(call_id) = self.call_id() {
616 if !call_ids.contains(&call_id) {
617 return false;
618 }
619 } else {
620 // Event has no call ID but filter requires specific call IDs
621 return false;
622 }
623 }
624
625 // Check call state filter
626 if let Some(call_states) = &filter.call_states {
627 if let ClientEvent::CallStateChanged { info, .. } = self {
628 if !call_states.contains(&info.new_state) {
629 return false;
630 }
631 }
632 }
633
634 // Check media event type filter
635 if let Some(media_types) = &filter.media_event_types {
636 if let ClientEvent::MediaEvent { info, .. } = self {
637 if !media_types.contains(&info.event_type) {
638 return false;
639 }
640 }
641 }
642
643 // Check registration ID filter
644 if let Some(registration_ids) = &filter.registration_ids {
645 if let ClientEvent::RegistrationStatusChanged { info, .. } = self {
646 if !registration_ids.contains(&info.registration_id) {
647 return false;
648 }
649 }
650 }
651
652 true
653 }
654}
655
656/// Enhanced event handler with filtering capabilities
657///
658/// Trait for handling VoIP client events. Implement this trait to receive
659/// and respond to various events that occur during client operation.
660///
661/// # Examples
662///
663/// ```rust
664/// use rvoip_client_core::events::{ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
665/// use async_trait::async_trait;
666///
667/// struct LoggingEventHandler;
668///
669/// #[async_trait]
670/// impl ClientEventHandler for LoggingEventHandler {
671/// async fn on_incoming_call(&self, call_info: IncomingCallInfo) -> CallAction {
672/// println!("Incoming call from: {}", call_info.caller_uri);
673/// CallAction::Accept
674/// }
675///
676/// async fn on_call_state_changed(&self, status_info: CallStatusInfo) {
677/// println!("Call state changed: {:?}", status_info.new_state);
678/// }
679///
680/// async fn on_registration_status_changed(&self, status_info: RegistrationStatusInfo) {
681/// println!("Registration status: {:?}", status_info.status);
682/// }
683/// }
684/// ```
685#[async_trait]
686pub trait ClientEventHandler: Send + Sync {
687 /// Handle an incoming call with action decision
688 ///
689 /// Called when a new call invitation is received. The implementation
690 /// should return the desired action (Accept, Reject, or Ignore).
691 ///
692 /// # Arguments
693 ///
694 /// * `call_info` - Information about the incoming call
695 ///
696 /// # Returns
697 ///
698 /// The action to take for this incoming call
699 async fn on_incoming_call(&self, call_info: IncomingCallInfo) -> CallAction;
700
701 /// Handle call state changes
702 ///
703 /// Called when a call's state changes (e.g., from ringing to connected).
704 /// This is useful for updating UI, logging, or triggering other actions.
705 ///
706 /// # Arguments
707 ///
708 /// * `status_info` - Information about the call state change
709 async fn on_call_state_changed(&self, status_info: CallStatusInfo);
710
711 /// Handle registration status changes
712 ///
713 /// Called when the SIP registration status changes with a server.
714 /// This includes successful registrations, failures, and expirations.
715 ///
716 /// # Arguments
717 ///
718 /// * `status_info` - Information about the registration status change
719 async fn on_registration_status_changed(&self, status_info: RegistrationStatusInfo);
720
721 /// Handle media events (optional - default implementation does nothing)
722 ///
723 /// Called when media-related events occur during calls. Override this
724 /// method to handle audio start/stop, quality changes, DTMF, etc.
725 ///
726 /// # Arguments
727 ///
728 /// * `media_info` - Information about the media event
729 async fn on_media_event(&self, _media_info: MediaEventInfo) {
730 // Default implementation - can be overridden for media event handling
731 }
732
733 /// Handle client errors (optional - default implementation logs)
734 ///
735 /// Called when client errors occur. Override this method to implement
736 /// custom error handling, logging, or recovery strategies.
737 ///
738 /// # Arguments
739 ///
740 /// * `error` - The error that occurred
741 /// * `call_id` - Call ID associated with the error (if any)
742 async fn on_client_error(&self, _error: crate::ClientError, _call_id: Option<CallId>) {
743 // Default implementation - can be overridden for error handling
744 }
745
746 /// Handle network events (optional - default implementation does nothing)
747 ///
748 /// Called when network connectivity changes are detected. Override this
749 /// method to handle connection state changes and implement reconnection logic.
750 ///
751 /// # Arguments
752 ///
753 /// * `connected` - Whether the network is now connected
754 /// * `reason` - Reason for the connectivity change (if known)
755 async fn on_network_event(&self, _connected: bool, _reason: Option<String>) {
756 // Default implementation - can be overridden for network event handling
757 }
758
759 /// Handle comprehensive client events with filtering
760 ///
761 /// This is the unified event handler that dispatches to specific event
762 /// handling methods. Generally, you don't need to override this method
763 /// unless you want custom event routing logic.
764 ///
765 /// # Arguments
766 ///
767 /// * `event` - The client event to handle
768 async fn on_client_event(&self, event: ClientEvent) {
769 match event {
770 ClientEvent::IncomingCall { info, .. } => {
771 self.on_incoming_call(info).await;
772 }
773 ClientEvent::CallStateChanged { info, .. } => {
774 self.on_call_state_changed(info).await;
775 }
776 ClientEvent::MediaEvent { info, .. } => {
777 self.on_media_event(info).await;
778 }
779 ClientEvent::RegistrationStatusChanged { info, .. } => {
780 self.on_registration_status_changed(info).await;
781 }
782 ClientEvent::ClientError { error, call_id, .. } => {
783 self.on_client_error(error, call_id).await;
784 }
785 ClientEvent::NetworkEvent { connected, reason, .. } => {
786 self.on_network_event(connected, reason).await;
787 }
788 }
789 }
790}
791
792/// Enhanced event subscription with filtering capabilities
793///
794/// Represents a subscription to client events with optional filtering.
795/// Subscriptions determine which events are delivered to which handlers.
796///
797/// # Examples
798///
799/// ```rust
800/// use rvoip_client_core::events::{EventSubscription, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
801/// use async_trait::async_trait;
802/// use std::sync::Arc;
803///
804/// struct TestHandler;
805///
806/// #[async_trait]
807/// impl ClientEventHandler for TestHandler {
808/// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
809/// CallAction::Accept
810/// }
811/// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
812/// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
813/// }
814///
815/// let handler = Arc::new(TestHandler);
816/// let subscription = EventSubscription::all_events(handler);
817/// ```
818pub struct EventSubscription {
819 /// The event handler that will receive events
820 handler: Arc<dyn ClientEventHandler>,
821 /// Filter criteria for this subscription
822 filter: EventFilter,
823 /// Unique identifier for this subscription
824 id: uuid::Uuid,
825}
826
827impl EventSubscription {
828 /// Create a new event subscription with filtering
829 ///
830 /// Creates a subscription that will deliver events matching the specified
831 /// filter criteria to the provided handler.
832 ///
833 /// # Arguments
834 ///
835 /// * `handler` - The event handler that will receive matching events
836 /// * `filter` - Filter criteria to determine which events to receive
837 ///
838 /// # Examples
839 ///
840 /// ```rust
841 /// use rvoip_client_core::events::{EventSubscription, EventFilter, EventPriority, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
842 /// use async_trait::async_trait;
843 /// use std::sync::Arc;
844 ///
845 /// struct TestHandler;
846 ///
847 /// #[async_trait]
848 /// impl ClientEventHandler for TestHandler {
849 /// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
850 /// CallAction::Accept
851 /// }
852 /// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
853 /// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
854 /// }
855 ///
856 /// let handler = Arc::new(TestHandler);
857 /// let filter = EventFilter {
858 /// min_priority: Some(EventPriority::High),
859 /// call_ids: None,
860 /// call_states: None,
861 /// media_event_types: None,
862 /// registration_ids: None,
863 /// };
864 /// let subscription = EventSubscription::new(handler, filter);
865 /// ```
866 pub fn new(handler: Arc<dyn ClientEventHandler>, filter: EventFilter) -> Self {
867 Self {
868 handler,
869 filter,
870 id: uuid::Uuid::new_v4(),
871 }
872 }
873
874 /// Create a subscription that receives all events
875 ///
876 /// Creates a subscription with no filtering - all events will be
877 /// delivered to the handler.
878 ///
879 /// # Arguments
880 ///
881 /// * `handler` - The event handler that will receive all events
882 ///
883 /// # Examples
884 ///
885 /// ```rust
886 /// use rvoip_client_core::events::{EventSubscription, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
887 /// use async_trait::async_trait;
888 /// use std::sync::Arc;
889 ///
890 /// struct AllEventsHandler;
891 ///
892 /// #[async_trait]
893 /// impl ClientEventHandler for AllEventsHandler {
894 /// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
895 /// CallAction::Accept
896 /// }
897 /// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
898 /// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
899 /// }
900 ///
901 /// let handler = Arc::new(AllEventsHandler);
902 /// let subscription = EventSubscription::all_events(handler);
903 /// ```
904 pub fn all_events(handler: Arc<dyn ClientEventHandler>) -> Self {
905 Self::new(handler, EventFilter::default())
906 }
907
908 /// Create a subscription for specific call events only
909 ///
910 /// Creates a subscription that only receives events related to a
911 /// specific call ID.
912 ///
913 /// # Arguments
914 ///
915 /// * `handler` - The event handler that will receive call events
916 /// * `call_id` - The specific call ID to monitor
917 ///
918 /// # Examples
919 ///
920 /// ```rust
921 /// use rvoip_client_core::events::{EventSubscription, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
922 /// use rvoip_client_core::call::CallId;
923 /// use async_trait::async_trait;
924 /// use std::sync::Arc;
925 ///
926 /// struct CallSpecificHandler;
927 ///
928 /// #[async_trait]
929 /// impl ClientEventHandler for CallSpecificHandler {
930 /// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
931 /// CallAction::Accept
932 /// }
933 /// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
934 /// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
935 /// }
936 ///
937 /// let handler = Arc::new(CallSpecificHandler);
938 /// let call_id = uuid::Uuid::new_v4();
939 /// let subscription = EventSubscription::call_events(handler, call_id);
940 /// ```
941 pub fn call_events(handler: Arc<dyn ClientEventHandler>, call_id: CallId) -> Self {
942 let mut call_ids = HashSet::new();
943 call_ids.insert(call_id);
944 let filter = EventFilter {
945 call_ids: Some(call_ids),
946 ..Default::default()
947 };
948 Self::new(handler, filter)
949 }
950
951 /// Create a subscription for high priority events only
952 ///
953 /// Creates a subscription that only receives high and critical priority events,
954 /// filtering out normal and low priority events.
955 ///
956 /// # Arguments
957 ///
958 /// * `handler` - The event handler that will receive high priority events
959 ///
960 /// # Examples
961 ///
962 /// ```rust
963 /// use rvoip_client_core::events::{EventSubscription, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
964 /// use async_trait::async_trait;
965 /// use std::sync::Arc;
966 ///
967 /// struct HighPriorityHandler;
968 ///
969 /// #[async_trait]
970 /// impl ClientEventHandler for HighPriorityHandler {
971 /// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
972 /// CallAction::Accept
973 /// }
974 /// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
975 /// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
976 /// }
977 ///
978 /// let handler = Arc::new(HighPriorityHandler);
979 /// let subscription = EventSubscription::high_priority_events(handler);
980 /// ```
981 pub fn high_priority_events(handler: Arc<dyn ClientEventHandler>) -> Self {
982 let filter = EventFilter {
983 min_priority: Some(EventPriority::High),
984 ..Default::default()
985 };
986 Self::new(handler, filter)
987 }
988
989 /// Get the subscription ID
990 ///
991 /// Returns the unique identifier for this subscription, which can be
992 /// used to unsubscribe later.
993 ///
994 /// # Examples
995 ///
996 /// ```rust
997 /// use rvoip_client_core::events::{EventSubscription, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
998 /// use async_trait::async_trait;
999 /// use std::sync::Arc;
1000 ///
1001 /// struct TestHandler;
1002 ///
1003 /// #[async_trait]
1004 /// impl ClientEventHandler for TestHandler {
1005 /// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
1006 /// CallAction::Accept
1007 /// }
1008 /// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
1009 /// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
1010 /// }
1011 ///
1012 /// let handler = Arc::new(TestHandler);
1013 /// let subscription = EventSubscription::all_events(handler);
1014 /// let id = subscription.id();
1015 /// println!("Subscription ID: {}", id);
1016 /// ```
1017 pub fn id(&self) -> uuid::Uuid {
1018 self.id
1019 }
1020
1021 /// Check if this subscription should receive the given event
1022 ///
1023 /// Tests whether the event matches this subscription's filter criteria.
1024 ///
1025 /// # Arguments
1026 ///
1027 /// * `event` - The event to test against the filter
1028 ///
1029 /// # Returns
1030 ///
1031 /// `true` if the event should be delivered to this subscription's handler
1032 ///
1033 /// # Examples
1034 ///
1035 /// ```rust
1036 /// use rvoip_client_core::events::{EventSubscription, ClientEvent, EventPriority, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
1037 /// use async_trait::async_trait;
1038 /// use std::sync::Arc;
1039 ///
1040 /// struct TestHandler;
1041 ///
1042 /// #[async_trait]
1043 /// impl ClientEventHandler for TestHandler {
1044 /// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
1045 /// CallAction::Accept
1046 /// }
1047 /// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
1048 /// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
1049 /// }
1050 ///
1051 /// let handler = Arc::new(TestHandler);
1052 /// let subscription = EventSubscription::high_priority_events(handler);
1053 ///
1054 /// let high_priority_event = ClientEvent::NetworkEvent {
1055 /// connected: false,
1056 /// reason: Some("Connection lost".to_string()),
1057 /// priority: EventPriority::High,
1058 /// };
1059 ///
1060 /// assert!(subscription.should_receive(&high_priority_event));
1061 /// ```
1062 pub fn should_receive(&self, event: &ClientEvent) -> bool {
1063 event.passes_filter(&self.filter)
1064 }
1065
1066 /// Deliver an event to this subscription's handler
1067 ///
1068 /// Delivers the event to the handler if it passes the subscription's filter.
1069 ///
1070 /// # Arguments
1071 ///
1072 /// * `event` - The event to potentially deliver
1073 pub async fn deliver_event(&self, event: ClientEvent) {
1074 if self.should_receive(&event) {
1075 self.handler.on_client_event(event).await;
1076 }
1077 }
1078}
1079
1080/// Event emission utilities for the ClientManager
1081///
1082/// Manages event subscriptions and handles event delivery to all matching
1083/// subscribers. This is the central hub for the event system.
1084///
1085/// # Examples
1086///
1087/// ```rust
1088/// use rvoip_client_core::events::{EventEmitter, EventSubscription, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
1089/// use async_trait::async_trait;
1090/// use std::sync::Arc;
1091///
1092/// struct TestHandler;
1093///
1094/// #[async_trait]
1095/// impl ClientEventHandler for TestHandler {
1096/// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
1097/// CallAction::Accept
1098/// }
1099/// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
1100/// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
1101/// }
1102///
1103/// let emitter = EventEmitter::new();
1104/// let handler = Arc::new(TestHandler);
1105/// let subscription = EventSubscription::all_events(handler);
1106/// let subscription_id = emitter.subscribe(subscription);
1107///
1108/// assert_eq!(emitter.subscription_count(), 1);
1109/// ```
1110pub struct EventEmitter {
1111 /// List of active event subscriptions
1112 subscriptions: std::sync::RwLock<Vec<EventSubscription>>,
1113}
1114
1115impl EventEmitter {
1116 /// Create a new event emitter
1117 ///
1118 /// Creates a new event emitter with no active subscriptions.
1119 ///
1120 /// # Examples
1121 ///
1122 /// ```rust
1123 /// use rvoip_client_core::events::EventEmitter;
1124 ///
1125 /// let emitter = EventEmitter::new();
1126 /// assert_eq!(emitter.subscription_count(), 0);
1127 /// ```
1128 pub fn new() -> Self {
1129 Self {
1130 subscriptions: std::sync::RwLock::new(Vec::new()),
1131 }
1132 }
1133
1134 /// Add an event subscription
1135 ///
1136 /// Registers a new event subscription with the emitter. The subscription
1137 /// will start receiving matching events immediately.
1138 ///
1139 /// # Arguments
1140 ///
1141 /// * `subscription` - The event subscription to add
1142 ///
1143 /// # Returns
1144 ///
1145 /// The unique ID of the subscription for later unsubscribing
1146 ///
1147 /// # Examples
1148 ///
1149 /// ```rust
1150 /// use rvoip_client_core::events::{EventEmitter, EventSubscription, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
1151 /// use async_trait::async_trait;
1152 /// use std::sync::Arc;
1153 ///
1154 /// struct TestHandler;
1155 ///
1156 /// #[async_trait]
1157 /// impl ClientEventHandler for TestHandler {
1158 /// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
1159 /// CallAction::Accept
1160 /// }
1161 /// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
1162 /// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
1163 /// }
1164 ///
1165 /// let emitter = EventEmitter::new();
1166 /// let handler = Arc::new(TestHandler);
1167 /// let subscription = EventSubscription::all_events(handler);
1168 /// let subscription_id = emitter.subscribe(subscription);
1169 /// ```
1170 pub fn subscribe(&self, subscription: EventSubscription) -> uuid::Uuid {
1171 let id = subscription.id();
1172 self.subscriptions.write().unwrap().push(subscription);
1173 id
1174 }
1175
1176 /// Remove an event subscription
1177 ///
1178 /// Unregisters an event subscription from the emitter. The subscription
1179 /// will stop receiving events.
1180 ///
1181 /// # Arguments
1182 ///
1183 /// * `subscription_id` - The unique ID of the subscription to remove
1184 ///
1185 /// # Returns
1186 ///
1187 /// `true` if the subscription was found and removed, `false` otherwise
1188 ///
1189 /// # Examples
1190 ///
1191 /// ```rust
1192 /// use rvoip_client_core::events::{EventEmitter, EventSubscription, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
1193 /// use async_trait::async_trait;
1194 /// use std::sync::Arc;
1195 ///
1196 /// struct TestHandler;
1197 ///
1198 /// #[async_trait]
1199 /// impl ClientEventHandler for TestHandler {
1200 /// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
1201 /// CallAction::Accept
1202 /// }
1203 /// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
1204 /// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
1205 /// }
1206 ///
1207 /// let emitter = EventEmitter::new();
1208 /// let handler = Arc::new(TestHandler);
1209 /// let subscription = EventSubscription::all_events(handler);
1210 /// let subscription_id = emitter.subscribe(subscription);
1211 ///
1212 /// assert!(emitter.unsubscribe(subscription_id));
1213 /// assert_eq!(emitter.subscription_count(), 0);
1214 /// ```
1215 pub fn unsubscribe(&self, subscription_id: uuid::Uuid) -> bool {
1216 let mut subscriptions = self.subscriptions.write().unwrap();
1217 if let Some(pos) = subscriptions.iter().position(|s| s.id() == subscription_id) {
1218 subscriptions.remove(pos);
1219 true
1220 } else {
1221 false
1222 }
1223 }
1224
1225 /// Emit an event to all matching subscriptions
1226 ///
1227 /// Delivers the event to all subscriptions whose filters match the event.
1228 /// Event delivery happens asynchronously and in parallel.
1229 ///
1230 /// # Arguments
1231 ///
1232 /// * `event` - The event to emit to matching subscriptions
1233 ///
1234 /// # Examples
1235 ///
1236 /// ```rust
1237 /// use rvoip_client_core::events::{EventEmitter, ClientEvent, EventPriority};
1238 ///
1239 /// # async fn example() {
1240 /// let emitter = EventEmitter::new();
1241 ///
1242 /// let network_event = ClientEvent::NetworkEvent {
1243 /// connected: true,
1244 /// reason: Some("Connection restored".to_string()),
1245 /// priority: EventPriority::Normal,
1246 /// };
1247 ///
1248 /// emitter.emit(network_event).await;
1249 /// # }
1250 /// ```
1251 pub async fn emit(&self, event: ClientEvent) {
1252 let subscriptions = self.subscriptions.read().unwrap().clone();
1253
1254 // Deliver event to all matching subscriptions in parallel
1255 let tasks: Vec<_> = subscriptions
1256 .into_iter()
1257 .map(|subscription| {
1258 let event_clone = event.clone();
1259 tokio::spawn(async move {
1260 subscription.deliver_event(event_clone).await;
1261 })
1262 })
1263 .collect();
1264
1265 // Wait for all deliveries to complete
1266 for task in tasks {
1267 if let Err(e) = task.await {
1268 tracing::error!("Error delivering event: {}", e);
1269 }
1270 }
1271 }
1272
1273 /// Get the number of active subscriptions
1274 ///
1275 /// Returns the current count of registered event subscriptions.
1276 ///
1277 /// # Examples
1278 ///
1279 /// ```rust
1280 /// use rvoip_client_core::events::{EventEmitter, EventSubscription, ClientEventHandler, IncomingCallInfo, CallAction, CallStatusInfo, RegistrationStatusInfo};
1281 /// use async_trait::async_trait;
1282 /// use std::sync::Arc;
1283 ///
1284 /// struct TestHandler;
1285 ///
1286 /// #[async_trait]
1287 /// impl ClientEventHandler for TestHandler {
1288 /// async fn on_incoming_call(&self, _call_info: IncomingCallInfo) -> CallAction {
1289 /// CallAction::Accept
1290 /// }
1291 /// async fn on_call_state_changed(&self, _status_info: CallStatusInfo) {}
1292 /// async fn on_registration_status_changed(&self, _status_info: RegistrationStatusInfo) {}
1293 /// }
1294 ///
1295 /// let emitter = EventEmitter::new();
1296 /// assert_eq!(emitter.subscription_count(), 0);
1297 ///
1298 /// let handler = Arc::new(TestHandler);
1299 /// let subscription = EventSubscription::all_events(handler);
1300 /// emitter.subscribe(subscription);
1301 ///
1302 /// assert_eq!(emitter.subscription_count(), 1);
1303 /// ```
1304 pub fn subscription_count(&self) -> usize {
1305 self.subscriptions.read().unwrap().len()
1306 }
1307}
1308
1309impl Default for EventEmitter {
1310 fn default() -> Self {
1311 Self::new()
1312 }
1313}
1314
1315impl Clone for EventSubscription {
1316 fn clone(&self) -> Self {
1317 Self {
1318 handler: self.handler.clone(),
1319 filter: self.filter.clone(),
1320 id: self.id,
1321 }
1322 }
1323}