use crate::{dummy_bytes, Conn, ErrorC};
use buffet::IntoHalves;
use enumflags2::BitFlags;
use loona_h2::{
ContinuationFlags, EncodedFrameType, Frame, FrameType, HeadersFlags, PrioritySpec, StreamId,
};
pub async fn sends_frame_with_unknown_type<IO: IntoHalves>(mut conn: Conn<IO>) -> eyre::Result<()> {
conn.handshake().await?;
conn.write_frame(
FrameType::Unknown(EncodedFrameType {
ty: 0xff,
flags: 0x0,
})
.into_frame(StreamId(0)),
dummy_bytes(8),
)
.await?;
conn.verify_connection_still_alive().await?;
Ok(())
}
pub async fn sends_frame_with_unused_flags<IO: IntoHalves>(mut conn: Conn<IO>) -> eyre::Result<()> {
conn.handshake().await?;
let data = b"sfunflgs";
conn.write_frame(
FrameType::Unknown(EncodedFrameType {
ty: 6, flags: 0b1110, })
.into_frame(StreamId::CONNECTION),
data,
)
.await?;
conn.verify_ping_frame_with_ack(data).await?;
Ok(())
}
pub async fn sends_frame_with_reserved_bit_set<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
conn.handshake().await?;
let data = b"sfresbit";
conn.write_frame(
Frame {
frame_type: FrameType::Ping(Default::default()),
reserved: 1,
..Default::default()
},
data,
)
.await?;
conn.verify_ping_frame_with_ack(data).await?;
Ok(())
}
pub async fn data_frame_with_max_length<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::EndHeaders, block_fragment)
.await?;
let data = dummy_bytes(conn.settings.max_frame_size as usize);
conn.write_data(stream_id, true, data).await?;
conn.verify_headers_frame(stream_id).await?;
Ok(())
}
pub async fn frame_exceeding_max_size<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::EndHeaders, block_fragment)
.await?;
_ = conn
.write_data(
stream_id,
true,
dummy_bytes(conn.settings.max_frame_size as usize + 1),
)
.await;
conn.verify_stream_error(ErrorC::FrameSizeError).await?;
Ok(())
}
pub async fn large_headers_frame_exceeding_max_size<IO: IntoHalves>(
mut conn: Conn<IO>,
) -> eyre::Result<()> {
let stream_id = StreamId(1);
conn.handshake().await?;
let mut headers = conn.common_headers("POST");
headers.extend(conn.dummy_headers(5));
let block_fragment = conn.encode_headers(&headers)?;
assert!(
block_fragment.len() > conn.settings.max_frame_size as usize,
"if this assertion fails the test is broken"
);
_ = conn
.write_headers(stream_id, HeadersFlags::EndHeaders, block_fragment)
.await;
conn.verify_connection_error(ErrorC::FrameSizeError).await?;
Ok(())
}
pub async fn invalid_header_block_fragment<IO: IntoHalves>(mut conn: Conn<IO>) -> eyre::Result<()> {
conn.handshake().await?;
conn.write_frame(
FrameType::Headers(HeadersFlags::EndStream | HeadersFlags::EndHeaders)
.into_frame(StreamId(1)),
b"\x40",
)
.await?;
conn.verify_connection_error(ErrorC::CompressionError)
.await?;
Ok(())
}
pub async fn priority_frame_while_sending_headers<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::EndHeaders, block_fragment)
.await?;
conn.write_priority(
stream_id,
PrioritySpec {
stream_dependency: StreamId(0),
exclusive: false,
weight: 255,
},
)
.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::ProtocolError).await?;
Ok(())
}
pub async fn headers_frame_to_another_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_1 = conn.encode_headers(&headers)?;
conn.write_headers(stream_id, BitFlags::default(), block_fragment_1)
.await?;
let block_fragment_2 = conn.encode_headers(&headers)?;
conn.write_headers(
StreamId(stream_id.0 + 2),
HeadersFlags::EndHeaders,
block_fragment_2,
)
.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_connection_error(ErrorC::ProtocolError).await?;
Ok(())
}