mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-10-22 13:02:26 +00:00
add trace route resolution
packet details now includes resolved route
This commit is contained in:
7 files changed
+102
-5
No files matched your search
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user