saorsa_webrtc/
service.rs

1//! WebRTC service orchestration
2
3use crate::call::{CallManager, CallManagerConfig};
4use crate::identity::PeerIdentity;
5use crate::media::MediaStreamManager;
6use crate::signaling::{SignalingHandler, SignalingTransport};
7use crate::types::{CallEvent, CallId, CallState, MediaConstraints, NativeQuicConfiguration};
8use serde::{Deserialize, Serialize};
9use std::sync::Arc;
10use thiserror::Error;
11use tokio::sync::broadcast;
12
13/// Service errors
14#[derive(Error, Debug)]
15pub enum ServiceError {
16    /// Initialization error
17    #[error("Initialization error: {0}")]
18    InitError(String),
19
20    /// Call error
21    #[error("Call error: {0}")]
22    CallError(String),
23}
24
25/// Top-level WebRTC events
26#[derive(Debug, Clone)]
27pub enum WebRtcEvent<I: PeerIdentity> {
28    /// Signaling event
29    Signaling(SignalingEvent),
30    /// Media event
31    Media(crate::media::MediaEvent),
32    /// Call event
33    Call(CallEvent<I>),
34}
35
36/// Signaling event (placeholder)
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub enum SignalingEvent {
39    /// Connected
40    Connected,
41    /// Disconnected
42    Disconnected,
43}
44
45/// WebRTC configuration
46#[derive(Debug, Clone)]
47pub struct WebRtcConfig {
48    /// QUIC configuration
49    pub quic_config: NativeQuicConfiguration,
50    /// Default media constraints
51    pub default_constraints: MediaConstraints,
52    /// Call manager config
53    pub call_config: CallManagerConfig,
54}
55
56impl Default for WebRtcConfig {
57    fn default() -> Self {
58        Self {
59            quic_config: NativeQuicConfiguration::default(),
60            default_constraints: MediaConstraints::audio_only(),
61            call_config: CallManagerConfig::default(),
62        }
63    }
64}
65
66/// Main WebRTC service
67pub struct WebRtcService<I: PeerIdentity, T: SignalingTransport> {
68    _signaling: Arc<SignalingHandler<T>>,
69    media: Arc<MediaStreamManager>,
70    call_manager: Arc<CallManager<I>>,
71    event_sender: broadcast::Sender<WebRtcEvent<I>>,
72}
73
74impl<I: PeerIdentity, T: SignalingTransport> WebRtcService<I, T> {
75    /// Create new WebRTC service
76    ///
77    /// # Errors
78    ///
79    /// Returns error if service creation fails
80    pub async fn new(
81        signaling: Arc<SignalingHandler<T>>,
82        config: WebRtcConfig,
83    ) -> Result<Self, ServiceError> {
84        let (event_sender, _) = broadcast::channel(1000);
85
86        let media = Arc::new(MediaStreamManager::new());
87        let call_manager = Arc::new(
88            CallManager::new(config.call_config)
89                .await
90                .map_err(|e| ServiceError::InitError(e.to_string()))?,
91        );
92
93        Ok(Self {
94            _signaling: signaling,
95            media,
96            call_manager,
97            event_sender,
98        })
99    }
100
101    /// Start the service
102    ///
103    /// # Errors
104    ///
105    /// Returns error if service cannot be started
106    pub async fn start(&self) -> Result<(), ServiceError> {
107        self.media
108            .initialize()
109            .await
110            .map_err(|e| ServiceError::InitError(e.to_string()))?;
111
112        self.call_manager
113            .start()
114            .await
115            .map_err(|e| ServiceError::InitError(e.to_string()))?;
116
117        Ok(())
118    }
119
120    /// Initiate a call
121    ///
122    /// # Errors
123    ///
124    /// Returns error if call cannot be initiated
125    pub async fn initiate_call(
126        &self,
127        callee: I,
128        constraints: MediaConstraints,
129    ) -> Result<CallId, ServiceError> {
130        self.call_manager
131            .initiate_call(callee, constraints)
132            .await
133            .map_err(|e| ServiceError::CallError(e.to_string()))
134    }
135
136    /// Accept a call
137    ///
138    /// # Errors
139    ///
140    /// Returns error if call cannot be accepted
141    pub async fn accept_call(
142        &self,
143        call_id: CallId,
144        constraints: MediaConstraints,
145    ) -> Result<(), ServiceError> {
146        self.call_manager
147            .accept_call(call_id, constraints)
148            .await
149            .map_err(|e| ServiceError::CallError(e.to_string()))
150    }
151
152    /// Reject a call
153    ///
154    /// # Errors
155    ///
156    /// Returns error if call cannot be rejected
157    pub async fn reject_call(&self, call_id: CallId) -> Result<(), ServiceError> {
158        self.call_manager
159            .reject_call(call_id)
160            .await
161            .map_err(|e| ServiceError::CallError(e.to_string()))
162    }
163
164    /// End a call
165    ///
166    /// # Errors
167    ///
168    /// Returns error if call cannot be ended
169    pub async fn end_call(&self, call_id: CallId) -> Result<(), ServiceError> {
170        self.call_manager
171            .end_call(call_id)
172            .await
173            .map_err(|e| ServiceError::CallError(e.to_string()))
174    }
175
176    /// Get call state
177    #[must_use]
178    pub async fn get_call_state(&self, call_id: CallId) -> Option<CallState> {
179        self.call_manager.get_call_state(call_id).await
180    }
181
182    /// Subscribe to events
183    #[must_use]
184    pub fn subscribe_events(&self) -> broadcast::Receiver<WebRtcEvent<I>> {
185        self.event_sender.subscribe()
186    }
187
188    /// Create a builder
189    #[must_use]
190    pub fn builder(signaling: Arc<SignalingHandler<T>>) -> WebRtcServiceBuilder<I, T> {
191        WebRtcServiceBuilder::new(signaling)
192    }
193}
194
195/// WebRTC service builder
196pub struct WebRtcServiceBuilder<I: PeerIdentity, T: SignalingTransport> {
197    signaling: Arc<SignalingHandler<T>>,
198    config: WebRtcConfig,
199    _phantom: std::marker::PhantomData<I>,
200}
201
202impl<I: PeerIdentity, T: SignalingTransport> WebRtcServiceBuilder<I, T> {
203    /// Create new builder
204    #[must_use]
205    pub fn new(signaling: Arc<SignalingHandler<T>>) -> Self {
206        Self {
207            signaling,
208            config: WebRtcConfig::default(),
209            _phantom: std::marker::PhantomData,
210        }
211    }
212
213    /// Set configuration
214    #[must_use]
215    pub fn with_config(mut self, config: WebRtcConfig) -> Self {
216        self.config = config;
217        self
218    }
219
220    /// Build the service
221    ///
222    /// # Errors
223    ///
224    /// Returns error if service creation fails
225    pub async fn build(self) -> Result<WebRtcService<I, T>, ServiceError> {
226        WebRtcService::new(self.signaling, self.config).await
227    }
228}