Skip to content

Commit 8584669

Browse files
refactor: remove DATA_RETRANSMISSION packet type and document announce-back
Since protocol v0.03 is already a breaking change, simplify the wire protocol by removing the DATA_RETRANSMISSION type. The receiver now checks the packet deduplicator for ALL incoming DATA packets. If the packet group was already fully processed, an ACK is sent and the fragment is discarded. This provides the same behavior with one fewer packet type. Packet type numbering is now: ANNOUNCE=1, LEAVE=2, DATA=3, ACK=4, NACK=5 Also document the announce-back behavior: when a node hears an announce from an unknown peer, it immediately sends its own announce via unicast to that peer. This gives instant bidirectional connection without waiting for the next announce cycle.
1 parent 1ee5f58 commit 8584669

3 files changed

Lines changed: 23 additions & 22 deletions

File tree

docs/explanation/nuclearnet.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,9 @@ sequenceDiagram
113113
Note over A: New peer heard!
114114
A->>A: Add B to peer list
115115
A->>A: Fire NetworkJoin event
116+
A->>B: AnnouncePacket (unicast reply)
116117
117-
Note over B: Hears A's announce
118+
Note over B: Immediate connection
118119
B->>B: Add A to peer list
119120
B->>B: Fire NetworkJoin event
120121
@@ -128,6 +129,11 @@ sequenceDiagram
128129
A->>A: Fire NetworkLeave event
129130
```
130131

132+
When a node hears an announce from an unknown peer,
133+
it immediately sends its own announce back via unicast directly to that peer.
134+
This eliminates the need to wait for the next periodic announce cycle —
135+
new peers connect within a single round trip rather than waiting up to one full announce interval.
136+
131137
### Announce address options
132138

133139
The announce address can be:
@@ -180,14 +186,13 @@ A received packet is only accepted if the magic bytes, version, and type field a
180186

181187
### Packet types
182188

183-
| Type | Value | Purpose |
184-
| ------------------- | ----- | -------------------------------------- |
185-
| ANNOUNCE | 1 | Periodic discovery broadcast |
186-
| LEAVE | 2 | Graceful departure notification |
187-
| DATA | 3 | Normal data payload |
188-
| DATA_RETRANSMISSION | 4 | Retransmitted data fragment |
189-
| ACK | 5 | Acknowledgment of received fragments |
190-
| NACK | 6 | Request for specific missing fragments |
189+
| Type | Value | Purpose |
190+
| -------- | ----- | -------------------------------------- |
191+
| ANNOUNCE | 1 | Periodic discovery broadcast |
192+
| LEAVE | 2 | Graceful departure notification |
193+
| DATA | 3 | Data payload (original or retransmission) |
194+
| ACK | 4 | Acknowledgment of received fragments |
195+
| NACK | 5 | Request for specific missing fragments |
191196

192197
### Announce packet
193198

@@ -324,7 +329,7 @@ sequenceDiagram
324329
325330
Note over S: Sees fragment 1 not ACKed
326331
Note over S: Wait RTO timeout...
327-
S->>R: DataRetransmission (id=42, no=1)
332+
S->>R: DataPacket (id=42, no=1, retransmit)
328333
329334
R->>S: ACK (id=42, bitset=[1,1,1])
330335
Note over R: All fragments received, deliver message

src/nuclearnet/NUClearNet.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ namespace network {
225225
for (const auto& req : retransmissions) {
226226
// Build header on stack, scatter-write header + fragment data
227227
DataPacket header{};
228-
header.type = DATA_RETRANSMISSION;
229228
header.packet_id = req.packet_id;
230229
header.packet_no = req.packet_no;
231230
header.packet_count = req.packet_count;
@@ -429,8 +428,7 @@ namespace network {
429428
discovery->process_leave(source);
430429
} break;
431430

432-
case DATA:
433-
case DATA_RETRANSMISSION: {
431+
case DATA: {
434432
if (length < sizeof(DataPacket)) {
435433
return;
436434
}
@@ -439,9 +437,8 @@ namespace network {
439437

440438
// Check for duplicates (at the packet group level)
441439
auto& dedup = deduplicators[source];
442-
bool is_retransmission = (header->type == DATA_RETRANSMISSION);
443440

444-
if (is_retransmission && dedup.is_duplicate(pkt->packet_id)) {
441+
if (dedup.is_duplicate(pkt->packet_id)) {
445442
// Already processed this packet group — send ACK if reliable
446443
if ((pkt->flags & RELIABLE) != 0) {
447444
std::vector<bool> all_received(pkt->packet_count, true);

src/nuclearnet/wire_protocol.hpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,11 @@ namespace network {
4141

4242
/// Packet type identifiers
4343
enum PacketType : uint8_t {
44-
ANNOUNCE = 1,
45-
LEAVE = 2,
46-
DATA = 3,
47-
DATA_RETRANSMISSION = 4,
48-
ACK = 5,
49-
NACK = 6,
44+
ANNOUNCE = 1,
45+
LEAVE = 2,
46+
DATA = 3,
47+
ACK = 4,
48+
NACK = 5,
5049
};
5150

5251
/// Data packet flags (bit field)
@@ -109,7 +108,7 @@ namespace network {
109108
* Data packet — carries message payload (possibly one fragment of a larger message).
110109
*
111110
* Wire layout (18+ bytes):
112-
* [0-4] PacketHeader (type = DATA or DATA_RETRANSMISSION)
111+
* [0-4] PacketHeader (type = DATA)
113112
* [5-6] packet_id (uint16_t) — unique identifier for this packet group
114113
* [7-8] packet_no (uint16_t) — fragment index within the group (0-based)
115114
* [9-10] packet_count (uint16_t) — total fragments in the group

0 commit comments

Comments
 (0)