oc-discovery -> conf

This commit is contained in:
mr
2026-04-08 10:04:41 +02:00
parent 46dee0a6cb
commit 29b26d366e
21 changed files with 1934 additions and 119 deletions

View File

@@ -0,0 +1,99 @@
// Package location resolves the geographic position of this node via IP
// geolocation and applies a privacy-preserving random offset proportional
// to the chosen granularity level before publishing the result.
package location
import (
"encoding/json"
"fmt"
"math/rand"
"net/http"
"time"
peer "cloud.o-forge.io/core/oc-lib/models/peer"
)
// fuzzRadius returns the maximum random offset (in degrees) for each axis
// given a granularity level.
//
// 0 → no location
// 1 → continent ±15° lat / ±20° lng
// 2 → country ±3° lat / ±4° lng (default)
// 3 → region ±0.5° lat / ±0.7° lng
// 4 → city ±0.05° lat / ±0.07° lng
func fuzzRadius(granularity int) (latR, lngR float64) {
switch granularity {
case 1:
return 15.0, 20.0
case 2:
return 3.0, 4.0
case 3:
return 0.5, 0.7
case 4:
return 0.05, 0.07
default:
return 3.0, 4.0
}
}
// clamp keeps a value inside [min, max].
func clamp(v, min, max float64) float64 {
if v < min {
return min
}
if v > max {
return max
}
return v
}
// ipAPIResponse is the subset of fields returned by ip-api.com/json.
type ipAPIResponse struct {
Status string `json:"status"`
Lat float64 `json:"lat"`
Lon float64 `json:"lon"`
Country string `json:"country"`
Region string `json:"regionName"`
City string `json:"city"`
}
// Geolocate resolves the current public IP location via ip-api.com (free,
// no key required for non-commercial use), then fuzzes the result according
// to granularity.
//
// Returns nil if granularity == 0 (opt-out) or if the lookup fails.
func Geolocate(granularity int) *peer.PeerLocation {
if granularity == 0 {
return nil
}
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Get("http://ip-api.com/json?fields=status,lat,lon,country,regionName,city")
if err != nil {
return nil
}
defer resp.Body.Close()
var result ipAPIResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil || result.Status != "success" {
return nil
}
latR, lngR := fuzzRadius(granularity)
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
fuzzedLat := result.Lat + (rng.Float64()*2-1)*latR
fuzzedLng := result.Lon + (rng.Float64()*2-1)*lngR
fuzzedLat = clamp(fuzzedLat, -85.0, 85.0)
fuzzedLng = clamp(fuzzedLng, -180.0, 180.0)
fmt.Printf("[location] granularity=%d raw=(%.4f,%.4f) fuzzed=(%.4f,%.4f)\n",
granularity, result.Lat, result.Lon, fuzzedLat, fuzzedLng)
return &peer.PeerLocation{
Latitude: fuzzedLat,
Longitude: fuzzedLng,
Granularity: granularity,
}
}