1
use crate::abi::envoy_dynamic_module_type_metrics_result;
2
use crate::buffer::EnvoyBuffer;
3
use crate::{
4
  abi,
5
  bytes_to_module_buffer,
6
  drop_wrapped_c_void_ptr,
7
  str_to_module_buffer,
8
  wrap_into_c_void_ptr,
9
  ClusterHostCount,
10
  EnvoyCounterId,
11
  EnvoyGaugeId,
12
  EnvoyHistogramId,
13
  NewNetworkFilterConfigFunction,
14
  NEW_NETWORK_FILTER_CONFIG_FUNCTION,
15
};
16
use mockall::*;
17

            
18
/// The trait that represents the Envoy network filter configuration.
19
/// This is used in [`NewNetworkFilterConfigFunction`] to pass the Envoy filter configuration
20
/// to the dynamic module.
21
#[automock]
22
pub trait EnvoyNetworkFilterConfig {
23
  /// Define a new counter scoped to this filter config with the given name.
24
  fn define_counter(
25
    &mut self,
26
    name: &str,
27
  ) -> Result<EnvoyCounterId, envoy_dynamic_module_type_metrics_result>;
28

            
29
  /// Define a new gauge scoped to this filter config with the given name.
30
  fn define_gauge(
31
    &mut self,
32
    name: &str,
33
  ) -> Result<EnvoyGaugeId, envoy_dynamic_module_type_metrics_result>;
34

            
35
  /// Define a new histogram scoped to this filter config with the given name.
36
  fn define_histogram(
37
    &mut self,
38
    name: &str,
39
  ) -> Result<EnvoyHistogramId, envoy_dynamic_module_type_metrics_result>;
40

            
41
  /// Create a new implementation of the [`EnvoyNetworkFilterConfigScheduler`] trait.
42
  ///
43
  /// This allows scheduling events to be delivered on the main thread.
44
  fn new_config_scheduler(&self) -> impl EnvoyNetworkFilterConfigScheduler + 'static;
45
}
46

            
47
/// The trait that represents the configuration for an Envoy network filter configuration.
48
/// This has one to one mapping with the [`EnvoyNetworkFilterConfig`] object.
49
///
50
/// The object is created when the corresponding Envoy network filter config is created, and it is
51
/// dropped when the corresponding Envoy network filter config is destroyed. Therefore, the
52
/// implementation is recommended to implement the [`Drop`] trait to handle the necessary cleanup.
53
///
54
/// Implementations must also be `Sync` since they are accessed from worker threads.
55
pub trait NetworkFilterConfig<ENF: EnvoyNetworkFilter>: Sync {
56
  /// This is called from a worker thread when a new TCP connection is established.
57
  fn new_network_filter(&self, _envoy: &mut ENF) -> Box<dyn NetworkFilter<ENF>>;
58

            
59
  /// This is called when the new event is scheduled via the
60
  /// [`EnvoyNetworkFilterConfigScheduler::commit`] for this [`NetworkFilterConfig`].
61
  ///
62
  /// * `event_id` is the ID of the event that was scheduled with
63
  ///   [`EnvoyNetworkFilterConfigScheduler::commit`] to distinguish multiple scheduled events.
64
  ///
65
  /// See [`EnvoyNetworkFilterConfig::new_config_scheduler`] for more details on how to use this.
66
  fn on_config_scheduled(&self, _event_id: u64) {}
67
}
68

            
69
/// The trait that corresponds to an Envoy network filter for each TCP connection
70
/// created via the [`NetworkFilterConfig::new_network_filter`] method.
71
///
72
/// All the event hooks are called on the same thread as the one that the [`NetworkFilter`] is
73
/// created via the [`NetworkFilterConfig::new_network_filter`] method.
74
pub trait NetworkFilter<ENF: EnvoyNetworkFilter> {
75
  /// This is called when a new TCP connection is established.
76
  ///
77
  /// This must return [`abi::envoy_dynamic_module_type_on_network_filter_data_status`] to
78
  /// indicate the status of the new connection processing.
79
  fn on_new_connection(
80
    &mut self,
81
    _envoy_filter: &mut ENF,
82
  ) -> abi::envoy_dynamic_module_type_on_network_filter_data_status {
83
    abi::envoy_dynamic_module_type_on_network_filter_data_status::Continue
84
  }
85

            
86
  /// This is called when data is read from the connection (downstream -> upstream direction).
87
  ///
88
  /// The `data_length` is the total length of the read data buffer.
89
  /// The `end_stream` indicates whether this is the last data (half-close from downstream).
90
  ///
91
  /// This must return [`abi::envoy_dynamic_module_type_on_network_filter_data_status`] to
92
  /// indicate the status of the read data processing.
93
  fn on_read(
94
    &mut self,
95
    _envoy_filter: &mut ENF,
96
    _data_length: usize,
97
    _end_stream: bool,
98
  ) -> abi::envoy_dynamic_module_type_on_network_filter_data_status {
99
    abi::envoy_dynamic_module_type_on_network_filter_data_status::Continue
100
  }
101

            
102
  /// This is called when data is to be written to the connection (upstream -> downstream
103
  /// direction).
104
  ///
105
  /// The `data_length` is the total length of the write data buffer.
106
  /// The `end_stream` indicates whether this is the last data.
107
  ///
108
  /// This must return [`abi::envoy_dynamic_module_type_on_network_filter_data_status`] to
109
  /// indicate the status of the write data processing.
110
  fn on_write(
111
    &mut self,
112
    _envoy_filter: &mut ENF,
113
    _data_length: usize,
114
    _end_stream: bool,
115
  ) -> abi::envoy_dynamic_module_type_on_network_filter_data_status {
116
    abi::envoy_dynamic_module_type_on_network_filter_data_status::Continue
117
  }
118

            
119
  /// This is called when a connection event occurs.
120
  fn on_event(
121
    &mut self,
122
    _envoy_filter: &mut ENF,
123
    _event: abi::envoy_dynamic_module_type_network_connection_event,
124
  ) {
125
  }
126

            
127
  /// This is called when an HTTP callout response is received.
128
  ///
129
  /// @param _callout_id is the ID of the callout returned by send_http_callout.
130
  /// @param _result is the result of the callout.
131
  /// @param _headers is the headers of the response. Empty if the callout failed.
132
  /// @param _body_chunks is the body chunks of the response. Empty if the callout failed.
133
  fn on_http_callout_done(
134
    &mut self,
135
    _envoy_filter: &mut ENF,
136
    _callout_id: u64,
137
    _result: abi::envoy_dynamic_module_type_http_callout_result,
138
    _headers: Vec<(EnvoyBuffer, EnvoyBuffer)>,
139
    _body_chunks: Vec<EnvoyBuffer>,
140
  ) {
141
  }
142

            
143
  /// This is called when the network filter is destroyed for each TCP connection.
144
  fn on_destroy(&mut self, _envoy_filter: &mut ENF) {}
145

            
146
  /// This is called when an event is scheduled via the [`EnvoyNetworkFilterScheduler::commit`]
147
  /// for this [`NetworkFilter`].
148
  ///
149
  /// * `event_id` is the ID of the event that was scheduled with
150
  ///   [`EnvoyNetworkFilterScheduler::commit`] to distinguish multiple scheduled events.
151
  ///
152
  /// See [`EnvoyNetworkFilter::new_scheduler`] for more details on how to use this.
153
  fn on_scheduled(&mut self, _envoy_filter: &mut ENF, _event_id: u64) {}
154

            
155
  /// This is called when the write buffer for the connection goes over its high watermark.
156
  /// This can be used to implement flow control by disabling reads when the write buffer is full.
157
  ///
158
  /// A typical implementation would call `envoy_filter.read_disable(true)` to stop reading
159
  /// from the downstream connection until the write buffer drains.
160
  fn on_above_write_buffer_high_watermark(&mut self, _envoy_filter: &mut ENF) {}
161

            
162
  /// This is called when the write buffer for the connection goes from over its high watermark
163
  /// to under its low watermark. This can be used to re-enable reads after flow control was
164
  /// applied.
165
  ///
166
  /// A typical implementation would call `envoy_filter.read_disable(false)` to resume reading
167
  /// from the downstream connection.
168
  fn on_below_write_buffer_low_watermark(&mut self, _envoy_filter: &mut ENF) {}
169
}
170

            
171
/// The trait that represents the Envoy network filter.
172
/// This is used in [`NetworkFilter`] to interact with the underlying Envoy network filter object.
173
pub trait EnvoyNetworkFilter {
174
  /// Get the read buffer chunks. This is valid after the first on_read callback for the lifetime
175
  /// of the connection.
176
  fn get_read_buffer_chunks(&mut self) -> (Vec<EnvoyBuffer>, usize);
177

            
178
  /// Get the write buffer chunks. This is valid after the first on_write callback for the lifetime
179
  /// of the connection.
180
  fn get_write_buffer_chunks(&mut self) -> (Vec<EnvoyBuffer>, usize);
181

            
182
  /// Drain bytes from the beginning of the read buffer.
183
  fn drain_read_buffer(&mut self, length: usize);
184

            
185
  /// Drain bytes from the beginning of the write buffer.
186
  fn drain_write_buffer(&mut self, length: usize);
187

            
188
  /// Prepend data to the beginning of the read buffer.
189
  fn prepend_read_buffer(&mut self, data: &[u8]);
190

            
191
  /// Append data to the end of the read buffer.
192
  fn append_read_buffer(&mut self, data: &[u8]);
193

            
194
  /// Prepend data to the beginning of the write buffer.
195
  fn prepend_write_buffer(&mut self, data: &[u8]);
196

            
197
  /// Append data to the end of the write buffer.
198
  fn append_write_buffer(&mut self, data: &[u8]);
199

            
200
  /// Write data directly to the connection (downstream).
201
  fn write(&mut self, data: &[u8], end_stream: bool);
202

            
203
  /// Inject data into the read filter chain (after this filter).
204
  fn inject_read_data(&mut self, data: &[u8], end_stream: bool);
205

            
206
  /// Inject data into the write filter chain (after this filter).
207
  fn inject_write_data(&mut self, data: &[u8], end_stream: bool);
208

            
209
  /// Continue reading after returning StopIteration.
210
  fn continue_reading(&mut self);
211

            
212
  /// Close the connection.
213
  fn close(&mut self, close_type: abi::envoy_dynamic_module_type_network_connection_close_type);
214

            
215
  /// Get the unique connection ID.
216
  fn get_connection_id(&self) -> u64;
217

            
218
  /// Get the remote (client) address and port.
219
  fn get_remote_address(&self) -> (String, u32);
220

            
221
  /// Get the local address and port.
222
  fn get_local_address(&self) -> (String, u32);
223

            
224
  /// Check if the connection uses SSL/TLS.
225
  fn is_ssl(&self) -> bool;
226

            
227
  /// Disable or enable connection close handling for this filter.
228
  fn disable_close(&mut self, disabled: bool);
229

            
230
  /// Close the connection with termination details.
231
  fn close_with_details(
232
    &mut self,
233
    close_type: abi::envoy_dynamic_module_type_network_connection_close_type,
234
    details: &str,
235
  );
236

            
237
  /// Get the requested server name (SNI).
238
  /// Returns None if SNI is not available.
239
  fn get_requested_server_name(&self) -> Option<EnvoyBuffer<'_>>;
240

            
241
  /// Get the direct remote (client) address and port without considering proxy protocol.
242
  /// Returns None if the address is not available or not an IP address.
243
  fn get_direct_remote_address(&self) -> Option<(EnvoyBuffer<'_>, u32)>;
244

            
245
  /// Get the SSL URI SANs from the peer certificate.
246
  /// Returns an empty vector if the connection is not SSL or no URI SANs are present.
247
  fn get_ssl_uri_sans(&self) -> Vec<EnvoyBuffer<'_>>;
248

            
249
  /// Get the SSL DNS SANs from the peer certificate.
250
  /// Returns an empty vector if the connection is not SSL or no DNS SANs are present.
251
  fn get_ssl_dns_sans(&self) -> Vec<EnvoyBuffer<'_>>;
252

            
253
  /// Get the SSL subject from the peer certificate.
254
  /// Returns None if the connection is not SSL or subject is not available.
255
  fn get_ssl_subject(&self) -> Option<EnvoyBuffer<'_>>;
256

            
257
  /// Set the filter state with the given key and byte value.
258
  /// Returns true if the operation is successful.
259
  fn set_filter_state_bytes(&mut self, key: &[u8], value: &[u8]) -> bool;
260

            
261
  /// Get the filter state bytes with the given key.
262
  /// Returns None if the filter state is not found.
263
  fn get_filter_state_bytes<'a>(&'a self, key: &[u8]) -> Option<EnvoyBuffer<'a>>;
264

            
265
  /// Set a typed filter state value with the given key. The value is deserialized by a
266
  /// registered `StreamInfo::FilterState::ObjectFactory` on the Envoy side. This is useful for
267
  /// setting filter state objects that other Envoy filters expect to read as specific C++ types
268
  /// (e.g., `PerConnectionCluster` used by TCP Proxy).
269
  ///
270
  /// Returns true if the operation is successful. This can fail if no ObjectFactory is registered
271
  /// for the key, if deserialization fails, or if the key already exists and is read-only.
272
  fn set_filter_state_typed(&mut self, key: &[u8], value: &[u8]) -> bool;
273

            
274
  /// Get the serialized value of a typed filter state object with the given key. The object must
275
  /// support `serializeAsString()` on the Envoy side.
276
  ///
277
  /// Returns None if the key does not exist, the object does not support serialization, or the
278
  /// filter state is not accessible.
279
  fn get_filter_state_typed<'a>(&'a self, key: &[u8]) -> Option<EnvoyBuffer<'a>>;
280

            
281
  /// Set the string-typed dynamic metadata value with the given namespace and key value.
282
  fn set_dynamic_metadata_string(&mut self, namespace: &str, key: &str, value: &str);
283

            
284
  /// Get the string-typed dynamic metadata value with the given namespace and key value.
285
  /// Returns None if the metadata is not found or is the wrong type.
286
  fn get_dynamic_metadata_string(&self, namespace: &str, key: &str) -> Option<String>;
287

            
288
  /// Set the number-typed dynamic metadata value with the given namespace and key value.
289
  /// Returns true if the operation is successful.
290
  fn set_dynamic_metadata_number(&mut self, namespace: &str, key: &str, value: f64);
291

            
292
  /// Get the number-typed dynamic metadata value with the given namespace and key value.
293
  /// Returns None if the metadata is not found or is the wrong type.
294
  fn get_dynamic_metadata_number(&self, namespace: &str, key: &str) -> Option<f64>;
295

            
296
  /// Set the bool-typed dynamic metadata value with the given namespace and key value.
297
  fn set_dynamic_metadata_bool(&mut self, namespace: &str, key: &str, value: bool);
298

            
299
  /// Get the bool-typed dynamic metadata value with the given namespace and key value.
300
  /// Returns None if the metadata is not found or is the wrong type.
301
  fn get_dynamic_metadata_bool(&self, namespace: &str, key: &str) -> Option<bool>;
302

            
303
  /// Set an integer socket option with the given level, name, and state.
304
  fn set_socket_option_int(
305
    &mut self,
306
    level: i64,
307
    name: i64,
308
    state: abi::envoy_dynamic_module_type_socket_option_state,
309
    value: i64,
310
  );
311

            
312
  /// Set a bytes socket option with the given level, name, and state.
313
  fn set_socket_option_bytes(
314
    &mut self,
315
    level: i64,
316
    name: i64,
317
    state: abi::envoy_dynamic_module_type_socket_option_state,
318
    value: &[u8],
319
  );
320

            
321
  /// Get an integer socket option value.
322
  fn get_socket_option_int(
323
    &self,
324
    level: i64,
325
    name: i64,
326
    state: abi::envoy_dynamic_module_type_socket_option_state,
327
  ) -> Option<i64>;
328

            
329
  /// Get a bytes socket option value.
330
  fn get_socket_option_bytes(
331
    &self,
332
    level: i64,
333
    name: i64,
334
    state: abi::envoy_dynamic_module_type_socket_option_state,
335
  ) -> Option<Vec<u8>>;
336

            
337
  /// List all socket options stored on the connection.
338
  fn get_socket_options(&self) -> Vec<SocketOption>;
339

            
340
  /// Send an HTTP callout to the given cluster with the given headers and body.
341
  /// Multiple callouts can be made from the same filter. Different callouts can be
342
  /// distinguished by the returned callout id.
343
  ///
344
  /// Headers must contain the `:method`, ":path", and `host` headers.
345
  ///
346
  /// This returns the status and callout id of the callout. The id is used to
347
  /// distinguish different callouts made from the same filter and is generated by Envoy.
348
  /// The meaning of the status is:
349
  ///
350
  ///   * Success: The callout was sent successfully.
351
  ///   * MissingRequiredHeaders: One of the required headers is missing: `:method`, `:path`, or
352
  ///     `host`.
353
  ///   * ClusterNotFound: The cluster with the given name was not found.
354
  ///   * DuplicateCalloutId: The callout ID is already in use.
355
  ///   * CannotCreateRequest: The request could not be created. This happens when, for example,
356
  ///     there's no healthy upstream host in the cluster.
357
  ///
358
  /// The callout result will be delivered to the [`NetworkFilter::on_http_callout_done`] method.
359
  fn send_http_callout<'a>(
360
    &mut self,
361
    _cluster_name: &'a str,
362
    _headers: Vec<(&'a str, &'a [u8])>,
363
    _body: Option<&'a [u8]>,
364
    _timeout_milliseconds: u64,
365
  ) -> (
366
    abi::envoy_dynamic_module_type_http_callout_init_result,
367
    u64, // callout handle
368
  );
369

            
370
  /// Increment the counter with the given id.
371
  fn increment_counter(
372
    &self,
373
    id: EnvoyCounterId,
374
    value: u64,
375
  ) -> Result<(), envoy_dynamic_module_type_metrics_result>;
376

            
377
  /// Set the value of the gauge with the given id.
378
  fn set_gauge(
379
    &self,
380
    id: EnvoyGaugeId,
381
    value: u64,
382
  ) -> Result<(), envoy_dynamic_module_type_metrics_result>;
383

            
384
  /// Increase the gauge with the given id.
385
  fn increase_gauge(
386
    &self,
387
    id: EnvoyGaugeId,
388
    value: u64,
389
  ) -> Result<(), envoy_dynamic_module_type_metrics_result>;
390

            
391
  /// Decrease the gauge with the given id.
392
  fn decrease_gauge(
393
    &self,
394
    id: EnvoyGaugeId,
395
    value: u64,
396
  ) -> Result<(), envoy_dynamic_module_type_metrics_result>;
397

            
398
  /// Record a value in the histogram with the given id.
399
  fn record_histogram_value(
400
    &self,
401
    id: EnvoyHistogramId,
402
    value: u64,
403
  ) -> Result<(), envoy_dynamic_module_type_metrics_result>;
404

            
405
  /// Retrieve the host counts for a cluster by name at the given priority level.
406
  /// Returns None if the cluster is not found or the priority level does not exist.
407
  ///
408
  /// This is useful for implementing scale-to-zero logic or custom load balancing decisions.
409
  fn get_cluster_host_count(&self, cluster_name: &str, priority: u32) -> Option<ClusterHostCount>;
410

            
411
  /// Get the upstream host address and port if an upstream host is selected.
412
  /// Returns None if no upstream host is set or the address is not an IP.
413
  fn get_upstream_host_address(&self) -> Option<(String, u32)>;
414

            
415
  /// Get the upstream host hostname if an upstream host is selected.
416
  /// Returns None if no upstream host is set or hostname is empty.
417
  fn get_upstream_host_hostname(&self) -> Option<String>;
418

            
419
  /// Get the upstream host cluster name if an upstream host is selected.
420
  /// Returns None if no upstream host is set.
421
  fn get_upstream_host_cluster(&self) -> Option<String>;
422

            
423
  /// Check if an upstream host has been selected for this connection.
424
  fn has_upstream_host(&self) -> bool;
425

            
426
  /// Signal to the filter manager to enable secure transport mode in upstream connection.
427
  /// This is done when upstream connection's transport socket is of startTLS type.
428
  /// Returns true if the upstream transport was successfully converted to secure mode.
429
  fn start_upstream_secure_transport(&mut self) -> bool;
430

            
431
  /// Get the current state of the connection (Open, Closing, or Closed).
432
  fn get_connection_state(&self) -> abi::envoy_dynamic_module_type_network_connection_state;
433

            
434
  /// Disable or enable reading from the connection. This is the primary mechanism for
435
  /// implementing back-pressure in TCP filters.
436
  ///
437
  /// When reads are disabled, no more data will be read from the socket. When re-enabled,
438
  /// if there is data in the input buffer, it will be re-dispatched through the filter chain.
439
  ///
440
  /// Note that this function reference counts calls. For example:
441
  /// ```text
442
  /// read_disable(true);  // Disables reading
443
  /// read_disable(true);  // Notes the connection is blocked by two sources
444
  /// read_disable(false); // Notes the connection is blocked by one source
445
  /// read_disable(false); // Marks the connection as unblocked, so resumes reading
446
  /// ```
447
  fn read_disable(
448
    &mut self,
449
    disable: bool,
450
  ) -> abi::envoy_dynamic_module_type_network_read_disable_status;
451

            
452
  /// Check if reading is currently enabled on the connection.
453
  fn read_enabled(&self) -> bool;
454

            
455
  /// Check if half-close semantics are enabled on this connection.
456
  /// When half-close is enabled, reading a remote half-close will not fully close the connection.
457
  fn is_half_close_enabled(&self) -> bool;
458

            
459
  /// Enable or disable half-close semantics on the connection.
460
  /// When half-close is enabled, reading a remote half-close will not fully close the connection,
461
  /// allowing the filter to continue writing data.
462
  fn enable_half_close(&mut self, enabled: bool);
463

            
464
  /// Get the current buffer limit set on the connection.
465
  fn get_buffer_limit(&self) -> u32;
466

            
467
  /// Set a soft limit on the size of buffers for the connection.
468
  ///
469
  /// For the read buffer, this limits the bytes read prior to flushing to further stages in the
470
  /// processing pipeline. For the write buffer, it sets watermarks. When enough data is buffered,
471
  /// [`NetworkFilter::on_above_write_buffer_high_watermark`] is called. When enough data is
472
  /// drained, [`NetworkFilter::on_below_write_buffer_low_watermark`] is called.
473
  fn set_buffer_limits(&mut self, limit: u32);
474

            
475
  /// Check if the connection is currently above the high watermark.
476
  fn above_high_watermark(&self) -> bool;
477

            
478
  /// Create a new implementation of the [`EnvoyNetworkFilterScheduler`] trait.
479
  ///
480
  /// ## Example Usage
481
  ///
482
  /// ```
483
  /// use envoy_proxy_dynamic_modules_rust_sdk::*;
484
  /// use std::thread;
485
  ///
486
  /// struct TestFilter;
487
  /// impl<ENF: EnvoyNetworkFilter> NetworkFilter<ENF> for TestFilter {
488
  ///   fn on_new_connection(
489
  ///     &mut self,
490
  ///     envoy_filter: &mut ENF,
491
  ///   ) -> abi::envoy_dynamic_module_type_on_network_filter_data_status {
492
  ///     let scheduler = envoy_filter.new_scheduler();
493
  ///     let _ = std::thread::spawn(move || {
494
  ///       // Do some work in a separate thread.
495
  ///       // ...
496
  ///       // Then schedule the event to continue processing.
497
  ///       scheduler.commit(123);
498
  ///     });
499
  ///     abi::envoy_dynamic_module_type_on_network_filter_data_status::StopIteration
500
  ///   }
501
  ///
502
  ///   fn on_scheduled(&mut self, _envoy_filter: &mut ENF, event_id: u64) {
503
  ///     // Handle the scheduled event.
504
  ///     assert_eq!(event_id, 123);
505
  ///   }
506
  /// }
507
  /// ```
508
  fn new_scheduler(&self) -> impl EnvoyNetworkFilterScheduler + 'static;
509

            
510
  /// Get the index of the current worker thread.
511
  fn get_worker_index(&self) -> u32;
512
}
513

            
514
/// This represents a thread-safe object that can be used to schedule a generic event to the
515
/// Envoy network filter on the worker thread where the network filter is running.
516
///
517
/// The scheduler is created by the [`EnvoyNetworkFilter::new_scheduler`] method. When calling
518
/// [`EnvoyNetworkFilterScheduler::commit`] with an event id, eventually
519
/// [`NetworkFilter::on_scheduled`] is called with the same event id on the worker thread where the
520
/// network filter is running, IF the filter is still alive by the time the event is committed.
521
///
522
/// Since this is primarily designed to be used from a different thread than the one
523
/// where the [`NetworkFilter`] instance was created, it is marked as `Send` so that
524
/// the [`Box<dyn EnvoyNetworkFilterScheduler>`] can be sent across threads.
525
///
526
/// It is also safe to be called concurrently, so it is marked as `Sync` as well.
527
#[automock]
528
pub trait EnvoyNetworkFilterScheduler: Send + Sync {
529
  /// Commit the scheduled event to the worker thread where [`NetworkFilter`] is running.
530
  ///
531
  /// It accepts an `event_id` which can be used to distinguish different events
532
  /// scheduled by the same filter. The `event_id` can be any value.
533
  ///
534
  /// Once this is called, [`NetworkFilter::on_scheduled`] will be called with
535
  /// the same `event_id` on the worker thread where the filter is running IF
536
  /// by the time the event is committed, the filter is still alive.
537
  fn commit(&self, event_id: u64);
538
}
539

            
540
/// This implements the [`EnvoyNetworkFilterScheduler`] trait with the given raw pointer to the
541
/// Envoy network filter scheduler object.
542
struct EnvoyNetworkFilterSchedulerImpl {
543
  raw_ptr: abi::envoy_dynamic_module_type_network_filter_scheduler_module_ptr,
544
}
545

            
546
unsafe impl Send for EnvoyNetworkFilterSchedulerImpl {}
547
unsafe impl Sync for EnvoyNetworkFilterSchedulerImpl {}
548

            
549
impl Drop for EnvoyNetworkFilterSchedulerImpl {
550
  fn drop(&mut self) {
551
    unsafe {
552
      abi::envoy_dynamic_module_callback_network_filter_scheduler_delete(self.raw_ptr);
553
    }
554
  }
555
}
556

            
557
impl EnvoyNetworkFilterScheduler for EnvoyNetworkFilterSchedulerImpl {
558
  fn commit(&self, event_id: u64) {
559
    unsafe {
560
      abi::envoy_dynamic_module_callback_network_filter_scheduler_commit(self.raw_ptr, event_id);
561
    }
562
  }
563
}
564

            
565
// Box<dyn EnvoyNetworkFilterScheduler> is returned by mockall, so we need to implement
566
// EnvoyNetworkFilterScheduler for it as well.
567
impl EnvoyNetworkFilterScheduler for Box<dyn EnvoyNetworkFilterScheduler> {
568
  fn commit(&self, event_id: u64) {
569
    (**self).commit(event_id);
570
  }
571
}
572

            
573
/// This represents a thread-safe object that can be used to schedule a generic event to the
574
/// Envoy network filter config on the main thread.
575
#[automock]
576
pub trait EnvoyNetworkFilterConfigScheduler: Send + Sync {
577
  /// Commit the scheduled event to the main thread.
578
  fn commit(&self, event_id: u64);
579
}
580

            
581
/// This implements the [`EnvoyNetworkFilterConfigScheduler`] trait.
582
struct EnvoyNetworkFilterConfigSchedulerImpl {
583
  raw_ptr: abi::envoy_dynamic_module_type_network_filter_config_scheduler_module_ptr,
584
}
585

            
586
unsafe impl Send for EnvoyNetworkFilterConfigSchedulerImpl {}
587
unsafe impl Sync for EnvoyNetworkFilterConfigSchedulerImpl {}
588

            
589
impl Drop for EnvoyNetworkFilterConfigSchedulerImpl {
590
  fn drop(&mut self) {
591
    unsafe {
592
      abi::envoy_dynamic_module_callback_network_filter_config_scheduler_delete(self.raw_ptr);
593
    }
594
  }
595
}
596

            
597
impl EnvoyNetworkFilterConfigScheduler for EnvoyNetworkFilterConfigSchedulerImpl {
598
  fn commit(&self, event_id: u64) {
599
    unsafe {
600
      abi::envoy_dynamic_module_callback_network_filter_config_scheduler_commit(
601
        self.raw_ptr,
602
        event_id,
603
      );
604
    }
605
  }
606
}
607

            
608
// Box<dyn EnvoyNetworkFilterConfigScheduler> is returned by mockall, so we need to implement
609
// EnvoyNetworkFilterConfigScheduler for it as well.
610
impl EnvoyNetworkFilterConfigScheduler for Box<dyn EnvoyNetworkFilterConfigScheduler> {
611
  fn commit(&self, event_id: u64) {
612
    (**self).commit(event_id);
613
  }
614
}
615

            
616
pub enum SocketOptionValue {
617
  Int(i64),
618
  Bytes(Vec<u8>),
619
}
620

            
621
pub struct SocketOption {
622
  pub level: i64,
623
  pub name: i64,
624
  pub state: abi::envoy_dynamic_module_type_socket_option_state,
625
  pub value: SocketOptionValue,
626
}
627

            
628
/// The implementation of [`EnvoyNetworkFilterConfig`] for the Envoy network filter configuration.
629
pub struct EnvoyNetworkFilterConfigImpl {
630
  pub(crate) raw: abi::envoy_dynamic_module_type_network_filter_config_envoy_ptr,
631
}
632

            
633
impl EnvoyNetworkFilterConfigImpl {
634
  pub fn new(raw: abi::envoy_dynamic_module_type_network_filter_config_envoy_ptr) -> Self {
635
    Self { raw }
636
  }
637
}
638

            
639
impl EnvoyNetworkFilterConfig for EnvoyNetworkFilterConfigImpl {
640
  fn define_counter(
641
    &mut self,
642
    name: &str,
643
  ) -> Result<EnvoyCounterId, envoy_dynamic_module_type_metrics_result> {
644
    let mut id: usize = 0;
645
    Result::from(unsafe {
646
      abi::envoy_dynamic_module_callback_network_filter_config_define_counter(
647
        self.raw,
648
        str_to_module_buffer(name),
649
        &mut id,
650
      )
651
    })?;
652
    Ok(EnvoyCounterId(id))
653
  }
654

            
655
  fn define_gauge(
656
    &mut self,
657
    name: &str,
658
  ) -> Result<EnvoyGaugeId, envoy_dynamic_module_type_metrics_result> {
659
    let mut id: usize = 0;
660
    Result::from(unsafe {
661
      abi::envoy_dynamic_module_callback_network_filter_config_define_gauge(
662
        self.raw,
663
        str_to_module_buffer(name),
664
        &mut id,
665
      )
666
    })?;
667
    Ok(EnvoyGaugeId(id))
668
  }
669

            
670
  fn define_histogram(
671
    &mut self,
672
    name: &str,
673
  ) -> Result<EnvoyHistogramId, envoy_dynamic_module_type_metrics_result> {
674
    let mut id: usize = 0;
675
    Result::from(unsafe {
676
      abi::envoy_dynamic_module_callback_network_filter_config_define_histogram(
677
        self.raw,
678
        str_to_module_buffer(name),
679
        &mut id,
680
      )
681
    })?;
682
    Ok(EnvoyHistogramId(id))
683
  }
684

            
685
  fn new_config_scheduler(&self) -> impl EnvoyNetworkFilterConfigScheduler + 'static {
686
    unsafe {
687
      let scheduler_ptr =
688
        abi::envoy_dynamic_module_callback_network_filter_config_scheduler_new(self.raw);
689
      EnvoyNetworkFilterConfigSchedulerImpl {
690
        raw_ptr: scheduler_ptr,
691
      }
692
    }
693
  }
694
}
695

            
696
/// The implementation of [`EnvoyNetworkFilter`] for the Envoy network filter.
697
pub struct EnvoyNetworkFilterImpl {
698
  pub(crate) raw: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
699
}
700

            
701
impl EnvoyNetworkFilterImpl {
702
  pub fn new(raw: abi::envoy_dynamic_module_type_network_filter_envoy_ptr) -> Self {
703
    Self { raw }
704
  }
705
}
706

            
707
impl EnvoyNetworkFilter for EnvoyNetworkFilterImpl {
708
  fn get_read_buffer_chunks(&mut self) -> (Vec<EnvoyBuffer>, usize) {
709
    let size = unsafe {
710
      abi::envoy_dynamic_module_callback_network_filter_get_read_buffer_chunks_size(self.raw)
711
    };
712
    if size == 0 {
713
      return (Vec::new(), 0);
714
    }
715

            
716
    let total_length =
717
      unsafe { abi::envoy_dynamic_module_callback_network_filter_get_read_buffer_size(self.raw) };
718
    if total_length == 0 {
719
      return (Vec::new(), 0);
720
    }
721

            
722
    let mut buffers: Vec<abi::envoy_dynamic_module_type_envoy_buffer> = vec![
723
      abi::envoy_dynamic_module_type_envoy_buffer {
724
        ptr: std::ptr::null_mut(),
725
        length: 0,
726
      };
727
      size
728
    ];
729
    unsafe {
730
      abi::envoy_dynamic_module_callback_network_filter_get_read_buffer_chunks(
731
        self.raw,
732
        buffers.as_mut_ptr(),
733
      )
734
    };
735
    let envoy_buffers: Vec<EnvoyBuffer> = buffers
736
      .iter()
737
      .map(|s| unsafe { EnvoyBuffer::new_from_raw(s.ptr as *const _, s.length) })
738
      .collect();
739
    (envoy_buffers, total_length)
740
  }
741

            
742
  fn get_write_buffer_chunks(&mut self) -> (Vec<EnvoyBuffer>, usize) {
743
    let size = unsafe {
744
      abi::envoy_dynamic_module_callback_network_filter_get_write_buffer_chunks_size(self.raw)
745
    };
746
    if size == 0 {
747
      return (Vec::new(), 0);
748
    }
749

            
750
    let total_length =
751
      unsafe { abi::envoy_dynamic_module_callback_network_filter_get_write_buffer_size(self.raw) };
752
    if total_length == 0 {
753
      return (Vec::new(), 0);
754
    }
755

            
756
    let mut buffers: Vec<abi::envoy_dynamic_module_type_envoy_buffer> = vec![
757
      abi::envoy_dynamic_module_type_envoy_buffer {
758
        ptr: std::ptr::null_mut(),
759
        length: 0,
760
      };
761
      size
762
    ];
763
    unsafe {
764
      abi::envoy_dynamic_module_callback_network_filter_get_write_buffer_chunks(
765
        self.raw,
766
        buffers.as_mut_ptr(),
767
      )
768
    };
769
    let envoy_buffers: Vec<EnvoyBuffer> = buffers
770
      .iter()
771
      .map(|s| unsafe { EnvoyBuffer::new_from_raw(s.ptr as *const _, s.length) })
772
      .collect();
773
    (envoy_buffers, total_length)
774
  }
775

            
776
  fn drain_read_buffer(&mut self, length: usize) {
777
    unsafe {
778
      abi::envoy_dynamic_module_callback_network_filter_drain_read_buffer(self.raw, length);
779
    }
780
  }
781

            
782
  fn drain_write_buffer(&mut self, length: usize) {
783
    unsafe {
784
      abi::envoy_dynamic_module_callback_network_filter_drain_write_buffer(self.raw, length);
785
    }
786
  }
787

            
788
  fn prepend_read_buffer(&mut self, data: &[u8]) {
789
    unsafe {
790
      let buffer = abi::envoy_dynamic_module_type_module_buffer {
791
        ptr: data.as_ptr() as abi::envoy_dynamic_module_type_buffer_module_ptr,
792
        length: data.len(),
793
      };
794
      abi::envoy_dynamic_module_callback_network_filter_prepend_read_buffer(self.raw, buffer);
795
    }
796
  }
797

            
798
  fn append_read_buffer(&mut self, data: &[u8]) {
799
    unsafe {
800
      let buffer = abi::envoy_dynamic_module_type_module_buffer {
801
        ptr: data.as_ptr() as abi::envoy_dynamic_module_type_buffer_module_ptr,
802
        length: data.len(),
803
      };
804
      abi::envoy_dynamic_module_callback_network_filter_append_read_buffer(self.raw, buffer);
805
    }
806
  }
807

            
808
  fn prepend_write_buffer(&mut self, data: &[u8]) {
809
    unsafe {
810
      let buffer = abi::envoy_dynamic_module_type_module_buffer {
811
        ptr: data.as_ptr() as abi::envoy_dynamic_module_type_buffer_module_ptr,
812
        length: data.len(),
813
      };
814
      abi::envoy_dynamic_module_callback_network_filter_prepend_write_buffer(self.raw, buffer);
815
    }
816
  }
817

            
818
  fn append_write_buffer(&mut self, data: &[u8]) {
819
    unsafe {
820
      let buffer = abi::envoy_dynamic_module_type_module_buffer {
821
        ptr: data.as_ptr() as abi::envoy_dynamic_module_type_buffer_module_ptr,
822
        length: data.len(),
823
      };
824
      abi::envoy_dynamic_module_callback_network_filter_append_write_buffer(self.raw, buffer);
825
    }
826
  }
827

            
828
  fn write(&mut self, data: &[u8], end_stream: bool) {
829
    unsafe {
830
      let buffer = abi::envoy_dynamic_module_type_module_buffer {
831
        ptr: data.as_ptr() as abi::envoy_dynamic_module_type_buffer_module_ptr,
832
        length: data.len(),
833
      };
834
      abi::envoy_dynamic_module_callback_network_filter_write(self.raw, buffer, end_stream);
835
    }
836
  }
837

            
838
  fn inject_read_data(&mut self, data: &[u8], end_stream: bool) {
839
    unsafe {
840
      let buffer = abi::envoy_dynamic_module_type_module_buffer {
841
        ptr: data.as_ptr() as abi::envoy_dynamic_module_type_buffer_module_ptr,
842
        length: data.len(),
843
      };
844
      abi::envoy_dynamic_module_callback_network_filter_inject_read_data(
845
        self.raw, buffer, end_stream,
846
      );
847
    }
848
  }
849

            
850
  fn inject_write_data(&mut self, data: &[u8], end_stream: bool) {
851
    unsafe {
852
      let buffer = abi::envoy_dynamic_module_type_module_buffer {
853
        ptr: data.as_ptr() as abi::envoy_dynamic_module_type_buffer_module_ptr,
854
        length: data.len(),
855
      };
856
      abi::envoy_dynamic_module_callback_network_filter_inject_write_data(
857
        self.raw, buffer, end_stream,
858
      );
859
    }
860
  }
861

            
862
  fn continue_reading(&mut self) {
863
    unsafe {
864
      abi::envoy_dynamic_module_callback_network_filter_continue_reading(self.raw);
865
    }
866
  }
867

            
868
  fn close(&mut self, close_type: abi::envoy_dynamic_module_type_network_connection_close_type) {
869
    unsafe {
870
      abi::envoy_dynamic_module_callback_network_filter_close(self.raw, close_type);
871
    }
872
  }
873

            
874
  fn get_connection_id(&self) -> u64 {
875
    unsafe { abi::envoy_dynamic_module_callback_network_filter_get_connection_id(self.raw) }
876
  }
877

            
878
  fn get_remote_address(&self) -> (String, u32) {
879
    let mut address = abi::envoy_dynamic_module_type_envoy_buffer {
880
      ptr: std::ptr::null_mut(),
881
      length: 0,
882
    };
883
    let mut port: u32 = 0;
884
    let result = unsafe {
885
      abi::envoy_dynamic_module_callback_network_filter_get_remote_address(
886
        self.raw,
887
        &mut address as *mut _ as *mut _,
888
        &mut port,
889
      )
890
    };
891
    if !result || address.length == 0 || address.ptr.is_null() {
892
      return (String::new(), 0);
893
    }
894
    let address = unsafe {
895
      std::str::from_utf8_unchecked(std::slice::from_raw_parts(
896
        address.ptr as *const _,
897
        address.length,
898
      ))
899
    };
900
    (address.to_string(), port)
901
  }
902

            
903
  fn get_local_address(&self) -> (String, u32) {
904
    let mut address = abi::envoy_dynamic_module_type_envoy_buffer {
905
      ptr: std::ptr::null_mut(),
906
      length: 0,
907
    };
908
    let mut port: u32 = 0;
909
    let result = unsafe {
910
      abi::envoy_dynamic_module_callback_network_filter_get_local_address(
911
        self.raw,
912
        &mut address as *mut _ as *mut _,
913
        &mut port,
914
      )
915
    };
916
    if !result || address.length == 0 || address.ptr.is_null() {
917
      return (String::new(), 0);
918
    }
919
    let address = unsafe {
920
      std::str::from_utf8_unchecked(std::slice::from_raw_parts(
921
        address.ptr as *const _,
922
        address.length,
923
      ))
924
    };
925
    (address.to_string(), port)
926
  }
927

            
928
  fn is_ssl(&self) -> bool {
929
    unsafe { abi::envoy_dynamic_module_callback_network_filter_is_ssl(self.raw) }
930
  }
931

            
932
  fn disable_close(&mut self, disabled: bool) {
933
    unsafe {
934
      abi::envoy_dynamic_module_callback_network_filter_disable_close(self.raw, disabled);
935
    }
936
  }
937

            
938
  fn close_with_details(
939
    &mut self,
940
    close_type: abi::envoy_dynamic_module_type_network_connection_close_type,
941
    details: &str,
942
  ) {
943
    unsafe {
944
      abi::envoy_dynamic_module_callback_network_filter_close_with_details(
945
        self.raw,
946
        close_type,
947
        str_to_module_buffer(details),
948
      );
949
    }
950
  }
951

            
952
  fn get_requested_server_name(&self) -> Option<EnvoyBuffer> {
953
    let mut result = abi::envoy_dynamic_module_type_envoy_buffer {
954
      ptr: std::ptr::null(),
955
      length: 0,
956
    };
957
    let success = unsafe {
958
      abi::envoy_dynamic_module_callback_network_filter_get_requested_server_name(
959
        self.raw,
960
        &mut result as *mut _ as *mut _,
961
      )
962
    };
963
    if success && !result.ptr.is_null() && result.length > 0 {
964
      Some(unsafe { EnvoyBuffer::new_from_raw(result.ptr as *const _, result.length) })
965
    } else {
966
      None
967
    }
968
  }
969

            
970
  fn get_direct_remote_address(&self) -> Option<(EnvoyBuffer, u32)> {
971
    let mut address = abi::envoy_dynamic_module_type_envoy_buffer {
972
      ptr: std::ptr::null(),
973
      length: 0,
974
    };
975
    let mut port: u32 = 0;
976
    let result = unsafe {
977
      abi::envoy_dynamic_module_callback_network_filter_get_direct_remote_address(
978
        self.raw,
979
        &mut address as *mut _ as *mut _,
980
        &mut port,
981
      )
982
    };
983
    if !result || address.length == 0 || address.ptr.is_null() {
984
      return None;
985
    }
986
    Some((
987
      unsafe { EnvoyBuffer::new_from_raw(address.ptr as *const _, address.length) },
988
      port,
989
    ))
990
  }
991

            
992
  fn get_ssl_uri_sans(&self) -> Vec<EnvoyBuffer> {
993
    let size =
994
      unsafe { abi::envoy_dynamic_module_callback_network_filter_get_ssl_uri_sans_size(self.raw) };
995
    if size == 0 {
996
      return Vec::new();
997
    }
998

            
999
    let mut sans_buffers: Vec<abi::envoy_dynamic_module_type_envoy_buffer> = vec![
      abi::envoy_dynamic_module_type_envoy_buffer {
        ptr: std::ptr::null(),
        length: 0,
      };
      size
    ];
    let ok = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_get_ssl_uri_sans(
        self.raw,
        sans_buffers.as_mut_ptr(),
      )
    };
    if !ok {
      return Vec::new();
    }
    sans_buffers
      .iter()
      .take(size)
      .map(|buf| {
        if !buf.ptr.is_null() && buf.length > 0 {
          unsafe { EnvoyBuffer::new_from_raw(buf.ptr as *const _, buf.length) }
        } else {
          EnvoyBuffer::default()
        }
      })
      .collect()
  }
  fn get_ssl_dns_sans(&self) -> Vec<EnvoyBuffer> {
    let size =
      unsafe { abi::envoy_dynamic_module_callback_network_filter_get_ssl_dns_sans_size(self.raw) };
    if size == 0 {
      return Vec::new();
    }
    let mut sans_buffers: Vec<abi::envoy_dynamic_module_type_envoy_buffer> = vec![
      abi::envoy_dynamic_module_type_envoy_buffer {
        ptr: std::ptr::null(),
        length: 0,
      };
      size
    ];
    let ok = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_get_ssl_dns_sans(
        self.raw,
        sans_buffers.as_mut_ptr(),
      )
    };
    if !ok {
      return Vec::new();
    }
    sans_buffers
      .iter()
      .take(size)
      .map(|buf| {
        if !buf.ptr.is_null() && buf.length > 0 {
          unsafe { EnvoyBuffer::new_from_raw(buf.ptr as *const _, buf.length) }
        } else {
          EnvoyBuffer::default()
        }
      })
      .collect()
  }
  fn get_ssl_subject(&self) -> Option<EnvoyBuffer> {
    let mut result = abi::envoy_dynamic_module_type_envoy_buffer {
      ptr: std::ptr::null(),
      length: 0,
    };
    let success = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_get_ssl_subject(
        self.raw,
        &mut result as *mut _ as *mut _,
      )
    };
    if success && !result.ptr.is_null() && result.length > 0 {
      Some(unsafe { EnvoyBuffer::new_from_raw(result.ptr as *const _, result.length) })
    } else {
      None
    }
  }
  fn set_filter_state_bytes(&mut self, key: &[u8], value: &[u8]) -> bool {
    unsafe {
      abi::envoy_dynamic_module_callback_network_set_filter_state_bytes(
        self.raw,
        bytes_to_module_buffer(key),
        abi::envoy_dynamic_module_type_module_buffer {
          ptr: value.as_ptr() as abi::envoy_dynamic_module_type_buffer_module_ptr,
          length: value.len(),
        },
      )
    }
  }
  fn get_filter_state_bytes(&self, key: &[u8]) -> Option<EnvoyBuffer> {
    let mut result = abi::envoy_dynamic_module_type_envoy_buffer {
      ptr: std::ptr::null(),
      length: 0,
    };
    let success = unsafe {
      abi::envoy_dynamic_module_callback_network_get_filter_state_bytes(
        self.raw,
        bytes_to_module_buffer(key),
        &mut result as *mut _ as *mut _,
      )
    };
    if success && !result.ptr.is_null() && result.length > 0 {
      Some(unsafe { EnvoyBuffer::new_from_raw(result.ptr as *const _, result.length) })
    } else {
      None
    }
  }
  fn set_filter_state_typed(&mut self, key: &[u8], value: &[u8]) -> bool {
    unsafe {
      abi::envoy_dynamic_module_callback_network_set_filter_state_typed(
        self.raw,
        bytes_to_module_buffer(key),
        bytes_to_module_buffer(value),
      )
    }
  }
  fn get_filter_state_typed(&self, key: &[u8]) -> Option<EnvoyBuffer> {
    let mut result = abi::envoy_dynamic_module_type_envoy_buffer {
      ptr: std::ptr::null(),
      length: 0,
    };
    let success = unsafe {
      abi::envoy_dynamic_module_callback_network_get_filter_state_typed(
        self.raw,
        bytes_to_module_buffer(key),
        &mut result as *mut _ as *mut _,
      )
    };
    if success && !result.ptr.is_null() && result.length > 0 {
      Some(unsafe { EnvoyBuffer::new_from_raw(result.ptr as *const _, result.length) })
    } else {
      None
    }
  }
  fn set_dynamic_metadata_string(&mut self, namespace: &str, key: &str, value: &str) {
    unsafe {
      abi::envoy_dynamic_module_callback_network_set_dynamic_metadata_string(
        self.raw,
        str_to_module_buffer(namespace),
        str_to_module_buffer(key),
        str_to_module_buffer(value),
      )
    }
  }
  fn get_dynamic_metadata_string(&self, namespace: &str, key: &str) -> Option<String> {
    let mut result = abi::envoy_dynamic_module_type_envoy_buffer {
      ptr: std::ptr::null(),
      length: 0,
    };
    let success = unsafe {
      abi::envoy_dynamic_module_callback_network_get_dynamic_metadata_string(
        self.raw,
        str_to_module_buffer(namespace),
        str_to_module_buffer(key),
        &mut result as *mut _ as *mut _,
      )
    };
    if success && !result.ptr.is_null() && result.length > 0 {
      let value_str = unsafe {
        std::str::from_utf8_unchecked(std::slice::from_raw_parts(
          result.ptr as *const _,
          result.length,
        ))
      };
      Some(value_str.to_string())
    } else {
      None
    }
  }
  fn set_dynamic_metadata_number(&mut self, namespace: &str, key: &str, value: f64) {
    unsafe {
      abi::envoy_dynamic_module_callback_network_set_dynamic_metadata_number(
        self.raw,
        str_to_module_buffer(namespace),
        str_to_module_buffer(key),
        value,
      )
    }
  }
  fn get_dynamic_metadata_number(&self, namespace: &str, key: &str) -> Option<f64> {
    let mut result: f64 = 0.0;
    let success = unsafe {
      abi::envoy_dynamic_module_callback_network_get_dynamic_metadata_number(
        self.raw,
        str_to_module_buffer(namespace),
        str_to_module_buffer(key),
        &mut result,
      )
    };
    if success {
      Some(result)
    } else {
      None
    }
  }
  fn set_dynamic_metadata_bool(&mut self, namespace: &str, key: &str, value: bool) {
    unsafe {
      abi::envoy_dynamic_module_callback_network_set_dynamic_metadata_bool(
        self.raw,
        str_to_module_buffer(namespace),
        str_to_module_buffer(key),
        value,
      )
    }
  }
  fn get_dynamic_metadata_bool(&self, namespace: &str, key: &str) -> Option<bool> {
    let mut result: bool = false;
    let success = unsafe {
      abi::envoy_dynamic_module_callback_network_get_dynamic_metadata_bool(
        self.raw,
        str_to_module_buffer(namespace),
        str_to_module_buffer(key),
        &mut result,
      )
    };
    if success {
      Some(result)
    } else {
      None
    }
  }
  fn set_socket_option_int(
    &mut self,
    level: i64,
    name: i64,
    state: abi::envoy_dynamic_module_type_socket_option_state,
    value: i64,
  ) {
    unsafe {
      abi::envoy_dynamic_module_callback_network_set_socket_option_int(
        self.raw, level, name, state, value,
      )
    }
  }
  fn set_socket_option_bytes(
    &mut self,
    level: i64,
    name: i64,
    state: abi::envoy_dynamic_module_type_socket_option_state,
    value: &[u8],
  ) {
    unsafe {
      abi::envoy_dynamic_module_callback_network_set_socket_option_bytes(
        self.raw,
        level,
        name,
        state,
        abi::envoy_dynamic_module_type_module_buffer {
          ptr: value.as_ptr() as *const _,
          length: value.len(),
        },
      )
    }
  }
  fn get_socket_option_int(
    &self,
    level: i64,
    name: i64,
    state: abi::envoy_dynamic_module_type_socket_option_state,
  ) -> Option<i64> {
    let mut value: i64 = 0;
    let success = unsafe {
      abi::envoy_dynamic_module_callback_network_get_socket_option_int(
        self.raw, level, name, state, &mut value,
      )
    };
    if success {
      Some(value)
    } else {
      None
    }
  }
  fn get_socket_option_bytes(
    &self,
    level: i64,
    name: i64,
    state: abi::envoy_dynamic_module_type_socket_option_state,
  ) -> Option<Vec<u8>> {
    let mut result = abi::envoy_dynamic_module_type_envoy_buffer {
      ptr: std::ptr::null(),
      length: 0,
    };
    let success = unsafe {
      abi::envoy_dynamic_module_callback_network_get_socket_option_bytes(
        self.raw,
        level,
        name,
        state,
        &mut result as *mut _ as *mut _,
      )
    };
    if success && !result.ptr.is_null() && result.length > 0 {
      let slice = unsafe { std::slice::from_raw_parts(result.ptr as *const u8, result.length) };
      Some(slice.to_vec())
    } else {
      None
    }
  }
  fn get_socket_options(&self) -> Vec<SocketOption> {
    let size =
      unsafe { abi::envoy_dynamic_module_callback_network_get_socket_options_size(self.raw) };
    if size == 0 {
      return Vec::new();
    }
    let mut options: Vec<abi::envoy_dynamic_module_type_socket_option> = vec![
      abi::envoy_dynamic_module_type_socket_option {
        level: 0,
        name: 0,
        state: abi::envoy_dynamic_module_type_socket_option_state::Prebind,
        value_type: abi::envoy_dynamic_module_type_socket_option_value_type::Int,
        int_value: 0,
        byte_value: abi::envoy_dynamic_module_type_envoy_buffer {
          ptr: std::ptr::null(),
          length: 0,
        },
      };
      size
    ];
    unsafe {
      abi::envoy_dynamic_module_callback_network_get_socket_options(self.raw, options.as_mut_ptr())
    };
    options
      .into_iter()
      .map(|opt| {
        let value = match opt.value_type {
          abi::envoy_dynamic_module_type_socket_option_value_type::Int => {
            SocketOptionValue::Int(opt.int_value)
          },
          abi::envoy_dynamic_module_type_socket_option_value_type::Bytes => {
            if !opt.byte_value.ptr.is_null() && opt.byte_value.length > 0 {
              let bytes = unsafe {
                std::slice::from_raw_parts(opt.byte_value.ptr as *const u8, opt.byte_value.length)
                  .to_vec()
              };
              SocketOptionValue::Bytes(bytes)
            } else {
              SocketOptionValue::Bytes(Vec::new())
            }
          },
        };
        SocketOption {
          level: opt.level,
          name: opt.name,
          state: opt.state,
          value,
        }
      })
      .collect()
  }
  fn send_http_callout<'a>(
    &mut self,
    cluster_name: &'a str,
    headers: Vec<(&'a str, &'a [u8])>,
    body: Option<&'a [u8]>,
    timeout_milliseconds: u64,
  ) -> (abi::envoy_dynamic_module_type_http_callout_init_result, u64) {
    let mut callout_id: u64 = 0;
    // Convert headers to module HTTP headers.
    let module_headers: Vec<abi::envoy_dynamic_module_type_module_http_header> = headers
      .iter()
      .map(|(k, v)| abi::envoy_dynamic_module_type_module_http_header {
        key_ptr: k.as_ptr() as *const _,
        key_length: k.len(),
        value_ptr: v.as_ptr() as *const _,
        value_length: v.len(),
      })
      .collect();
    let body_buffer = match body {
      Some(b) => abi::envoy_dynamic_module_type_module_buffer {
        ptr: b.as_ptr() as *const _,
        length: b.len(),
      },
      None => abi::envoy_dynamic_module_type_module_buffer {
        ptr: std::ptr::null(),
        length: 0,
      },
    };
    let result = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_http_callout(
        self.raw,
        &mut callout_id,
        str_to_module_buffer(cluster_name),
        module_headers.as_ptr() as *mut _,
        module_headers.len(),
        body_buffer,
        timeout_milliseconds,
      )
    };
    (result, callout_id)
  }
  fn increment_counter(
    &self,
    id: EnvoyCounterId,
    value: u64,
  ) -> Result<(), envoy_dynamic_module_type_metrics_result> {
    let EnvoyCounterId(id) = id;
    let res = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_increment_counter(self.raw, id, value)
    };
    if res == envoy_dynamic_module_type_metrics_result::Success {
      Ok(())
    } else {
      Err(res)
    }
  }
  fn set_gauge(
    &self,
    id: EnvoyGaugeId,
    value: u64,
  ) -> Result<(), envoy_dynamic_module_type_metrics_result> {
    let EnvoyGaugeId(id) = id;
    let res =
      unsafe { abi::envoy_dynamic_module_callback_network_filter_set_gauge(self.raw, id, value) };
    if res == envoy_dynamic_module_type_metrics_result::Success {
      Ok(())
    } else {
      Err(res)
    }
  }
  fn increase_gauge(
    &self,
    id: EnvoyGaugeId,
    value: u64,
  ) -> Result<(), envoy_dynamic_module_type_metrics_result> {
    let EnvoyGaugeId(id) = id;
    let res = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_increment_gauge(self.raw, id, value)
    };
    if res == envoy_dynamic_module_type_metrics_result::Success {
      Ok(())
    } else {
      Err(res)
    }
  }
  fn decrease_gauge(
    &self,
    id: EnvoyGaugeId,
    value: u64,
  ) -> Result<(), envoy_dynamic_module_type_metrics_result> {
    let EnvoyGaugeId(id) = id;
    let res = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_decrement_gauge(self.raw, id, value)
    };
    if res == envoy_dynamic_module_type_metrics_result::Success {
      Ok(())
    } else {
      Err(res)
    }
  }
  fn record_histogram_value(
    &self,
    id: EnvoyHistogramId,
    value: u64,
  ) -> Result<(), envoy_dynamic_module_type_metrics_result> {
    let EnvoyHistogramId(id) = id;
    let res = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_record_histogram_value(self.raw, id, value)
    };
    if res == envoy_dynamic_module_type_metrics_result::Success {
      Ok(())
    } else {
      Err(res)
    }
  }
  fn get_cluster_host_count(&self, cluster_name: &str, priority: u32) -> Option<ClusterHostCount> {
    let mut total: usize = 0;
    let mut healthy: usize = 0;
    let mut degraded: usize = 0;
    let success = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_get_cluster_host_count(
        self.raw,
        str_to_module_buffer(cluster_name),
        priority,
        &mut total as *mut _,
        &mut healthy as *mut _,
        &mut degraded as *mut _,
      )
    };
    if success {
      Some(ClusterHostCount {
        total,
        healthy,
        degraded,
      })
    } else {
      None
    }
  }
  fn get_upstream_host_address(&self) -> Option<(String, u32)> {
    let mut address = abi::envoy_dynamic_module_type_envoy_buffer {
      ptr: std::ptr::null_mut(),
      length: 0,
    };
    let mut port: u32 = 0;
    let result = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_get_upstream_host_address(
        self.raw,
        &mut address as *mut _ as *mut _,
        &mut port,
      )
    };
    if !result || address.length == 0 || address.ptr.is_null() {
      return None;
    }
    let address_str = unsafe {
      std::str::from_utf8_unchecked(std::slice::from_raw_parts(
        address.ptr as *const _,
        address.length,
      ))
    };
    Some((address_str.to_string(), port))
  }
  fn get_upstream_host_hostname(&self) -> Option<String> {
    let mut hostname = abi::envoy_dynamic_module_type_envoy_buffer {
      ptr: std::ptr::null_mut(),
      length: 0,
    };
    let result = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_get_upstream_host_hostname(
        self.raw,
        &mut hostname as *mut _ as *mut _,
      )
    };
    if !result || hostname.length == 0 || hostname.ptr.is_null() {
      return None;
    }
    let hostname_str = unsafe {
      std::str::from_utf8_unchecked(std::slice::from_raw_parts(
        hostname.ptr as *const _,
        hostname.length,
      ))
    };
    Some(hostname_str.to_string())
  }
  fn get_upstream_host_cluster(&self) -> Option<String> {
    let mut cluster_name = abi::envoy_dynamic_module_type_envoy_buffer {
      ptr: std::ptr::null_mut(),
      length: 0,
    };
    let result = unsafe {
      abi::envoy_dynamic_module_callback_network_filter_get_upstream_host_cluster(
        self.raw,
        &mut cluster_name as *mut _ as *mut _,
      )
    };
    if !result || cluster_name.length == 0 || cluster_name.ptr.is_null() {
      return None;
    }
    let cluster_str = unsafe {
      std::str::from_utf8_unchecked(std::slice::from_raw_parts(
        cluster_name.ptr as *const _,
        cluster_name.length,
      ))
    };
    Some(cluster_str.to_string())
  }
  fn has_upstream_host(&self) -> bool {
    unsafe { abi::envoy_dynamic_module_callback_network_filter_has_upstream_host(self.raw) }
  }
  fn start_upstream_secure_transport(&mut self) -> bool {
    unsafe {
      abi::envoy_dynamic_module_callback_network_filter_start_upstream_secure_transport(self.raw)
    }
  }
  fn get_connection_state(&self) -> abi::envoy_dynamic_module_type_network_connection_state {
    unsafe { abi::envoy_dynamic_module_callback_network_filter_get_connection_state(self.raw) }
  }
  fn read_disable(
    &mut self,
    disable: bool,
  ) -> abi::envoy_dynamic_module_type_network_read_disable_status {
    unsafe { abi::envoy_dynamic_module_callback_network_filter_read_disable(self.raw, disable) }
  }
  fn read_enabled(&self) -> bool {
    unsafe { abi::envoy_dynamic_module_callback_network_filter_read_enabled(self.raw) }
  }
  fn is_half_close_enabled(&self) -> bool {
    unsafe { abi::envoy_dynamic_module_callback_network_filter_is_half_close_enabled(self.raw) }
  }
  fn enable_half_close(&mut self, enabled: bool) {
    unsafe {
      abi::envoy_dynamic_module_callback_network_filter_enable_half_close(self.raw, enabled)
    }
  }
  fn get_buffer_limit(&self) -> u32 {
    unsafe { abi::envoy_dynamic_module_callback_network_filter_get_buffer_limit(self.raw) }
  }
  fn set_buffer_limits(&mut self, limit: u32) {
    unsafe { abi::envoy_dynamic_module_callback_network_filter_set_buffer_limits(self.raw, limit) }
  }
  fn above_high_watermark(&self) -> bool {
    unsafe { abi::envoy_dynamic_module_callback_network_filter_above_high_watermark(self.raw) }
  }
  fn new_scheduler(&self) -> impl EnvoyNetworkFilterScheduler + 'static {
    unsafe {
      let scheduler_ptr = abi::envoy_dynamic_module_callback_network_filter_scheduler_new(self.raw);
      EnvoyNetworkFilterSchedulerImpl {
        raw_ptr: scheduler_ptr,
      }
    }
  }
  fn get_worker_index(&self) -> u32 {
    unsafe { abi::envoy_dynamic_module_callback_network_filter_get_worker_index(self.raw) }
  }
}
// Network Filter Event Hook Implementations
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_config_new(
  envoy_filter_config_ptr: abi::envoy_dynamic_module_type_network_filter_config_envoy_ptr,
  name: abi::envoy_dynamic_module_type_envoy_buffer,
  config: abi::envoy_dynamic_module_type_envoy_buffer,
) -> abi::envoy_dynamic_module_type_network_filter_config_module_ptr {
  let mut envoy_filter_config = EnvoyNetworkFilterConfigImpl::new(envoy_filter_config_ptr);
  let name_str = unsafe {
    std::str::from_utf8_unchecked(std::slice::from_raw_parts(
      name.ptr as *const _,
      name.length,
    ))
  };
  let config_slice = unsafe { std::slice::from_raw_parts(config.ptr as *const _, config.length) };
  init_network_filter_config(
    &mut envoy_filter_config,
    name_str,
    config_slice,
    NEW_NETWORK_FILTER_CONFIG_FUNCTION
      .get()
      .expect("NEW_NETWORK_FILTER_CONFIG_FUNCTION must be set"),
  )
}
pub(crate) fn init_network_filter_config<EC: EnvoyNetworkFilterConfig, ENF: EnvoyNetworkFilter>(
  envoy_filter_config: &mut EC,
  name: &str,
  config: &[u8],
  new_network_filter_config_fn: &NewNetworkFilterConfigFunction<EC, ENF>,
) -> abi::envoy_dynamic_module_type_network_filter_config_module_ptr {
  let network_filter_config = new_network_filter_config_fn(envoy_filter_config, name, config);
  match network_filter_config {
    Some(config) => wrap_into_c_void_ptr!(config),
    None => std::ptr::null(),
  }
}
/// # Safety
///
/// This is an FFI function called by Envoy. All pointer arguments must be valid as guaranteed
/// by the Envoy dynamic module ABI.
#[no_mangle]
pub unsafe extern "C" fn envoy_dynamic_module_on_network_filter_config_destroy(
  filter_config_ptr: abi::envoy_dynamic_module_type_network_filter_config_module_ptr,
) {
  drop_wrapped_c_void_ptr!(
    filter_config_ptr,
    NetworkFilterConfig<EnvoyNetworkFilterImpl>
  );
}
/// # Safety
///
/// This is an FFI function called by Envoy. All pointer arguments must be valid as guaranteed
/// by the Envoy dynamic module ABI.
#[no_mangle]
pub unsafe extern "C" fn envoy_dynamic_module_on_network_filter_new(
  filter_config_ptr: abi::envoy_dynamic_module_type_network_filter_config_module_ptr,
  envoy_filter_ptr: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
) -> abi::envoy_dynamic_module_type_network_filter_module_ptr {
  let mut envoy_filter = EnvoyNetworkFilterImpl::new(envoy_filter_ptr);
  let filter_config = {
    let raw = filter_config_ptr as *const *const dyn NetworkFilterConfig<EnvoyNetworkFilterImpl>;
    &**raw
  };
  envoy_dynamic_module_on_network_filter_new_impl(&mut envoy_filter, filter_config)
}
pub(crate) fn envoy_dynamic_module_on_network_filter_new_impl(
  envoy_filter: &mut EnvoyNetworkFilterImpl,
  filter_config: &dyn NetworkFilterConfig<EnvoyNetworkFilterImpl>,
) -> abi::envoy_dynamic_module_type_network_filter_module_ptr {
  let filter = filter_config.new_network_filter(envoy_filter);
  wrap_into_c_void_ptr!(filter)
}
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_new_connection(
  envoy_ptr: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
  filter_ptr: abi::envoy_dynamic_module_type_network_filter_module_ptr,
) -> abi::envoy_dynamic_module_type_on_network_filter_data_status {
  let filter = filter_ptr as *mut Box<dyn NetworkFilter<EnvoyNetworkFilterImpl>>;
  let filter = unsafe { &mut *filter };
  filter.on_new_connection(&mut EnvoyNetworkFilterImpl::new(envoy_ptr))
}
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_read(
  envoy_ptr: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
  filter_ptr: abi::envoy_dynamic_module_type_network_filter_module_ptr,
  data_length: usize,
  end_stream: bool,
) -> abi::envoy_dynamic_module_type_on_network_filter_data_status {
  let filter = filter_ptr as *mut Box<dyn NetworkFilter<EnvoyNetworkFilterImpl>>;
  let filter = unsafe { &mut *filter };
  filter.on_read(
    &mut EnvoyNetworkFilterImpl::new(envoy_ptr),
    data_length,
    end_stream,
  )
}
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_write(
  envoy_ptr: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
  filter_ptr: abi::envoy_dynamic_module_type_network_filter_module_ptr,
  data_length: usize,
  end_stream: bool,
) -> abi::envoy_dynamic_module_type_on_network_filter_data_status {
  let filter = filter_ptr as *mut Box<dyn NetworkFilter<EnvoyNetworkFilterImpl>>;
  let filter = unsafe { &mut *filter };
  filter.on_write(
    &mut EnvoyNetworkFilterImpl::new(envoy_ptr),
    data_length,
    end_stream,
  )
}
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_event(
  envoy_ptr: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
  filter_ptr: abi::envoy_dynamic_module_type_network_filter_module_ptr,
  event: abi::envoy_dynamic_module_type_network_connection_event,
) {
  let filter = filter_ptr as *mut Box<dyn NetworkFilter<EnvoyNetworkFilterImpl>>;
  let filter = unsafe { &mut *filter };
  filter.on_event(&mut EnvoyNetworkFilterImpl::new(envoy_ptr), event);
}
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_destroy(
  filter_ptr: abi::envoy_dynamic_module_type_network_filter_module_ptr,
) {
  let _ =
    unsafe { Box::from_raw(filter_ptr as *mut Box<dyn NetworkFilter<EnvoyNetworkFilterImpl>>) };
}
#[no_mangle]
/// # Safety
/// Caller must ensure `filter_ptr`, `headers`, and `body_chunks` point to valid memory for the
/// provided sizes, and that the pointed-to data lives for the duration of this call.
pub unsafe extern "C" fn envoy_dynamic_module_on_network_filter_http_callout_done(
  envoy_ptr: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
  filter_ptr: abi::envoy_dynamic_module_type_network_filter_module_ptr,
  callout_id: u64,
  result: abi::envoy_dynamic_module_type_http_callout_result,
  headers: *const abi::envoy_dynamic_module_type_envoy_http_header,
  headers_size: usize,
  body_chunks: *const abi::envoy_dynamic_module_type_envoy_buffer,
  body_chunks_size: usize,
) {
  let filter = filter_ptr as *mut Box<dyn NetworkFilter<EnvoyNetworkFilterImpl>>;
  let filter = unsafe { &mut *filter };
  // Convert headers to Vec<(EnvoyBuffer, EnvoyBuffer)>.
  let header_vec = if headers.is_null() || headers_size == 0 {
    Vec::new()
  } else {
    let headers_slice = unsafe { std::slice::from_raw_parts(headers, headers_size) };
    headers_slice
      .iter()
      .map(|h| {
        (
          unsafe { EnvoyBuffer::new_from_raw(h.key_ptr as *const _, h.key_length) },
          unsafe { EnvoyBuffer::new_from_raw(h.value_ptr as *const _, h.value_length) },
        )
      })
      .collect()
  };
  // Convert body chunks to Vec<EnvoyBuffer>.
  let body_vec = if body_chunks.is_null() || body_chunks_size == 0 {
    Vec::new()
  } else {
    let chunks_slice = unsafe { std::slice::from_raw_parts(body_chunks, body_chunks_size) };
    chunks_slice
      .iter()
      .map(|c| unsafe { EnvoyBuffer::new_from_raw(c.ptr as *const _, c.length) })
      .collect()
  };
  filter.on_http_callout_done(
    &mut EnvoyNetworkFilterImpl::new(envoy_ptr),
    callout_id,
    result,
    header_vec,
    body_vec,
  );
}
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_scheduled(
  envoy_ptr: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
  filter_ptr: abi::envoy_dynamic_module_type_network_filter_module_ptr,
  event_id: u64,
) {
  let filter = filter_ptr as *mut Box<dyn NetworkFilter<EnvoyNetworkFilterImpl>>;
  let filter = unsafe { &mut *filter };
  filter.on_scheduled(&mut EnvoyNetworkFilterImpl::new(envoy_ptr), event_id);
}
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_config_scheduled(
  filter_config_ptr: abi::envoy_dynamic_module_type_network_filter_config_module_ptr,
  event_id: u64,
) {
  let filter_config = {
    let raw = filter_config_ptr as *const *const dyn NetworkFilterConfig<EnvoyNetworkFilterImpl>;
    unsafe { &**raw }
  };
  filter_config.on_config_scheduled(event_id);
}
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_above_write_buffer_high_watermark(
  envoy_ptr: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
  filter_ptr: abi::envoy_dynamic_module_type_network_filter_module_ptr,
) {
  let filter = filter_ptr as *mut Box<dyn NetworkFilter<EnvoyNetworkFilterImpl>>;
  let filter = unsafe { &mut *filter };
  filter.on_above_write_buffer_high_watermark(&mut EnvoyNetworkFilterImpl::new(envoy_ptr));
}
#[no_mangle]
pub extern "C" fn envoy_dynamic_module_on_network_filter_below_write_buffer_low_watermark(
  envoy_ptr: abi::envoy_dynamic_module_type_network_filter_envoy_ptr,
  filter_ptr: abi::envoy_dynamic_module_type_network_filter_module_ptr,
) {
  let filter = filter_ptr as *mut Box<dyn NetworkFilter<EnvoyNetworkFilterImpl>>;
  let filter = unsafe { &mut *filter };
  filter.on_below_write_buffer_low_watermark(&mut EnvoyNetworkFilterImpl::new(envoy_ptr));
}