1use std::{hash::Hash, net::SocketAddr, num::ParseIntError, time::Duration};
5
6use serde::{Deserialize, Serialize};
7use unix_time::Instant as UnixInstant;
8
9pub type PluginInputType = u32;
10pub type PluginOutputType = i64;
11pub type WASMPtr = u32;
12pub type WASMLen = u32;
13pub type APIResult = i64;
14
15#[derive(Clone, Debug)]
17pub enum ConversionError {
18 InvalidBool,
19 InvalidI32,
20 InvalidI64,
21 InvalidU32,
22 InvalidU64,
23 InvalidF32,
24 InvalidF64,
25 InvalidUsize,
26 InvalidBytes,
27 InvalidDuration,
28 InvalidInstant,
29 InvalidFrame,
30 InvalidFrameParam,
31 InvalidHeader,
32 InvalidSentPacket,
33 InvalidSocketAddr,
34 InvalidQVal,
35}
36
37#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, PartialOrd)]
41pub enum PluginOp {
42 Init,
44
45 Test,
47
48 PluginControl(u64),
50
51 OnPluginTimeout(u64),
53
54 DecodeTransportParameter(u64),
56 WriteTransportParameter(u64),
58
59 LogFrame(u64),
61 NotifyFrame(u64),
63 OnFrameReserved(u64),
65 ParseFrame(u64),
67 PrepareFrame(u64),
69 ProcessFrame(u64),
71 ShouldSendFrame(u64),
74 WireLen(u64),
76 WriteFrame(u64),
78
79 #[doc(hidden)]
80 UpdateRtt,
81
82 Other([u8; 32]),
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum Anchor {
89 Before,
91 Define,
93 After,
95}
96
97impl Anchor {
98 pub fn index(&self) -> usize {
100 match self {
101 Anchor::Before => 0,
102 Anchor::Define => 1,
103 Anchor::After => 2,
104 }
105 }
106}
107
108fn extract_po_param(name: &str) -> Result<u64, ParseIntError> {
109 let end_num = name.rfind('_').map(|i| &name[i + 1..]).unwrap_or("");
110 u64::from_str_radix(end_num, 16)
111}
112
113impl PluginOp {
114 pub fn from_name(name: &str) -> (PluginOp, Anchor) {
118 let (name, anchor) = if let Some(po_name) = name.strip_prefix("pre_") {
119 (po_name, Anchor::Before)
120 } else if let Some(po_name) = name.strip_prefix("before_") {
121 (po_name, Anchor::Before)
122 } else if let Some(po_name) = name.strip_prefix("post_") {
123 (po_name, Anchor::After)
124 } else if let Some(po_name) = name.strip_prefix("after_") {
125 (po_name, Anchor::After)
126 } else {
127 (name, Anchor::Define)
128 };
129
130 if name == "init" {
131 (PluginOp::Init, anchor)
132 } else if name.starts_with("decode_transport_parameter_") {
133 match extract_po_param(name) {
134 Ok(frame_type) => (PluginOp::DecodeTransportParameter(frame_type), anchor),
135 Err(_) => panic!("Invalid protocol operation name"),
136 }
137 } else if name.starts_with("write_transport_parameter_") {
138 match extract_po_param(name) {
139 Ok(frame_type) => (PluginOp::WriteTransportParameter(frame_type), anchor),
140 Err(_) => panic!("Invalid protocol operation name"),
141 }
142 } else if name.starts_with("log_frame_") {
143 match extract_po_param(name) {
144 Ok(frame_type) => (PluginOp::LogFrame(frame_type), anchor),
145 Err(_) => panic!("Invalid protocol operation name"),
146 }
147 } else if name.starts_with("notify_frame_") {
148 match extract_po_param(name) {
149 Ok(frame_type) => (PluginOp::NotifyFrame(frame_type), anchor),
150 Err(_) => panic!("Invalid protocol operation name"),
151 }
152 } else if name.starts_with("on_frame_reserved_") {
153 match extract_po_param(name) {
154 Ok(frame_type) => (PluginOp::OnFrameReserved(frame_type), anchor),
155 Err(_) => panic!("Invalid protocol operation name"),
156 }
157 } else if name.starts_with("parse_frame_") {
158 match extract_po_param(name) {
159 Ok(frame_type) => (PluginOp::ParseFrame(frame_type), anchor),
160 Err(_) => panic!("Invalid protocol operation name"),
161 }
162 } else if name.starts_with("prepare_frame_") {
163 match extract_po_param(name) {
164 Ok(frame_type) => (PluginOp::PrepareFrame(frame_type), anchor),
165 Err(_) => panic!("Invalid protocol operation name"),
166 }
167 } else if name.starts_with("process_frame_") {
168 match extract_po_param(name) {
169 Ok(frame_type) => (PluginOp::ProcessFrame(frame_type), anchor),
170 Err(_) => panic!("Invalid protocol operation name"),
171 }
172 } else if name.starts_with("should_send_frame_") {
173 match extract_po_param(name) {
174 Ok(frame_type) => (PluginOp::ShouldSendFrame(frame_type), anchor),
175 Err(_) => panic!("Invalid protocol operation name"),
176 }
177 } else if name.starts_with("wire_len_") {
178 match extract_po_param(name) {
179 Ok(frame_type) => (PluginOp::WireLen(frame_type), anchor),
180 Err(e) => panic!("Invalid protocol operation name: {e}"),
181 }
182 } else if name.starts_with("write_frame_") {
183 match extract_po_param(name) {
184 Ok(frame_type) => (PluginOp::WriteFrame(frame_type), anchor),
185 Err(e) => panic!("Invalid protocol operation name: {e}"),
186 }
187 } else if name.starts_with("plugin_control_") {
188 match extract_po_param(name) {
189 Ok(val) => (PluginOp::PluginControl(val), anchor),
190 Err(e) => panic!("Invalid protocol operation name: {e}"),
191 }
192 } else if name.starts_with("on_plugin_timeout_") {
193 match extract_po_param(name) {
194 Ok(val) => (PluginOp::OnPluginTimeout(val), anchor),
195 Err(e) => panic!("Invalid protocol operation name: {e}"),
196 }
197 } else if name == "update_rtt" {
198 (PluginOp::UpdateRtt, anchor)
199 } else {
200 let mut name_array = [0; 32];
201 name_array[..name.len()].copy_from_slice(name.as_bytes());
202 (PluginOp::Other(name_array), anchor)
203 }
204 }
205
206 pub fn always_enabled(&self) -> bool {
209 matches!(
210 self,
211 PluginOp::Init
212 | PluginOp::DecodeTransportParameter(_)
213 | PluginOp::WriteTransportParameter(_)
214 )
215 }
216}
217
218#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, PartialOrd, Eq, Ord)]
221pub struct Bytes {
222 pub tag: u64,
224 pub max_read_len: u64,
226 pub max_write_len: u64,
228}
229
230#[allow(clippy::large_enum_variant)]
233#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, PartialOrd)]
234pub enum PluginVal {
235 Bool(bool),
237 I32(i32),
239 I64(i64),
241 U32(u32),
243 U64(u64),
245 F32(f32),
247 F64(f64),
249 Usize(u64),
251 Bytes(Bytes),
253 Duration(Duration),
255 UNIXInstant(UnixInstant),
257 SocketAddr(SocketAddr),
259 QUIC(quic::QVal),
261}
262
263macro_rules! impl_from_try_from {
264 ($e:ident, $v:ident, $t:ty, $err:ident, $verr:ident) => {
265 impl From<$t> for $e {
266 fn from(v: $t) -> Self {
267 $e::$v(v)
268 }
269 }
270
271 impl TryFrom<$e> for $t {
272 type Error = $err;
273
274 fn try_from(v: $e) -> Result<Self, Self::Error> {
275 match v {
276 $e::$v(v) => Ok(v),
277 _ => Err($err::$verr),
278 }
279 }
280 }
281 };
282}
283
284impl From<usize> for PluginVal {
285 fn from(value: usize) -> Self {
286 PluginVal::Usize(value as u64)
287 }
288}
289
290impl TryFrom<PluginVal> for usize {
291 type Error = ConversionError;
292
293 fn try_from(value: PluginVal) -> Result<Self, Self::Error> {
294 match value {
295 PluginVal::Usize(v) => Ok(v as Self),
296 _ => Err(ConversionError::InvalidUsize),
297 }
298 }
299}
300
301impl TryFrom<PluginVal> for () {
302 type Error = ConversionError;
303
304 fn try_from(_: PluginVal) -> Result<Self, Self::Error> {
305 Ok(())
306 }
307}
308
309impl_from_try_from!(PluginVal, Bool, bool, ConversionError, InvalidBool);
310impl_from_try_from!(PluginVal, I32, i32, ConversionError, InvalidI32);
311impl_from_try_from!(PluginVal, I64, i64, ConversionError, InvalidI64);
312impl_from_try_from!(PluginVal, U32, u32, ConversionError, InvalidU32);
313impl_from_try_from!(PluginVal, U64, u64, ConversionError, InvalidU64);
314impl_from_try_from!(PluginVal, F32, f32, ConversionError, InvalidF32);
315impl_from_try_from!(PluginVal, F64, f64, ConversionError, InvalidF64);
316impl_from_try_from!(PluginVal, Bytes, Bytes, ConversionError, InvalidBytes);
317impl_from_try_from!(
318 PluginVal,
319 Duration,
320 Duration,
321 ConversionError,
322 InvalidDuration
323);
324impl_from_try_from!(
325 PluginVal,
326 UNIXInstant,
327 UnixInstant,
328 ConversionError,
329 InvalidInstant
330);
331impl_from_try_from!(
332 PluginVal,
333 SocketAddr,
334 SocketAddr,
335 ConversionError,
336 InvalidSocketAddr
337);
338impl_from_try_from!(PluginVal, QUIC, quic::QVal, ConversionError, InvalidQVal);
339
340pub mod quic;