1use std::sync::mpsc::{channel, Sender};
2use std::thread;
3
4use log::error;
5
6use crate::datachannel::{DataChannelEvent, DataChannelId, DataChannelInit, DataChannelMessage};
7use crate::{
8 BundlePolicy, DescriptionType, IceCandidate, MediaStreamId, SdpType, SessionDescription,
9};
10use crate::{WebRtcBackend, WebRtcControllerBackend, WebRtcSignaller};
11
12use servo_media_streams::MediaStreamType;
13
14#[derive(Clone)]
15pub struct WebRtcController {
17 sender: Sender<RtcThreadEvent>,
18}
19
20impl WebRtcController {
21 pub fn new<T: WebRtcBackend>(signaller: Box<dyn WebRtcSignaller>) -> Self {
22 let (sender, receiver) = channel();
23
24 let t = WebRtcController { sender };
25
26 let mut controller = T::construct_webrtc_controller(signaller, t.clone());
27
28 thread::spawn(move || {
29 while let Ok(event) = receiver.recv() {
30 if !handle_rtc_event(&mut controller, event) {
31 break;
33 }
34 }
35 });
36
37 t
38 }
39 pub fn configure(&self, stun_server: String, policy: BundlePolicy) {
40 let _ = self
41 .sender
42 .send(RtcThreadEvent::ConfigureStun(stun_server, policy));
43 }
44 pub fn set_remote_description(
45 &self,
46 desc: SessionDescription,
47 cb: Box<dyn FnOnce() + Send + 'static>,
48 ) {
49 let _ = self
50 .sender
51 .send(RtcThreadEvent::SetRemoteDescription(desc, cb));
52 }
53 pub fn set_local_description(
54 &self,
55 desc: SessionDescription,
56 cb: Box<dyn FnOnce() + Send + 'static>,
57 ) {
58 let _ = self
59 .sender
60 .send(RtcThreadEvent::SetLocalDescription(desc, cb));
61 }
62 pub fn add_ice_candidate(&self, candidate: IceCandidate) {
63 let _ = self.sender.send(RtcThreadEvent::AddIceCandidate(candidate));
64 }
65 pub fn create_offer(&self, cb: Box<dyn FnOnce(SessionDescription) + Send + 'static>) {
66 let _ = self.sender.send(RtcThreadEvent::CreateOffer(cb));
67 }
68 pub fn create_answer(&self, cb: Box<dyn FnOnce(SessionDescription) + Send + 'static>) {
69 let _ = self.sender.send(RtcThreadEvent::CreateAnswer(cb));
70 }
71 pub fn add_stream(&self, stream: &MediaStreamId) {
72 let _ = self.sender.send(RtcThreadEvent::AddStream(stream.clone()));
73 }
74 pub fn create_data_channel(&self, init: DataChannelInit) -> Option<DataChannelId> {
75 let (sender, receiver) = channel();
76 let _ = self
77 .sender
78 .send(RtcThreadEvent::CreateDataChannel(init, sender));
79 receiver.recv().unwrap()
80 }
81 pub fn send_data_channel_message(&self, id: &DataChannelId, message: DataChannelMessage) {
82 let _ = self
83 .sender
84 .send(RtcThreadEvent::SendDataChannelMessage(*id, message));
85 }
86 pub fn close_data_channel(&self, id: &DataChannelId) {
87 let _ = self.sender.send(RtcThreadEvent::CloseDataChannel(*id));
88 }
89
90 pub fn internal_event(&self, event: InternalEvent) {
92 let _ = self.sender.send(RtcThreadEvent::InternalEvent(event));
93 }
94
95 pub fn quit(&self) {
96 let _ = self.sender.send(RtcThreadEvent::Quit);
97 }
98}
99
100pub enum RtcThreadEvent {
101 ConfigureStun(String, BundlePolicy),
102 SetRemoteDescription(SessionDescription, Box<dyn FnOnce() + Send + 'static>),
103 SetLocalDescription(SessionDescription, Box<dyn FnOnce() + Send + 'static>),
104 AddIceCandidate(IceCandidate),
105 CreateOffer(Box<dyn FnOnce(SessionDescription) + Send + 'static>),
106 CreateAnswer(Box<dyn FnOnce(SessionDescription) + Send + 'static>),
107 AddStream(MediaStreamId),
108 CreateDataChannel(DataChannelInit, Sender<Option<DataChannelId>>),
109 CloseDataChannel(DataChannelId),
110 SendDataChannelMessage(DataChannelId, DataChannelMessage),
111 InternalEvent(InternalEvent),
112 Quit,
113}
114
115pub enum InternalEvent {
121 OnNegotiationNeeded,
122 OnIceCandidate(IceCandidate),
123 OnAddStream(MediaStreamId, MediaStreamType),
124 OnDataChannelEvent(DataChannelId, DataChannelEvent),
125 DescriptionAdded(
126 Box<dyn FnOnce() + Send + 'static>,
127 DescriptionType,
128 SdpType,
129 u32,
130 ),
131 UpdateSignalingState,
132 UpdateGatheringState,
133 UpdateIceConnectionState,
134}
135
136pub fn handle_rtc_event(
137 controller: &mut dyn WebRtcControllerBackend,
138 event: RtcThreadEvent,
139) -> bool {
140 let result = match event {
141 RtcThreadEvent::ConfigureStun(server, policy) => controller.configure(&server, policy),
142 RtcThreadEvent::SetRemoteDescription(desc, cb) => {
143 controller.set_remote_description(desc, cb)
144 },
145 RtcThreadEvent::SetLocalDescription(desc, cb) => controller.set_local_description(desc, cb),
146 RtcThreadEvent::AddIceCandidate(candidate) => controller.add_ice_candidate(candidate),
147 RtcThreadEvent::CreateOffer(cb) => controller.create_offer(cb),
148 RtcThreadEvent::CreateAnswer(cb) => controller.create_answer(cb),
149 RtcThreadEvent::AddStream(media) => controller.add_stream(&media),
150 RtcThreadEvent::CreateDataChannel(init, sender) => controller
151 .create_data_channel(&init)
152 .map(|id| {
153 let _ = sender.send(Some(id));
154 ()
155 })
156 .map_err(|e| {
157 let _ = sender.send(None);
158 e
159 }),
160 RtcThreadEvent::CloseDataChannel(id) => controller.close_data_channel(&id),
161 RtcThreadEvent::SendDataChannelMessage(id, message) => {
162 controller.send_data_channel_message(&id, &message)
163 },
164 RtcThreadEvent::InternalEvent(e) => controller.internal_event(e),
165 RtcThreadEvent::Quit => {
166 controller.quit();
167 return false;
168 },
169 };
170 if let Err(e) = result {
171 error!("WebRTC backend encountered error: {:?}", e);
172 }
173 true
174}