aws/s2n-quic

Implement congestion controller trait over `enum`

Opened this issue · 0 comments

#2078

Problem:

Due to the endpoint builder preferring completely static types, it makes it difficult to swap implementations of providers based on config:

let builder = if use_bbr {
    build.with_congestion_controller(congestion_controller::Bbr::default())?
} else {
    build.with_congestion_controller(congestion_controller::Cubic::default())?
};

Solution:

To make this pattern easier, we can provide an enum impl that is implemented generically for two different CCAs and dispatches at runtime:

enum Either<A, B> {
    Left(A),
    Right(B),
}

impl<A, B> CongestionController for Either<A, B>
where
    A: CongestionController,
    B: CongestionController,
{
    type PacketInfo = Either<A::PacketInfo, B::PacketInfo>;

    #[inline]
    fn congestion_window(&self) -> u32 {
        match self {
            Self::Left(cca) => cca.congestion_window(),
            Self::Right(cca) => cca.congestion_window(),
        }
    }

    ...
}

The application would then be able to switch at runtime:

let builder = if use_bbr {
    build.with_congestion_controller(Either::Left(congestion_controller::Bbr::default()))?
} else {
    build.with_congestion_controller(Either::Right(congestion_controller::Cubic::default()))?
};

It might make sense to use the either crate, or just define our own in s2n-quic-core to avoid the dependency.