1use inquire::error::InquireResult;
29use inquire::validator::Validation;
30use inquire::CustomUserError;
31use inquire::Select;
32use inquire::Text;
33use qlog::events::quic::ErrorSpace;
34
35use crate::prompts::h3;
36
37use super::SuggestionResult;
38
39pub const NO_ERROR: &str = "NO_ERROR";
40pub const INTERNAL_ERROR: &str = "INTERNAL_ERROR";
41pub const CONNECTION_REFUSED: &str = "CONNECTION_REFUSED";
42pub const FLOW_CONTROL_ERROR: &str = "FLOW_CONTROL_ERROR";
43pub const STREAM_LIMIT_ERROR: &str = "STREAM_LIMIT_ERROR";
44pub const STREAM_STATE_ERROR: &str = "STREAM_STATE_ERROR";
45pub const FINAL_SIZE_ERROR: &str = "FINAL_SIZE_ERROR";
46pub const FRAME_ENCODING_ERROR: &str = "FRAME_ENCODING_ERROR";
47pub const TRANSPORT_PARAMETER_ERROR: &str = "TRANSPORT_PARAMETER_ERROR";
48pub const CONNECTION_ID_LIMIT_ERROR: &str = "CONNECTION_ID_LIMIT_ERROR";
49pub const PROTOCOL_VIOLATION: &str = "PROTOCOL_VIOLATION";
50pub const INVALID_TOKEN: &str = "INVALID_TOKEN";
51pub const APPLICATION_ERROR: &str = "APPLICATION_ERROR";
52pub const CRYPTO_BUFFER_EXCEEDED: &str = "CRYPTO_BUFFER_EXCEEDED";
53pub const KEY_UPDATE_ERROR: &str = "KEY_UPDATE_ERROR";
54pub const AEAD_LIMIT_REACHED: &str = "AEAD_LIMIT_REACHED";
55pub const NO_VIABLE_PATH: &str = "NO_VIABLE_PATH";
56pub const VERSION_NEGOTIATION_ERROR: &str = "VERSION_NEGOTIATION_ERROR";
57
58pub const H3_DATAGRAM_ERROR: &str = "H3_DATAGRAM_ERROR";
59pub const H3_NO_ERROR: &str = "H3_NO_ERROR";
60pub const H3_GENERAL_PROTOCOL_ERROR: &str = "H3_GENERAL_PROTOCOL_ERROR";
61pub const H3_INTERNAL_ERROR: &str = "H3_INTERNAL_ERROR";
62pub const H3_STREAM_CREATION_ERROR: &str = "H3_STREAM_CREATION_ERROR";
63pub const H3_CLOSED_CRITICAL_STREAM: &str = "H3_CLOSED_CRITICAL_STREAM";
64pub const H3_FRAME_UNEXPECTED: &str = "H3_FRAME_UNEXPECTED";
65pub const H3_FRAME_ERROR: &str = "H3_FRAME_ERROR";
66pub const H3_EXCESSIVE_LOAD: &str = "H3_EXCESSIVE_LOAD";
67pub const H3_ID_ERROR: &str = "H3_ID_ERROR";
68pub const H3_SETTINGS_ERROR: &str = "H3_SETTINGS_ERROR";
69pub const H3_MISSING_SETTINGS: &str = "H3_MISSING_SETTINGS";
70pub const H3_REQUEST_REJECTED: &str = "H3_REQUEST_REJECTED";
71pub const H3_REQUEST_CANCELLED: &str = "H3_REQUEST_CANCELLED";
72pub const H3_REQUEST_INCOMPLETE: &str = "H3_REQUEST_INCOMPLETE";
73pub const H3_MESSAGE_ERROR: &str = "H3_MESSAGE_ERROR";
74pub const H3_CONNECT_ERROR: &str = "H3_CONNECT_ERROR";
75pub const H3_VERSION_FALLBACK: &str = "H3_VERSION_FALLBACK";
76pub const QPACK_DECOMPRESSION_FAILED: &str = "QPACK_DECOMPRESSION_FAILED";
77pub const QPACK_ENCODER_STREAM_ERROR: &str = "QPACK_ENCODER_STREAM_ERROR";
78pub const QPACK_DECODER_STREAM_ERROR: &str = "QPACK_DECODER_STREAM_ERROR";
79
80pub const TRANSPORT: &str = "transport";
81pub const APPLICATION: &str = "application";
82
83pub fn prompt_transport_or_app_error() -> InquireResult<(ErrorSpace, u64)> {
85 let trans_or_app = prompt_transport_or_app()?;
86 let space = if trans_or_app == TRANSPORT {
87 ErrorSpace::TransportError
88 } else {
89 ErrorSpace::ApplicationError
90 };
91
92 let error_code = if matches!(space, ErrorSpace::TransportError) {
93 let error_code = Text::new("error code:")
94 .with_validator(validate_transport_error_code)
95 .with_autocomplete(&transport_error_code_suggestor)
96 .with_page_size(18)
97 .prompt()?;
98
99 match error_code.as_str() {
100 NO_ERROR => 0x0,
101 INTERNAL_ERROR => 0x1,
102 CONNECTION_REFUSED => 0x2,
103 FLOW_CONTROL_ERROR => 0x3,
104 STREAM_LIMIT_ERROR => 0x4,
105 STREAM_STATE_ERROR => 0x5,
106 FINAL_SIZE_ERROR => 0x6,
107 FRAME_ENCODING_ERROR => 0x7,
108 TRANSPORT_PARAMETER_ERROR => 0x8,
109 CONNECTION_ID_LIMIT_ERROR => 0x9,
110 PROTOCOL_VIOLATION => 0x0a,
111 INVALID_TOKEN => 0x0b,
112 APPLICATION_ERROR => 0x0c,
113 CRYPTO_BUFFER_EXCEEDED => 0x0d,
114 KEY_UPDATE_ERROR => 0x0e,
115 AEAD_LIMIT_REACHED => 0x0f,
116 NO_VIABLE_PATH => 0x10,
117 VERSION_NEGOTIATION_ERROR => 0x11,
118
119 v => v.parse::<u64>().unwrap(),
120 }
121 } else {
122 let error_code = Text::new("error code:")
123 .with_validator(validate_h3_error_code)
124 .with_autocomplete(&h3_error_code_suggestor)
125 .with_page_size(22)
126 .prompt()?;
127
128 match error_code.as_str() {
129 H3_DATAGRAM_ERROR => 0x33,
130 H3_NO_ERROR => 0x100,
131 H3_GENERAL_PROTOCOL_ERROR => 0x101,
132 H3_INTERNAL_ERROR => 0x102,
133 H3_STREAM_CREATION_ERROR => 0x103,
134 H3_CLOSED_CRITICAL_STREAM => 0x104,
135 H3_FRAME_UNEXPECTED => 0x105,
136 H3_FRAME_ERROR => 0x106,
137 H3_EXCESSIVE_LOAD => 0x107,
138 H3_ID_ERROR => 0x108,
139 H3_SETTINGS_ERROR => 0x109,
140 H3_MISSING_SETTINGS => 0x10a,
141 H3_REQUEST_REJECTED => 0x10b,
142 H3_REQUEST_CANCELLED => 0x10c,
143 H3_REQUEST_INCOMPLETE => 0x10d,
144 H3_MESSAGE_ERROR => 0x10e,
145 H3_CONNECT_ERROR => 0x10f,
146 H3_VERSION_FALLBACK => 0x110,
147 QPACK_DECOMPRESSION_FAILED => 0x200,
148 QPACK_ENCODER_STREAM_ERROR => 0x201,
149 QPACK_DECODER_STREAM_ERROR => 0x202,
150
151 v => v.parse::<u64>().unwrap(),
152 }
153 };
154
155 Ok((space, error_code))
156}
157
158fn prompt_transport_or_app() -> InquireResult<String> {
159 Ok(
160 Select::new("transport or application:", vec![TRANSPORT, APPLICATION])
161 .prompt()?
162 .to_string(),
163 )
164}
165
166fn validate_transport_error_code(
167 id: &str,
168) -> Result<Validation, CustomUserError> {
169 if matches!(
170 id,
171 NO_ERROR |
172 INTERNAL_ERROR |
173 CONNECTION_REFUSED |
174 FLOW_CONTROL_ERROR |
175 STREAM_LIMIT_ERROR |
176 STREAM_STATE_ERROR |
177 FINAL_SIZE_ERROR |
178 FRAME_ENCODING_ERROR |
179 TRANSPORT_PARAMETER_ERROR |
180 CONNECTION_ID_LIMIT_ERROR |
181 PROTOCOL_VIOLATION |
182 INVALID_TOKEN |
183 APPLICATION_ERROR |
184 CRYPTO_BUFFER_EXCEEDED |
185 KEY_UPDATE_ERROR |
186 AEAD_LIMIT_REACHED |
187 NO_VIABLE_PATH |
188 VERSION_NEGOTIATION_ERROR
189 ) {
190 return Ok(Validation::Valid);
191 }
192
193 h3::validate_varint(id)
194}
195
196fn transport_error_code_suggestor(
197 val: &str,
198) -> Result<Vec<String>, CustomUserError> {
199 let suggestions = [
200 NO_ERROR,
201 INTERNAL_ERROR,
202 CONNECTION_REFUSED,
203 FLOW_CONTROL_ERROR,
204 STREAM_LIMIT_ERROR,
205 STREAM_STATE_ERROR,
206 FINAL_SIZE_ERROR,
207 FRAME_ENCODING_ERROR,
208 TRANSPORT_PARAMETER_ERROR,
209 CONNECTION_ID_LIMIT_ERROR,
210 PROTOCOL_VIOLATION,
211 INVALID_TOKEN,
212 APPLICATION_ERROR,
213 CRYPTO_BUFFER_EXCEEDED,
214 KEY_UPDATE_ERROR,
215 AEAD_LIMIT_REACHED,
216 NO_VIABLE_PATH,
217 VERSION_NEGOTIATION_ERROR,
218 ];
219
220 super::squish_suggester(&suggestions, val)
221}
222
223fn validate_h3_error_code(id: &str) -> SuggestionResult<Validation> {
224 if matches!(
225 id,
226 H3_NO_ERROR |
227 H3_GENERAL_PROTOCOL_ERROR |
228 H3_INTERNAL_ERROR |
229 H3_STREAM_CREATION_ERROR |
230 H3_CLOSED_CRITICAL_STREAM |
231 H3_FRAME_UNEXPECTED |
232 H3_FRAME_ERROR |
233 H3_EXCESSIVE_LOAD |
234 H3_ID_ERROR |
235 H3_SETTINGS_ERROR |
236 H3_MISSING_SETTINGS |
237 H3_REQUEST_REJECTED |
238 H3_REQUEST_CANCELLED |
239 H3_REQUEST_INCOMPLETE |
240 H3_MESSAGE_ERROR |
241 H3_CONNECT_ERROR |
242 H3_VERSION_FALLBACK |
243 QPACK_DECOMPRESSION_FAILED |
244 QPACK_ENCODER_STREAM_ERROR |
245 QPACK_DECODER_STREAM_ERROR |
246 H3_DATAGRAM_ERROR
247 ) {
248 return Ok(Validation::Valid);
249 }
250
251 h3::validate_varint(id)
252}
253
254fn h3_error_code_suggestor(val: &str) -> SuggestionResult<Vec<String>> {
255 let suggestions = [
256 H3_NO_ERROR,
257 H3_GENERAL_PROTOCOL_ERROR,
258 H3_INTERNAL_ERROR,
259 H3_STREAM_CREATION_ERROR,
260 H3_CLOSED_CRITICAL_STREAM,
261 H3_FRAME_UNEXPECTED,
262 H3_FRAME_ERROR,
263 H3_EXCESSIVE_LOAD,
264 H3_ID_ERROR,
265 H3_SETTINGS_ERROR,
266 H3_MISSING_SETTINGS,
267 H3_REQUEST_REJECTED,
268 H3_REQUEST_CANCELLED,
269 H3_REQUEST_INCOMPLETE,
270 H3_MESSAGE_ERROR,
271 H3_CONNECT_ERROR,
272 H3_VERSION_FALLBACK,
273 QPACK_DECOMPRESSION_FAILED,
274 QPACK_ENCODER_STREAM_ERROR,
275 QPACK_DECODER_STREAM_ERROR,
276 H3_DATAGRAM_ERROR,
277 ];
278
279 super::squish_suggester(&suggestions, val)
280}