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