CURSOR · ON · TARGET — RUST v0.0.1-pre   /   PRE-M0

takrs

A Rust kernel for the TAK ecosystem.

Drop-in replacement for the messaging core of the upstream Java TAK Server. Single-node mTLS streaming, alloc-free hot path, sub-millisecond p99 dispatch under load.

Linux-first MIT · Apache-2.0 148 / 148 tests
SCROLL
Section I  /  Performance

Measured,
not claimed.

Numbers from the harness, not the slide deck. Every figure below is reproducible from the test suite or a five-minute soak run on commodity Linux.

0µs

p99 dispatch round-trip

Single-connection probe at 20 Hz, alongside ~1 k msg/s of cross-fan-out load. The probe publishes a frame and reads the same bytes back through its wildcard subscription — the dispatch path round-trip end-to-end.

5-min soak · loopback · 50 conns × 200 Hz
0

Heap allocations on the hot path

tak_bus::dispatch performs zero heap allocations in steady state, regardless of subscriber count. Verified by a dhat integration test that fails the build if a single block is allocated during a burst.

Invariant H1 · tak-bus/tests/no_alloc.rs
0B

Fuzz executions, zero crashes

Two libFuzzer targets — the XML decoder and the streaming framer — ran for thirty minutes each with sanitizers on. Combined: 2.04 billion parses, zero panics, zero out-of-bounds, zero artifacts.

decode_xml: 318 M · decode_stream: 1.72 B
0/ 148

Tests passing

Workspace-wide. Includes property tests, conformance scenarios, loom concurrency models, and the dhat-gated allocation invariant. cargo nextest run is the runner. No flakes.

cargo-nextest · main · 2026-04-29
0kB / min

RSS slope under sustained load

Linear regression of resident set size during the late window of a 300-second soak under 10 k msg/s offered load. Threshold gate: 1024 kB/min. Steady-state working set: ~40 MB.

tak-soak · postgis testcontainer · mimalloc
0/ 10

Conformance scenarios pinned

End-to-end scenarios drive a real tak-server via a postgis testcontainer with mock ATAK clients. Pins byte-identity, fan-out, replay, multi-publisher concurrency, drop accounting, persistence, and lifecycle. Tenth (mTLS handshake) is queued.

tak-conformance · nextest · ~14s suite
Section II  /  Architecture

By design,
by default.

The hot path is fast because the architecture refuses to do slow things. Five locked decisions, machine-enforced.

H2

Decoders borrow from input.

Codec::decode returns a borrowed view that points into the original byte slice. No copy, no String::from, no to_owned(). The XML detail block survives as &str all the way to fan-out.

// every public decoder
fn decode<'a>(buf: &'a [u8])
    -> Result<View<'a>>
H3

Fan-out is an Arc bump.

Dispatching one frame to N subscribers means N reference-count increments on a single Bytes, not N memcpys. Vec<u8>::clone is forbidden in the dispatch path; reviews catch it, the bench harness would detect it.

// for each matched sub:
entry.sender.try_send(payload.clone())
// Bytes::clone => Arc bump, not memcpy
H4

Group AND is four instructions.

Group authorization uses a fixed [u64; 4] bitvector. Intersection is the bitwise OR of four ANDs — ~4 instructions on x86, vs an unbounded BigInteger.and() allocation in the upstream Java reference implementation.

pub fn intersects(a: &Self, b: &Self) -> bool {
    (a.0[0] & b.0[0])
  | (a.0[1] & b.0[1])
  | (a.0[2] & b.0[2])
  | (a.0[3] & b.0[3]) != 0
}
D1

Library code cannot panic.

unwrap, expect, panic!, todo!, and unimplemented! are denied by clippy in every library crate. Errors are thiserror enums; anyhow is allowed only inside binary crates. A panic in a library is a denial-of-service.

// every lib crate
#![deny(
    clippy::unwrap_used,
    clippy::expect_used,
    clippy::panic,
)]
D7

Persistence cannot block delivery.

The persistence side-channel is a bounded mpsc off the dispatch loop. If the channel fills, the persist drops with a counter increment. Delivery to live subscribers is never blocked by the database.

match store.try_insert_event(row) {
    Ok(()) => {}
    Err(_) => // counter++, drop, move on
}
Section III  /  Verification

Verified,
not vibed.

Six independent layers of proof. Each runs on every commit; none of them are decoration.

L1

Property tests

proptest

Generators on every codec invariant: round-trip, byte-stable proto, BigInteger-comparison for the group bitvector. "For all inputs, X holds."

L2

Fuzz

2.04 B execs · 0 crashes

libFuzzer with sanitizers on the XML decoder and the streaming framer. Runs nightly via cargo +nightly fuzz.

L3

VOPR

deterministic

Seed-replay verification harness for the bus. --alloc-mode verifies H1; --minimize shrinks failure traces with linear delta-debugging.

L4

Loom

model-checked

Concurrency model checker explores all schedules of concurrent subscribe / unsubscribe / dispatch. No data race, no deadlock, no lost message.

L5

Conformance

9 scenarios · mock ATAK

In-process tak-server against a real postgis container, driven by mock ATAK clients. Byte-identity, fan-out, replay, drop accounting.

L6

Soak

RSS-drift gated

Wall-clock harness drives sustained load while sampling /proc/<pid>/status. Linear regression fails the build if RSS drifts; pinned latency probe gates p99.

Section IV  /  Frequent questions

Plain
answers.

What people evaluating a Rust replacement for the Java TAK Server actually ask. No marketing, no hedging.

What is tak.rs?

tak.rs is a high-performance Rust kernel for the Team Awareness Kit (TAK) ecosystem. It is a drop-in replacement for the messaging core of the upstream Java TAK Server, optimized for single-node deployments at 10,000+ concurrent mTLS streaming clients on commodity Linux hardware.

Is tak.rs ATAK, iTAK, and WinTAK compatible?

Yes. tak.rs speaks TAK Protocol Version 1 (the magic byte 0xBF varint-prefixed protobuf TakMessage) on the streaming firehose — the same wire format that ATAK (Android), iTAK (iOS), and WinTAK use. The conformance suite drives mock ATAK clients through canonical Cursor-on-Target exchanges and pins byte-identity end-to-end.

How does tak.rs compare to FreeTAKServer, OpenTAKServer, taky, or GoATAK?

FreeTAKServer (Python), OpenTAKServer (Python), and taky (Python) are user-friendly community implementations; GoATAK is a Go alternative. tak.rs targets a different point in the design space: a Rust kernel optimized for single-node throughput at 10,000+ concurrent mTLS streaming clients with sub-millisecond p99 dispatch, alloc-free fan-out, and machine-enforced invariants. The hot path is built to be a drop-in for the upstream Java TAK Server, not a reinvention.

Is tak.rs production ready?

Pre-M0. The hot path is verified by six layers of proof: property tests (proptest), 2.04 billion fuzz executions across two libFuzzer targets with zero crashes, deterministic seed-replay verification (VOPR), Loom concurrency model checking, nine end-to-end conformance scenarios with mock ATAK clients, and a wall-clock soak harness with RSS-drift gating. Public deployment is gated on an mTLS handshake conformance scenario and a 24-hour soak baseline.

What TAK Protocol versions does tak.rs support?

TAK Protocol Version 1 (binary): magic byte 0xBF, varint-prefixed protobuf TakMessage. The streaming firehose on port 8089 (mTLS) is the production path; plain TCP on 8087 / 8088 is opt-in. The CoT XML codec round-trips Detail.xmlDetail byte-for-byte to preserve plug-in payloads ATAK clients depend on.

What is the license?

MIT or Apache-2.0, at the consumer's option — the standard Rust ecosystem license posture.

Why Rust instead of Java?

Two specific architectural wins. First, the Java TAK Server's hot path is dominated by per-message XPath evaluation; tak.rs compiles subscriptions into a struct (type prefix trie + geo R-tree + UID set + group mask) at subscribe time and dispatches as index lookups + bitwise AND at runtime. Second, group authorization in Java uses BigInteger.and() per message; tak.rs uses a fixed [u64; 4] bitvector that intersects in roughly four x86 instructions. Combined with bytes::Bytes Arc-counted fan-out and rustls (no OpenSSL), the hot path moves from milliseconds to microseconds.

How fast is tak.rs?

Sub-millisecond p99 dispatch round-trip under sustained load. Reference number: 144 µs p99 in a five-minute soak with 50 concurrent connections publishing at 200 Hz each (10,000 messages / second offered, 8,820 delivered / second after fan-out). Hot-path allocations: zero, verified by a dhat-gated invariant test that fails the build on a single allocation.

Does tak.rs federate with the official TAK Server?

Federation is deferred. v1 is single-node only, no Ignite, no clustering. The Mission API and CoT firehose are the in-scope surfaces; cross-server federation is queued for a later milestone.

How do I run tak.rs?

git clone the repository, then cargo nextest run for the test suite, cargo +nightly fuzz run --fuzz-dir crates/tak-cot/fuzz decode_xml for the codec fuzz harness, and tak-soak --duration-secs 300 for a baseline soak with the pinned latency probe. Every claim on this page is reproducible from a fresh clone.

Section V  /  Source

Read
the code.

Every claim above is reproducible from a clone. Run cargo nextest run, cargo +nightly fuzz run, or tak-soak and compare. The measurement harness ships with the kernel.

View on GitHub github.com/copyleftdev/tak-rs
git clone cargo nextest run cargo bench