1use std::cell::Cell;
6use std::ptr;
7
8use dom_struct::dom_struct;
9use js::context::JSContext;
10use js::conversions::ToJSValConvertible;
11use js::jsapi::JSObject;
12use js::jsval::UndefinedValue;
13use js::realm::CurrentRealm;
14use js::rust::CustomAutoRooterGuard;
15use js::typedarray::{ArrayBuffer, ArrayBufferU8, ArrayBufferView};
16use script_bindings::cell::DomRefCell;
17use script_bindings::match_domstring_ascii;
18use script_bindings::reflector::reflect_dom_object;
19use script_bindings::weakref::WeakRef;
20use servo_constellation_traits::BlobImpl;
21use servo_media::webrtc::{
22 DataChannelId, DataChannelInit, DataChannelMessage, DataChannelState, WebRtcError,
23};
24
25use crate::conversions::Convert;
26use crate::dom::bindings::buffer_source::create_buffer_source;
27use crate::dom::bindings::codegen::Bindings::RTCDataChannelBinding::{
28 RTCDataChannelInit, RTCDataChannelMethods, RTCDataChannelState,
29};
30use crate::dom::bindings::codegen::Bindings::RTCErrorBinding::{RTCErrorDetailType, RTCErrorInit};
31use crate::dom::bindings::error::{Error, Fallible};
32use crate::dom::bindings::inheritance::Castable;
33use crate::dom::bindings::reflector::DomGlobal;
34use crate::dom::bindings::root::{Dom, DomRoot};
35use crate::dom::bindings::str::{DOMString, USVString};
36use crate::dom::blob::Blob;
37use crate::dom::event::{Event, EventBubbles, EventCancelable};
38use crate::dom::eventtarget::EventTarget;
39use crate::dom::globalscope::GlobalScope;
40use crate::dom::messageevent::MessageEvent;
41use crate::dom::rtcerror::RTCError;
42use crate::dom::rtcerrorevent::RTCErrorEvent;
43use crate::dom::rtcpeerconnection::RTCPeerConnection;
44
45#[derive(JSTraceable, MallocSizeOf)]
46struct DroppableRTCDataChannel {
47 #[ignore_malloc_size_of = "defined in servo-media"]
48 servo_media_id: DataChannelId,
49 peer_connection: WeakRef<RTCPeerConnection>,
50}
51
52impl DroppableRTCDataChannel {
53 fn new(peer_connection: WeakRef<RTCPeerConnection>, servo_media_id: DataChannelId) -> Self {
54 DroppableRTCDataChannel {
55 servo_media_id,
56 peer_connection,
57 }
58 }
59
60 pub(crate) fn get_servo_media_id(&self) -> DataChannelId {
61 self.servo_media_id
62 }
63}
64
65impl Drop for DroppableRTCDataChannel {
66 fn drop(&mut self) {
67 if let Some(root) = self.peer_connection.root() {
68 root.unregister_data_channel(&self.get_servo_media_id());
69 }
70 }
71}
72
73#[dom_struct]
74pub(crate) struct RTCDataChannel {
75 eventtarget: EventTarget,
76 label: USVString,
77 ordered: bool,
78 max_packet_life_time: Option<u16>,
79 max_retransmits: Option<u16>,
80 protocol: USVString,
81 negotiated: bool,
82 id: Option<u16>,
83 ready_state: Cell<RTCDataChannelState>,
84 binary_type: DomRefCell<DOMString>,
85 peer_connection: Dom<RTCPeerConnection>,
86 droppable: DroppableRTCDataChannel,
87}
88
89impl RTCDataChannel {
90 pub(crate) fn new_inherited(
91 peer_connection: &RTCPeerConnection,
92 label: USVString,
93 options: &RTCDataChannelInit,
94 servo_media_id: Option<DataChannelId>,
95 ) -> RTCDataChannel {
96 let mut init: DataChannelInit = options.convert();
97 init.label = label.0.clone();
98
99 let controller = peer_connection.get_webrtc_controller().borrow();
100 let servo_media_id = servo_media_id.unwrap_or(
101 controller
102 .as_ref()
103 .unwrap()
104 .create_data_channel(init)
105 .expect("Expected data channel id"),
106 );
107
108 RTCDataChannel {
109 eventtarget: EventTarget::new_inherited(),
110 label,
111 ordered: options.ordered,
112 max_packet_life_time: options.maxPacketLifeTime,
113 max_retransmits: options.maxRetransmits,
114 protocol: options.protocol.clone(),
115 negotiated: options.negotiated,
116 id: options.id,
117 ready_state: Cell::new(RTCDataChannelState::Connecting),
118 binary_type: DomRefCell::new(DOMString::from_static("blob")),
119 peer_connection: Dom::from_ref(peer_connection),
120 droppable: DroppableRTCDataChannel::new(WeakRef::new(peer_connection), servo_media_id),
121 }
122 }
123
124 pub(crate) fn new(
125 cx: &mut JSContext,
126 global: &GlobalScope,
127 peer_connection: &RTCPeerConnection,
128 label: USVString,
129 options: &RTCDataChannelInit,
130 servo_media_id: Option<DataChannelId>,
131 ) -> DomRoot<RTCDataChannel> {
132 let rtc_data_channel = reflect_dom_object(
133 cx,
134 Box::new(RTCDataChannel::new_inherited(
135 peer_connection,
136 label,
137 options,
138 servo_media_id,
139 )),
140 global,
141 );
142
143 peer_connection
144 .register_data_channel(rtc_data_channel.get_servo_media_id(), &rtc_data_channel);
145
146 rtc_data_channel
147 }
148
149 pub(crate) fn get_servo_media_id(&self) -> DataChannelId {
150 self.droppable.get_servo_media_id()
151 }
152
153 pub(crate) fn on_open(&self, cx: &mut JSContext) {
154 let event = Event::new(
155 cx,
156 &self.global(),
157 atom!("open"),
158 EventBubbles::DoesNotBubble,
159 EventCancelable::NotCancelable,
160 );
161 event.upcast::<Event>().fire(cx, self.upcast());
162 }
163
164 pub(crate) fn on_close(&self, cx: &mut JSContext) {
165 let event = Event::new(
166 cx,
167 &self.global(),
168 atom!("close"),
169 EventBubbles::DoesNotBubble,
170 EventCancelable::NotCancelable,
171 );
172 event.upcast::<Event>().fire(cx, self.upcast());
173
174 self.peer_connection
175 .unregister_data_channel(&self.get_servo_media_id());
176 }
177
178 pub(crate) fn on_error(&self, cx: &mut CurrentRealm, error: WebRtcError) {
179 let global = self.global();
180 let window = global.as_window();
181 let init = RTCErrorInit {
182 errorDetail: RTCErrorDetailType::Data_channel_failure,
183 httpRequestStatusCode: None,
184 receivedAlert: None,
185 sctpCauseCode: None,
186 sdpLineNumber: None,
187 sentAlert: None,
188 };
189 let message = match error {
190 WebRtcError::Backend(message) => DOMString::from(message),
191 };
192 let error = RTCError::new(cx, window, &init, message);
193 let event = RTCErrorEvent::new(cx, window, atom!("error"), false, false, &error);
194 event.upcast::<Event>().fire(cx, self.upcast());
195 }
196
197 pub(crate) fn on_message(&self, cx: &mut CurrentRealm, channel_message: DataChannelMessage) {
198 let global = self.global();
199 rooted!(&in(cx) let mut message = UndefinedValue());
200
201 match channel_message {
202 DataChannelMessage::Text(text) => {
203 text.to_jsval(cx, message.handle_mut());
204 },
205 DataChannelMessage::Binary(data) => {
206 let binary_type = self.binary_type.borrow();
207 match_domstring_ascii!(binary_type,
208 "blob" => {
209 let blob = Blob::new(
210 cx,
211 &global,
212 BlobImpl::new_from_bytes(data, String::new()),
213 );
214 blob.to_jsval(cx, message.handle_mut());
215 },
216 "arraybuffer" => {
217 rooted!(&in(cx) let mut array_buffer = ptr::null_mut::<JSObject>());
218 assert!(
219 create_buffer_source::<ArrayBufferU8>(
220 cx,
221 &data,
222 array_buffer.handle_mut()
223 )
224 .is_ok()
225 );
226 (*array_buffer).to_jsval(cx, message.handle_mut());
227 },
228 _ => unreachable!(),
229 )
230 },
231 }
232
233 MessageEvent::dispatch_jsval(
234 cx,
235 self.upcast(),
236 &global,
237 message.handle(),
238 Some(global.origin().immutable().ascii_serialization().as_ref()),
239 None,
240 vec![],
241 );
242 }
243
244 pub(crate) fn on_state_change(&self, cx: &mut JSContext, state: DataChannelState) {
245 if let DataChannelState::Closing = state {
246 let event = Event::new(
247 cx,
248 &self.global(),
249 atom!("closing"),
250 EventBubbles::DoesNotBubble,
251 EventCancelable::NotCancelable,
252 );
253 event.upcast::<Event>().fire(cx, self.upcast());
254 };
255 self.ready_state.set(state.convert());
256 }
257
258 fn send(&self, source: &SendSource) -> Fallible<()> {
259 if self.ready_state.get() != RTCDataChannelState::Open {
260 return Err(Error::InvalidState(None));
261 }
262
263 let message = match source {
264 SendSource::String(string) => DataChannelMessage::Text(string.0.clone()),
265 SendSource::Blob(blob) => {
266 DataChannelMessage::Binary(blob.get_bytes().unwrap_or(vec![]))
267 },
268 SendSource::ArrayBuffer(array) => {
269 DataChannelMessage::Binary(array.to_vec().unwrap_or_default())
270 },
271 SendSource::ArrayBufferView(array) => {
272 DataChannelMessage::Binary(array.to_vec().unwrap_or_default())
273 },
274 };
275
276 let controller = self.peer_connection.get_webrtc_controller().borrow();
277 controller
278 .as_ref()
279 .unwrap()
280 .send_data_channel_message(&self.get_servo_media_id(), message);
281
282 Ok(())
283 }
284}
285
286enum SendSource<'a, 'b> {
287 String(&'a USVString),
288 Blob(&'a Blob),
289 ArrayBuffer(CustomAutoRooterGuard<'b, ArrayBuffer>),
290 ArrayBufferView(CustomAutoRooterGuard<'b, ArrayBufferView>),
291}
292
293impl RTCDataChannelMethods<crate::DomTypeHolder> for RTCDataChannel {
294 event_handler!(open, GetOnopen, SetOnopen);
296 event_handler!(
298 bufferedamountlow,
299 GetOnbufferedamountlow,
300 SetOnbufferedamountlow
301 );
302 event_handler!(error, GetOnerror, SetOnerror);
304 event_handler!(closing, GetOnclosing, SetOnclosing);
306 event_handler!(close, GetOnclose, SetOnclose);
308 event_handler!(message, GetOnmessage, SetOnmessage);
310
311 fn Label(&self) -> USVString {
313 self.label.clone()
314 }
315 fn Ordered(&self) -> bool {
317 self.ordered
318 }
319
320 fn GetMaxPacketLifeTime(&self) -> Option<u16> {
322 self.max_packet_life_time
323 }
324
325 fn GetMaxRetransmits(&self) -> Option<u16> {
327 self.max_retransmits
328 }
329
330 fn Protocol(&self) -> USVString {
332 self.protocol.clone()
333 }
334
335 fn Negotiated(&self) -> bool {
337 self.negotiated
338 }
339
340 fn GetId(&self) -> Option<u16> {
342 self.id
343 }
344
345 fn ReadyState(&self) -> RTCDataChannelState {
347 self.ready_state.get()
348 }
349
350 fn Close(&self) {
359 let controller = self.peer_connection.get_webrtc_controller().borrow();
360 controller
361 .as_ref()
362 .unwrap()
363 .close_data_channel(&self.get_servo_media_id());
364 }
365
366 fn BinaryType(&self) -> DOMString {
368 self.binary_type.borrow().clone()
369 }
370
371 fn SetBinaryType(&self, value: DOMString) -> Fallible<()> {
373 if value != "blob" || value != "arraybuffer" {
374 return Err(Error::Syntax(None));
375 }
376 *self.binary_type.borrow_mut() = value;
377 Ok(())
378 }
379
380 fn Send(&self, data: USVString) -> Fallible<()> {
382 self.send(&SendSource::String(&data))
383 }
384
385 fn Send_(&self, data: &Blob) -> Fallible<()> {
387 self.send(&SendSource::Blob(data))
388 }
389
390 fn Send__(&self, data: CustomAutoRooterGuard<ArrayBuffer>) -> Fallible<()> {
392 self.send(&SendSource::ArrayBuffer(data))
393 }
394
395 fn Send___(&self, data: CustomAutoRooterGuard<ArrayBufferView>) -> Fallible<()> {
397 self.send(&SendSource::ArrayBufferView(data))
398 }
399}
400
401impl Convert<DataChannelInit> for &RTCDataChannelInit {
402 fn convert(self) -> DataChannelInit {
403 DataChannelInit {
404 label: String::new(),
405 id: self.id,
406 max_packet_life_time: self.maxPacketLifeTime,
407 max_retransmits: self.maxRetransmits,
408 negotiated: self.negotiated,
409 ordered: self.ordered,
410 protocol: self.protocol.to_string(),
411 }
412 }
413}
414
415impl Convert<RTCDataChannelState> for DataChannelState {
416 fn convert(self) -> RTCDataChannelState {
417 match self {
418 DataChannelState::Connecting | DataChannelState::__Unknown(_) => {
419 RTCDataChannelState::Connecting
420 },
421 DataChannelState::Open => RTCDataChannelState::Open,
422 DataChannelState::Closing => RTCDataChannelState::Closing,
423 DataChannelState::Closed => RTCDataChannelState::Closed,
424 }
425 }
426}