Skip to content

wowinter13/licklider

Repository files navigation

licklider

The first Rust implementation of the Licklider Transmission Protocol (LTP, RFC 5326) — the retransmission-based reliable transport NASA uses between planets.

⚠️ Experimental — not flight software. A faithful, well-tested implementation intended for research, testbeds, and as the missing LTP convergence layer for the Rust DTN ecosystem — not for operational spacecraft.

LTP is the standard convergence layer under the Bundle Protocol (BPv7, RFC 9171) in delay-tolerant networks: links with round-trip times of minutes to hours, scheduled intermittent connectivity, and possibly one-way channels. That means no handshakes, no negotiation, massive concurrent state retention, and retransmission timers that are suspended during known link outages.

Named after J. C. R. Licklider, who imagined an "Intergalactic Computer Network".

Design: sans-I/O

licklider-core is a sans-I/O protocol engine — no sockets, no clocks, no threads, no async. You feed it events with an explicit timestamp and drain its outputs; it is a pure state machine. This is the quinn-proto / smoltcp / str0m pattern, and it is what makes interplanetary-scale testing tractable: a 40-minute Earth–Mars round trip is simulated by advancing a mock clock, so the full retransmission and outage-suspension logic runs in milliseconds.

flowchart LR
    subgraph driver["driver (licklider-udp / simulator / your runtime)"]
        SOCK[UDP socket / SimLink]:::io
        CLOCK[clock]:::io
        APP[client service]:::io
    end
    subgraph core["licklider-core::Engine  — pure state, no I/O"]
        direction TB
        SESS[session tables]
        TT[timer wheel\nsingle deadline]
        Q[per-peer queues]
    end
    SOCK -- "handle_input(now, Segment)" --> core
    CLOCK -- "handle_timeout(now)" --> core
    APP -- "request_transmission(now, …) → SessionId" --> core
    core -- "poll_output(now) → Transmit" --> SOCK
    core -- "poll_output(now) → Notice" --> APP
    core -- "next_timeout() → Option<Timestamp>" --> CLOCK
    classDef io fill:#eef;
Loading

Workspace

Crate What it is
licklider-core The sans-I/O engine: SDNV + segment codec, sender/receiver state machines (RFC 5326 §8), timers with outage suspend/resume (§6.5/§6.6). One dependency: bytes.
licklider-udp Tokio UDP link service, wire-compatible with NASA ION's udplso/udplsi: one LTP segment per datagram, port 1113 (IANA ltp-deepspace).
licklider-cli licklider send / licklider recv file transfer with built-in link impairment.
licklider-sim Deterministic two-engine link simulator (virtual clock, seeded loss/dup/reorder, contact plans). The Mars test lives here. Not published.

How it compares

licklider ION-DTN HDTN Unibo-LTP
Language Rust C C++ C
License MIT OR Apache-2.0 various (NASA OSA) NASA OSA GPL-2.0+
Sans-I/O core
Async-agnostic ✅ (core has no runtime)
Fuzzed ✅ (cargo-fuzz, decoder + stateful engine) partial
Flight-used ❌ (experimental)

Try it

$ licklider recv --listen 127.0.0.1:1113 --engine 2 --peer 1@127.0.0.1:1114 --out got.bin &
$ licklider send file.bin --to 2@127.0.0.1:1113 --engine 1 --listen 127.0.0.1:1114 \
      --red all --impair loss=0.3,dup=0.05,seed=7
 INFO sending block bytes=200000 red_len=200000 to=127.0.0.1:1113
 INFO session started sid=1/2523736422
 INFO initial transmission complete
 INFO ✓ transmission complete (red part acknowledged)
$ cmp file.bin got.bin && echo identical
identical

A 200 KB block delivered byte-identically over a link dropping 30 % of datagrams and duplicating 5 %, purely through LTP checkpoint/report/ retransmission — no external netem required.

The Mars test

cargo test -p licklider-sim --test mars --release -- --nocapture transfers a 10 MiB block across a 4- or 20-minute one-way-light-time link with hour-long contacts, three-hour outages, and 5 % loss, and prints:

MARS[20min] owlt=20min block=10MiB mtu=1400
  complete in 3 contact cycle(s), virtual 8.7h
  DS tx 8056 (566 rxmt, 7.6%), RS 36, RA 34
  outage emissions: 0 ✓

Zero segments are emitted during an outage; retransmission timers are suspended across the dark and resumed on the next contact — LTP's defining behavior, and the whole reason for the sans-I/O + virtual-clock design.

Conformance

Every MUST / SHOULD / MAY of RFC 5326 §3–§8, and each of its internal procedures, is tracked in docs/rfc5326-checklist.md against the implementing function and the covering test. Local implementation choices are recorded in DECISIONS.md. Architecture and state diagrams are in docs/ARCHITECTURE.md.

Out of scope for v0.1

  • RFC 5327 authentication — extensions are parsed and skipped only (the cookie extension is prohibited by CCSDS 734.1-B-1 anyway).
  • LTP Service Data Aggregation (client service ID 2).
  • CCSDS AOS / Encapsulation framing — a LinkService boundary is designed for it; v0.1 ships UDP only.
  • Session persistence across restarts — in-memory only.
  • Congestion control — LTP has none by design; rate control is the link layer's responsibility.

License

MIT OR Apache-2.0, at your option.

About

LTP (RFC 5326) in Rust: reliable transport for J.C.R. Licklider's "Intergalactic Computer Network," built sans-I/O like quinn-proto and tested against a virtual Mars. The Dream Machine @ Stripe Press

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors