126 lines
3.4 KiB
Go
126 lines
3.4 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"flag"
|
||
|
kademlia "gitlab.lrz.de/netintum/teaching/p2psec_projects_2024/DHT-6/pkg"
|
||
|
"gopkg.in/ini.v1"
|
||
|
"log"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
// Config holds the config variables for the DHT module
|
||
|
|
||
|
func main() {
|
||
|
|
||
|
path := flag.String("c", "", "Path to configuration file")
|
||
|
flag.Parse()
|
||
|
|
||
|
if *path == "" {
|
||
|
log.Fatalln("[Config Parser] Please provide a configuration file")
|
||
|
}
|
||
|
|
||
|
dhtConfig := ParseConfig(*path)
|
||
|
|
||
|
Setup(dhtConfig)
|
||
|
}
|
||
|
|
||
|
func ParseConfig(configPath string) *kademlia.Config {
|
||
|
config, err := ini.Load(configPath)
|
||
|
if err != nil {
|
||
|
log.Fatalln("[Config Parser] Error reading file: ", err)
|
||
|
}
|
||
|
|
||
|
var dhtConfig kademlia.Config
|
||
|
|
||
|
section := config.Section("dht")
|
||
|
|
||
|
ip, port, err := parseIP(section.Key("p2p_address").String())
|
||
|
if err != nil {
|
||
|
// Without P2P address we cannot work
|
||
|
log.Fatalf("[Config Parser]: Invalid P2P address provided: %v", err)
|
||
|
}
|
||
|
dhtConfig.P2PAddress = ip
|
||
|
dhtConfig.P2PPort = port
|
||
|
|
||
|
// If one wants to only provide an additional node to the network without interacting with it oneself, this might
|
||
|
// be fine
|
||
|
ip, port, err = parseIP(section.Key("api_address").String())
|
||
|
if err != nil {
|
||
|
// Without API setup it would work in theory, one simply would add an additional node to the network
|
||
|
log.Printf("[Config Parser: Invalid API config: %v | API Server will be unreachable", err)
|
||
|
}
|
||
|
dhtConfig.APIAddress = ip
|
||
|
dhtConfig.APIPort = port
|
||
|
|
||
|
// Invalid or empty bootstrapper field will result in no bootstrap. This is for example required for the first node
|
||
|
// To join/start the network
|
||
|
ip, port, err = parseIP(section.Key("bootstrapper").String())
|
||
|
if err != nil {
|
||
|
log.Print("[Config Parser] Unable to parse bootstrapper, node will skip boostrap.")
|
||
|
}
|
||
|
dhtConfig.Bootstrapper = ip
|
||
|
dhtConfig.BootstrapperPort = port
|
||
|
|
||
|
dhtConfig.PrefixLength, err = section.Key("prefix_length").Uint64()
|
||
|
if err != nil {
|
||
|
log.Printf("[Config Parser] Falied to parse prefix length, defaulting to 5: %v", err)
|
||
|
dhtConfig.PrefixLength = 5
|
||
|
} else if dhtConfig.PrefixLength <= 0 || dhtConfig.PrefixLength > 64 {
|
||
|
log.Fatalf("[Config Parser] Prefix length must be in [1,64], but was %d. Values over 10 are not recommended.", dhtConfig.PrefixLength)
|
||
|
}
|
||
|
|
||
|
dhtConfig.KeyFile = section.Key("key_file").String()
|
||
|
if len(dhtConfig.KeyFile) == 0 {
|
||
|
dhtConfig.KeyFile = "key.pem"
|
||
|
}
|
||
|
|
||
|
dhtConfig.CertFile = section.Key("cert_file").String()
|
||
|
if len(dhtConfig.CertFile) == 0 {
|
||
|
dhtConfig.CertFile = "cert.pem"
|
||
|
}
|
||
|
|
||
|
dhtConfig.BootstrapperCert = section.Key("bootstrapper_cert").String()
|
||
|
|
||
|
interval, err := section.Key("republish_interval").Uint64()
|
||
|
if err != nil || interval == 0 {
|
||
|
log.Printf("[Config Parser] Falied to parse republish interval, defaulting to 1 hour, %v", err)
|
||
|
interval = 3600
|
||
|
}
|
||
|
|
||
|
dhtConfig.RepublishInterval = time.Duration(interval) * time.Second
|
||
|
|
||
|
return &dhtConfig
|
||
|
}
|
||
|
|
||
|
func Setup(dhtConfig *kademlia.Config) {
|
||
|
dht := kademlia.NewDHT(dhtConfig)
|
||
|
|
||
|
go initializeAPIServer(dhtConfig, dht)
|
||
|
initializeP2PServer(dhtConfig, dht)
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
parseIP splits a string conforming to the syntax for ipv4 and ipv6 addresses into IP and port
|
||
|
*/
|
||
|
func parseIP(line string) (string, uint64, error) {
|
||
|
var temp []string
|
||
|
if strings.HasPrefix(line, "[") {
|
||
|
temp = strings.Split(line[1:], "]:")
|
||
|
} else {
|
||
|
temp = strings.Split(line, ":")
|
||
|
}
|
||
|
if len(temp) != 2 {
|
||
|
return "", 0, errors.New("invalid IP format")
|
||
|
}
|
||
|
|
||
|
portTemp, err := strconv.Atoi(temp[1])
|
||
|
if err != nil {
|
||
|
return "", 0, err
|
||
|
}
|
||
|
port := uint64(portTemp)
|
||
|
return temp[0], port, nil
|
||
|
}
|