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