xref: /webrtc/data/src/data_channel/mod.rs (revision 7ceeeeb0)
1 #[cfg(test)]
2 mod data_channel_test;
3 
4 use crate::error::Result;
5 use crate::{
6     error::Error, message::message_channel_ack::*, message::message_channel_open::*, message::*,
7 };
8 
9 use sctp::{
10     association::Association, chunk::chunk_payload_data::PayloadProtocolIdentifier, stream::*,
11 };
12 use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
13 use util::marshal::*;
14 
15 use bytes::{Buf, Bytes};
16 use derive_builder::Builder;
17 use std::borrow::Borrow;
18 use std::fmt;
19 use std::future::Future;
20 use std::io;
21 use std::net::Shutdown;
22 use std::pin::Pin;
23 use std::sync::atomic::{AtomicUsize, Ordering};
24 use std::sync::Arc;
25 use std::task::{Context, Poll};
26 
27 const RECEIVE_MTU: usize = 8192;
28 
29 /// Config is used to configure the data channel.
30 #[derive(Eq, PartialEq, Default, Clone, Debug, Builder)]
31 pub struct Config {
32     #[builder(default)]
33     pub channel_type: ChannelType,
34     #[builder(default)]
35     pub negotiated: bool,
36     #[builder(default)]
37     pub priority: u16,
38     #[builder(default)]
39     pub reliability_parameter: u32,
40     #[builder(default)]
41     pub label: String,
42     #[builder(default)]
43     pub protocol: String,
44 }
45 
46 /// DataChannel represents a data channel
47 #[derive(Debug, Default, Clone)]
48 pub struct DataChannel {
49     pub config: Config,
50     stream: Arc<Stream>,
51 
52     // stats
53     messages_sent: Arc<AtomicUsize>,
54     messages_received: Arc<AtomicUsize>,
55     bytes_sent: Arc<AtomicUsize>,
56     bytes_received: Arc<AtomicUsize>,
57 }
58 
59 impl DataChannel {
60     pub fn new(stream: Arc<Stream>, config: Config) -> Self {
61         Self {
62             config,
63             stream,
64             ..Default::default()
65         }
66     }
67 
68     /// Dial opens a data channels over SCTP
69     pub async fn dial(
70         association: &Arc<Association>,
71         identifier: u16,
72         config: Config,
73     ) -> Result<Self> {
74         let stream = association
75             .open_stream(identifier, PayloadProtocolIdentifier::Binary)
76             .await?;
77 
78         Self::client(stream, config).await
79     }
80 
81     /// Accept is used to accept incoming data channels over SCTP
82     pub async fn accept<T>(
83         association: &Arc<Association>,
84         config: Config,
85         existing_channels: &[T],
86     ) -> Result<Self>
87     where
88         T: Borrow<Self>,
89     {
90         let stream = association
91             .accept_stream()
92             .await
93             .ok_or(Error::ErrStreamClosed)?;
94 
95         for channel in existing_channels.iter().map(|ch| ch.borrow()) {
96             if channel.stream_identifier() == stream.stream_identifier() {
97                 let ch = channel.to_owned();
98                 ch.stream
99                     .set_default_payload_type(PayloadProtocolIdentifier::Binary);
100                 return Ok(ch);
101             }
102         }
103 
104         stream.set_default_payload_type(PayloadProtocolIdentifier::Binary);
105 
106         Self::server(stream, config).await
107     }
108 
109     /// Client opens a data channel over an SCTP stream
110     pub async fn client(stream: Arc<Stream>, config: Config) -> Result<Self> {
111         if !config.negotiated {
112             let msg = Message::DataChannelOpen(DataChannelOpen {
113                 channel_type: config.channel_type,
114                 priority: config.priority,
115                 reliability_parameter: config.reliability_parameter,
116                 label: config.label.bytes().collect(),
117                 protocol: config.protocol.bytes().collect(),
118             })
119             .marshal()?;
120 
121             stream
122                 .write_sctp(&msg, PayloadProtocolIdentifier::Dcep)
123                 .await?;
124         }
125         Ok(DataChannel::new(stream, config))
126     }
127 
128     /// Server accepts a data channel over an SCTP stream
129     pub async fn server(stream: Arc<Stream>, mut config: Config) -> Result<Self> {
130         let mut buf = vec![0u8; RECEIVE_MTU];
131 
132         let (n, ppi) = stream.read_sctp(&mut buf).await?;
133 
134         if ppi != PayloadProtocolIdentifier::Dcep {
135             return Err(Error::InvalidPayloadProtocolIdentifier(ppi as u8));
136         }
137 
138         let mut read_buf = &buf[..n];
139         let msg = Message::unmarshal(&mut read_buf)?;
140 
141         if let Message::DataChannelOpen(dco) = msg {
142             config.channel_type = dco.channel_type;
143             config.priority = dco.priority;
144             config.reliability_parameter = dco.reliability_parameter;
145             config.label = String::from_utf8(dco.label)?;
146             config.protocol = String::from_utf8(dco.protocol)?;
147         } else {
148             return Err(Error::InvalidMessageType(msg.message_type() as u8));
149         };
150 
151         let data_channel = DataChannel::new(stream, config);
152 
153         data_channel.write_data_channel_ack().await?;
154         data_channel.commit_reliability_params();
155 
156         Ok(data_channel)
157     }
158 
159     /// Read reads a packet of len(p) bytes as binary data.
160     ///
161     /// See [`sctp::stream::Stream::read_sctp`].
162     pub async fn read(&self, buf: &mut [u8]) -> Result<usize> {
163         self.read_data_channel(buf).await.map(|(n, _)| n)
164     }
165 
166     /// ReadDataChannel reads a packet of len(p) bytes. It returns the number of bytes read and
167     /// `true` if the data read is a string.
168     ///
169     /// See [`sctp::stream::Stream::read_sctp`].
170     pub async fn read_data_channel(&self, buf: &mut [u8]) -> Result<(usize, bool)> {
171         loop {
172             //TODO: add handling of cancel read_data_channel
173             let (mut n, ppi) = match self.stream.read_sctp(buf).await {
174                 Ok((0, PayloadProtocolIdentifier::Unknown)) => {
175                     // The incoming stream was reset or the reading half was shutdown
176                     return Ok((0, false));
177                 }
178                 Ok((n, ppi)) => (n, ppi),
179                 Err(err) => {
180                     // Shutdown the stream and send the reset request to the remote.
181                     self.close().await?;
182                     return Err(err.into());
183                 }
184             };
185 
186             let mut is_string = false;
187             match ppi {
188                 PayloadProtocolIdentifier::Dcep => {
189                     let mut data = &buf[..n];
190                     match self.handle_dcep(&mut data).await {
191                         Ok(()) => {}
192                         Err(err) => {
193                             log::error!("Failed to handle DCEP: {:?}", err);
194                         }
195                     }
196                     continue;
197                 }
198                 PayloadProtocolIdentifier::String | PayloadProtocolIdentifier::StringEmpty => {
199                     is_string = true;
200                 }
201                 _ => {}
202             };
203 
204             match ppi {
205                 PayloadProtocolIdentifier::StringEmpty | PayloadProtocolIdentifier::BinaryEmpty => {
206                     n = 0;
207                 }
208                 _ => {}
209             };
210 
211             self.messages_received.fetch_add(1, Ordering::SeqCst);
212             self.bytes_received.fetch_add(n, Ordering::SeqCst);
213 
214             return Ok((n, is_string));
215         }
216     }
217 
218     /// MessagesSent returns the number of messages sent
219     pub fn messages_sent(&self) -> usize {
220         self.messages_sent.load(Ordering::SeqCst)
221     }
222 
223     /// MessagesReceived returns the number of messages received
224     pub fn messages_received(&self) -> usize {
225         self.messages_received.load(Ordering::SeqCst)
226     }
227 
228     /// BytesSent returns the number of bytes sent
229     pub fn bytes_sent(&self) -> usize {
230         self.bytes_sent.load(Ordering::SeqCst)
231     }
232 
233     /// BytesReceived returns the number of bytes received
234     pub fn bytes_received(&self) -> usize {
235         self.bytes_received.load(Ordering::SeqCst)
236     }
237 
238     /// StreamIdentifier returns the Stream identifier associated to the stream.
239     pub fn stream_identifier(&self) -> u16 {
240         self.stream.stream_identifier()
241     }
242 
243     async fn handle_dcep<B>(&self, data: &mut B) -> Result<()>
244     where
245         B: Buf,
246     {
247         let msg = Message::unmarshal(data)?;
248 
249         match msg {
250             Message::DataChannelOpen(_) => {
251                 // Note: DATA_CHANNEL_OPEN message is handled inside Server() method.
252                 // Therefore, the message will not reach here.
253                 log::debug!("Received DATA_CHANNEL_OPEN");
254                 let _ = self.write_data_channel_ack().await?;
255             }
256             Message::DataChannelAck(_) => {
257                 log::debug!("Received DATA_CHANNEL_ACK");
258                 self.commit_reliability_params();
259             }
260         };
261 
262         Ok(())
263     }
264 
265     /// Write writes len(p) bytes from p as binary data
266     pub async fn write(&self, data: &Bytes) -> Result<usize> {
267         self.write_data_channel(data, false).await
268     }
269 
270     /// WriteDataChannel writes len(p) bytes from p
271     pub async fn write_data_channel(&self, data: &Bytes, is_string: bool) -> Result<usize> {
272         let data_len = data.len();
273 
274         // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-12#section-6.6
275         // SCTP does not support the sending of empty user messages.  Therefore,
276         // if an empty message has to be sent, the appropriate PPID (WebRTC
277         // String Empty or WebRTC Binary Empty) is used and the SCTP user
278         // message of one zero byte is sent.  When receiving an SCTP user
279         // message with one of these PPIDs, the receiver MUST ignore the SCTP
280         // user message and process it as an empty message.
281         let ppi = match (is_string, data_len) {
282             (false, 0) => PayloadProtocolIdentifier::BinaryEmpty,
283             (false, _) => PayloadProtocolIdentifier::Binary,
284             (true, 0) => PayloadProtocolIdentifier::StringEmpty,
285             (true, _) => PayloadProtocolIdentifier::String,
286         };
287 
288         let n = if data_len == 0 {
289             let _ = self
290                 .stream
291                 .write_sctp(&Bytes::from_static(&[0]), ppi)
292                 .await?;
293             0
294         } else {
295             let n = self.stream.write_sctp(data, ppi).await?;
296             self.bytes_sent.fetch_add(n, Ordering::SeqCst);
297             n
298         };
299 
300         self.messages_sent.fetch_add(1, Ordering::SeqCst);
301         Ok(n)
302     }
303 
304     async fn write_data_channel_ack(&self) -> Result<usize> {
305         let ack = Message::DataChannelAck(DataChannelAck {}).marshal()?;
306         Ok(self
307             .stream
308             .write_sctp(&ack, PayloadProtocolIdentifier::Dcep)
309             .await?)
310     }
311 
312     /// Close closes the DataChannel and the underlying SCTP stream.
313     pub async fn close(&self) -> Result<()> {
314         // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.7
315         // Closing of a data channel MUST be signaled by resetting the
316         // corresponding outgoing streams [RFC6525].  This means that if one
317         // side decides to close the data channel, it resets the corresponding
318         // outgoing stream.  When the peer sees that an incoming stream was
319         // reset, it also resets its corresponding outgoing stream.  Once this
320         // is completed, the data channel is closed.  Resetting a stream sets
321         // the Stream Sequence Numbers (SSNs) of the stream back to 'zero' with
322         // a corresponding notification to the application layer that the reset
323         // has been performed.  Streams are available for reuse after a reset
324         // has been performed.
325         Ok(self.stream.shutdown(Shutdown::Both).await?)
326     }
327 
328     /// BufferedAmount returns the number of bytes of data currently queued to be
329     /// sent over this stream.
330     pub fn buffered_amount(&self) -> usize {
331         self.stream.buffered_amount()
332     }
333 
334     /// BufferedAmountLowThreshold returns the number of bytes of buffered outgoing
335     /// data that is considered "low." Defaults to 0.
336     pub fn buffered_amount_low_threshold(&self) -> usize {
337         self.stream.buffered_amount_low_threshold()
338     }
339 
340     /// SetBufferedAmountLowThreshold is used to update the threshold.
341     /// See BufferedAmountLowThreshold().
342     pub fn set_buffered_amount_low_threshold(&self, threshold: usize) {
343         self.stream.set_buffered_amount_low_threshold(threshold)
344     }
345 
346     /// OnBufferedAmountLow sets the callback handler which would be called when the
347     /// number of bytes of outgoing data buffered is lower than the threshold.
348     pub async fn on_buffered_amount_low(&self, f: OnBufferedAmountLowFn) {
349         self.stream.on_buffered_amount_low(f).await
350     }
351 
352     fn commit_reliability_params(&self) {
353         let (unordered, reliability_type) = match self.config.channel_type {
354             ChannelType::Reliable => (false, ReliabilityType::Reliable),
355             ChannelType::ReliableUnordered => (true, ReliabilityType::Reliable),
356             ChannelType::PartialReliableRexmit => (false, ReliabilityType::Rexmit),
357             ChannelType::PartialReliableRexmitUnordered => (true, ReliabilityType::Rexmit),
358             ChannelType::PartialReliableTimed => (false, ReliabilityType::Timed),
359             ChannelType::PartialReliableTimedUnordered => (true, ReliabilityType::Timed),
360         };
361 
362         self.stream.set_reliability_params(
363             unordered,
364             reliability_type,
365             self.config.reliability_parameter,
366         );
367     }
368 }
369 
370 /// Default capacity of the temporary read buffer used by [`PollStream`].
371 const DEFAULT_READ_BUF_SIZE: usize = 8192;
372 
373 /// State of the read `Future` in [`PollStream`].
374 enum ReadFut {
375     /// Nothing in progress.
376     Idle,
377     /// Reading data from the underlying stream.
378     Reading(Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send>>),
379     /// Finished reading, but there's unread data in the temporary buffer.
380     RemainingData(Vec<u8>),
381 }
382 
383 impl ReadFut {
384     /// Gets a mutable reference to the future stored inside `Reading(future)`.
385     ///
386     /// # Panics
387     ///
388     /// Panics if `ReadFut` variant is not `Reading`.
389     fn get_reading_mut(&mut self) -> &mut Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send>> {
390         match self {
391             ReadFut::Reading(ref mut fut) => fut,
392             _ => panic!("expected ReadFut to be Reading"),
393         }
394     }
395 }
396 
397 /// A wrapper around around [`DataChannel`], which implements [`AsyncRead`] and
398 /// [`AsyncWrite`].
399 ///
400 /// Both `poll_read` and `poll_write` calls allocate temporary buffers, which results in an
401 /// additional overhead.
402 pub struct PollDataChannel {
403     data_channel: Arc<DataChannel>,
404 
405     read_fut: ReadFut,
406     write_fut: Option<Pin<Box<dyn Future<Output = Result<usize>> + Send>>>,
407     shutdown_fut: Option<Pin<Box<dyn Future<Output = Result<()>> + Send>>>,
408 
409     read_buf_cap: usize,
410 }
411 
412 impl PollDataChannel {
413     /// Constructs a new `PollDataChannel`.
414     ///
415     /// # Examples
416     ///
417     /// ```
418     /// use webrtc_data::data_channel::{DataChannel, PollDataChannel, Config};
419     /// use sctp::stream::Stream;
420     /// use std::sync::Arc;
421     ///
422     /// let dc = Arc::new(DataChannel::new(Arc::new(Stream::default()), Config::default()));
423     /// let poll_dc = PollDataChannel::new(dc);
424     /// ```
425     pub fn new(data_channel: Arc<DataChannel>) -> Self {
426         Self {
427             data_channel,
428             read_fut: ReadFut::Idle,
429             write_fut: None,
430             shutdown_fut: None,
431             read_buf_cap: DEFAULT_READ_BUF_SIZE,
432         }
433     }
434 
435     /// Get back the inner data_channel.
436     pub fn into_inner(self) -> Arc<DataChannel> {
437         self.data_channel
438     }
439 
440     /// Obtain a clone of the inner data_channel.
441     pub fn clone_inner(&self) -> Arc<DataChannel> {
442         self.data_channel.clone()
443     }
444 
445     /// MessagesSent returns the number of messages sent
446     pub fn messages_sent(&self) -> usize {
447         self.data_channel.messages_sent()
448     }
449 
450     /// MessagesReceived returns the number of messages received
451     pub fn messages_received(&self) -> usize {
452         self.data_channel.messages_received()
453     }
454 
455     /// BytesSent returns the number of bytes sent
456     pub fn bytes_sent(&self) -> usize {
457         self.data_channel.bytes_sent()
458     }
459 
460     /// BytesReceived returns the number of bytes received
461     pub fn bytes_received(&self) -> usize {
462         self.data_channel.bytes_received()
463     }
464 
465     /// StreamIdentifier returns the Stream identifier associated to the stream.
466     pub fn stream_identifier(&self) -> u16 {
467         self.data_channel.stream_identifier()
468     }
469 
470     /// BufferedAmount returns the number of bytes of data currently queued to be
471     /// sent over this stream.
472     pub fn buffered_amount(&self) -> usize {
473         self.data_channel.buffered_amount()
474     }
475 
476     /// BufferedAmountLowThreshold returns the number of bytes of buffered outgoing
477     /// data that is considered "low." Defaults to 0.
478     pub fn buffered_amount_low_threshold(&self) -> usize {
479         self.data_channel.buffered_amount_low_threshold()
480     }
481 
482     /// Set the capacity of the temporary read buffer (default: 8192).
483     pub fn set_read_buf_capacity(&mut self, capacity: usize) {
484         self.read_buf_cap = capacity
485     }
486 }
487 
488 impl AsyncRead for PollDataChannel {
489     fn poll_read(
490         mut self: Pin<&mut Self>,
491         cx: &mut Context<'_>,
492         buf: &mut ReadBuf<'_>,
493     ) -> Poll<io::Result<()>> {
494         if buf.remaining() == 0 {
495             return Poll::Ready(Ok(()));
496         }
497 
498         let fut = match self.read_fut {
499             ReadFut::Idle => {
500                 // read into a temporary buffer because `buf` has an unonymous lifetime, which can
501                 // be shorter than the lifetime of `read_fut`.
502                 let data_channel = self.data_channel.clone();
503                 let mut temp_buf = vec![0; self.read_buf_cap];
504                 self.read_fut = ReadFut::Reading(Box::pin(async move {
505                     data_channel.read(temp_buf.as_mut_slice()).await.map(|n| {
506                         temp_buf.truncate(n);
507                         temp_buf
508                     })
509                 }));
510                 self.read_fut.get_reading_mut()
511             }
512             ReadFut::Reading(ref mut fut) => fut,
513             ReadFut::RemainingData(ref mut data) => {
514                 let remaining = buf.remaining();
515                 let len = std::cmp::min(data.len(), remaining);
516                 buf.put_slice(&data[..len]);
517                 if data.len() > remaining {
518                     // ReadFut remains to be RemainingData
519                     data.drain(..len);
520                 } else {
521                     self.read_fut = ReadFut::Idle;
522                 }
523                 return Poll::Ready(Ok(()));
524             }
525         };
526 
527         loop {
528             match fut.as_mut().poll(cx) {
529                 Poll::Pending => return Poll::Pending,
530                 // retry immediately upon empty data or incomplete chunks
531                 // since there's no way to setup a waker.
532                 Poll::Ready(Err(Error::Sctp(sctp::Error::ErrTryAgain))) => {}
533                 // EOF has been reached => don't touch buf and just return Ok
534                 Poll::Ready(Err(Error::Sctp(sctp::Error::ErrEof))) => {
535                     self.read_fut = ReadFut::Idle;
536                     return Poll::Ready(Ok(()));
537                 }
538                 Poll::Ready(Err(e)) => {
539                     self.read_fut = ReadFut::Idle;
540                     return Poll::Ready(Err(e.into()));
541                 }
542                 Poll::Ready(Ok(mut temp_buf)) => {
543                     let remaining = buf.remaining();
544                     let len = std::cmp::min(temp_buf.len(), remaining);
545                     buf.put_slice(&temp_buf[..len]);
546                     if temp_buf.len() > remaining {
547                         temp_buf.drain(..len);
548                         self.read_fut = ReadFut::RemainingData(temp_buf);
549                     } else {
550                         self.read_fut = ReadFut::Idle;
551                     }
552                     return Poll::Ready(Ok(()));
553                 }
554             }
555         }
556     }
557 }
558 
559 impl AsyncWrite for PollDataChannel {
560     fn poll_write(
561         mut self: Pin<&mut Self>,
562         cx: &mut Context<'_>,
563         buf: &[u8],
564     ) -> Poll<io::Result<usize>> {
565         if buf.is_empty() {
566             return Poll::Ready(Ok(0));
567         }
568 
569         let (fut, fut_is_new) = match self.write_fut.as_mut() {
570             Some(fut) => (fut, false),
571             None => {
572                 let data_channel = self.data_channel.clone();
573                 let bytes = Bytes::copy_from_slice(buf);
574                 (
575                     self.write_fut
576                         .get_or_insert(Box::pin(async move { data_channel.write(&bytes).await })),
577                     true,
578                 )
579             }
580         };
581 
582         match fut.as_mut().poll(cx) {
583             Poll::Pending => {
584                 // If it's the first time we're polling the future, `Poll::Pending` can't be
585                 // returned because that would mean the `PollStream` is not ready for writing. And
586                 // this is not true since we've just created a future, which is going to write the
587                 // buf to the underlying stream.
588                 //
589                 // It's okay to return `Poll::Ready` if the data is buffered (this is what the
590                 // buffered writer and `File` do).
591                 if fut_is_new {
592                     Poll::Ready(Ok(buf.len()))
593                 } else {
594                     // If it's the subsequent poll, it's okay to return `Poll::Pending` as it
595                     // indicates that the `PollStream` is not ready for writing. Only one future
596                     // can be in progress at the time.
597                     Poll::Pending
598                 }
599             }
600             Poll::Ready(Err(e)) => {
601                 self.write_fut = None;
602                 Poll::Ready(Err(e.into()))
603             }
604             Poll::Ready(Ok(n)) => {
605                 self.write_fut = None;
606                 Poll::Ready(Ok(n))
607             }
608         }
609     }
610 
611     fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
612         match self.write_fut.as_mut() {
613             Some(fut) => match fut.as_mut().poll(cx) {
614                 Poll::Pending => Poll::Pending,
615                 Poll::Ready(Err(e)) => {
616                     self.write_fut = None;
617                     Poll::Ready(Err(e.into()))
618                 }
619                 Poll::Ready(Ok(_)) => {
620                     self.write_fut = None;
621                     Poll::Ready(Ok(()))
622                 }
623             },
624             None => Poll::Ready(Ok(())),
625         }
626     }
627 
628     fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
629         let fut = match self.shutdown_fut.as_mut() {
630             Some(fut) => fut,
631             None => {
632                 let data_channel = self.data_channel.clone();
633                 self.shutdown_fut.get_or_insert(Box::pin(async move {
634                     data_channel
635                         .stream
636                         .shutdown(Shutdown::Write)
637                         .await
638                         .map_err(Error::Sctp)
639                 }))
640             }
641         };
642 
643         match fut.as_mut().poll(cx) {
644             Poll::Pending => Poll::Pending,
645             Poll::Ready(Err(e)) => {
646                 self.shutdown_fut = None;
647                 Poll::Ready(Err(e.into()))
648             }
649             Poll::Ready(Ok(_)) => {
650                 self.shutdown_fut = None;
651                 Poll::Ready(Ok(()))
652             }
653         }
654     }
655 }
656 
657 impl Clone for PollDataChannel {
658     fn clone(&self) -> PollDataChannel {
659         PollDataChannel::new(self.clone_inner())
660     }
661 }
662 
663 impl fmt::Debug for PollDataChannel {
664     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
665         f.debug_struct("PollDataChannel")
666             .field("data_channel", &self.data_channel)
667             .field("read_buf_cap", &self.read_buf_cap)
668             .finish()
669     }
670 }
671 
672 impl AsRef<DataChannel> for PollDataChannel {
673     fn as_ref(&self) -> &DataChannel {
674         &self.data_channel
675     }
676 }
677