h3/error/
connection_error_creators.rs1use std::task::Poll;
4
5use bytes::Buf;
6
7use crate::{
8 connection::ConnectionInner,
9 frame::FrameStreamError,
10 quic::{self, ConnectionErrorIncoming, StreamErrorIncoming},
11 shared_state::ConnectionState,
12};
13
14use super::{
15 codes::Code,
16 internal_error::{ErrorOrigin, InternalConnectionError},
17 ConnectionError, LocalError, StreamError,
18};
19
20impl<C, B> ConnectionInner<C, B>
22where
23 C: quic::Connection<B>,
24 B: Buf,
25{
26 pub fn handle_connection_error<T: Into<ErrorOrigin>>(&mut self, error: T) -> ConnectionError {
30 if let Some(ref error) = self.handled_connection_error {
31 return error.clone();
32 }
33
34 let err = self.set_conn_error(error.into());
35 let err = self.close_if_needed(err);
36 self.convert_to_connection_error(err)
38 }
39
40 fn close_if_needed(&mut self, error: ErrorOrigin) -> ErrorOrigin {
43 match error {
44 ErrorOrigin::Internal(ref internal_error) => {
45 self.close_connection(internal_error.code, internal_error.message.clone())
46 }
47 ErrorOrigin::Quic(ConnectionErrorIncoming::InternalError(ref reason)) => {
48 self.close_connection(Code::H3_INTERNAL_ERROR, reason.clone())
49 }
50
51 _ => (),
53 }
54 error
55 }
56
57 fn convert_to_connection_error(&mut self, error: ErrorOrigin) -> ConnectionError {
61 let error = convert_to_connection_error(error);
62 self.handled_connection_error = Some(error.clone());
63 error
64 }
65
66 pub fn poll_connection_error(
70 &mut self,
71 cx: &mut std::task::Context<'_>,
72 ) -> Poll<Result<(), ConnectionError>> {
73 if let Some(ref error) = self.handled_connection_error {
74 return Poll::Ready(Err(error.clone()));
75 };
76
77 if let Some(err) = self.get_conn_error() {
79 let err = self.close_if_needed(err);
80 return Poll::Ready(Err(self.convert_to_connection_error(err)));
82 }
83 self.waker().register(cx.waker());
84 Poll::Pending
85 }
86
87 pub fn close_connection(&mut self, code: Code, reason: String) -> () {
89 self.conn.close(code, reason.as_bytes())
90 }
91}
92
93fn convert_to_connection_error(error: ErrorOrigin) -> ConnectionError {
95 match error {
96 ErrorOrigin::Internal(internal_error) => ConnectionError::Local {
97 error: LocalError::Application {
98 code: internal_error.code,
99 reason: internal_error.message,
100 },
101 },
102 ErrorOrigin::Quic(ConnectionErrorIncoming::Timeout) => ConnectionError::Timeout,
103 ErrorOrigin::Quic(connection_error) => ConnectionError::Remote(connection_error),
104 }
105}
106
107pub trait CloseStream: ConnectionState {
109 fn handle_connection_error_on_stream(
111 &mut self,
112 internal_error: InternalConnectionError,
113 ) -> StreamError {
114 let err = self.set_conn_error_and_wake(internal_error);
115 StreamError::ConnectionError(convert_to_connection_error(err))
116 }
117
118 fn handle_quic_stream_error(&self, error: StreamErrorIncoming) -> StreamError {
120 match error {
121 StreamErrorIncoming::ConnectionErrorIncoming { connection_error } => {
122 let err = self.set_conn_error_and_wake(connection_error);
123 StreamError::ConnectionError(convert_to_connection_error(err))
124 }
125 StreamErrorIncoming::StreamTerminated { error_code } => StreamError::RemoteTerminate {
126 code: Code::from(error_code),
127 },
128 StreamErrorIncoming::Unknown(custom_quic_impl_error) => {
129 StreamError::Undefined(custom_quic_impl_error)
130 }
131 }
132 }
133
134 fn check_peer_connection_closing(&self) -> Option<StreamError> {
136 if self.is_closing() {
137 return Some(StreamError::RemoteClosing);
138 };
139 None
140 }
141}
142
143pub(crate) trait CloseRawQuicConnection<B: Buf>: quic::Connection<B> {
144 fn handle_quic_error_raw(&mut self, error: ConnectionErrorIncoming) -> ConnectionError {
146 match error {
147 ConnectionErrorIncoming::Timeout => ConnectionError::Timeout,
148 ConnectionErrorIncoming::InternalError(reason) => {
149 let local_error = LocalError::Application {
150 code: Code::H3_INTERNAL_ERROR,
151 reason: reason.to_string(),
152 };
153 self.close(Code::H3_INTERNAL_ERROR, reason.as_bytes());
154 let conn_error = ConnectionError::Local { error: local_error };
155 conn_error
156 }
157 _ => ConnectionError::Remote(error),
158 }
159 }
160
161 fn close_raw_connection_with_h3_error(
163 &mut self,
164 internal_error: InternalConnectionError,
165 ) -> ConnectionError {
166 let error = ConnectionError::Local {
167 error: internal_error.clone().into(),
168 };
169 self.close(internal_error.code, internal_error.message.as_bytes());
170 error
171 }
172}
173
174impl<T, B> CloseRawQuicConnection<B> for T
175where
176 T: quic::Connection<B>,
177 B: Buf,
178{
179}
180
181pub(crate) trait HandleFrameStreamErrorOnRequestStream {
182 fn handle_frame_stream_error_on_request_stream(
183 &mut self,
184 error: FrameStreamError,
185 ) -> StreamError;
186}
187
188impl<T> HandleFrameStreamErrorOnRequestStream for T
189where
190 T: CloseStream,
191{
192 fn handle_frame_stream_error_on_request_stream(
193 &mut self,
194 error: FrameStreamError,
195 ) -> StreamError {
196 match error {
197 FrameStreamError::Quic(error) => self.handle_quic_stream_error(error),
198 FrameStreamError::Proto(frame_error) => self.handle_connection_error_on_stream(
199 InternalConnectionError::got_frame_error(frame_error).into(),
200 ),
201 FrameStreamError::UnexpectedEnd => {
202 self.handle_connection_error_on_stream(InternalConnectionError::new(
203 Code::H3_FRAME_ERROR,
204 "received incomplete frame".to_string(),
205 ))
206 }
207 }
208 }
209}