use buffet::IntoHalves;
use enumflags2::BitFlags;
use loona_h2::{ContinuationFlags, EncodedFrameType, FrameType, HeadersFlags, Setting, StreamId};
use crate::{dummy_bytes, Conn, ErrorC};
pub async fn idle_sends_data_frame<IO: IntoHalves>(mut conn: Conn<IO>) -> eyre::Result<()> {
conn.handshake().await?;
conn.write_data(StreamId(1), true, b"test").await?;
conn.verify_stream_error(ErrorC::ProtocolError | ErrorC::StreamClosed)
.await?;
Ok(())
}
pub async fn idle_sends_rst_stream_frame<IO: IntoHalves>(mut conn: Conn<IO>) -> eyre::Result<()> {
conn.handshake().await?;
conn.write_rst_stream(StreamId(1), ErrorC::Cancel).await?;
conn.verify_connection_error(ErrorC::ProtocolError).await?;
Ok(())
}
pub async fn idle_sends_window_update_frame<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
conn.handshake().await?;
conn.write_window_update(StreamId(1), 100).await?;
conn.verify_connection_error(ErrorC::ProtocolError).await?;
Ok(())
}
pub async fn idle_sends_continuation_frame<IO: IntoHalves>(mut conn: Conn<IO>) -> eyre::Result<()> {
conn.handshake().await?;
let block_fragment = conn.encode_headers(&conn.common_headers("POST"))?;
conn.write_continuation(StreamId(1), ContinuationFlags::EndHeaders, block_fragment)
.await?;
conn.verify_connection_error(ErrorC::ProtocolError).await?;
Ok(())
}
pub async fn half_closed_remote_sends_data_frame<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
conn.send_empty_post_to_root(stream_id).await?;
conn.write_data(stream_id, true, b"test").await?;
conn.verify_stream_error(ErrorC::StreamClosed).await?;
Ok(())
}
pub async fn half_closed_remote_sends_headers_frame<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
conn.send_empty_post_to_root(stream_id).await?;
conn.send_empty_post_to_root(stream_id).await?;
conn.verify_stream_error(ErrorC::StreamClosed).await?;
Ok(())
}
pub async fn half_closed_remote_sends_continuation_frame<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
conn.send_empty_post_to_root(stream_id).await?;
let headers = conn.common_headers("POST");
let block_fragment = conn.encode_headers(&headers)?;
conn.write_continuation(stream_id, ContinuationFlags::EndHeaders, block_fragment)
.await?;
conn.verify_stream_error(ErrorC::StreamClosed | ErrorC::ProtocolError)
.await?;
Ok(())
}
pub async fn closed_sends_data_frame_after_rst_stream<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
let headers = conn.common_headers("POST");
let block_fragment = conn.encode_headers(&headers)?;
conn.write_headers(stream_id, HeadersFlags::EndHeaders, block_fragment)
.await?;
conn.write_rst_stream(stream_id, ErrorC::Cancel).await?;
conn.write_data(stream_id, true, b"test").await?;
conn.verify_stream_error(ErrorC::StreamClosed).await?;
Ok(())
}
pub async fn closed_sends_headers_frame_after_rst_stream<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
let headers = conn.common_headers("POST");
let block_fragment = conn.encode_headers(&headers)?;
conn.write_headers(stream_id, HeadersFlags::EndHeaders, block_fragment.clone())
.await?;
conn.write_rst_stream(stream_id, ErrorC::Cancel).await?;
conn.send_empty_post_to_root(stream_id).await?;
conn.verify_stream_error(ErrorC::StreamClosed).await?;
Ok(())
}
pub async fn closed_sends_continuation_frame_after_rst_stream<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
let headers = conn.common_headers("POST");
let block_fragment = conn.encode_headers(&headers)?;
conn.write_headers(stream_id, HeadersFlags::EndHeaders, block_fragment)
.await?;
conn.write_rst_stream(stream_id, ErrorC::Cancel).await?;
let dummy_headers = conn.dummy_headers(1);
let continuation_fragment = conn.encode_headers(&dummy_headers)?;
conn.write_continuation(
stream_id,
ContinuationFlags::EndHeaders,
continuation_fragment,
)
.await?;
conn.verify_stream_error(ErrorC::StreamClosed | ErrorC::ProtocolError)
.await?;
Ok(())
}
pub async fn closed_sends_data_frame<IO: IntoHalves>(mut conn: Conn<IO>) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
conn.send_empty_post_to_root(stream_id).await?;
conn.verify_stream_close(stream_id).await?;
conn.write_data(stream_id, true, b"test").await?;
conn.verify_stream_error(ErrorC::StreamClosed).await?;
Ok(())
}
pub async fn closed_sends_headers_frame<IO: IntoHalves>(mut conn: Conn<IO>) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
conn.send_empty_post_to_root(stream_id).await?;
conn.verify_stream_close(stream_id).await?;
conn.send_empty_post_to_root(stream_id).await?;
conn.verify_connection_error(ErrorC::StreamClosed).await?;
Ok(())
}
pub async fn closed_sends_continuation_frame<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
conn.send_empty_post_to_root(stream_id).await?;
conn.verify_stream_close(stream_id).await?;
let continuation_fragment = conn.encode_headers(&conn.dummy_headers(1))?;
conn.write_continuation(
stream_id,
ContinuationFlags::EndHeaders,
continuation_fragment,
)
.await?;
conn.verify_connection_error(ErrorC::StreamClosed | ErrorC::ProtocolError)
.await?;
Ok(())
}
pub async fn sends_even_numbered_stream_identifier<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
conn.handshake().await?;
conn.send_empty_post_to_root(StreamId(2)).await?;
conn.verify_connection_error(ErrorC::ProtocolError).await?;
Ok(())
}
pub async fn sends_smaller_stream_identifier<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
conn.handshake().await?;
conn.send_empty_post_to_root(StreamId(5)).await?;
conn.send_empty_post_to_root(StreamId(3)).await?;
conn.verify_connection_error(ErrorC::ProtocolError).await?;
Ok(())
}
pub async fn exceeds_concurrent_stream_limit<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
conn.handshake().await?;
let max_streams = match conn.settings.max_concurrent_streams {
Some(value) => value,
None => return Ok(()), };
conn.write_settings(&[(Setting::InitialWindowSize, 0)])
.await?;
for i in 0..=max_streams {
conn.send_empty_post_to_root(StreamId(1 + i * 2)).await?;
}
conn.verify_stream_error(ErrorC::ProtocolError | ErrorC::RefusedStream)
.await?;
Ok(())
}
pub async fn invalid_ping_frame_for_connection_close<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
conn.handshake().await?;
conn.write_frame(
FrameType::Ping(BitFlags::default()).into_frame(StreamId(3)),
dummy_bytes(8),
)
.await?;
conn.verify_connection_close().await?;
Ok(())
}
pub async fn test_invalid_ping_frame_for_goaway<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
conn.handshake().await?;
conn.write_frame(
FrameType::Ping(BitFlags::default()).into_frame(StreamId(3)),
dummy_bytes(8),
)
.await?;
conn.verify_connection_error(ErrorC::ProtocolError).await?;
Ok(())
}
pub async fn unknown_extension_frame_in_header_block<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
let block_fragment = conn.encode_headers(&conn.common_headers("POST"))?;
conn.write_headers(stream_id, HeadersFlags::EndStream, block_fragment)
.await?;
conn.write_frame(
FrameType::Unknown(EncodedFrameType {
ty: 0xff,
flags: 0x0,
})
.into_frame(stream_id),
dummy_bytes(8),
)
.await?;
conn.verify_connection_error(ErrorC::ProtocolError).await?;
Ok(())
}