tokio_quiche/quic/io/
connection_stage.rs1use std::fmt::Debug;
28use std::ops::ControlFlow;
29use std::time::Instant;
30
31use tokio::sync::mpsc;
32
33use crate::quic::connection::ApplicationOverQuic;
34use crate::quic::connection::HandshakeError;
35use crate::quic::connection::HandshakeInfo;
36use crate::quic::connection::Incoming;
37use crate::quic::connection::QuicConnectionStatsShared;
38use crate::quic::QuicheConnection;
39use crate::QuicResult;
40
41pub trait ConnectionStage: Send + Debug {
54 fn on_read<A: ApplicationOverQuic>(
55 &mut self, _received_packets: bool, _qconn: &mut QuicheConnection,
56 _ctx: &mut ConnectionStageContext<A>,
57 ) -> QuicResult<()> {
58 Ok(())
59 }
60
61 fn on_flush<A: ApplicationOverQuic>(
62 &mut self, _qconn: &mut QuicheConnection,
63 _ctx: &mut ConnectionStageContext<A>,
64 ) -> ControlFlow<QuicResult<()>> {
65 ControlFlow::Continue(())
66 }
67
68 fn wait_deadline(&mut self) -> Option<Instant> {
69 None
70 }
71
72 fn post_wait(
73 &self, _qconn: &mut QuicheConnection,
74 ) -> ControlFlow<QuicResult<()>> {
75 ControlFlow::Continue(())
76 }
77}
78
79pub struct ConnectionStageContext<A> {
81 pub in_pkt: Option<Incoming>,
82 pub application: A,
83 pub incoming_pkt_receiver: mpsc::Receiver<Incoming>,
84 pub stats: QuicConnectionStatsShared,
85}
86
87#[derive(Debug)]
88pub struct Handshake {
89 pub handshake_info: HandshakeInfo,
90}
91
92impl Handshake {
93 fn check_handshake_timeout_expired(
94 &self, conn: &mut QuicheConnection,
95 ) -> QuicResult<()> {
96 if self.handshake_info.is_expired() {
97 let _ = conn.close(
98 false,
99 quiche::WireErrorCode::ApplicationError as u64,
100 &[],
101 );
102 return Err(HandshakeError::Timeout.into());
103 }
104
105 Ok(())
106 }
107}
108
109impl ConnectionStage for Handshake {
110 fn on_flush<A: ApplicationOverQuic>(
111 &mut self, qconn: &mut QuicheConnection,
112 _ctx: &mut ConnectionStageContext<A>,
113 ) -> ControlFlow<QuicResult<()>> {
114 if qconn.is_established() || qconn.is_in_early_data() {
117 ControlFlow::Break(Ok(()))
118 } else {
119 ControlFlow::Continue(())
120 }
121 }
122
123 fn wait_deadline(&mut self) -> Option<Instant> {
124 self.handshake_info.deadline()
125 }
126
127 fn post_wait(
128 &self, qconn: &mut QuicheConnection,
129 ) -> ControlFlow<QuicResult<()>> {
130 match self.check_handshake_timeout_expired(qconn) {
131 Ok(_) => ControlFlow::Continue(()),
132 Err(e) => ControlFlow::Break(Err(e)),
133 }
134 }
135}
136
137#[derive(Debug)]
138pub struct RunningApplication;
139
140impl ConnectionStage for RunningApplication {
141 fn on_read<A: ApplicationOverQuic>(
142 &mut self, received_packets: bool, qconn: &mut QuicheConnection,
143 ctx: &mut ConnectionStageContext<A>,
144 ) -> QuicResult<()> {
145 if ctx.application.should_act() {
146 if received_packets {
147 ctx.application.process_reads(qconn)?;
148 }
149
150 if qconn.is_established() {
151 ctx.application.process_writes(qconn)?;
152 }
153 }
154
155 Ok(())
156 }
157}
158
159#[derive(Debug)]
160pub struct Close {
161 pub work_loop_result: QuicResult<()>,
162}
163
164impl ConnectionStage for Close {}