aboutsummaryrefslogtreecommitdiffstats
path: root/serve/link.h
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-29 07:06:27 +0100
committereunhhu <[email protected]>2026-09-29 07:06:27 +0100
commita052b95c8135cdc5f9b91f8efc991cac80fbbe8b (patch)
tree2b7b0d7a0ccd5bc6ceaa603a01eb87deb6c1f2e8 /serve/link.h
parent0b4a9f7225b5873e606106b8eaf9174b254c0c0f (diff)
downloadpure-a052b95c8135cdc5f9b91f8efc991cac80fbbe8b.tar.gz
pure-a052b95c8135cdc5f9b91f8efc991cac80fbbe8b.zip
Put the links and the crypto they use in link/, a part of their own
libpure-link.a holds them; pure-serve and the M5 harness link it instead of naming its source files.
Diffstat (limited to 'serve/link.h')
-rw-r--r--serve/link.h118
1 files changed, 0 insertions, 118 deletions
diff --git a/serve/link.h b/serve/link.h
deleted file mode 100644
index 83cc645..0000000
--- a/serve/link.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#ifndef PURE_LINK_H
-#define PURE_LINK_H
-#include "module.h"
-#include "seal.h"
-
-/* Links without connections (docs/design/011-pure-transport.md): one node's
- * saved sends to another node's input over UDP, sealed with a key the two
- * nodes' keys share, with no handshake: the first packet carries records.
- * A link's lasting state is the apps' own: the sender's outbox (what to send
- * and send again) and the receiver's heard numbers (what it applied, saved
- * with the events). What either side keeps in memory is a cache, so either
- * may restart and the other goes on with the next packet.
- *
- * A packet is a header in the clear, then frames sealed with AES-128-GCM
- * (the header as associated data):
- * u8 0x70 (version 0), u32le the key id of the node that sent it (FNV-1a
- * of its public key; two keys may share an id, and a receiver tries the
- * keys it allows with it), u64le that node's run (random, new each time it
- * starts, so no nonce repeats under a key across restarts), u64le the
- * packet's number in its run.
- * Keys come from the secret the two nodes' keys share (X25519) by
- * HKDF-SHA256, with both public keys and the sending node's run: a sender's
- * packets use its own run; a receiver's answers add the run they answer,
- * so an answer opens only in that run. The nonce is the key's base with the
- * packet's number in its last eight bytes (XOR, big-endian, as QUIC does).
- *
- * Frames (numbers little-endian):
- * 0x01 STREAM source (u8 length, bytes), input (u8 length, bytes), u32 the
- * shape of the messages (the sender's output and the
- * receiver's input must have the same): the stream the
- * records after it are of
- * 0x02 RECORD u64 number, u32 size, u32 offset, u16 length, bytes: a piece
- * of a saved send (pieces are 1000 bytes, the last shorter)
- * 0x03 ACK u64 largest number, u32 delay (µs), u8 ranges, each as u64
- * first and u64 last, newest first
- * 0x04 STORED source, input (as STREAM), u64 the last number heard
- * (applied and saved), u8 flags (1: a record after a gap was
- * not taken: send what follows it again), u32 credit (records
- * it takes past that)
- * 0x05 PING to be acknowledged
- * 0x06 RECORDS u64 the first one's number, u8 count, then whole records one
- * after another (numbers following on), each its size (a
- * varint: LEB128) and its bytes: a send that fits the packet
- * whole, with 1 to 3 bytes of framing, not the 19 of RECORD
- * 0x00 PADDING to the end of the packet: a full packet sent in a burst is
- * a whole datagram
- * Losses are detected as RFC 9002 says; congestion control is its NewReno
- * (RFC 9002 §7). */
-
-/* The sending side: one output's saved sends to url, pure://host:port/INPUT,
- * as source (a Pure receiver's name for it), from own (this node's key,
- * whose public half is own_public) to the receiver's public key, given by
- * pure_link_peer before pure_link_start. The owner queues and trims as it
- * does a wire's (serve/deliver.h): a send counts as delivered once the
- * receiver says it saved it. */
-typedef struct PureLink PureLink;
-PureLink *pure_link_open(const PureModule *m, const char *output, const char *url, const char *source,
- const PureSealKey *own, const unsigned char own_public[PURE_SEAL_KEY], char *error,
- size_t size);
-void pure_link_peer(PureLink *, const unsigned char peer[PURE_SEAL_KEY]);
-uint32_t pure_link_output(const PureLink *);
-bool pure_link_queue(PureLink *, uint64_t seq, PureSpan payload);
-uint64_t pure_link_queued(PureLink *);
-/* The last number the receiver saved; any thread. */
-uint64_t pure_link_delivered(PureLink *);
-/* Send on a thread of the link's own, calling notify when more was saved. */
-bool pure_link_start(PureLink *, void (*notify)(void *), void *context, char *error, size_t size);
-void pure_link_close(PureLink *);
-
-/* The receiving side: packets on a UDP port, from the senders allowed (a
- * source name and the key it seals with, a few bytes each however many
- * there are: see pure_link_idle). Whole records of a stream, in
- * order, go to deliver (on the listener's thread) as one delivery; the host
- * applies them from the one after the source's last heard number, stops at
- * a gap, saves, and then calls pure_link_done (any thread) with the last
- * number heard. Records wait here until then, and only the saved ones are
- * acknowledged as stored. */
-typedef struct {
- uint32_t input;
- const char *source;
- uint64_t first;
- unsigned count;
- const unsigned char *records; /* count of: u32le size, bytes */
- size_t size;
- void *token; /* for pure_link_done */
-} PureLinkDelivery;
-typedef struct PureLinkListener PureLinkListener;
-PureLinkListener *pure_link_listen(const PureModule *m, unsigned port, const PureSealKey *own,
- const unsigned char own_public[PURE_SEAL_KEY],
- bool (*deliver)(void *, const PureLinkDelivery *), void *context, char *error,
- size_t size);
-bool pure_link_allow(PureLinkListener *, const char *source, const unsigned char key[PURE_SEAL_KEY], char *error,
- size_t size);
-/* A sender quiet for ms (30 s at first) with nothing of it waiting lets its
- * keys, addresses and streams go: an idle link costs the listener only its
- * allowing, and the sender's next packet makes them again (one X25519). */
-void pure_link_idle(PureLinkListener *, uint64_t ms);
-/* Remember the secret each sender's key shares with the node's in a file
- * (path, 0600; begun again for another node's key): a place a sender in
- * the order allowed, mapped, so a sender at rest takes no memory for it.
- * A node that starts again then makes no X25519 for a sender it heard from
- * before. After the senders are allowed, before serving. */
-bool pure_link_remember(PureLinkListener *, const char *path, char *error, size_t size);
-bool pure_link_serve(PureLinkListener *, char *error, size_t size);
-/* stored: the delivery's save succeeded; gap: it stopped at a gap. */
-void pure_link_done(PureLinkListener *, void *token, uint64_t heard, bool stored, bool gap);
-
-/* Counts for a host's report: packets and records sent, records sent again,
- * packets lost and acknowledged, packets received, deliveries handed over,
- * the last number stored; a listener's senders woken (their active state
- * made), of them with a secret remembered (no X25519), let go when idle,
- * and active when it closed. A listener's are given when it closes. */
-typedef struct {
- uint64_t packets, records, resent, lost, acknowledged, received, deliveries, stored, woken, remembered, swept, active;
-} PureLinkCounts;
-void pure_link_counts(PureLink *, PureLinkCounts *);
-void pure_link_listener_close(PureLinkListener *, PureLinkCounts *counts);
-#endif