mirror of
https://github.com/mrvasil/ctf-ad-mirror-tool-rust.git
synced 2026-10-23 16:31:02 +00:00
39 lines
3.4 KiB
Markdown
39 lines
3.4 KiB
Markdown
# Engine implementation contract
|
|
|
|
Implement `src/engine.rs` and `tests/forwarding.rs`. Root owns config.rs and other modules. Export from lib.rs by adding `pub mod engine;` only; do not edit config or Cargo dependencies without coordinating.
|
|
|
|
Public types:
|
|
```rust
|
|
pub struct Engine; // cloneable handle, internally shared
|
|
impl Engine {
|
|
pub fn new(settings: crate::config::NetworkConfig) -> Self;
|
|
pub async fn upsert(&self, service: &crate::config::ServiceConfig, teams: &[crate::config::Team]) -> anyhow::Result<()>;
|
|
pub async fn remove(&self, id: &str) -> anyhow::Result<()>;
|
|
pub fn snapshots(&self) -> std::collections::BTreeMap<String, EngineStatus>;
|
|
pub async fn shutdown(&self);
|
|
}
|
|
#[derive(Clone, Debug, serde::Serialize)]
|
|
pub struct EngineStatus {
|
|
pub running: bool,
|
|
pub stats: TrafficStats,
|
|
pub last_error: Option<String>,
|
|
}
|
|
#[derive(Clone, Debug, Default, serde::Serialize)]
|
|
pub struct TrafficStats {
|
|
pub accepted: u64, pub active: u64, pub completed: u64,
|
|
pub connect_errors: u64, pub io_errors: u64, pub rejected: u64, pub accept_errors: u64,
|
|
pub bytes_up: u64, pub bytes_down: u64,
|
|
pub replica_disconnects: u64, pub replica_errors: u64, pub replica_bytes: u64,
|
|
}
|
|
```
|
|
|
|
`upsert` binds before success, returns bind errors to caller, updates targets without restarting an unchanged listener, keeps existing sessions on their original route, supports enabled=false (stop accepting, let old sessions drain; bound drain/cancel on whole engine shutdown). Re-enable must be reliable. Explicit remove should retire metrics only after no leaked tasks; stop accepting and bound existing drain is acceptable, document semantics. Only forward new streams to the configured primary, no midstream retry/replay.
|
|
|
|
Tokio only, no subprocess/thread-per-connection. Process-wide connection semaphore before accept/spawn to bound tasks (or shed promptly with `rejected` counter). `TcpSocket`/TcpListener, TCP_NODELAY; connect timeout only, no short socket I/O timeout. Preserve both directions until EOF/half-close; shutdown opposite write half, do not abort reply on request EOF. Isolate requests and replica responses: always drain replica replies concurrently, ignore content. Memory bound by configured queue and chunk sizes, `Bytes` shared across sinks, no per-replica payload clones if feasible.
|
|
|
|
Replica policies:
|
|
- `Isolate` (default): a bounded non-blocking queue per replica. A full queue or replica error explicitly disconnects that replica for THIS session and increments a counter. Never drop an arbitrary chunk and continue sending an invalid stream. Primary proceeds independently. No replica reconnect/replay midstream.
|
|
- `Strict`: connect all required replicas before sending client bytes; bounded queues apply backpressure; replica failure ends the session explicitly (error metrics) instead of silently proceeding. Strict mode cannot promise availability/primary throughput when a replica is slower or absent.
|
|
|
|
Connection/task shutdown must be cancellation-safe, close owned sockets and release permits. Active metrics increment/decrement using RAII or equivalently reliable path. Increments on hot path relaxed atomics, no locked logging of payloads. No unsafe code needed. Include normal bulk bidirectional delivery, half-close, >3s idle, live retarget old/new streams, slow/failing replica behavior, bind conflict/error, connection limits, clean shutdown tests. Meaningful integration tests using loopback.
|