mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-10-17 02:50:00 +00:00
Imported boundaries override borderFile on the border map and for foreign marking, falling back to the manual border when MeshMapper has none.
85 lines
2.2 KiB
Go
85 lines
2.2 KiB
Go
// Copyright 2026 Beacon Contributors
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"maps"
|
|
"os"
|
|
"slices"
|
|
|
|
"github.com/MeshCore-Beacon/beacon-server/internal/borders"
|
|
"github.com/paulmach/orb"
|
|
"github.com/paulmach/orb/geojson"
|
|
)
|
|
|
|
func (c *Config) hasBorderFile() bool {
|
|
for _, details := range c.IATAs {
|
|
if details.BorderFile != "" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// LoadLocalBorders reads the validated border files used for foreign marking,
|
|
// keyed by IATA. IATA airport coordinates are not boundaries. Nil when disabled.
|
|
func LoadLocalBorders(cfg *Config) (map[string]json.RawMessage, error) {
|
|
if !cfg.Nodes.MarkForeign {
|
|
return nil, nil
|
|
}
|
|
files := map[string]json.RawMessage{}
|
|
for code, details := range cfg.IATAs {
|
|
if details.BorderFile == "" {
|
|
continue
|
|
}
|
|
raw, err := os.ReadFile(details.BorderFile)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("nodes.mark_foreign: reading border for %s: %w", code, err)
|
|
}
|
|
validated, err := ValidateBorder(raw)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("nodes.mark_foreign: invalid border for %s: %w", code, err)
|
|
}
|
|
files[code] = validated
|
|
}
|
|
// Fail at startup rather than on the first rebuild.
|
|
if _, err := BuildLocalBorders(files, nil); err != nil {
|
|
return nil, err
|
|
}
|
|
return files, nil
|
|
}
|
|
|
|
// BuildLocalBorders unions validated borders; an imported boundary replaces
|
|
// the same IATA's file. Nil when there are none.
|
|
func BuildLocalBorders(files, imported map[string]json.RawMessage) (*borders.Local, error) {
|
|
merged := maps.Clone(files)
|
|
if merged == nil {
|
|
merged = map[string]json.RawMessage{}
|
|
}
|
|
maps.Copy(merged, imported)
|
|
if len(merged) == 0 {
|
|
return nil, nil
|
|
}
|
|
var polygons []orb.Polygon
|
|
for _, code := range slices.Sorted(maps.Keys(merged)) {
|
|
feature, err := geojson.UnmarshalFeature(merged[code])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("nodes.mark_foreign: decoding border for %s: %w", code, err)
|
|
}
|
|
switch geometry := feature.Geometry.(type) {
|
|
case orb.Polygon:
|
|
polygons = append(polygons, geometry)
|
|
case orb.MultiPolygon:
|
|
polygons = append(polygons, geometry...)
|
|
}
|
|
}
|
|
local, err := borders.New(polygons)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("nodes.mark_foreign: %w", err)
|
|
}
|
|
return local, nil
|
|
}
|