xref: /webrtc/webrtc/src/data_channel/mod.rs (revision 3d8b2967)
1 #[cfg(test)]
2 mod data_channel_test;
3 
4 pub mod data_channel_init;
5 pub mod data_channel_message;
6 pub mod data_channel_parameters;
7 pub mod data_channel_state;
8 
9 use data_channel_message::*;
10 use data_channel_parameters::*;
11 
12 use arc_swap::ArcSwapOption;
13 use bytes::Bytes;
14 use std::{
15     future::Future,
16     pin::Pin,
17     sync::{
18         atomic::{AtomicBool, AtomicU16, AtomicU8, AtomicUsize, Ordering},
19         Arc, Weak,
20     },
21     time::SystemTime,
22 };
23 
24 use data::message::message_channel_open::ChannelType;
25 use sctp::stream::OnBufferedAmountLowFn;
26 use tokio::sync::{Mutex, Notify};
27 use util::sync::Mutex as SyncMutex;
28 
29 use data_channel_state::RTCDataChannelState;
30 
31 use crate::api::setting_engine::SettingEngine;
32 use crate::error::{Error, OnErrorHdlrFn, Result};
33 use crate::sctp_transport::RTCSctpTransport;
34 use crate::stats::stats_collector::StatsCollector;
35 use crate::stats::{DataChannelStats, StatsReportType};
36 
37 /// message size limit for Chromium
38 const DATA_CHANNEL_BUFFER_SIZE: u16 = u16::MAX;
39 
40 pub type OnMessageHdlrFn = Box<
41     dyn (FnMut(DataChannelMessage) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>)
42         + Send
43         + Sync,
44 >;
45 
46 pub type OnOpenHdlrFn =
47     Box<dyn (FnOnce() -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>) + Send + Sync>;
48 
49 pub type OnCloseHdlrFn =
50     Box<dyn (FnMut() -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>) + Send + Sync>;
51 
52 /// DataChannel represents a WebRTC DataChannel
53 /// The DataChannel interface represents a network channel
54 /// which can be used for bidirectional peer-to-peer transfers of arbitrary data
55 #[derive(Default)]
56 pub struct RTCDataChannel {
57     pub(crate) stats_id: String,
58     pub(crate) label: String,
59     pub(crate) ordered: bool,
60     pub(crate) max_packet_lifetime: u16,
61     pub(crate) max_retransmits: u16,
62     pub(crate) protocol: String,
63     pub(crate) negotiated: bool,
64     pub(crate) id: AtomicU16,
65     pub(crate) ready_state: Arc<AtomicU8>, // DataChannelState
66     pub(crate) buffered_amount_low_threshold: AtomicUsize,
67     pub(crate) detach_called: Arc<AtomicBool>,
68 
69     // The binaryType represents attribute MUST, on getting, return the value to
70     // which it was last set. On setting, if the new value is either the string
71     // "blob" or the string "arraybuffer", then set the IDL attribute to this
72     // new value. Otherwise, throw a SyntaxError. When an DataChannel object
73     // is created, the binaryType attribute MUST be initialized to the string
74     // "blob". This attribute controls how binary data is exposed to scripts.
75     // binaryType                 string
76     pub(crate) on_message_handler: Arc<ArcSwapOption<Mutex<OnMessageHdlrFn>>>,
77     pub(crate) on_open_handler: SyncMutex<Option<OnOpenHdlrFn>>,
78     pub(crate) on_close_handler: Arc<ArcSwapOption<Mutex<OnCloseHdlrFn>>>,
79     pub(crate) on_error_handler: Arc<ArcSwapOption<Mutex<OnErrorHdlrFn>>>,
80 
81     pub(crate) on_buffered_amount_low: Mutex<Option<OnBufferedAmountLowFn>>,
82 
83     pub(crate) sctp_transport: Mutex<Option<Weak<RTCSctpTransport>>>,
84     pub(crate) data_channel: Mutex<Option<Arc<data::data_channel::DataChannel>>>,
85 
86     pub(crate) notify_tx: Arc<Notify>,
87 
88     // A reference to the associated api object used by this datachannel
89     pub(crate) setting_engine: Arc<SettingEngine>,
90 }
91 
92 impl RTCDataChannel {
93     // create the DataChannel object before the networking is set up.
new(params: DataChannelParameters, setting_engine: Arc<SettingEngine>) -> Self94     pub(crate) fn new(params: DataChannelParameters, setting_engine: Arc<SettingEngine>) -> Self {
95         // the id value if non-negotiated doesn't matter, since it will be overwritten
96         // on opening
97         let id = params.negotiated.unwrap_or(0);
98         RTCDataChannel {
99             stats_id: format!(
100                 "DataChannel-{}",
101                 SystemTime::now()
102                     .duration_since(SystemTime::UNIX_EPOCH)
103                     .map_or(0, |d| d.as_nanos())
104             ),
105             label: params.label,
106             protocol: params.protocol,
107             negotiated: params.negotiated.is_some(),
108             id: AtomicU16::new(id),
109             ordered: params.ordered,
110             max_packet_lifetime: params.max_packet_life_time,
111             max_retransmits: params.max_retransmits,
112             ready_state: Arc::new(AtomicU8::new(RTCDataChannelState::Connecting as u8)),
113             detach_called: Arc::new(AtomicBool::new(false)),
114 
115             notify_tx: Arc::new(Notify::new()),
116 
117             setting_engine,
118             ..Default::default()
119         }
120     }
121 
122     /// open opens the datachannel over the sctp transport
open(&self, sctp_transport: Arc<RTCSctpTransport>) -> Result<()>123     pub(crate) async fn open(&self, sctp_transport: Arc<RTCSctpTransport>) -> Result<()> {
124         if let Some(association) = sctp_transport.association().await {
125             {
126                 let mut st = self.sctp_transport.lock().await;
127                 if st.is_none() {
128                     *st = Some(Arc::downgrade(&sctp_transport));
129                 } else {
130                     return Ok(());
131                 }
132             }
133 
134             let channel_type;
135             let reliability_parameter;
136 
137             if self.max_packet_lifetime == 0 && self.max_retransmits == 0 {
138                 reliability_parameter = 0u32;
139                 if self.ordered {
140                     channel_type = ChannelType::Reliable;
141                 } else {
142                     channel_type = ChannelType::ReliableUnordered;
143                 }
144             } else if self.max_retransmits != 0 {
145                 reliability_parameter = self.max_retransmits as u32;
146                 if self.ordered {
147                     channel_type = ChannelType::PartialReliableRexmit;
148                 } else {
149                     channel_type = ChannelType::PartialReliableRexmitUnordered;
150                 }
151             } else {
152                 reliability_parameter = self.max_packet_lifetime as u32;
153                 if self.ordered {
154                     channel_type = ChannelType::PartialReliableTimed;
155                 } else {
156                     channel_type = ChannelType::PartialReliableTimedUnordered;
157                 }
158             }
159 
160             let cfg = data::data_channel::Config {
161                 channel_type,
162                 priority: data::message::message_channel_open::CHANNEL_PRIORITY_NORMAL,
163                 reliability_parameter,
164                 label: self.label.clone(),
165                 protocol: self.protocol.clone(),
166                 negotiated: self.negotiated,
167             };
168 
169             if !self.negotiated {
170                 self.id.store(
171                     sctp_transport
172                         .generate_and_set_data_channel_id(
173                             sctp_transport.dtls_transport.role().await,
174                         )
175                         .await?,
176                     Ordering::SeqCst,
177                 );
178             }
179 
180             let dc = data::data_channel::DataChannel::dial(&association, self.id(), cfg).await?;
181 
182             // buffered_amount_low_threshold and on_buffered_amount_low might be set earlier
183             dc.set_buffered_amount_low_threshold(
184                 self.buffered_amount_low_threshold.load(Ordering::SeqCst),
185             );
186             {
187                 let mut on_buffered_amount_low = self.on_buffered_amount_low.lock().await;
188                 if let Some(f) = on_buffered_amount_low.take() {
189                     dc.on_buffered_amount_low(f);
190                 }
191             }
192 
193             self.handle_open(Arc::new(dc)).await;
194 
195             Ok(())
196         } else {
197             Err(Error::ErrSCTPNotEstablished)
198         }
199     }
200 
201     /// transport returns the SCTPTransport instance the DataChannel is sending over.
transport(&self) -> Option<Weak<RTCSctpTransport>>202     pub async fn transport(&self) -> Option<Weak<RTCSctpTransport>> {
203         let sctp_transport = self.sctp_transport.lock().await;
204         sctp_transport.clone()
205     }
206 
207     /// on_open sets an event handler which is invoked when
208     /// the underlying data transport has been established (or re-established).
on_open(&self, f: OnOpenHdlrFn)209     pub fn on_open(&self, f: OnOpenHdlrFn) {
210         let _ = self.on_open_handler.lock().replace(f);
211 
212         if self.ready_state() == RTCDataChannelState::Open {
213             self.do_open();
214         }
215     }
216 
do_open(&self)217     fn do_open(&self) {
218         let on_open_handler = self.on_open_handler.lock().take();
219         if on_open_handler.is_none() {
220             return;
221         }
222 
223         let detach_data_channels = self.setting_engine.detach.data_channels;
224         let detach_called = Arc::clone(&self.detach_called);
225         tokio::spawn(async move {
226             if let Some(f) = on_open_handler {
227                 f().await;
228 
229                 // self.check_detach_after_open();
230                 // After onOpen is complete check that the user called detach
231                 // and provide an error message if the call was missed
232                 if detach_data_channels && !detach_called.load(Ordering::SeqCst) {
233                     log::warn!(
234                         "webrtc.DetachDataChannels() enabled but didn't Detach, call Detach from OnOpen"
235                     );
236                 }
237             }
238         });
239     }
240 
241     /// on_close sets an event handler which is invoked when
242     /// the underlying data transport has been closed.
on_close(&self, f: OnCloseHdlrFn)243     pub fn on_close(&self, f: OnCloseHdlrFn) {
244         self.on_close_handler.store(Some(Arc::new(Mutex::new(f))));
245     }
246 
247     /// on_message sets an event handler which is invoked on a binary
248     /// message arrival over the sctp transport from a remote peer.
249     /// OnMessage can currently receive messages up to 16384 bytes
250     /// in size. Check out the detach API if you want to use larger
251     /// message sizes. Note that browser support for larger messages
252     /// is also limited.
on_message(&self, f: OnMessageHdlrFn)253     pub fn on_message(&self, f: OnMessageHdlrFn) {
254         self.on_message_handler.store(Some(Arc::new(Mutex::new(f))));
255     }
256 
do_message(&self, msg: DataChannelMessage)257     async fn do_message(&self, msg: DataChannelMessage) {
258         if let Some(handler) = &*self.on_message_handler.load() {
259             let mut f = handler.lock().await;
260             f(msg).await;
261         }
262     }
263 
handle_open(&self, dc: Arc<data::data_channel::DataChannel>)264     pub(crate) async fn handle_open(&self, dc: Arc<data::data_channel::DataChannel>) {
265         {
266             let mut data_channel = self.data_channel.lock().await;
267             *data_channel = Some(Arc::clone(&dc));
268         }
269         self.set_ready_state(RTCDataChannelState::Open);
270 
271         self.do_open();
272 
273         if !self.setting_engine.detach.data_channels {
274             let ready_state = Arc::clone(&self.ready_state);
275             let on_message_handler = Arc::clone(&self.on_message_handler);
276             let on_close_handler = Arc::clone(&self.on_close_handler);
277             let on_error_handler = Arc::clone(&self.on_error_handler);
278             let notify_rx = self.notify_tx.clone();
279             tokio::spawn(async move {
280                 RTCDataChannel::read_loop(
281                     notify_rx,
282                     dc,
283                     ready_state,
284                     on_message_handler,
285                     on_close_handler,
286                     on_error_handler,
287                 )
288                 .await;
289             });
290         }
291     }
292 
293     /// on_error sets an event handler which is invoked when
294     /// the underlying data transport cannot be read.
on_error(&self, f: OnErrorHdlrFn)295     pub fn on_error(&self, f: OnErrorHdlrFn) {
296         self.on_error_handler.store(Some(Arc::new(Mutex::new(f))));
297     }
298 
read_loop( notify_rx: Arc<Notify>, data_channel: Arc<data::data_channel::DataChannel>, ready_state: Arc<AtomicU8>, on_message_handler: Arc<ArcSwapOption<Mutex<OnMessageHdlrFn>>>, on_close_handler: Arc<ArcSwapOption<Mutex<OnCloseHdlrFn>>>, on_error_handler: Arc<ArcSwapOption<Mutex<OnErrorHdlrFn>>>, )299     async fn read_loop(
300         notify_rx: Arc<Notify>,
301         data_channel: Arc<data::data_channel::DataChannel>,
302         ready_state: Arc<AtomicU8>,
303         on_message_handler: Arc<ArcSwapOption<Mutex<OnMessageHdlrFn>>>,
304         on_close_handler: Arc<ArcSwapOption<Mutex<OnCloseHdlrFn>>>,
305         on_error_handler: Arc<ArcSwapOption<Mutex<OnErrorHdlrFn>>>,
306     ) {
307         let mut buffer = vec![0u8; DATA_CHANNEL_BUFFER_SIZE as usize];
308         loop {
309             let (n, is_string) = tokio::select! {
310                 _ = notify_rx.notified() => break,
311                 result = data_channel.read_data_channel(&mut buffer) => {
312                     match result{
313                         // EOF (`data_channel` was either closed or the underlying stream got
314                         // reset by the remote) => close and run `on_close` handler.
315                         Ok((0, _)) =>
316                         {
317                             ready_state.store(RTCDataChannelState::Closed as u8, Ordering::SeqCst);
318 
319                             let on_close_handler2 = Arc::clone(&on_close_handler);
320                             tokio::spawn(async move {
321                                 if let Some(handler) = &*on_close_handler2.load() {
322                                     let mut f = handler.lock().await;
323                                     f().await;
324                                 }
325                             });
326 
327                             break;
328                         }
329                         Ok((n, is_string)) => (n, is_string),
330                         Err(err) => {
331                             ready_state.store(RTCDataChannelState::Closed as u8, Ordering::SeqCst);
332 
333                             let on_error_handler2 = Arc::clone(&on_error_handler);
334                             tokio::spawn(async move {
335                                 if let Some(handler) = &*on_error_handler2.load() {
336                                     let mut f = handler.lock().await;
337                                     f(err.into()).await;
338                                 }
339                             });
340 
341                             let on_close_handler2 = Arc::clone(&on_close_handler);
342                             tokio::spawn(async move {
343                                 if let Some(handler) = &*on_close_handler2.load() {
344                                     let mut f = handler.lock().await;
345                                     f().await;
346                                 }
347                             });
348 
349                             break;
350                         }
351                     }
352                 }
353             };
354 
355             if let Some(handler) = &*on_message_handler.load() {
356                 let mut f = handler.lock().await;
357                 f(DataChannelMessage {
358                     is_string,
359                     data: Bytes::from(buffer[..n].to_vec()),
360                 })
361                 .await;
362             }
363         }
364     }
365 
366     /// send sends the binary message to the DataChannel peer
send(&self, data: &Bytes) -> Result<usize>367     pub async fn send(&self, data: &Bytes) -> Result<usize> {
368         self.ensure_open()?;
369 
370         let data_channel = self.data_channel.lock().await;
371         if let Some(dc) = &*data_channel {
372             Ok(dc.write_data_channel(data, false).await?)
373         } else {
374             Err(Error::ErrClosedPipe)
375         }
376     }
377 
378     /// send_text sends the text message to the DataChannel peer
send_text(&self, s: impl Into<String>) -> Result<usize>379     pub async fn send_text(&self, s: impl Into<String>) -> Result<usize> {
380         self.ensure_open()?;
381 
382         let data_channel = self.data_channel.lock().await;
383         if let Some(dc) = &*data_channel {
384             Ok(dc.write_data_channel(&Bytes::from(s.into()), true).await?)
385         } else {
386             Err(Error::ErrClosedPipe)
387         }
388     }
389 
ensure_open(&self) -> Result<()>390     fn ensure_open(&self) -> Result<()> {
391         if self.ready_state() != RTCDataChannelState::Open {
392             Err(Error::ErrClosedPipe)
393         } else {
394             Ok(())
395         }
396     }
397 
398     /// detach allows you to detach the underlying datachannel. This provides
399     /// an idiomatic API to work with, however it disables the OnMessage callback.
400     /// Before calling Detach you have to enable this behavior by calling
401     /// webrtc.DetachDataChannels(). Combining detached and normal data channels
402     /// is not supported.
403     /// Please refer to the data-channels-detach example and the
404     /// pion/datachannel documentation for the correct way to handle the
405     /// resulting DataChannel object.
detach(&self) -> Result<Arc<data::data_channel::DataChannel>>406     pub async fn detach(&self) -> Result<Arc<data::data_channel::DataChannel>> {
407         if !self.setting_engine.detach.data_channels {
408             return Err(Error::ErrDetachNotEnabled);
409         }
410 
411         let data_channel = self.data_channel.lock().await;
412         if let Some(dc) = &*data_channel {
413             self.detach_called.store(true, Ordering::SeqCst);
414 
415             Ok(Arc::clone(dc))
416         } else {
417             Err(Error::ErrDetachBeforeOpened)
418         }
419     }
420 
421     /// Close Closes the DataChannel. It may be called regardless of whether
422     /// the DataChannel object was created by this peer or the remote peer.
close(&self) -> Result<()>423     pub async fn close(&self) -> Result<()> {
424         if self.ready_state() == RTCDataChannelState::Closed {
425             return Ok(());
426         }
427 
428         self.set_ready_state(RTCDataChannelState::Closing);
429         self.notify_tx.notify_waiters();
430 
431         let data_channel = self.data_channel.lock().await;
432         if let Some(dc) = &*data_channel {
433             Ok(dc.close().await?)
434         } else {
435             Ok(())
436         }
437     }
438 
439     /// label represents a label that can be used to distinguish this
440     /// DataChannel object from other DataChannel objects. Scripts are
441     /// allowed to create multiple DataChannel objects with the same label.
label(&self) -> &str442     pub fn label(&self) -> &str {
443         self.label.as_str()
444     }
445 
446     /// Ordered returns true if the DataChannel is ordered, and false if
447     /// out-of-order delivery is allowed.
ordered(&self) -> bool448     pub fn ordered(&self) -> bool {
449         self.ordered
450     }
451 
452     /// max_packet_lifetime represents the length of the time window (msec) during
453     /// which transmissions and retransmissions may occur in unreliable mode.
max_packet_lifetime(&self) -> u16454     pub fn max_packet_lifetime(&self) -> u16 {
455         self.max_packet_lifetime
456     }
457 
458     /// max_retransmits represents the maximum number of retransmissions that are
459     /// attempted in unreliable mode.
max_retransmits(&self) -> u16460     pub fn max_retransmits(&self) -> u16 {
461         self.max_retransmits
462     }
463 
464     /// protocol represents the name of the sub-protocol used with this
465     /// DataChannel.
protocol(&self) -> &str466     pub fn protocol(&self) -> &str {
467         self.protocol.as_str()
468     }
469 
470     /// negotiated represents whether this DataChannel was negotiated by the
471     /// application (true), or not (false).
negotiated(&self) -> bool472     pub fn negotiated(&self) -> bool {
473         self.negotiated
474     }
475 
476     /// ID represents the ID for this DataChannel. The value is initially
477     /// null, which is what will be returned if the ID was not provided at
478     /// channel creation time, and the DTLS role of the SCTP transport has not
479     /// yet been negotiated. Otherwise, it will return the ID that was either
480     /// selected by the script or generated. After the ID is set to a non-null
481     /// value, it will not change.
id(&self) -> u16482     pub fn id(&self) -> u16 {
483         self.id.load(Ordering::SeqCst)
484     }
485 
486     /// ready_state represents the state of the DataChannel object.
ready_state(&self) -> RTCDataChannelState487     pub fn ready_state(&self) -> RTCDataChannelState {
488         self.ready_state.load(Ordering::SeqCst).into()
489     }
490 
491     /// buffered_amount represents the number of bytes of application data
492     /// (UTF-8 text and binary data) that have been queued using send(). Even
493     /// though the data transmission can occur in parallel, the returned value
494     /// MUST NOT be decreased before the current task yielded back to the event
495     /// loop to prevent race conditions. The value does not include framing
496     /// overhead incurred by the protocol, or buffering done by the operating
497     /// system or network hardware. The value of buffered_amount slot will only
498     /// increase with each call to the send() method as long as the ready_state is
499     /// open; however, buffered_amount does not reset to zero once the channel
500     /// closes.
buffered_amount(&self) -> usize501     pub async fn buffered_amount(&self) -> usize {
502         let data_channel = self.data_channel.lock().await;
503         if let Some(dc) = &*data_channel {
504             dc.buffered_amount()
505         } else {
506             0
507         }
508     }
509 
510     /// buffered_amount_low_threshold represents the threshold at which the
511     /// bufferedAmount is considered to be low. When the bufferedAmount decreases
512     /// from above this threshold to equal or below it, the bufferedamountlow
513     /// event fires. buffered_amount_low_threshold is initially zero on each new
514     /// DataChannel, but the application may change its value at any time.
515     /// The threshold is set to 0 by default.
buffered_amount_low_threshold(&self) -> usize516     pub async fn buffered_amount_low_threshold(&self) -> usize {
517         let data_channel = self.data_channel.lock().await;
518         if let Some(dc) = &*data_channel {
519             dc.buffered_amount_low_threshold()
520         } else {
521             self.buffered_amount_low_threshold.load(Ordering::SeqCst)
522         }
523     }
524 
525     /// set_buffered_amount_low_threshold is used to update the threshold.
526     /// See buffered_amount_low_threshold().
set_buffered_amount_low_threshold(&self, th: usize)527     pub async fn set_buffered_amount_low_threshold(&self, th: usize) {
528         self.buffered_amount_low_threshold
529             .store(th, Ordering::SeqCst);
530         let data_channel = self.data_channel.lock().await;
531         if let Some(dc) = &*data_channel {
532             dc.set_buffered_amount_low_threshold(th);
533         }
534     }
535 
536     /// on_buffered_amount_low sets an event handler which is invoked when
537     /// the number of bytes of outgoing data becomes lower than the
538     /// buffered_amount_low_threshold.
on_buffered_amount_low(&self, f: OnBufferedAmountLowFn)539     pub async fn on_buffered_amount_low(&self, f: OnBufferedAmountLowFn) {
540         let data_channel = self.data_channel.lock().await;
541         if let Some(dc) = &*data_channel {
542             dc.on_buffered_amount_low(f);
543         } else {
544             let mut on_buffered_amount_low = self.on_buffered_amount_low.lock().await;
545             *on_buffered_amount_low = Some(f);
546         }
547     }
548 
get_stats_id(&self) -> &str549     pub(crate) fn get_stats_id(&self) -> &str {
550         self.stats_id.as_str()
551     }
552 
collect_stats(&self, collector: &StatsCollector)553     pub(crate) async fn collect_stats(&self, collector: &StatsCollector) {
554         let stats = DataChannelStats::from(self).await;
555         collector.insert(self.stats_id.clone(), StatsReportType::DataChannel(stats));
556     }
557 
set_ready_state(&self, r: RTCDataChannelState)558     pub(crate) fn set_ready_state(&self, r: RTCDataChannelState) {
559         self.ready_state.store(r as u8, Ordering::SeqCst);
560     }
561 }
562