use super::*;
impl From<usize> for &'static Stream {
#[inline(always)]
fn from(address: usize) -> &'static Stream {
unsafe { &*(address as *const Stream) }
}
}
impl<'a> From<usize> for &'a mut Stream {
#[inline(always)]
fn from(address: usize) -> &'a mut Stream {
unsafe { &mut *(address as *mut Stream) }
}
}
impl From<&Stream> for usize {
#[inline(always)]
fn from(stream: &Stream) -> Self {
stream as *const Stream as usize
}
}
impl From<&mut Stream> for usize {
#[inline(always)]
fn from(stream: &mut Stream) -> Self {
stream as *mut Stream as usize
}
}
impl AsRef<Stream> for Stream {
#[inline(always)]
fn as_ref(&self) -> &Self {
let address: usize = self.into();
address.into()
}
}
impl AsMut<Stream> for Stream {
#[inline(always)]
fn as_mut(&mut self) -> &mut Self {
let address: usize = self.into();
address.into()
}
}
impl Lifetime for Stream {
#[inline(always)]
unsafe fn leak(&self) -> &'static Self {
let address: usize = self.into();
address.into()
}
#[inline(always)]
unsafe fn leak_mut(&self) -> &'static mut Self {
let address: usize = self.into();
address.into()
}
}
impl Transport for TcpStream {
fn peer_addr(&self) -> Result<SocketAddr, io::Error> {
TcpStream::peer_addr(self)
}
fn local_addr(&self) -> Result<SocketAddr, io::Error> {
TcpStream::local_addr(self)
}
}
impl Drop for PooledReader<'_> {
fn drop(&mut self) {
let buffer: Vec<u8> = mem::take(self.get_mut_buffer());
return_read_buffer(buffer);
}
}
impl AsyncRead for PooledReader<'_> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
let this: &mut Self = self.get_mut();
if this.get_start() < this.get_end() {
let available: usize = this.get_end() - this.get_start();
let amount: usize = available.min(buf.remaining());
let end: usize = this.get_start() + amount;
buf.put_slice(&this.get_buffer()[this.get_start()..end]);
this.set_start(end);
return Poll::Ready(Ok(()));
}
Pin::new(&mut **this.get_mut_stream()).poll_read(cx, buf)
}
}
impl AsyncBufRead for PooledReader<'_> {
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
let this: &mut Self = self.get_mut();
let PooledReader {
stream,
buffer,
start,
end,
} = this;
if *start >= *end {
*start = 0;
*end = 0;
let mut read_buf: ReadBuf<'_> = ReadBuf::new(buffer);
match Pin::new(&mut **stream).poll_read(cx, &mut read_buf) {
Poll::Ready(Ok(())) => {
*end = read_buf.filled().len();
}
Poll::Ready(Err(error)) => return Poll::Ready(Err(error)),
Poll::Pending => return Poll::Pending,
}
}
Poll::Ready(Ok(&buffer[*start..*end]))
}
fn consume(self: Pin<&mut Self>, amount: usize) {
let this: &mut Self = self.get_mut();
let new_start: usize = (this.get_start() + amount).min(this.get_end());
this.set_start(new_start);
}
}
impl Stream {
pub fn from_transport<T>(transport: T, request_config: RequestConfig, closed: bool) -> Self
where
T: Transport + 'static,
{
Self {
stream: Box::new(transport),
request_config,
closed,
leftover: Vec::new(),
leftover_start: 0,
leftover_end: 0,
line_buffer: String::with_capacity(REQUEST_LINE_BUFFER_CAPACITY),
header_line_buffer: String::with_capacity(HEADER_LINE_BUFFER_CAPACITY),
}
}
pub fn new(stream: TcpStream, request_config: RequestConfig, closed: bool) -> Self {
Self::from_transport(stream, request_config, closed)
}
#[inline(always)]
pub fn get_peer_addr(&self) -> Result<SocketAddr, io::Error> {
self.get_stream().peer_addr()
}
#[inline(always)]
pub fn get_local_addr(&self) -> Result<SocketAddr, io::Error> {
self.get_stream().local_addr()
}
#[inline(always)]
pub fn is_keep_alive(&self, keep_alive: bool) -> bool {
!self.get_closed() && keep_alive
}
async fn fill_http_from_stream(&mut self, request: &mut Request) -> Result<(), RequestError> {
request.reset();
let config: RequestConfig = *self.get_request_config();
let buffer_size: usize = config.get_buffer_size();
let max_path_size: usize = config.get_max_path_size();
let seeded: Vec<u8> = {
let start: usize = self.get_leftover_start();
let end: usize = self.get_leftover_end();
let mut pending: Vec<u8> = Vec::new();
if start < end {
let leftover: Vec<u8> = mem::take(self.get_mut_leftover());
let take: usize = (end - start).min(leftover.len());
pending.extend_from_slice(&leftover[start..start + take]);
}
self.set_leftover(Vec::new());
self.set_leftover_start(0);
self.set_leftover_end(0);
pending
};
let buffer: Vec<u8> = take_read_buffer(buffer_size);
let Stream {
stream,
line_buffer,
header_line_buffer,
..
} = self;
let mut reader: PooledReader<'_> = PooledReader::new(stream, buffer);
if !seeded.is_empty() {
let target: &mut Vec<u8> = reader.get_mut_buffer();
let copy_len: usize = seeded.len().min(target.len());
target[..copy_len].copy_from_slice(&seeded[..copy_len]);
reader.set_end(copy_len);
}
line_buffer.clear();
AsyncBufReadExt::read_line(&mut reader, line_buffer).await?;
let (method, path, version): (RequestMethod, &str, RequestVersion) =
Request::get_http_first_line(line_buffer)?;
Request::check_http_path_size(path, max_path_size)?;
let hash_index: Option<usize> = path.find(HASH);
let query_index: Option<usize> = path.find(QUERY);
let query: &str = Request::get_http_query(path, query_index, hash_index);
Request::fill_http_querys(query, request.get_mut_querys());
let path_slice: &str = Request::get_http_path(path, query_index, hash_index);
request.get_mut_path().push_str(path_slice);
let content_size: usize = request
.get_http_headers(&mut reader, &config, header_line_buffer)
.await?;
request.set_method(method);
request.set_version(version);
Request::fill_http_body(&mut reader, request.get_mut_body(), content_size).await?;
let reader_start: usize = reader.get_start();
let reader_end: usize = reader.get_end();
let pending: Vec<u8> = if reader_start < reader_end {
reader.get_buffer()[reader_start..reader_end].to_vec()
} else {
Vec::new()
};
drop(reader);
let pending_len: usize = pending.len();
self.set_leftover(pending);
self.set_leftover_start(0);
self.set_leftover_end(pending_len);
Ok(())
}
pub async fn try_fill_http_request(
&mut self,
request: &mut Request,
) -> Result<(), RequestError> {
if self.get_closed() {
return Err(RequestError::ServerClosedConnection(HttpStatus::BadRequest));
}
let timeout_ms: u64 = self.get_request_config().get_read_timeout_ms();
if timeout_ms == DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS {
return self.fill_http_from_stream(request).await;
}
let duration: Duration = Duration::from_millis(timeout_ms);
let mut reading: Pin<&mut _> = pin!(self.fill_http_from_stream(request));
if let Some(result) = poll_once(reading.as_mut()).await {
return result;
}
timeout(duration, reading).await?
}
pub async fn try_get_http_request(&mut self) -> Result<Request, RequestError> {
let mut request: Request = Request::default();
self.try_fill_http_request(&mut request).await?;
Ok(request)
}
pub async fn try_get_websocket_request(&mut self) -> Result<RequestBody, RequestError> {
if self.get_closed() {
return Err(RequestError::ServerClosedConnection(HttpStatus::BadRequest));
}
let config: RequestConfig = *self.get_request_config();
let buffer_size: usize = config.get_buffer_size();
let read_timeout_ms: u64 = config.get_read_timeout_ms();
let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
let mut full_frame: Vec<u8> = Vec::new();
let mut is_client_response: bool = false;
let duration_opt: Option<Duration> =
if read_timeout_ms == DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS {
None
} else {
let adjusted_timeout_ms: u64 = (read_timeout_ms >> 1) + (read_timeout_ms & 1);
Some(Duration::from_millis(adjusted_timeout_ms))
};
loop {
let len: usize = match self
.get_websocket_from_stream(&mut temp_buffer, duration_opt, &mut is_client_response)
.await
{
Ok(Some(len)) => len,
Ok(None) => continue,
Err(error) => return Err(error),
};
if len == 0 {
return Err(RequestError::IncompleteWebSocketFrame(
HttpStatus::BadRequest,
));
}
dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
is_client_response = true;
dynamic_buffer.drain(0..consumed);
match frame.get_opcode() {
WebSocketOpcode::Close => {
return Err(RequestError::ClientClosedConnection(HttpStatus::BadRequest));
}
WebSocketOpcode::Ping | WebSocketOpcode::Pong => continue,
WebSocketOpcode::Text | WebSocketOpcode::Binary => {
match frame.build_full_frame(&mut full_frame) {
Ok(Some(result)) => return Ok(result),
Ok(None) => continue,
Err(error) => return Err(error),
}
}
_ => {
return Err(RequestError::WebSocketOpcodeUnsupported(
HttpStatus::NotImplemented,
));
}
}
}
}
}
pub(crate) async fn get_websocket_from_stream(
&mut self,
buffer: &mut [u8],
duration_opt: Option<Duration>,
is_client_response: &mut bool,
) -> Result<Option<usize>, RequestError> {
let stream: &mut Box<dyn Transport> = self.get_mut_stream();
if let Some(duration) = duration_opt {
return match timeout(duration, stream.read(buffer)).await {
Ok(result) => match result {
Ok(len) => Ok(Some(len)),
Err(error) => Err(error.into()),
},
Err(error) => {
if !*is_client_response {
return Err(error.into());
}
*is_client_response = false;
self.try_send(&PING_FRAME).await?;
Ok(None)
}
};
}
match stream.read(buffer).await {
Ok(len) => Ok(Some(len)),
Err(error) => Err(error.into()),
}
}
pub async fn try_send<D>(&mut self, data: D) -> Result<(), ResponseError>
where
D: AsRef<[u8]>,
{
if self.get_closed() {
return Err(ResponseError::ConnectionClosed);
}
Ok(self.get_mut_stream().write_all(data.as_ref()).await?)
}
pub async fn send<D>(&mut self, data: D)
where
D: AsRef<[u8]>,
{
self.try_send(data).await.unwrap();
}
pub async fn try_send_list<I, D>(&mut self, data_iter: I) -> Result<(), ResponseError>
where
I: IntoIterator<Item = D>,
D: AsRef<[u8]>,
{
if self.get_closed() {
return Err(ResponseError::ConnectionClosed);
}
let stream: &mut Box<dyn Transport> = self.get_mut_stream();
for data in data_iter {
stream.write_all(data.as_ref()).await?;
}
Ok(())
}
pub async fn send_list<I, D>(&mut self, data_iter: I)
where
I: IntoIterator<Item = D>,
D: AsRef<[u8]>,
{
self.try_send_list(data_iter).await.unwrap();
}
pub async fn try_flush(&mut self) -> Result<(), ResponseError> {
if self.get_closed() {
return Err(ResponseError::ConnectionClosed);
}
Ok(self.get_mut_stream().flush().await?)
}
pub async fn flush(&mut self) {
self.try_flush().await.unwrap();
}
}