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