mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-08-28 03:44:13 +00:00
## Summary Ports the firmware-1.16.0 extended ACK decoding from the ingestor (PR #1618, issue #1610) into the server-side re-decoder. Previously `cmd/server/decoder.go` silently dropped `ackLen`, `ackAttempt`, and `ackRand` (and the multipart inner equivalents) — the server emitted plain 4-byte ACKs even when the wire carried the 5/6-byte extended form. Now both decoders agree byte-for-byte. Closes #1694. ## What changed - `cmd/server/decoder.go::decodeAck`: sets `AckLen` (capped at 6), `AckAttempt` (`buf[4]` when `len>=5`), `AckRand` (`buf[5]` when `len>=6`). Mirrors `cmd/ingestor/decoder.go:279-305`. - `cmd/server/decoder.go::decodeMultipart` ACK branch: sets `InnerAckLen = len(buf)-1` (capped at 6), `InnerAckAttempt`, `InnerAckRand`. Mirrors `cmd/ingestor/decoder.go:696-714`. - `Payload` struct gains six `*int` fields tagged `omitempty`: `AckLen`, `AckAttempt`, `AckRand`, `InnerAckLen`, `InnerAckAttempt`, `InnerAckRand`. Backward-compatible JSON — legacy 4-byte ACKs leave attempt/rand nil and the fields are omitted from the output. No other decoder consumer is touched. Routes / store auto-surface the new fields via JSON marshaling. ## Test layout `cmd/server/decoder_ack_extended_test.go` drives `decodeAck` table-driven across the three wire shapes: | Buffer | AckLen | AckAttempt | AckRand | |---|---|---|---| | `EF BE AD DE` (CRC only) | 4 | nil | nil | | `EF BE AD DE 07` | 5 | 7 | nil | | `EF BE AD DE 07 42` | 6 | 7 | 0x42 | Plus `TestDecodeMultipartAckExtendedInner` for a 7-byte multipart buffer (`0x33` header + 6-byte inner ACK), asserting `InnerAckLen=6`, `InnerAckAttempt=7`, `InnerAckRand=0x42`. ## TDD trail - **Red commit** (test + struct stubs only, `decodeAck`/`decodeMultipart` unchanged) → assertions fail on `AckLen=nil`. - **Green commit** (port implementation) → all assertions pass. Full `cd cmd/server && go test ./...` passes locally. ## Firmware refs - `firmware/src/helpers/BaseChatMesh.cpp:218-234` (extended ACK layout) - firmware commit `f6e6fdaa` (attempt counter) - firmware commit `a130a95a` (RNG byte) --------- Co-authored-by: Kpa-clawbot <bot@kpa-clawbot>
This commit is contained in:
co-authored by
Kpa-clawbot
parent
547b141530
commit
e96f0f9f9f
+44
-1
@@ -91,6 +91,11 @@ type Payload struct {
|
||||
MAC string `json:"mac,omitempty"`
|
||||
EncryptedData string `json:"encryptedData,omitempty"`
|
||||
ExtraHash string `json:"extraHash,omitempty"`
|
||||
// Extended ACK fields per firmware 1.16.0 (issue #1610) — populated by
|
||||
// decodeAck once the server-side re-decoder is upgraded (issue #1694).
|
||||
AckLen *int `json:"ackLen,omitempty"`
|
||||
AckAttempt *int `json:"ackAttempt,omitempty"`
|
||||
AckRand *int `json:"ackRand,omitempty"`
|
||||
PubKey string `json:"pubKey,omitempty"`
|
||||
Timestamp uint32 `json:"timestamp,omitempty"`
|
||||
TimestampISO string `json:"timestampISO,omitempty"`
|
||||
@@ -124,6 +129,11 @@ type Payload struct {
|
||||
InnerType *int `json:"innerType,omitempty"`
|
||||
InnerTypeName string `json:"innerTypeName,omitempty"`
|
||||
InnerAckCrc string `json:"innerAckCrc,omitempty"`
|
||||
// Extended ACK inner fields (issue #1610 / #1694) — populated by
|
||||
// decodeMultipart once ACK parity is ported from the ingestor.
|
||||
InnerAckLen *int `json:"innerAckLen,omitempty"`
|
||||
InnerAckAttempt *int `json:"innerAckAttempt,omitempty"`
|
||||
InnerAckRand *int `json:"innerAckRand,omitempty"`
|
||||
InnerPayload string `json:"innerPayload,omitempty"`
|
||||
// CONTROL (PAYLOAD_TYPE_CONTROL=0x0B) byte0 flags, per
|
||||
// firmware/src/Mesh.cpp:69 — high-bit = zero-hop direct subset.
|
||||
@@ -241,10 +251,27 @@ func decodeAck(buf []byte) Payload {
|
||||
return Payload{Type: "ACK", Error: "too short", RawHex: hex.EncodeToString(buf)}
|
||||
}
|
||||
checksum := binary.LittleEndian.Uint32(buf[0:4])
|
||||
return Payload{
|
||||
ackLen := len(buf)
|
||||
if ackLen > 6 {
|
||||
ackLen = 6
|
||||
}
|
||||
p := Payload{
|
||||
Type: "ACK",
|
||||
ExtraHash: fmt.Sprintf("%08x", checksum),
|
||||
AckLen: &ackLen,
|
||||
}
|
||||
// Firmware 1.16.0 extended ACK (issue #1610): 5th byte is the attempt
|
||||
// counter (commit f6e6fdaa), 6th byte is a random byte added so identical
|
||||
// attempts still hash uniquely (commit a130a95a).
|
||||
if len(buf) >= 5 {
|
||||
attempt := int(buf[4])
|
||||
p.AckAttempt = &attempt
|
||||
}
|
||||
if len(buf) >= 6 {
|
||||
rnd := int(buf[5])
|
||||
p.AckRand = &rnd
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func decodeAdvert(buf []byte, validateSignatures bool) Payload {
|
||||
@@ -378,6 +405,22 @@ func decodeMultipart(buf []byte) Payload {
|
||||
if innerType == PayloadACK && len(buf) >= 5 {
|
||||
crc := binary.LittleEndian.Uint32(buf[1:5])
|
||||
p.InnerAckCrc = fmt.Sprintf("%08x", crc)
|
||||
// Firmware 1.16.0 extended ACK (issue #1610): inner ACK blob may be
|
||||
// 5 or 6 bytes (payload_len = 1 + ack_len) instead of always 4.
|
||||
// Attempt counter added in commit f6e6fdaa, RNG byte in commit a130a95a.
|
||||
ackLen := len(buf) - 1
|
||||
if ackLen > 6 {
|
||||
ackLen = 6
|
||||
}
|
||||
p.InnerAckLen = &ackLen
|
||||
if len(buf) >= 6 {
|
||||
attempt := int(buf[5])
|
||||
p.InnerAckAttempt = &attempt
|
||||
}
|
||||
if len(buf) >= 7 {
|
||||
rnd := int(buf[6])
|
||||
p.InnerAckRand = &rnd
|
||||
}
|
||||
} else if len(buf) > 1 {
|
||||
p.InnerPayload = hex.EncodeToString(buf[1:])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user