aboutsummaryrefslogtreecommitdiffstats
path: root/link/link-protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'link/link-protocol.c')
-rw-r--r--link/link-protocol.c19
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;