add trace route resolution

packet details now includes resolved route
This commit is contained in:
Enot (ded) Skelly committed 2026-06-04 11:58:45 -07:00
1 parent 538f80d344
commit ec7cf67a10
7 files changed
+102 -5

No files matched your search

+2 -1
View File
@@ -421,10 +421,11 @@ For paginated responses use the generic page wrapper:
- [x] Parse payloads (that we can decrypt) into DB and return with packet
details
- [x] Propagation time calculation
- [x] Trace route resolution via path hashes (resolvedRoute on packet detail)
### In progress / next
- [ ] Routes and traces endpoints
- [ ] Dedicated routes and traces endpoints (see issue #32)
### Future
+78
View File
@@ -1289,6 +1289,84 @@ func (s *Store) GetPacket(ctx context.Context, packetHash []byte) (*api.Packet,
}
p.Observations = append(p.Observations, obs)
}
if row.PayloadType == 9 && len(obsRows) > 0 {
var tracePayload struct {
PathHashes []string `json:"pathHashes"`
Flags byte `json:"flags"`
}
if err := json.Unmarshal(row.ParsedPayload, &tracePayload); err == nil && len(tracePayload.PathHashes) > 0 {
hashSize := int(1 << (tracePayload.Flags & 0x03))
hashes := make([][]byte, 0, len(tracePayload.PathHashes))
for _, h := range tracePayload.PathHashes {
b, err := hex.DecodeString(h)
if err == nil {
hashes = append(hashes, b)
}
}
// collect unique IATAs from observations
seenIATAs := make(map[string]struct{})
for _, v := range obsRows {
seenIATAs[v.Iata] = struct{}{}
}
// merge results across all IATAs — best confidence per hop wins
// confidence priority: high > ambiguous > none
type hopResult struct {
confidence string
entries []api.ResolvedPathEntry
}
merged := make([]hopResult, len(hashes))
for i := range merged {
merged[i] = hopResult{confidence: "none"}
}
confidenceRank := map[string]int{"none": 0, "ambiguous": 1, "high": 2}
for iata := range seenIATAs {
resolved, err := s.ResolvePathHashes(ctx, iata, hashes)
if err != nil {
log.Printf("store: trace route resolution failed for iata=%s: %v", iata, err)
continue
}
for i, hash := range hashes {
key := hex.EncodeToString(hash[:hashSize])
entries := resolved[key]
var confidence string
switch len(entries) {
case 0:
confidence = "none"
case 1:
confidence = "high"
default:
confidence = "ambiguous"
}
if confidenceRank[confidence] > confidenceRank[merged[i].confidence] {
merged[i] = hopResult{confidence: confidence, entries: entries}
}
}
}
route := make([]api.ResolvedHop, 0, len(hashes))
for _, hr := range merged {
hop := api.ResolvedHop{
Confidence: hr.confidence,
Nodes: make([]api.ResolvedNode, 0, len(hr.entries)),
}
for _, e := range hr.entries {
hop.Nodes = append(hop.Nodes, api.ResolvedNode{
ID: e.NodeID,
Name: e.Name,
Latitude: e.Latitude,
Longitude: e.Longitude,
PublicKey: hex.EncodeToString(e.PublicKey),
})
}
route = append(route, hop)
}
p.ResolvedRoute = route
}
}
return p, nil
}
+7 -1
View File
@@ -937,7 +937,7 @@ const docTemplate = `{
"tags": [
"Packets"
],
"summary": "Get full packet detail",
"summary": "Get full packet detail. For trace packets (payloadType=9), includes resolvedRoute",
"parameters": [
{
"type": "string",
@@ -1846,6 +1846,12 @@ const docTemplate = `{
"rawPayload": {
"type": "string"
},
"resolvedRoute": {
"type": "array",
"items": {
"$ref": "#/definitions/github_com_MeshCore-Tower_tower-server_internal_api.ResolvedHop"
}
},
"scope": {
"type": "string"
},
+7 -1
View File
@@ -935,7 +935,7 @@
"tags": [
"Packets"
],
"summary": "Get full packet detail",
"summary": "Get full packet detail. For trace packets (payloadType=9), includes resolvedRoute",
"parameters": [
{
"type": "string",
@@ -1844,6 +1844,12 @@
"rawPayload": {
"type": "string"
},
"resolvedRoute": {
"type": "array",
"items": {
"$ref": "#/definitions/github_com_MeshCore-Tower_tower-server_internal_api.ResolvedHop"
}
},
"scope": {
"type": "string"
},
+6 -1
View File
@@ -363,6 +363,10 @@ definitions:
type: array
rawPayload:
type: string
resolvedRoute:
items:
$ref: '#/definitions/github_com_MeshCore-Tower_tower-server_internal_api.ResolvedHop'
type: array
scope:
type: string
transportCodes:
@@ -1310,7 +1314,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/internal_api_handlers.APIError'
summary: Get full packet detail
summary: Get full packet detail. For trace packets (payloadType=9), includes
resolvedRoute
tags:
- Packets
/regions:
+1 -1
View File
@@ -123,7 +123,7 @@ func listPackets(reader api.Reader) http.HandlerFunc {
// getPacket godoc
//
// @Summary Get full packet detail
// @Summary Get full packet detail. For trace packets (payloadType=9), includes resolvedRoute
// @Tags Packets
// @Produce json
// @Param packetHash path string true "Packet hash (hex)"
+1
View File
@@ -176,6 +176,7 @@ type Packet struct {
LastHeardAt int64 `json:"lastHeardAt"`
FirstToLastMs int64 `json:"firstToLastMs"`
ObservationCount int32 `json:"observationCount"`
ResolvedRoute []ResolvedHop `json:"resolvedRoute,omitempty"`
Observations []PacketObservationDetail `json:"observations"`
}