aboutsummaryrefslogtreecommitdiffstats
path: root/link/test-link.c
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-29 16:41:24 +0100
committereunhhu <[email protected]>2026-09-29 16:41:24 +0100
commit3bd9b6c924c801dc5033510391ac251a7309219f (patch)
treed0465bb16850b822e4b2a09a73cf370993fd4f16 /link/test-link.c
parent590cbb9d0c73c9e48ac4a637c2e88a7e99c7965f (diff)
downloadpure-3bd9b6c924c801dc5033510391ac251a7309219f.tar.gz
pure-3bd9b6c924c801dc5033510391ac251a7309219f.zip
Take no send larger than a receiver holds: 16 MiB, not 64
A sender took sends up to 64 MiB, but a receiver holds 16 MiB of a stream not yet stored, so a send between the two went again forever. The most a send may be is now PURE_LINK_RECORD_MOST, what a receiver holds; test-link sends one that large whole and is refused one byte more.
Diffstat (limited to 'link/test-link.c')
-rw-r--r--link/test-link.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/link/test-link.c b/link/test-link.c
index 1d84804..9b709ce 100644
--- a/link/test-link.c
+++ b/link/test-link.c
@@ -652,6 +652,64 @@ static void flood(const char *dir) {
free(w.packets);
}
+/* The largest send (PURE_LINK_RECORD_MOST) goes whole, over a receiver that
+ * never heard of the stream before; one byte more is not taken to send. */
+typedef struct { World *w; PureLinkSender *s; } Largest;
+static bool deliver_largest(void *context, const PureLinkDelivery *d) {
+ World *w = context;
+ uint32_t size = (uint32_t)d->records[0] | (uint32_t)d->records[1] << 8 | (uint32_t)d->records[2] << 16 |
+ (uint32_t)d->records[3] << 24;
+ bool same = d->first == 1 && d->count == 1 && size == PURE_LINK_RECORD_MOST;
+ for (size_t i = 0; same && i < size; i += 4099) same = d->records[4 + i] == record_byte(1, i);
+ CHECK(same, "largest: a delivery of %u records from %llu, the first %u bytes", d->count,
+ (unsigned long long)d->first, size);
+ w->heard = same ? 1 : w->heard;
+ w->done[w->done_count++] = (PureLinkDone){d->token, 1, true, false};
+ return true;
+}
+static bool answer_largest(void *context, const unsigned char *packet, size_t size, const unsigned char *to,
+ size_t to_size) {
+ (void)to, (void)to_size;
+ Largest *l = context;
+ pure_link_sender_take(l->s, packet, size, l->w->now);
+ return true;
+}
+static void largest(const char *dir) {
+ unsigned char public_a[PURE_SEAL_KEY], public_b[PURE_SEAL_KEY], out[PURE_LINK_DATAGRAM_MOST];
+ char error[256];
+ PureSealKey *a = key(dir, "a.key", public_a), *b = key(dir, "b.key", public_b);
+ World w = {0};
+ PureLinkReceiver *r = pure_link_receiver(b, public_b, &(PureLinkHost){input_of, deliver_largest, &w}, error,
+ sizeof(error));
+ PureLinkSender *s = pure_link_sender("test.ordered", "order", 0x5eed, a, public_a);
+ unsigned char *bytes = malloc(PURE_LINK_RECORD_MOST + 1);
+ if (!r || !s || !bytes || !pure_link_allow(r, "test.ordered", public_a, error, sizeof(error)) ||
+ !pure_link_sender_peer(s, public_b))
+ exit(1);
+ for (size_t i = 0; i <= PURE_LINK_RECORD_MOST; ++i) bytes[i] = record_byte(1, i);
+ CHECK(!pure_link_sender_queue(s, 1, bytes, PURE_LINK_RECORD_MOST + 1), "largest: a send past the most was taken");
+ CHECK(pure_link_sender_queue(s, 1, bytes, PURE_LINK_RECORD_MOST), "largest: the most a send may be was not taken");
+ free(bytes);
+ Largest l = {&w, s};
+ uint64_t number;
+ for (; w.now < 60000 * MS && pure_link_sender_stored(s) < 1; w.now += MS) {
+ for (size_t size; (size = pure_link_sender_packet(s, out, false, w.now, &number));)
+ pure_link_receiver_take(r, out, size, "sender0", 7, w.now);
+ size_t told = w.done_count;
+ memcpy(w.told, w.done, told * sizeof(*w.done));
+ w.done_count = 0;
+ pure_link_receiver_turn(r, w.told, told, w.now, answer_largest, &l);
+ pure_link_sender_tick(s, w.now);
+ }
+ CHECK(w.heard == 1 && pure_link_sender_stored(s) == 1, "largest: heard %llu, stored %llu after %llu ms",
+ (unsigned long long)w.heard, (unsigned long long)pure_link_sender_stored(s), (unsigned long long)(w.now / MS));
+ printf("{\"case\":\"largest\",\"bytes\":%d,\"virtual_ms\":%llu}\n", PURE_LINK_RECORD_MOST,
+ (unsigned long long)(w.now / MS));
+ pure_link_sender_free(s);
+ pure_link_receiver_free(r);
+ pure_seal_key_free(a), pure_seal_key_free(b);
+}
+
int main(void) {
char dir[] = "/tmp/pure-test-link-XXXXXX", error[256];
if (!mkdtemp(dir) || !pure_seal_ready(error, sizeof(error))) {
@@ -710,6 +768,7 @@ int main(void) {
o.hole ? "opened" : "never opened", o.datagram);
impostors(dir);
flood(dir);
+ largest(dir);
char command[600];
snprintf(command, sizeof(command), "rm -rf %s", dir);
if (system(command)) { /* left behind in /tmp */ }