quic/s2n-quic-core/src/packet/interceptor.rs (248 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use crate::{
event::api::{SocketAddress, Subject},
havoc,
packet::number::{PacketNumber, PacketNumberSpace},
path::{LocalAddress, RemoteAddress},
time::Timestamp,
varint::VarInt,
};
use core::ops::RangeInclusive;
use s2n_codec::encoder::scatter;
pub use s2n_codec::{DecoderBufferMut, EncoderBuffer};
pub mod loss;
pub use loss::Loss;
/// TODO add `non_exhaustive` once/if this feature is stable
#[derive(Debug)]
pub struct Packet {
pub number: PacketNumber,
pub timestamp: Timestamp,
}
/// TODO add `non_exhaustive` once/if this feature is stable
#[derive(Debug)]
pub struct Datagram<'a> {
pub remote_address: SocketAddress<'a>,
pub local_address: SocketAddress<'a>,
pub timestamp: Timestamp,
}
pub trait Ack {
fn space(&self) -> PacketNumberSpace;
fn insert_range(&mut self, range: RangeInclusive<VarInt>);
}
/// Trait which enables an application to intercept packets that are transmitted and received
pub trait Interceptor: 'static + Send {
#[inline(always)]
fn intercept_rx_ack<A: Ack>(&mut self, subject: &Subject, ack: &mut A) {
let _ = subject;
let _ = ack;
}
#[inline(always)]
fn intercept_rx_local_address(&mut self, subject: &Subject, addr: &mut LocalAddress) {
let _ = subject;
let _ = addr;
}
#[inline(always)]
fn intercept_rx_remote_address(&mut self, subject: &Subject, addr: &mut RemoteAddress) {
let _ = subject;
let _ = addr;
}
#[inline(always)]
fn intercept_rx_datagram<'a>(
&mut self,
subject: &Subject,
datagram: &Datagram,
payload: DecoderBufferMut<'a>,
) -> DecoderBufferMut<'a> {
let _ = subject;
let _ = datagram;
payload
}
#[inline(always)]
fn intercept_rx_payload<'a>(
&mut self,
subject: &Subject,
packet: &Packet,
payload: DecoderBufferMut<'a>,
) -> DecoderBufferMut<'a> {
let _ = subject;
let _ = packet;
payload
}
#[inline(always)]
fn intercept_tx_datagram(
&mut self,
subject: &Subject,
datagram: &Datagram,
payload: &mut EncoderBuffer,
) {
let _ = subject;
let _ = datagram;
let _ = payload;
}
#[inline(always)]
fn intercept_tx_payload(
&mut self,
subject: &Subject,
packet: &Packet,
payload: &mut scatter::Buffer,
) {
let _ = subject;
let _ = packet;
let _ = payload;
}
}
#[derive(Debug, Default)]
pub struct Disabled(());
impl Interceptor for Disabled {}
impl<X, Y> Interceptor for (X, Y)
where
X: Interceptor,
Y: Interceptor,
{
#[inline(always)]
fn intercept_rx_ack<A: Ack>(&mut self, subject: &Subject, ack: &mut A) {
self.0.intercept_rx_ack(subject, ack);
self.1.intercept_rx_ack(subject, ack);
}
#[inline(always)]
fn intercept_rx_local_address(&mut self, subject: &Subject, addr: &mut LocalAddress) {
self.0.intercept_rx_local_address(subject, addr);
self.1.intercept_rx_local_address(subject, addr);
}
#[inline(always)]
fn intercept_rx_remote_address(&mut self, subject: &Subject, addr: &mut RemoteAddress) {
self.0.intercept_rx_remote_address(subject, addr);
self.1.intercept_rx_remote_address(subject, addr);
}
#[inline(always)]
fn intercept_rx_datagram<'a>(
&mut self,
subject: &Subject,
datagram: &Datagram,
payload: DecoderBufferMut<'a>,
) -> DecoderBufferMut<'a> {
let payload = self.0.intercept_rx_datagram(subject, datagram, payload);
self.1.intercept_rx_datagram(subject, datagram, payload)
}
#[inline(always)]
fn intercept_rx_payload<'a>(
&mut self,
subject: &Subject,
packet: &Packet,
payload: DecoderBufferMut<'a>,
) -> DecoderBufferMut<'a> {
let payload = self.0.intercept_rx_payload(subject, packet, payload);
self.1.intercept_rx_payload(subject, packet, payload)
}
#[inline(always)]
fn intercept_tx_datagram(
&mut self,
subject: &Subject,
datagram: &Datagram,
payload: &mut EncoderBuffer,
) {
self.0.intercept_tx_datagram(subject, datagram, payload);
self.1.intercept_tx_datagram(subject, datagram, payload);
}
#[inline(always)]
fn intercept_tx_payload(
&mut self,
subject: &Subject,
packet: &Packet,
payload: &mut scatter::Buffer,
) {
self.0.intercept_tx_payload(subject, packet, payload);
self.1.intercept_tx_payload(subject, packet, payload);
}
}
#[derive(Debug, Default)]
pub struct Havoc<Rx, Tx, P, R>
where
Rx: 'static + Send + havoc::Strategy,
Tx: 'static + Send + havoc::Strategy,
P: 'static + Send + havoc::Strategy,
R: 'static + Send + havoc::Random,
{
pub rx: Rx,
pub tx: Tx,
pub port: P,
pub random: R,
}
impl<Rx, Tx, P, R> Interceptor for Havoc<Rx, Tx, P, R>
where
Rx: 'static + Send + havoc::Strategy,
Tx: 'static + Send + havoc::Strategy,
P: 'static + Send + havoc::Strategy,
R: 'static + Send + havoc::Random,
{
#[inline]
fn intercept_rx_remote_address(&mut self, _subject: &Subject, addr: &mut RemoteAddress) {
let port = addr.port();
let port = self.port.havoc_u16(&mut self.random, port);
addr.set_port(port);
}
#[inline]
fn intercept_rx_payload<'a>(
&mut self,
_subject: &Subject,
_packet: &Packet,
payload: DecoderBufferMut<'a>,
) -> DecoderBufferMut<'a> {
let payload = payload.into_less_safe_slice();
let len = payload.len();
let len = {
use s2n_codec::Encoder;
let mut payload = EncoderBuffer::new(payload);
payload.set_position(len);
self.rx.havoc(&mut self.random, &mut payload);
payload.len()
};
let payload = &mut payload[..len];
DecoderBufferMut::new(payload)
}
#[inline]
fn intercept_tx_payload(
&mut self,
_subject: &Subject,
_packet: &Packet,
payload: &mut scatter::Buffer,
) {
let payload = payload.flatten();
self.tx.havoc(&mut self.random, payload);
}
}
impl<T: Interceptor> Interceptor for Option<T> {
#[inline]
fn intercept_rx_local_address(&mut self, subject: &Subject, addr: &mut LocalAddress) {
if let Some(inner) = self.as_mut() {
inner.intercept_rx_local_address(subject, addr)
}
}
#[inline]
fn intercept_rx_remote_address(&mut self, subject: &Subject, addr: &mut RemoteAddress) {
if let Some(inner) = self.as_mut() {
inner.intercept_rx_remote_address(subject, addr)
}
}
#[inline]
fn intercept_rx_payload<'a>(
&mut self,
subject: &Subject,
packet: &Packet,
payload: DecoderBufferMut<'a>,
) -> DecoderBufferMut<'a> {
if let Some(inner) = self.as_mut() {
inner.intercept_rx_payload(subject, packet, payload)
} else {
payload
}
}
#[inline]
fn intercept_tx_payload(
&mut self,
subject: &Subject,
packet: &Packet,
payload: &mut scatter::Buffer,
) {
if let Some(inner) = self.as_mut() {
inner.intercept_tx_payload(subject, packet, payload)
}
}
}