diff options
| author | eunhhu <[email protected]> | 2026-09-29 14:39:27 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-29 14:39:27 +0100 |
| commit | dee0c1442202272de1f4a8ebe555af35874d691b (patch) | |
| tree | bbdbca2ff30ec155b48cff7b8c601a16abda03c9 /link/link-protocol.c | |
| parent | 0bbc12658c63f5f5fce2683798d4ac08b1e26e08 (diff) | |
| download | pure-dee0c1442202272de1f4a8ebe555af35874d691b.tar.gz pure-dee0c1442202272de1f4a8ebe555af35874d691b.zip | |
Begin an epoch only from the answer to this offer, not an earlier one
A sender that took its epoch for lost offers epoch 1 again with a new
key. The receiver accepts it in the turn, after the answers; until then
its answers still carried the ACCEPT of the earlier offer, which named
the same epoch. The sender began its epoch from that one, the two sides
held different secrets, and 2 s later it took the epoch for lost again:
a turn of that each time the order fell so. Now an ACCEPT carries the
first four bytes of the key it answers, and a sender begins its epoch
only from one that answers its own.
test-link cuts the path for 3 s the moment the sender begins an epoch,
three times; a sender's counts say how many epochs it took for lost,
and it must be three. Before, it was four.
Diffstat (limited to 'link/link-protocol.c')
| -rw-r--r-- | link/link-protocol.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/link/link-protocol.c b/link/link-protocol.c index 1f43e6c..8845ea5 100644 --- a/link/link-protocol.c +++ b/link/link-protocol.c @@ -22,8 +22,9 @@ enum { F_PADDING = 0, F_STREAM = 1, F_RECORD = 2, F_ACK = 3, F_STORED = 4, F_PIN F_RESPONSE = 8, F_OFFER = 9, F_ACCEPT = 10, STORED_GAP = 1 }; /* A packet's first byte is VERSION with the sending side's epoch (mod 16) * in its low four bits; OFFER and ACCEPT are an epoch's number (u32) and a - * public key made for it. */ -enum { EPOCH_MASK = 15, EPOCH_FRAME = 1 + 4 + PURE_SEAL_KEY }; + * public key made for it, and ACCEPT the first bytes of the key it answers + * (a sender may offer an epoch again with another key). */ +enum { EPOCH_MASK = 15, EPOCH_FRAME = 1 + 4 + PURE_SEAL_KEY, ANSWERS = 4, ACCEPT_FRAME = EPOCH_FRAME + ANSWERS }; enum { RECORDS_HEAD = 10 }; /* type, the first number, the count */ enum { RANGES = 32, RUNS = 2, UNITS = 64, CREDIT = 1024, BATCH = 256, RECORD_HEAD = 19 }; enum { WINDOW_FIRST = 10 * DATAGRAM, WINDOW_LEAST = 2 * DATAGRAM }; @@ -712,10 +713,12 @@ void pure_link_sender_take(PureLinkSender *l, const unsigned char *packet, size_ if (l->responding < RESPONSES) ++l->responding; } at += 8; - } else if (type == F_ACCEPT) { /* the epoch offered begins */ - if (at + EPOCH_FRAME - 1 > size) break; - if (l->offering && get32(plain + at) == l->offer_epoch) begin_epoch(l, plain + at + 4, now); - at += EPOCH_FRAME - 1; + } else if (type == F_ACCEPT) { /* the epoch offered begins: an answer to this offer, not one before */ + if (at + ACCEPT_FRAME - 1 > size) break; + if (l->offering && get32(plain + at) == l->offer_epoch && + !memcmp(plain + at + EPOCH_FRAME - 1, l->offer_public, ANSWERS)) + begin_epoch(l, plain + at + 4, now); + at += ACCEPT_FRAME - 1; } else if (type != F_PING) break; /* padding, or what this side does not know: the rest */ } @@ -954,6 +957,7 @@ void pure_link_sender_tick(PureLinkSender *l, uint64_t now) { offer(l, 1); l->renegotiating = true; l->offer_again = 0; + ++l->counts.fallbacks; } if (l->loss_time && l->loss_time <= now) detect_lost(l, now); else if (l->eliciting && l->last_eliciting + pto_period(l) <= now) { @@ -2165,7 +2169,8 @@ static void answer(PureLinkReceiver *s, uint64_t now, PureLinkSend *send, void * body[at] = F_ACCEPT; put32(body + at + 1, r->accept_epoch); memcpy(body + at + 5, r->accept_public, PURE_SEAL_KEY); - at += EPOCH_FRAME; + memcpy(body + at + EPOCH_FRAME, r->offered, ANSWERS); + at += ACCEPT_FRAME; } if (r->ack_due && r->got_count) { body[at++] = F_ACK; |
