use std::task::{Context, Waker}; use std::time::Instant; use std::usize;
/// Tracks Stream related state /// /// # Reference counting /// /// There can be a number of outstanding handles to a single Stream. These are /// tracked using reference counting. The `ref_count` field represents the /// number of outstanding userspace handles that can reach this stream. /// /// It's important to note that when the stream is placed in an internal queue /// (such as an accept queue), this is **not** tracked by a reference count. /// Thus, `ref_count` can be zero and the stream still has to be kept around. #[derive(Debug)] pub(super) struct Stream { /// The h2 stream identifier pub id: StreamId,
/// Current state of the stream pub state: State,
/// Set to `true` when the stream is counted against the connection's max /// concurrent streams. pub is_counted: bool,
/// Number of outstanding handles pointing to this stream pub ref_count: usize,
// ===== Fields related to sending ===== /// Next node in the accept linked list pub next_pending_send: Option<store::Key>,
/// Set to true when the stream is pending accept pub is_pending_send: bool,
/// Send data flow control pub send_flow: FlowControl,
/// Amount of send capacity that has been requested, but not yet allocated. pub requested_send_capacity: WindowSize,
/// Amount of data buffered at the prioritization layer. /// TODO: Technically this could be greater than the window size... pub buffered_send_data: usize,
/// Returns true if stream is currently being held for some time because of /// a local reset. pubfn is_pending_reset_expiration(&self) -> bool { self.reset_at.is_some()
}
/// Returns true if frames for this stream are ready to be sent over the wire pubfn is_send_ready(&self) -> bool { // Why do we check pending_open? // // We allow users to call send_request() which schedules a stream to be pending_open // if there is no room according to the concurrency limit (max_send_streams), and we // also allow data to be buffered for send with send_data() if there is no capacity for // the stream to send the data, which attempts to place the stream in pending_send. // If the stream is not open, we don't want the stream to be scheduled for // execution (pending_send). Note that if the stream is in pending_open, it will be // pushed to pending_send when there is room for an open stream. // // In pending_push we track whether a PushPromise still needs to be sent // from a different stream before we can start sending frames on this one. // This is different from the "open" check because reserved streams don't count // toward the concurrency limit. // See https://httpwg.org/specs/rfc7540.html#rfc.section.5.1.2
!self.is_pending_open && !self.is_pending_push
}
/// Returns true if the stream is closed pubfn is_closed(&self) -> bool { // The state has fully transitioned to closed. self.state.is_closed() && // Because outbound frames transition the stream state before being // buffered, we have to ensure that all frames have been flushed. self.pending_send.is_empty() && // Sometimes large data frames are sent out in chunks. After a chunk // of the frame is sent, the remainder is pushed back onto the send // queue to be rescheduled. // // Checking for additional buffered data lets us catch this case. self.buffered_send_data == 0
}
/// Returns true if the stream is no longer in use pubfn is_released(&self) -> bool { // The stream is closed and fully flushed self.is_closed() && // There are no more outstanding references to the stream self.ref_count == 0 && // The stream is not in any queue
!self.is_pending_send && !self.is_pending_send_capacity &&
!self.is_pending_accept && !self.is_pending_window_update &&
!self.is_pending_open && self.reset_at.is_none()
}
/// Returns true when the consumer of the stream has dropped all handles /// (indicating no further interest in the stream) and the stream state is /// not actually closed. /// /// In this case, a reset should be sent. pubfn is_canceled_interest(&self) -> bool { self.ref_count == 0 && !self.state.is_closed()
}
/// Current available stream send capacity pubfn capacity(&self, max_buffer_size: usize) -> WindowSize { let available = self.send_flow.available().as_size() as usize; let buffered = self.buffered_send_data;
available.min(max_buffer_size).saturating_sub(buffered) as WindowSize
}
// TODO: proper error handling let _res = self.send_flow.send_data(len);
debug_assert!(_res.is_ok());
// Decrement the stream's buffered data counter
debug_assert!(self.buffered_send_data >= len as usize); self.buffered_send_data -= len as usize; self.requested_send_capacity -= len;
if prev_capacity < self.capacity(max_buffer_size) { self.notify_capacity();
}
}
/// If the capacity was limited because of the max_send_buffer_size, /// then consider waking the send task again... pubfn notify_capacity(&mutself) { self.send_capacity_inc = true;
tracing::trace!(" notifying task"); self.notify_send();
}
/// Returns `Err` when the decrement cannot be completed due to overflow. pubfn dec_content_length(&mutself, len: usize) -> Result<(), ()> { matchself.content_length {
ContentLength::Remaining(refmut rem) => match rem.checked_sub(len as u64) {
Some(val) => *rem = val,
None => return Err(()),
},
ContentLength::Head => { if len != 0 { return Err(());
}
}
_ => {}
}
fn set_queued(stream: &mut Stream, val: bool) { if val { // ensure that stream is not queued for being opened // if it's being put into queue for sending data
debug_assert!(!stream.is_pending_open);
}
stream.is_pending_send = val;
}
}
fn set_queued(stream: &mut Stream, val: bool) { if val { // ensure that stream is not queued for being sent // if it's being put into queue for opening the stream
debug_assert!(!stream.is_pending_send);
}
stream.is_pending_open = val;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.