# brutal-core

A small core implementation of a Brutal-style congestion controller.

`brutal-core` is a bandwidth-hint-driven congestion control core that computes congestion window from estimated bandwidth-delay product (BDP), RTT, and optional ACK-rate compensation.

It is transport-agnostic and runtime-agnostic. This crate does **not** implement pacing or a full QUIC stack.

## Features

- minimal and reusable core logic
- no runtime dependency
- no QUIC-stack dependency
- BDP-style congestion window calculation
- optional ACK-rate compensation
- `tracing` support

## Caveat

This crate does **not** provide pacing.

The configured bandwidth is used as an input for congestion-window estimation, not as a strict send-rate limit. In integrations without pacing, short-term burstiness may exceed the nominal bandwidth target.

## Installation

```toml
[dependencies]
brutal-core = "0.1"
```

## Example

```rust
use std::time::{Duration, Instant};

use brutal_core::{BrutalConfigCore, BrutalCore};

fn main() {
    let now = Instant::now();
    let mut cc = BrutalCore::new(BrutalConfigCore::default(), now, 1200);

    cc.set_peer_bandwidth_hint(Some(10_000_000));
    cc.on_sent(1200);
    cc.on_ack_bytes(1200, Duration::from_millis(80));
    cc.on_end_acks(Instant::now());

    println!("cwnd = {}", cc.window_cached());
}
```

## Model

The controller computes congestion window roughly as:

```text
cwnd ≈ bandwidth * rtt * cwnd_gain / effective_ack_rate / 8
```

and clamps the result to at least:

- `min_window`
- `mtu`

## API overview

- `BrutalCore::new(config, now, mtu)`
- `on_sent(bytes)`
- `on_ack_bytes(bytes, rtt)`
- `on_loss_bytes(bytes)`
- `on_end_acks(now)`
- `set_peer_bandwidth_hint(bps)`
- `on_mtu_update(mtu)`
- `window_cached()`

## Notes

- bandwidth unit: bits per second
- window unit: bytes
- RTT type: `Duration`

## License

MIT OR Apache-2.0
