1 #[cfg(test)] 2 mod stream_test; 3 4 use crate::association::AssociationState; 5 use crate::chunk::chunk_payload_data::{ChunkPayloadData, PayloadProtocolIdentifier}; 6 use crate::error::{Error, Result}; 7 use crate::queue::pending_queue::PendingQueue; 8 use crate::queue::reassembly_queue::ReassemblyQueue; 9 10 use arc_swap::ArcSwapOption; 11 use bytes::Bytes; 12 use std::{ 13 fmt, 14 future::Future, 15 io, 16 net::Shutdown, 17 pin::Pin, 18 sync::atomic::{AtomicBool, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, Ordering}, 19 sync::Arc, 20 task::{Context, Poll}, 21 }; 22 use tokio::{ 23 io::{AsyncRead, AsyncWrite, ReadBuf}, 24 sync::{mpsc, Mutex, Notify}, 25 }; 26 27 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 28 #[repr(C)] 29 pub enum ReliabilityType { 30 /// ReliabilityTypeReliable is used for reliable transmission 31 Reliable = 0, 32 /// ReliabilityTypeRexmit is used for partial reliability by retransmission count 33 Rexmit = 1, 34 /// ReliabilityTypeTimed is used for partial reliability by retransmission duration 35 Timed = 2, 36 } 37 38 impl Default for ReliabilityType { 39 fn default() -> Self { 40 ReliabilityType::Reliable 41 } 42 } 43 44 impl fmt::Display for ReliabilityType { 45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 46 let s = match *self { 47 ReliabilityType::Reliable => "Reliable", 48 ReliabilityType::Rexmit => "Rexmit", 49 ReliabilityType::Timed => "Timed", 50 }; 51 write!(f, "{}", s) 52 } 53 } 54 55 impl From<u8> for ReliabilityType { 56 fn from(v: u8) -> ReliabilityType { 57 match v { 58 1 => ReliabilityType::Rexmit, 59 2 => ReliabilityType::Timed, 60 _ => ReliabilityType::Reliable, 61 } 62 } 63 } 64 65 pub type OnBufferedAmountLowFn = 66 Box<dyn (FnMut() -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>) + Send + Sync>; 67 68 // TODO: benchmark performance between multiple Atomic+Mutex vs one Mutex<StreamInternal> 69 70 /// Stream represents an SCTP stream 71 #[derive(Default)] 72 pub struct Stream { 73 pub(crate) max_payload_size: u32, 74 pub(crate) max_message_size: Arc<AtomicU32>, // clone from association 75 pub(crate) state: Arc<AtomicU8>, // clone from association 76 pub(crate) awake_write_loop_ch: Option<Arc<mpsc::Sender<()>>>, 77 pub(crate) pending_queue: Arc<PendingQueue>, 78 79 pub(crate) stream_identifier: u16, 80 pub(crate) default_payload_type: AtomicU32, //PayloadProtocolIdentifier, 81 pub(crate) reassembly_queue: Mutex<ReassemblyQueue>, 82 pub(crate) sequence_number: AtomicU16, 83 pub(crate) read_notifier: Notify, 84 pub(crate) read_shutdown: AtomicBool, 85 pub(crate) write_shutdown: AtomicBool, 86 pub(crate) unordered: AtomicBool, 87 pub(crate) reliability_type: AtomicU8, //ReliabilityType, 88 pub(crate) reliability_value: AtomicU32, 89 pub(crate) buffered_amount: AtomicUsize, 90 pub(crate) buffered_amount_low: AtomicUsize, 91 pub(crate) on_buffered_amount_low: ArcSwapOption<Mutex<OnBufferedAmountLowFn>>, 92 pub(crate) name: String, 93 } 94 95 impl fmt::Debug for Stream { 96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 97 f.debug_struct("Stream") 98 .field("max_payload_size", &self.max_payload_size) 99 .field("max_message_size", &self.max_message_size) 100 .field("state", &self.state) 101 .field("awake_write_loop_ch", &self.awake_write_loop_ch) 102 .field("stream_identifier", &self.stream_identifier) 103 .field("default_payload_type", &self.default_payload_type) 104 .field("reassembly_queue", &self.reassembly_queue) 105 .field("sequence_number", &self.sequence_number) 106 .field("read_shutdown", &self.read_shutdown) 107 .field("write_shutdown", &self.write_shutdown) 108 .field("unordered", &self.unordered) 109 .field("reliability_type", &self.reliability_type) 110 .field("reliability_value", &self.reliability_value) 111 .field("buffered_amount", &self.buffered_amount) 112 .field("buffered_amount_low", &self.buffered_amount_low) 113 .field("name", &self.name) 114 .finish() 115 } 116 } 117 118 impl Stream { 119 pub(crate) fn new( 120 name: String, 121 stream_identifier: u16, 122 max_payload_size: u32, 123 max_message_size: Arc<AtomicU32>, 124 state: Arc<AtomicU8>, 125 awake_write_loop_ch: Option<Arc<mpsc::Sender<()>>>, 126 pending_queue: Arc<PendingQueue>, 127 ) -> Self { 128 Stream { 129 max_payload_size, 130 max_message_size, 131 state, 132 awake_write_loop_ch, 133 pending_queue, 134 135 stream_identifier, 136 default_payload_type: AtomicU32::new(0), //PayloadProtocolIdentifier::Unknown, 137 reassembly_queue: Mutex::new(ReassemblyQueue::new(stream_identifier)), 138 sequence_number: AtomicU16::new(0), 139 read_notifier: Notify::new(), 140 read_shutdown: AtomicBool::new(false), 141 write_shutdown: AtomicBool::new(false), 142 unordered: AtomicBool::new(false), 143 reliability_type: AtomicU8::new(0), //ReliabilityType::Reliable, 144 reliability_value: AtomicU32::new(0), 145 buffered_amount: AtomicUsize::new(0), 146 buffered_amount_low: AtomicUsize::new(0), 147 on_buffered_amount_low: ArcSwapOption::empty(), 148 name, 149 } 150 } 151 152 /// stream_identifier returns the Stream identifier associated to the stream. 153 pub fn stream_identifier(&self) -> u16 { 154 self.stream_identifier 155 } 156 157 /// set_default_payload_type sets the default payload type used by write. 158 pub fn set_default_payload_type(&self, default_payload_type: PayloadProtocolIdentifier) { 159 self.default_payload_type 160 .store(default_payload_type as u32, Ordering::SeqCst); 161 } 162 163 /// set_reliability_params sets reliability parameters for this stream. 164 pub fn set_reliability_params(&self, unordered: bool, rel_type: ReliabilityType, rel_val: u32) { 165 log::debug!( 166 "[{}] reliability params: ordered={} type={} value={}", 167 self.name, 168 !unordered, 169 rel_type, 170 rel_val 171 ); 172 self.unordered.store(unordered, Ordering::SeqCst); 173 self.reliability_type 174 .store(rel_type as u8, Ordering::SeqCst); 175 self.reliability_value.store(rel_val, Ordering::SeqCst); 176 } 177 178 /// Reads a packet of len(p) bytes, dropping the Payload Protocol Identifier. 179 /// 180 /// Returns `Error::ErrShortBuffer` if `p` is too short. 181 /// Returns `0` if the reading half of this stream is shutdown or it (the stream) was reset. 182 pub async fn read(&self, p: &mut [u8]) -> Result<usize> { 183 let (n, _) = self.read_sctp(p).await?; 184 Ok(n) 185 } 186 187 /// Reads a packet of len(p) bytes and returns the associated Payload Protocol Identifier. 188 /// 189 /// Returns `Error::ErrShortBuffer` if `p` is too short. 190 /// Returns `(0, PayloadProtocolIdentifier::Unknown)` if the reading half of this stream is shutdown or it (the stream) was reset. 191 pub async fn read_sctp(&self, p: &mut [u8]) -> Result<(usize, PayloadProtocolIdentifier)> { 192 loop { 193 if self.read_shutdown.load(Ordering::SeqCst) { 194 return Ok((0, PayloadProtocolIdentifier::Unknown)); 195 } 196 197 let result = { 198 let mut reassembly_queue = self.reassembly_queue.lock().await; 199 reassembly_queue.read(p) 200 }; 201 202 match result { 203 Ok(_) | Err(Error::ErrShortBuffer) => return result, 204 Err(_) => { 205 // wait for the next chunk to become available 206 self.read_notifier.notified().await; 207 } 208 } 209 } 210 } 211 212 pub(crate) async fn handle_data(&self, pd: ChunkPayloadData) { 213 let readable = { 214 let mut reassembly_queue = self.reassembly_queue.lock().await; 215 if reassembly_queue.push(pd) { 216 let readable = reassembly_queue.is_readable(); 217 log::debug!("[{}] reassemblyQueue readable={}", self.name, readable); 218 readable 219 } else { 220 false 221 } 222 }; 223 224 if readable { 225 log::debug!("[{}] readNotifier.signal()", self.name); 226 self.read_notifier.notify_one(); 227 log::debug!("[{}] readNotifier.signal() done", self.name); 228 } 229 } 230 231 pub(crate) async fn handle_forward_tsn_for_ordered(&self, ssn: u16) { 232 if self.unordered.load(Ordering::SeqCst) { 233 return; // unordered chunks are handled by handleForwardUnordered method 234 } 235 236 // Remove all chunks older than or equal to the new TSN from 237 // the reassembly_queue. 238 let readable = { 239 let mut reassembly_queue = self.reassembly_queue.lock().await; 240 reassembly_queue.forward_tsn_for_ordered(ssn); 241 reassembly_queue.is_readable() 242 }; 243 244 // Notify the reader asynchronously if there's a data chunk to read. 245 if readable { 246 self.read_notifier.notify_one(); 247 } 248 } 249 250 pub(crate) async fn handle_forward_tsn_for_unordered(&self, new_cumulative_tsn: u32) { 251 if !self.unordered.load(Ordering::SeqCst) { 252 return; // ordered chunks are handled by handleForwardTSNOrdered method 253 } 254 255 // Remove all chunks older than or equal to the new TSN from 256 // the reassembly_queue. 257 let readable = { 258 let mut reassembly_queue = self.reassembly_queue.lock().await; 259 reassembly_queue.forward_tsn_for_unordered(new_cumulative_tsn); 260 reassembly_queue.is_readable() 261 }; 262 263 // Notify the reader asynchronously if there's a data chunk to read. 264 if readable { 265 self.read_notifier.notify_one(); 266 } 267 } 268 269 /// Writes `p` to the DTLS connection with the default Payload Protocol Identifier. 270 /// 271 /// Returns an error if the write half of this stream is shutdown or `p` is too large. 272 pub async fn write(&self, p: &Bytes) -> Result<usize> { 273 self.write_sctp(p, self.default_payload_type.load(Ordering::SeqCst).into()) 274 .await 275 } 276 277 /// Writes `p` to the DTLS connection with the given Payload Protocol Identifier. 278 /// 279 /// Returns an error if the write half of this stream is shutdown or `p` is too large. 280 pub async fn write_sctp(&self, p: &Bytes, ppi: PayloadProtocolIdentifier) -> Result<usize> { 281 let chunks = self.prepare_write(p, ppi)?; 282 self.send_payload_data(chunks).await?; 283 284 Ok(p.len()) 285 } 286 287 /// common stuff for write and try_write 288 fn prepare_write( 289 &self, 290 p: &Bytes, 291 ppi: PayloadProtocolIdentifier, 292 ) -> Result<Vec<ChunkPayloadData>> { 293 if self.write_shutdown.load(Ordering::SeqCst) { 294 return Err(Error::ErrStreamClosed); 295 } 296 297 if p.len() > self.max_message_size.load(Ordering::SeqCst) as usize { 298 return Err(Error::ErrOutboundPacketTooLarge); 299 } 300 301 let state: AssociationState = self.state.load(Ordering::SeqCst).into(); 302 match state { 303 AssociationState::ShutdownSent 304 | AssociationState::ShutdownAckSent 305 | AssociationState::ShutdownPending 306 | AssociationState::ShutdownReceived => return Err(Error::ErrStreamClosed), 307 _ => {} 308 }; 309 310 Ok(self.packetize(p, ppi)) 311 } 312 313 fn packetize(&self, raw: &Bytes, ppi: PayloadProtocolIdentifier) -> Vec<ChunkPayloadData> { 314 let mut i = 0; 315 let mut remaining = raw.len(); 316 317 // From draft-ietf-rtcweb-data-protocol-09, section 6: 318 // All Data Channel Establishment Protocol messages MUST be sent using 319 // ordered delivery and reliable transmission. 320 let unordered = 321 ppi != PayloadProtocolIdentifier::Dcep && self.unordered.load(Ordering::SeqCst); 322 323 let mut chunks = vec![]; 324 325 let head_abandoned = Arc::new(AtomicBool::new(false)); 326 let head_all_inflight = Arc::new(AtomicBool::new(false)); 327 while remaining != 0 { 328 let fragment_size = std::cmp::min(self.max_payload_size as usize, remaining); //self.association.max_payload_size 329 330 // Copy the userdata since we'll have to store it until acked 331 // and the caller may re-use the buffer in the mean time 332 let user_data = raw.slice(i..i + fragment_size); 333 334 let chunk = ChunkPayloadData { 335 stream_identifier: self.stream_identifier, 336 user_data, 337 unordered, 338 beginning_fragment: i == 0, 339 ending_fragment: remaining - fragment_size == 0, 340 immediate_sack: false, 341 payload_type: ppi, 342 stream_sequence_number: self.sequence_number.load(Ordering::SeqCst), 343 abandoned: head_abandoned.clone(), // all fragmented chunks use the same abandoned 344 all_inflight: head_all_inflight.clone(), // all fragmented chunks use the same all_inflight 345 ..Default::default() 346 }; 347 348 chunks.push(chunk); 349 350 remaining -= fragment_size; 351 i += fragment_size; 352 } 353 354 // RFC 4960 Sec 6.6 355 // Note: When transmitting ordered and unordered data, an endpoint does 356 // not increment its Stream Sequence Number when transmitting a DATA 357 // chunk with U flag set to 1. 358 if !unordered { 359 self.sequence_number.fetch_add(1, Ordering::SeqCst); 360 } 361 362 let old_value = self.buffered_amount.fetch_add(raw.len(), Ordering::SeqCst); 363 log::trace!("[{}] bufferedAmount = {}", self.name, old_value + raw.len()); 364 365 chunks 366 } 367 368 /// Closes both read and write halves of this stream. 369 /// 370 /// Use [`Stream::shutdown`] instead. 371 #[deprecated] 372 pub async fn close(&self) -> Result<()> { 373 self.shutdown(Shutdown::Both).await 374 } 375 376 /// Shuts down the read, write, or both halves of this stream. 377 /// 378 /// This function will cause all pending and future I/O on the specified portions to return 379 /// immediately with an appropriate value (see the documentation of [`Shutdown`]). 380 /// 381 /// Resets the stream when both halves of this stream are shutdown. 382 pub async fn shutdown(&self, how: Shutdown) -> Result<()> { 383 if self.read_shutdown.load(Ordering::SeqCst) && self.write_shutdown.load(Ordering::SeqCst) { 384 return Ok(()); 385 } 386 387 if how == Shutdown::Write || how == Shutdown::Both { 388 self.write_shutdown.store(true, Ordering::SeqCst); 389 } 390 391 if (how == Shutdown::Read || how == Shutdown::Both) 392 && !self.read_shutdown.swap(true, Ordering::SeqCst) 393 { 394 self.read_notifier.notify_waiters(); 395 } 396 397 if how == Shutdown::Both 398 || (self.read_shutdown.load(Ordering::SeqCst) 399 && self.write_shutdown.load(Ordering::SeqCst)) 400 { 401 // Reset the stream 402 // https://tools.ietf.org/html/rfc6525 403 self.send_reset_request(self.stream_identifier).await?; 404 } 405 406 Ok(()) 407 } 408 409 /// buffered_amount returns the number of bytes of data currently queued to be sent over this stream. 410 pub fn buffered_amount(&self) -> usize { 411 self.buffered_amount.load(Ordering::SeqCst) 412 } 413 414 /// buffered_amount_low_threshold returns the number of bytes of buffered outgoing data that is 415 /// considered "low." Defaults to 0. 416 pub fn buffered_amount_low_threshold(&self) -> usize { 417 self.buffered_amount_low.load(Ordering::SeqCst) 418 } 419 420 /// set_buffered_amount_low_threshold is used to update the threshold. 421 /// See buffered_amount_low_threshold(). 422 pub fn set_buffered_amount_low_threshold(&self, th: usize) { 423 self.buffered_amount_low.store(th, Ordering::SeqCst); 424 } 425 426 /// on_buffered_amount_low sets the callback handler which would be called when the number of 427 /// bytes of outgoing data buffered is lower than the threshold. 428 pub fn on_buffered_amount_low(&self, f: OnBufferedAmountLowFn) { 429 self.on_buffered_amount_low 430 .store(Some(Arc::new(Mutex::new(f)))); 431 } 432 433 /// This method is called by association's read_loop (go-)routine to notify this stream 434 /// of the specified amount of outgoing data has been delivered to the peer. 435 pub(crate) async fn on_buffer_released(&self, n_bytes_released: i64) { 436 if n_bytes_released <= 0 { 437 return; 438 } 439 440 let from_amount = self.buffered_amount.load(Ordering::SeqCst); 441 let new_amount = if from_amount < n_bytes_released as usize { 442 self.buffered_amount.store(0, Ordering::SeqCst); 443 log::error!( 444 "[{}] released buffer size {} should be <= {}", 445 self.name, 446 n_bytes_released, 447 0, 448 ); 449 0 450 } else { 451 self.buffered_amount 452 .fetch_sub(n_bytes_released as usize, Ordering::SeqCst); 453 454 from_amount - n_bytes_released as usize 455 }; 456 457 let buffered_amount_low = self.buffered_amount_low.load(Ordering::SeqCst); 458 459 log::trace!( 460 "[{}] bufferedAmount = {}, from_amount = {}, buffered_amount_low = {}", 461 self.name, 462 new_amount, 463 from_amount, 464 buffered_amount_low, 465 ); 466 467 if from_amount > buffered_amount_low && new_amount <= buffered_amount_low { 468 if let Some(handler) = &*self.on_buffered_amount_low.load() { 469 let mut f = handler.lock().await; 470 f().await; 471 } 472 } 473 } 474 475 /// get_num_bytes_in_reassembly_queue returns the number of bytes of data currently queued to 476 /// be read (once chunk is complete). 477 pub(crate) async fn get_num_bytes_in_reassembly_queue(&self) -> usize { 478 // No lock is required as it reads the size with atomic load function. 479 let reassembly_queue = self.reassembly_queue.lock().await; 480 reassembly_queue.get_num_bytes() 481 } 482 483 /// get_state atomically returns the state of the Association. 484 fn get_state(&self) -> AssociationState { 485 self.state.load(Ordering::SeqCst).into() 486 } 487 488 fn awake_write_loop(&self) { 489 //log::debug!("[{}] awake_write_loop_ch.notify_one", self.name); 490 if let Some(awake_write_loop_ch) = &self.awake_write_loop_ch { 491 let _ = awake_write_loop_ch.try_send(()); 492 } 493 } 494 495 async fn send_payload_data(&self, chunks: Vec<ChunkPayloadData>) -> Result<()> { 496 let state = self.get_state(); 497 if state != AssociationState::Established { 498 return Err(Error::ErrPayloadDataStateNotExist); 499 } 500 501 // NOTE: append is used here instead of push in order to prevent chunks interlacing. 502 self.pending_queue.append(chunks).await; 503 504 self.awake_write_loop(); 505 Ok(()) 506 } 507 508 async fn send_reset_request(&self, stream_identifier: u16) -> Result<()> { 509 let state = self.get_state(); 510 if state != AssociationState::Established { 511 return Err(Error::ErrResetPacketInStateNotExist); 512 } 513 514 // Create DATA chunk which only contains valid stream identifier with 515 // nil userData and use it as a EOS from the stream. 516 let c = ChunkPayloadData { 517 stream_identifier, 518 beginning_fragment: true, 519 ending_fragment: true, 520 user_data: Bytes::new(), 521 ..Default::default() 522 }; 523 524 self.pending_queue.push(c).await; 525 526 self.awake_write_loop(); 527 Ok(()) 528 } 529 } 530 531 /// Default capacity of the temporary read buffer used by [`PollStream`]. 532 const DEFAULT_READ_BUF_SIZE: usize = 8192; 533 534 /// State of the read `Future` in [`PollStream`]. 535 enum ReadFut { 536 /// Nothing in progress. 537 Idle, 538 /// Reading data from the underlying stream. 539 Reading(Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send>>), 540 /// Finished reading, but there's unread data in the temporary buffer. 541 RemainingData(Vec<u8>), 542 } 543 544 enum ShutdownFut { 545 /// Nothing in progress. 546 Idle, 547 /// Reading data from the underlying stream. 548 ShuttingDown(Pin<Box<dyn Future<Output = std::result::Result<(), crate::error::Error>>>>), 549 /// Shutdown future has run 550 Done, 551 Errored(crate::error::Error), 552 } 553 554 impl ReadFut { 555 /// Gets a mutable reference to the future stored inside `Reading(future)`. 556 /// 557 /// # Panics 558 /// 559 /// Panics if `ReadFut` variant is not `Reading`. 560 fn get_reading_mut(&mut self) -> &mut Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send>> { 561 match self { 562 ReadFut::Reading(ref mut fut) => fut, 563 _ => panic!("expected ReadFut to be Reading"), 564 } 565 } 566 } 567 568 impl ShutdownFut { 569 /// Gets a mutable reference to the future stored inside `ShuttingDown(future)`. 570 /// 571 /// # Panics 572 /// 573 /// Panics if `ShutdownFut` variant is not `ShuttingDown`. 574 fn get_shutting_down_mut( 575 &mut self, 576 ) -> &mut Pin<Box<dyn Future<Output = std::result::Result<(), crate::error::Error>>>> { 577 match self { 578 ShutdownFut::ShuttingDown(ref mut fut) => fut, 579 _ => panic!("expected ShutdownFut to be ShuttingDown"), 580 } 581 } 582 } 583 584 /// A wrapper around around [`Stream`], which implements [`AsyncRead`] and 585 /// [`AsyncWrite`]. 586 /// 587 /// Both `poll_read` and `poll_write` calls allocate temporary buffers, which results in an 588 /// additional overhead. 589 pub struct PollStream { 590 stream: Arc<Stream>, 591 592 read_fut: ReadFut, 593 write_fut: Option<Pin<Box<dyn Future<Output = Result<usize>>>>>, 594 shutdown_fut: ShutdownFut, 595 596 read_buf_cap: usize, 597 } 598 599 impl PollStream { 600 /// Constructs a new `PollStream`. 601 /// 602 /// # Examples 603 /// 604 /// ``` 605 /// use webrtc_sctp::stream::{Stream, PollStream}; 606 /// use std::sync::Arc; 607 /// 608 /// let stream = Arc::new(Stream::default()); 609 /// let poll_stream = PollStream::new(stream); 610 /// ``` 611 pub fn new(stream: Arc<Stream>) -> Self { 612 Self { 613 stream, 614 read_fut: ReadFut::Idle, 615 write_fut: None, 616 shutdown_fut: ShutdownFut::Idle, 617 read_buf_cap: DEFAULT_READ_BUF_SIZE, 618 } 619 } 620 621 /// Get back the inner stream. 622 #[must_use] 623 pub fn into_inner(self) -> Arc<Stream> { 624 self.stream 625 } 626 627 /// Obtain a clone of the inner stream. 628 #[must_use] 629 pub fn clone_inner(&self) -> Arc<Stream> { 630 self.stream.clone() 631 } 632 633 /// stream_identifier returns the Stream identifier associated to the stream. 634 pub fn stream_identifier(&self) -> u16 { 635 self.stream.stream_identifier 636 } 637 638 /// buffered_amount returns the number of bytes of data currently queued to be sent over this stream. 639 pub fn buffered_amount(&self) -> usize { 640 self.stream.buffered_amount.load(Ordering::SeqCst) 641 } 642 643 /// buffered_amount_low_threshold returns the number of bytes of buffered outgoing data that is 644 /// considered "low." Defaults to 0. 645 pub fn buffered_amount_low_threshold(&self) -> usize { 646 self.stream.buffered_amount_low.load(Ordering::SeqCst) 647 } 648 649 /// get_num_bytes_in_reassembly_queue returns the number of bytes of data currently queued to 650 /// be read (once chunk is complete). 651 pub(crate) async fn get_num_bytes_in_reassembly_queue(&self) -> usize { 652 // No lock is required as it reads the size with atomic load function. 653 let reassembly_queue = self.stream.reassembly_queue.lock().await; 654 reassembly_queue.get_num_bytes() 655 } 656 657 /// Set the capacity of the temporary read buffer (default: 8192). 658 pub fn set_read_buf_capacity(&mut self, capacity: usize) { 659 self.read_buf_cap = capacity 660 } 661 } 662 663 impl AsyncRead for PollStream { 664 fn poll_read( 665 mut self: Pin<&mut Self>, 666 cx: &mut Context<'_>, 667 buf: &mut ReadBuf<'_>, 668 ) -> Poll<io::Result<()>> { 669 if buf.remaining() == 0 { 670 return Poll::Ready(Ok(())); 671 } 672 673 let fut = match self.read_fut { 674 ReadFut::Idle => { 675 // read into a temporary buffer because `buf` has an unonymous lifetime, which can 676 // be shorter than the lifetime of `read_fut`. 677 let stream = self.stream.clone(); 678 let mut temp_buf = vec![0; self.read_buf_cap]; 679 self.read_fut = ReadFut::Reading(Box::pin(async move { 680 stream.read(temp_buf.as_mut_slice()).await.map(|n| { 681 temp_buf.truncate(n); 682 temp_buf 683 }) 684 })); 685 self.read_fut.get_reading_mut() 686 } 687 ReadFut::Reading(ref mut fut) => fut, 688 ReadFut::RemainingData(ref mut data) => { 689 let remaining = buf.remaining(); 690 let len = std::cmp::min(data.len(), remaining); 691 buf.put_slice(&data[..len]); 692 if data.len() > remaining { 693 // ReadFut remains to be RemainingData 694 data.drain(0..len); 695 } else { 696 self.read_fut = ReadFut::Idle; 697 } 698 return Poll::Ready(Ok(())); 699 } 700 }; 701 702 loop { 703 match fut.as_mut().poll(cx) { 704 Poll::Pending => return Poll::Pending, 705 // retry immediately upon empty data or incomplete chunks 706 // since there's no way to setup a waker. 707 Poll::Ready(Err(Error::ErrTryAgain)) => {} 708 // EOF has been reached => don't touch buf and just return Ok 709 Poll::Ready(Err(Error::ErrEof)) => { 710 self.read_fut = ReadFut::Idle; 711 return Poll::Ready(Ok(())); 712 } 713 Poll::Ready(Err(e)) => { 714 self.read_fut = ReadFut::Idle; 715 return Poll::Ready(Err(e.into())); 716 } 717 Poll::Ready(Ok(mut temp_buf)) => { 718 let remaining = buf.remaining(); 719 let len = std::cmp::min(temp_buf.len(), remaining); 720 buf.put_slice(&temp_buf[..len]); 721 if temp_buf.len() > remaining { 722 temp_buf.drain(0..len); 723 self.read_fut = ReadFut::RemainingData(temp_buf); 724 } else { 725 self.read_fut = ReadFut::Idle; 726 } 727 return Poll::Ready(Ok(())); 728 } 729 } 730 } 731 } 732 } 733 734 impl AsyncWrite for PollStream { 735 fn poll_write( 736 mut self: Pin<&mut Self>, 737 cx: &mut Context<'_>, 738 buf: &[u8], 739 ) -> Poll<io::Result<usize>> { 740 if buf.is_empty() { 741 return Poll::Ready(Ok(0)); 742 } 743 744 if let Some(fut) = self.write_fut.as_mut() { 745 match fut.as_mut().poll(cx) { 746 Poll::Pending => Poll::Pending, 747 Poll::Ready(Err(e)) => { 748 let stream = self.stream.clone(); 749 let bytes = Bytes::copy_from_slice(buf); 750 self.write_fut = Some(Box::pin(async move { stream.write(&bytes).await })); 751 Poll::Ready(Err(e.into())) 752 } 753 // Given the data is buffered, it's okay to ignore the number of written bytes. 754 // 755 // TODO: In the long term, `stream.write` should be made sync. Then we could 756 // remove the whole `if` condition and just call `stream.write`. 757 Poll::Ready(Ok(_)) => { 758 let stream = self.stream.clone(); 759 let bytes = Bytes::copy_from_slice(buf); 760 self.write_fut = Some(Box::pin(async move { stream.write(&bytes).await })); 761 Poll::Ready(Ok(buf.len())) 762 } 763 } 764 } else { 765 let stream = self.stream.clone(); 766 let bytes = Bytes::copy_from_slice(buf); 767 let fut = self 768 .write_fut 769 .insert(Box::pin(async move { stream.write(&bytes).await })); 770 771 match fut.as_mut().poll(cx) { 772 // If it's the first time we're polling the future, `Poll::Pending` can't be 773 // returned because that would mean the `PollStream` is not ready for writing. And 774 // this is not true since we've just created a future, which is going to write the 775 // buf to the underlying stream. 776 // 777 // It's okay to return `Poll::Ready` if the data is buffered (this is what the 778 // buffered writer and `File` do). 779 Poll::Pending => Poll::Ready(Ok(buf.len())), 780 Poll::Ready(Err(e)) => { 781 self.write_fut = None; 782 Poll::Ready(Err(e.into())) 783 } 784 Poll::Ready(Ok(n)) => { 785 self.write_fut = None; 786 Poll::Ready(Ok(n)) 787 } 788 } 789 } 790 } 791 792 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { 793 match self.write_fut.as_mut() { 794 Some(fut) => match fut.as_mut().poll(cx) { 795 Poll::Pending => Poll::Pending, 796 Poll::Ready(Err(e)) => { 797 self.write_fut = None; 798 Poll::Ready(Err(e.into())) 799 } 800 Poll::Ready(Ok(_)) => { 801 self.write_fut = None; 802 Poll::Ready(Ok(())) 803 } 804 }, 805 None => Poll::Ready(Ok(())), 806 } 807 } 808 809 fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { 810 match self.as_mut().poll_flush(cx) { 811 Poll::Pending => return Poll::Pending, 812 Poll::Ready(_) => {} 813 } 814 let fut = match self.shutdown_fut { 815 ShutdownFut::Done => return Poll::Ready(Ok(())), 816 ShutdownFut::Errored(ref err) => return Poll::Ready(Err(err.clone().into())), 817 ShutdownFut::ShuttingDown(ref mut fut) => fut, 818 ShutdownFut::Idle => { 819 let stream = self.stream.clone(); 820 self.shutdown_fut = ShutdownFut::ShuttingDown(Box::pin(async move { 821 stream.shutdown(Shutdown::Write).await 822 })); 823 self.shutdown_fut.get_shutting_down_mut() 824 } 825 }; 826 827 match fut.as_mut().poll(cx) { 828 Poll::Pending => Poll::Pending, 829 Poll::Ready(Err(e)) => { 830 self.shutdown_fut = ShutdownFut::Errored(e.clone()); 831 Poll::Ready(Err(e.into())) 832 } 833 Poll::Ready(Ok(_)) => { 834 self.shutdown_fut = ShutdownFut::Done; 835 Poll::Ready(Ok(())) 836 } 837 } 838 } 839 } 840 841 impl Clone for PollStream { 842 fn clone(&self) -> PollStream { 843 PollStream::new(self.clone_inner()) 844 } 845 } 846 847 impl fmt::Debug for PollStream { 848 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 849 f.debug_struct("PollStream") 850 .field("stream", &self.stream) 851 .field("read_buf_cap", &self.read_buf_cap) 852 .finish() 853 } 854 } 855 856 impl AsRef<Stream> for PollStream { 857 fn as_ref(&self) -> &Stream { 858 &self.stream 859 } 860 } 861