depot/packages/networking/hyprspace/config/config.go
Max 9954f8eb03 packages/hyprspace: 0.7.1 -> 0.8.0
- config overhaul
- remove unnecessary cli args
- remove down command
2023-10-27 00:32:18 +02:00

193 lines
4.7 KiB
Go

package config
import (
"encoding/json"
"fmt"
"log"
"net"
"os"
"strings"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
"github.com/multiformats/go-multibase"
"github.com/yl2chen/cidranger"
)
// Config is the main Configuration Struct for Hyprspace.
type Config struct {
Path string `json:"-"`
Interface string `json:"-"`
EncodedListenAddresses []string `json:"listenAddresses"`
ListenAddresses []multiaddr.Multiaddr `json:"-"`
Peers []Peer `json:"peers"`
PeerLookup PeerLookup `json:"-"`
EncodedPrivateKey string `json:"privateKey"`
PrivateKey crypto.PrivKey `json:"-"`
BuiltinAddr net.IP `json:"-"`
}
// Peer defines a peer in the configuration. We might add more to this later.
type Peer struct {
ID peer.ID `json:"id"`
Name string `json:"name"`
BuiltinAddr net.IP `json:"-"`
Routes []Route `json:"routes"`
}
type Route struct {
NetworkStr string `json:"net"`
Network net.IPNet `json:"-"`
}
// PeerLookup is a helper struct for quickly looking up a peer based on various parameters
type PeerLookup struct {
ByRoute cidranger.Ranger
ByName map[string]Peer
}
type RouteTableEntry struct {
Net net.IPNet
Target Peer
}
func (rte RouteTableEntry) Network() net.IPNet {
return rte.Net
}
// Read initializes a config from a file.
func Read(path string) (*Config, error) {
in, err := os.ReadFile(path)
if err != nil {
return nil, err
}
result := Config{
EncodedListenAddresses: []string{
"/ip4/0.0.0.0/tcp/8001",
"/ip4/0.0.0.0/udp/8001/quic-v1",
"/ip6/::/tcp/8001",
"/ip6/::/udp/8001/quic-v1",
},
}
// Read in config settings from file.
err = json.Unmarshal(in, &result)
if err != nil {
return nil, err
}
_, keyBytes, err := multibase.Decode(result.EncodedPrivateKey)
if err != nil {
return nil, err
}
pk, err := crypto.UnmarshalPrivateKey(keyBytes)
if err != nil {
return nil, err
}
result.PrivateKey = pk
if err != nil {
return nil, err
}
peerID, err := peer.IDFromPrivateKey(result.PrivateKey)
if err != nil {
return nil, err
}
result.BuiltinAddr = mkBuiltinAddr(peerID)
for _, addrString := range result.EncodedListenAddresses {
addr, err := multiaddr.NewMultiaddr(addrString)
if err != nil {
return nil, err
}
result.ListenAddresses = append(result.ListenAddresses, addr)
}
result.PeerLookup.ByRoute = cidranger.NewPCTrieRanger()
result.PeerLookup.ByName = make(map[string]Peer)
for i, p := range result.Peers {
p.BuiltinAddr = mkBuiltinAddr(p.ID)
p.Routes = append(p.Routes, Route{
Network: net.IPNet{
IP: p.BuiltinAddr,
Mask: net.IPv4Mask(255, 255, 255, 255),
},
})
for _, r := range p.Routes {
if r.NetworkStr != "" {
_, n, err := net.ParseCIDR(r.NetworkStr)
if err != nil {
log.Fatal("[!] Invalid network:", r.NetworkStr)
}
r.Network = *n
}
result.PeerLookup.ByRoute.Insert(&RouteTableEntry{
Net: r.Network,
Target: p,
})
fmt.Printf("[+] Route %s via /p2p/%s\n", r.Network.String(), p.ID)
}
if p.Name != "" {
result.PeerLookup.ByName[strings.ToLower(p.Name)] = p
}
result.Peers[i] = p
}
// Overwrite path of config to input.
result.Path = path
return &result, nil
}
func mkBuiltinAddr(p peer.ID) net.IP {
builtinAddr := []byte{100, 64, 1, 2}
for i, b := range []byte(p) {
builtinAddr[(i%2)+2] ^= b
}
return net.IP(builtinAddr)
}
func FindPeer(peers []Peer, needle peer.ID) (*Peer, bool) {
for _, p := range peers {
if p.ID == needle {
return &p, true
}
}
return nil, false
}
func (cfg Config) FindRoute(needle net.IPNet) (*RouteTableEntry, bool) {
networks, err := cfg.PeerLookup.ByRoute.CoveredNetworks(needle)
if err != nil {
fmt.Println(err)
return nil, false
} else if len(networks) == 0 {
return nil, false
} else if len(networks) > 1 {
for _, n := range networks {
fmt.Printf("[!] Found duplicate route %s to /p2p/%s for %s\n", n.Network(), n.(RouteTableEntry).Target.ID, needle)
}
}
return networks[0].(*RouteTableEntry), true
}
func (cfg Config) FindRouteForIP(needle net.IP) (*RouteTableEntry, bool) {
networks, err := cfg.PeerLookup.ByRoute.ContainingNetworks(needle)
if err != nil {
fmt.Println(err)
return nil, false
} else if len(networks) == 0 {
return nil, false
} else if len(networks) > 1 {
for _, n := range networks {
fmt.Printf("[!] Found duplicate route %s to /p2p/%s for %s\n", n.Network(), n.(RouteTableEntry).Target.ID, needle)
}
}
return networks[0].(*RouteTableEntry), true
}