aboutsummaryrefslogtreecommitdiffstats
path: root/link/link-protocol.h
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-30 05:58:38 +0100
committereunhhu <[email protected]>2026-09-30 05:58:38 +0100
commit5ce7655d613689223050715ff3f8fe5c456ebf11 (patch)
tree03c55f96e604f6d42a102cbea7de73bc040e5a1c /link/link-protocol.h
parentb0bec448d30f198dc4817d71fc8c72654907a3a9 (diff)
downloadpure-5ce7655d613689223050715ff3f8fe5c456ebf11.tar.gz
pure-5ce7655d613689223050715ff3f8fe5c456ebf11.zip
Take a delivery's fields by name, dropping none
A message from another node was taken only in its input's exact shape (the link's STREAM shape, fields and order alike; over HTTP, every field). So a board whose nodes are upgraded one after the other stopped both ways until both were, and an output and its input whose fields differ only in order were refused for good (docs/design/014). An input now takes a message when it has every field the sender sends, by name, of the same type or one that holds its values (a u32 in a number, text in bytes); a field only the input has is 0 or empty. One that sends a field the input lacks is refused: taking it would drop the value, and with its number heard the value would never come again (two boards apart for good). So add fields to receivers first and take them from senders first, and nothing stops or is lost. The link carries a sender's fields in a new frame, FIELDS (0x0d: names, shape, u8 count, each {type, name length, name}): after a REFUSED for another shape the sender puts it in its packets (after OFFER, before the records, so a receiver that knows no FIELDS reads what it read before) until the stream is taken, the first time at once. A receiver seeing another shape waits for the packet's FIELDS before refusing, and asks its host with them (PureLinkHost.input takes them); REFUSED says 4 when the input lacks a field. Deliveries carry the fields and the host lays each record out anew (pure_module_takes, pure_module_recast, pure_module_fields, over pure_send_recast's rule). A stream whose sender starts again in another shape lets go what it held; the sender sends it again laid out anew. A refusal already queued for a stream now says the last reason judged, not the first. Over HTTP a delivery (X-Pure-Source) may lack fields; an unknown member is still refused. test-link named: a stream of another shape naming its fields is taken, 200 stored in 47 ms with every delivery naming them; an input that does not take them refuses (4) and the sender backs off. check.py server_fields: five outputs, three linked and two over HTTP, fields in another order taken, an input with a field more taking messages without it, one lacking a field refusing until it starts again with it, then taking all. server_upgrade's new receiver declares its fields in another order. 012 names the frame and the rules.
Diffstat (limited to 'link/link-protocol.h')
-rw-r--r--link/link-protocol.h26
1 files changed, 21 insertions, 5 deletions
diff --git a/link/link-protocol.h b/link/link-protocol.h
index e4d3080..feff543 100644
--- a/link/link-protocol.h
+++ b/link/link-protocol.h
@@ -111,6 +111,12 @@
* sender sends one packet of them a wait from then (a
* second, twice as long each time, 64 s at most) until one
* is stored
+ * 0x0d FIELDS source, input, u32 shape (as STREAM), then the fields the
+ * stream's records are laid out with (core/module.h's
+ * pure_module_fields): after a REFUSED for another shape,
+ * in every packet (after OFFER, before records) until the
+ * stream is taken. A receiver whose input has every field
+ * takes it by name (docs/design/014-fields-by-name.md)
* 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, with RACK's patience for packets
@@ -129,9 +135,10 @@
enum { PURE_LINK_DATAGRAM = 1200, PURE_LINK_DATAGRAM_MOST = 1452, PURE_LINK_NAME = 64, PURE_LINK_ADDRESS = 48,
PURE_LINK_RECORD_MOST = 16 << 20 };
/* Why a receiver refuses a stream (REFUSED): no input of that name takes
- * messages, the input takes messages of another shape, or the sender's key
- * may not send as that source. */
-enum { PURE_LINK_NO_INPUT = 1, PURE_LINK_OTHER_SHAPE = 2, PURE_LINK_NOT_ALLOWED = 3 };
+ * messages, the input takes messages of another shape (send FIELDS), the
+ * sender's key may not send as that source, or the input lacks fields the
+ * stream sends (it would drop them). */
+enum { PURE_LINK_NO_INPUT = 1, PURE_LINK_OTHER_SHAPE = 2, PURE_LINK_NOT_ALLOWED = 3, PURE_LINK_FIELDS_LACKED = 4 };
/* Counts for a host's report: packets and records sent, records sent again,
* packets lost and acknowledged, packets received, deliveries handed over,
@@ -193,6 +200,9 @@ unsigned pure_link_sender_refusal(const PureLinkSender *);
/* How often it moves on to a new epoch (ns), and after how many bytes sent
* (an hour and a GiB at first). */
void pure_link_sender_epochs(PureLinkSender *, uint64_t every_ns, uint64_t bytes);
+/* The fields its records are laid out with (pure_module_fields), for a
+ * receiver whose input takes another shape (FIELDS); none at first. */
+bool pure_link_sender_fields(PureLinkSender *, const unsigned char *fields, size_t size);
/* The last number queued; the last the receiver stored. */
uint64_t pure_link_sender_queued(const PureLinkSender *);
uint64_t pure_link_sender_stored(const PureLinkSender *);
@@ -206,7 +216,9 @@ void pure_link_sender_free(PureLinkSender *);
* pure_link_idle). A stream (a source to an input) goes to the host's input
* its name and shape find: its number, or -PURE_LINK_OTHER_SHAPE when it
* takes another shape, or -1 (PURE_LINK_NO_INPUT) when none takes messages
- * by that name; a stream refused is said to be (REFUSED). Whole
+ * by that name; asked again with the fields the sender names (FIELDS),
+ * its number when it takes them by name, else -PURE_LINK_FIELDS_LACKED. A
+ * stream refused is said to be (REFUSED). Whole
* records of a stream, in order, go to deliver as one delivery; the host
* applies them from the one after the source's last heard number, stops at
* a gap, saves, and then says so with a done (pure_link_receiver_turn).
@@ -220,9 +232,13 @@ typedef struct {
const unsigned char *records; /* count of: u32le size, bytes (the receiver's: the host's during the call) */
size_t size;
void *token; /* for its done */
+ /* The fields the records are laid out with when the input took them by
+ * name (the host lays each out anew for it), else NULL. */
+ const unsigned char *fields;
+ size_t fields_size;
} PureLinkDelivery;
typedef struct {
- int (*input)(void *context, const char *name, uint32_t shape);
+ int (*input)(void *context, const char *name, uint32_t shape, const unsigned char *fields, size_t fields_size);
bool (*deliver)(void *context, const PureLinkDelivery *);
void *context;
} PureLinkHost;