summaryrefslogtreecommitdiffstats
path: root/src/transport/mod.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-25 20:33:40 +0100
committertv <tv@krebsco.de>2026-10-25 20:33:40 +0100
commit944bd3a9da9c14153247b483ba2cfe1457fc84d2 (patch)
tree447a444cbef42e4911fffd53fb2acfd961239ee4 /src/transport/mod.rs
parent7a3b0f46b1c899305cdfe8b06e2a64e9748d5b42 (diff)
late messages don't flip peer's epoch back
Diffstat (limited to 'src/transport/mod.rs')
-rw-r--r--src/transport/mod.rs25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/transport/mod.rs b/src/transport/mod.rs
index c5769ca..564aada 100644
--- a/src/transport/mod.rs
+++ b/src/transport/mod.rs
@@ -86,6 +86,8 @@ pub struct Keepalive {
/// Only comparable between nodes on the same epoch.
pub heads: HeadsSummary,
pub epoch: Epoch,
+ /// See `SyncEnvelope::epoch_seq`.
+ pub epoch_seq: u32,
/// The sender is ready (same meaning as `SyncEnvelope::ready`).
pub ready: bool,
/// The sender would sync with the recipient: counts it as an active member on its
@@ -131,6 +133,8 @@ impl std::fmt::Display for BlobId {
pub struct BlobMessage {
/// The sender's epoch (every message carries it).
pub epoch: Epoch,
+ /// See `SyncEnvelope::epoch_seq`.
+ pub epoch_seq: u32,
pub id: BlobId,
pub body: BlobBody,
}
@@ -215,6 +219,17 @@ impl ParsedMessage {
ParsedMessage::Blob(blob) => blob.epoch,
}
}
+
+ /// `SyncEnvelope::epoch_seq`, as every message carries it.
+ pub fn epoch_seq(&self) -> u32 {
+ match self {
+ ParsedMessage::Hello(hello) => hello.epoch_seq,
+ ParsedMessage::HelloReply(reply) => reply.epoch_seq,
+ ParsedMessage::Sync(envelope) => envelope.epoch_seq,
+ ParsedMessage::Ping(keepalive) | ParsedMessage::Pong(keepalive) => keepalive.epoch_seq,
+ ParsedMessage::Blob(blob) => blob.epoch_seq,
+ }
+ }
}
#[derive(Debug, Clone)]
@@ -223,6 +238,8 @@ pub struct HelloRequest {
/// another swarm doesn't answer.
pub swarm_id: Option<String>,
pub epoch: Epoch,
+ /// See `SyncEnvelope::epoch_seq`.
+ pub epoch_seq: u32,
/// Proof of the swarm key (`swarm::auth`); empty without one.
pub auth: Vec<u8>,
/// The sender is ready (same meaning as `SyncEnvelope::ready`).
@@ -236,6 +253,8 @@ pub struct HelloReply {
pub swarm_id: String,
pub peers: Vec<String>,
pub epoch: Epoch,
+ /// See `SyncEnvelope::epoch_seq`.
+ pub epoch_seq: u32,
/// Proof of the swarm key (`swarm::auth`); empty without one.
pub auth: Vec<u8>,
/// The sender is ready.
@@ -246,6 +265,8 @@ pub struct HelloReply {
/// How long before this HELLO the sender had last heard from the recipient, if ever
/// (in milliseconds): tells a restarted node how long it was away.
pub away_ms: Option<u64>,
+ /// The sender's own run (as its HELLOs carry it): a new one means it restarted.
+ pub sender_run_id: RunId,
}
#[derive(Debug, Clone)]
@@ -253,6 +274,10 @@ pub struct SyncEnvelope {
pub swarm_id: String,
/// Epoch of the document the message was generated from.
pub epoch: Epoch,
+ /// How many times the sender changed epoch in its current run, when it sent this
+ /// (`Replica::epoch_seq`). Messages may arrive late and out of order: the receiver
+ /// ignores an epoch older than the newest it has seen in the same session.
+ pub epoch_seq: u32,
pub message: Message,
/// The sender was ready when it generated the message: its document is the swarm's,
/// not one it is still filling (joining, rejoining). Only such a peer can tell a