// QUIC stream state machines (RFC 9000 §3). A stream has independent send and receive
// halves, each a small state machine. The sender moves Ready -> Send -> Data Sent ->
// Data Recvd as it writes and its data is acknowledged, or into Reset Sent -> Reset
// Recvd when it resets. The receiver moves Recv -> Size Known -> Data Recvd -> Data Read
// as data and the final size arrive and the application reads, or into Reset Recvd ->
// Reset Read on an incoming reset. These are the pure transitions the stream manager
// drives; an illegal transition raises.
///|
/// The send half's state (RFC 9000 §3.1).
pub(all) enum SendStreamState {
Ready
Send
DataSent
DataRecvd
ResetSent
ResetRecvd
} derive(Eq, Debug)
///|
/// A send-half event: writing a STREAM frame (with `fin` on the last), all sent data
/// being acknowledged, sending a RESET_STREAM, or that reset being acknowledged.
pub(all) enum SendStreamEvent {
Write(fin~ : Bool)
AllAcked
ResetStream
ResetAcked
} derive(Eq, Debug)
///|
/// An illegal stream-state transition.
pub suberror StreamStateError {
StreamStateError(String)
}
///|
/// The next send state for `event` in `state` (RFC 9000 §3.1). A stream may be reset
/// from any pre-terminal state; writing after a terminal or reset state is illegal.
pub fn send_stream_next(
state : SendStreamState,
event : SendStreamEvent,
) -> SendStreamState raise StreamStateError {
match (state, event) {
(Ready, Write(fin~)) | (Send, Write(fin~)) =>
if fin {
DataSent
} else {
Send
}
(DataSent, AllAcked) => DataRecvd
(Ready, ResetStream) | (Send, ResetStream) | (DataSent, ResetStream) =>
ResetSent
(ResetSent, ResetAcked) => ResetRecvd
_ => raise StreamStateError("illegal send-stream transition")
}
}
///|
/// The receive half's state (RFC 9000 §3.2).
pub(all) enum RecvStreamState {
Recv
SizeKnown
DataReceived
DataRead
ResetReceived
ResetRead
} derive(Eq, Debug)
///|
/// A receive-half event: a STREAM frame arriving (with `fin` fixing the final size), all
/// data up to the final size received, the application reading all data, a RESET_STREAM
/// arriving, or the application being notified of that reset.
pub(all) enum RecvStreamEvent {
Receive(fin~ : Bool)
AllReceived
AppRead
ReceiveReset
AppReadReset
} derive(Eq, Debug)
///|
/// The next receive state for `event` in `state` (RFC 9000 §3.2). A stream may be reset
/// from any pre-terminal state; the read events apply only once the data or reset has
/// fully arrived.
pub fn recv_stream_next(
state : RecvStreamState,
event : RecvStreamEvent,
) -> RecvStreamState raise StreamStateError {
match (state, event) {
(Recv, Receive(fin~)) => if fin { SizeKnown } else { Recv }
(SizeKnown, AllReceived) => DataReceived
(DataReceived, AppRead) => DataRead
(Recv, ReceiveReset)
| (SizeKnown, ReceiveReset)
| (DataReceived, ReceiveReset) => ResetReceived
(ResetReceived, AppReadReset) => ResetRead
_ => raise StreamStateError("illegal recv-stream transition")
}
}