DHT-kademlia-P2Psec/cmd/main.go

126 lines
3.4 KiB
Go
Raw Normal View History

2024-09-13 07:04:40 +02:00
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
}