use core::ptr::NonNull;
use core::sync::atomic::Ordering;
use bun_core::Error;
use bun_picohttp as picohttp;
use super::client_session::ClientSession;
use crate::HTTPClient;
pub struct Stream {
pub id: u32,
pub session: *mut ClientSession,
pub client: Option<NonNull<HTTPClient<'static>>>,
pub header_block: Vec<u8>,
pub body_buffer: Vec<u8>,
pub decoded_bytes: Vec<u8>,
pub decoded_headers: Vec<picohttp::Header>,
pub status_code: u32,
pub state: State,
pub rst_done: bool,
pub headers_ready: bool,
pub headers_end_stream: bool,
pub awaiting_continue: bool,
pub fatal_error: Option<Error>,
pub unacked_bytes: u32,
pub data_bytes_received: u64,
pub send_window: i32,
pub pending_body: bun_ptr::RawSlice<u8>,
}
impl Stream {
#[inline]
pub fn client_mut(&mut self) -> Option<&mut HTTPClient<'static>> {
self.client.map(super::client_session::stream_client_mut)
}
#[inline]
pub fn client_ref(&self) -> Option<&HTTPClient<'static>> {
self.client
.map(|c| &*super::client_session::stream_client_mut(c))
}
}
#[repr(u8)] #[derive(Copy, Clone, PartialEq, Eq)]
pub enum State {
Open,
HalfClosedLocal,
HalfClosedRemote,
Closed,
}
impl Drop for Stream {
fn drop(&mut self) {
let _ = super::LIVE_STREAMS.fetch_sub(1, Ordering::Relaxed);
}
}
impl Stream {
pub fn new(
id: u32,
session: *mut ClientSession,
client: Option<NonNull<HTTPClient<'static>>>,
send_window: i32,
) -> Box<Self> {
Box::new(Self {
id,
session,
client,
header_block: Vec::new(),
body_buffer: Vec::new(),
decoded_bytes: Vec::new(),
decoded_headers: Vec::new(),
status_code: 0,
state: State::Open,
rst_done: false,
headers_ready: false,
headers_end_stream: false,
awaiting_continue: false,
fatal_error: None,
unacked_bytes: 0,
data_bytes_received: 0,
send_window,
pending_body: bun_ptr::RawSlice::EMPTY,
})
}
pub fn sent_end_stream(&mut self) {
self.state = match self.state {
State::Open => State::HalfClosedLocal,
State::HalfClosedRemote => State::Closed,
other => other,
};
}
pub fn recv_end_stream(&mut self) {
self.state = match self.state {
State::Open => State::HalfClosedRemote,
State::HalfClosedLocal => State::Closed,
other => other,
};
}
#[inline]
pub fn local_closed(&self) -> bool {
self.state == State::HalfClosedLocal || self.state == State::Closed
}
#[inline]
pub fn remote_closed(&self) -> bool {
self.state == State::HalfClosedRemote || self.state == State::Closed
}
}