s2n_quic_core/stream/state/
send.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::state::{event, is};
5
6//= https://www.rfc-editor.org/rfc/rfc9000#section-3.1
7//#        o
8//#       | Create Stream (Sending)
9//#       | Peer Creates Bidirectional Stream
10//#       v
11//#   +-------+
12//#   | Ready | Send RESET_STREAM
13//#   |       |-----------------------.
14//#   +-------+                       |
15//#       |                           |
16//#       | Send STREAM /             |
17//#       |      STREAM_DATA_BLOCKED  |
18//#       v                           |
19//#   +-------+                       |
20//#   | Send  | Send RESET_STREAM     |
21//#   |       |---------------------->|
22//#   +-------+                       |
23//#       |                           |
24//#       | Send STREAM + FIN         |
25//#       v                           v
26//#   +-------+                   +-------+
27//#   | Data  | Send RESET_STREAM | Reset |
28//#   | Sent  |------------------>| Sent  |
29//#   +-------+                   +-------+
30//#       |                           |
31//#       | Recv All ACKs             | Recv ACK
32//#       v                           v
33//#   +-------+                   +-------+
34//#   | Data  |                   | Reset |
35//#   | Recvd |                   | Recvd |
36//#   +-------+                   +-------+
37
38#[derive(Clone, Debug, Default, PartialEq, Eq)]
39pub enum Sender {
40    #[default]
41    Ready,
42    Send,
43    DataSent,
44    DataRecvd,
45    /// An additional state for implementations to separate queueing a RESET_STREAM from actually
46    /// sending it
47    ResetQueued,
48    ResetSent,
49    ResetRecvd,
50}
51
52impl Sender {
53    is!(is_ready, Ready);
54    is!(is_sending, Send);
55    is!(is_data_sent, DataSent);
56    is!(is_data_received, DataRecvd);
57    is!(is_reset_queued, ResetQueued);
58    is!(is_reset_sent, ResetSent);
59    is!(is_reset_received, ResetRecvd);
60    is!(is_terminal, DataRecvd | ResetRecvd);
61
62    event! {
63        on_send_stream(Ready => Send);
64        // we can jump from Ready to DataSent even though the
65        // diagram doesn't explicitly highlight this transition
66        on_send_fin(Ready | Send => DataSent);
67        on_recv_all_acks(DataSent | ResetQueued => DataRecvd);
68
69        on_queue_reset(Ready | Send | DataSent => ResetQueued);
70        on_send_reset(Ready | Send | DataSent | ResetQueued => ResetSent);
71        on_recv_reset_ack(ResetSent => ResetRecvd);
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use insta::{assert_debug_snapshot, assert_snapshot};
79
80    #[test]
81    #[cfg_attr(miri, ignore)]
82    fn snapshots() {
83        assert_debug_snapshot!(Sender::test_transitions());
84    }
85
86    #[test]
87    #[cfg_attr(miri, ignore)]
88    fn dot_test() {
89        assert_snapshot!(Sender::dot());
90    }
91}