Skip to content
Snippets Groups Projects
autopeering.go 3.85 KiB
Newer Older
package autopeering

import (
	"encoding/base64"
	"fmt"
	"net"
	"github.com/iotaledger/goshimmer/plugins/autopeering/local"

	"github.com/iotaledger/autopeering-sim/discover"
	"github.com/iotaledger/autopeering-sim/logger"
	"github.com/iotaledger/autopeering-sim/peer"
capossele's avatar
capossele committed
	"github.com/iotaledger/autopeering-sim/peer/service"
	"github.com/iotaledger/autopeering-sim/selection"
	"github.com/iotaledger/autopeering-sim/server"
	"github.com/iotaledger/autopeering-sim/transport"
	"github.com/iotaledger/hive.go/daemon"
	"github.com/iotaledger/hive.go/parameter"
	"github.com/pkg/errors"
	// Discovery is the peer discovery protocol.
	Discovery *discover.Protocol
	// Selection is the peer selection protocol.
	Selection *selection.Protocol
)

const defaultZLC = `{
	"level": "info",
	"development": false,
	"outputPaths": ["./autopeering.log"],
	"errorOutputPaths": ["stderr"],
	"encoding": "console",
	"encoderConfig": {
	  "timeKey": "ts",
	  "levelKey": "level",
	  "nameKey": "logger",
	  "callerKey": "caller",
	  "messageKey": "msg",
	  "stacktraceKey": "stacktrace",
	  "lineEnding": "",
	  "levelEncoder": "",
	  "timeEncoder": "iso8601",
	  "durationEncoder": "",
	  "callerEncoder": ""
	}
  }`

var zLogger = logger.NewLogger(defaultZLC, logLevel)
capossele's avatar
capossele committed

func configureAP() {
	masterPeers, err := parseEntryNodes()
	if err != nil {
		log.Errorf("Invalid entry nodes; ignoring: %v", err)
capossele's avatar
capossele committed
	}
	log.Debugf("Master peers: %v", masterPeers)
	Discovery = discover.New(local.GetInstance(), discover.Config{
capossele's avatar
capossele committed
		Log:         zLogger.Named("disc"),
		MasterPeers: masterPeers,
	})
capossele's avatar
capossele committed

	if parameter.NodeConfig.GetBool(CFG_SELECTION) {
		Selection = selection.New(local.GetInstance(), Discovery, selection.Config{
capossele's avatar
capossele committed
			Log: zLogger.Named("sel"),
capossele's avatar
capossele committed
			Param: &selection.Parameters{
capossele's avatar
capossele committed
				SaltLifetime:    selection.DefaultSaltLifetime,
				RequiredService: []service.Key{service.GossipKey},
capossele's avatar
capossele committed
			},
		})
	}
capossele's avatar
capossele committed
func start() {
	defer log.Info("Stopping Auto Peering server ... done")

	addr := local.GetInstance().Services().Get(service.PeeringKey)
	udpAddr, err := net.ResolveUDPAddr(addr.Network(), addr.String())
	if err != nil {
		log.Fatalf("ResolveUDPAddr: %v", err)
	}

	// if the ip is an external ip, set it to unspecified
	if udpAddr.IP.IsGlobalUnicast() {
		if udpAddr.IP.To4() != nil {
			udpAddr.IP = net.IPv4zero
		} else {
			udpAddr.IP = net.IPv6unspecified
		}
	}

	conn, err := net.ListenUDP(addr.Network(), udpAddr)
	if err != nil {
		log.Fatalf("ListenUDP: %v", err)
	}

	// use the UDP connection for transport
	trans := transport.Conn(conn, func(network, address string) (net.Addr, error) { return net.ResolveUDPAddr(network, address) })
	defer trans.Close()

	handlers := []server.Handler{Discovery}
	if Selection != nil {
		handlers = append(handlers, Selection)
	}

	// start a server doing discovery and peering
	srv := server.Listen(local.GetInstance(), trans, zLogger.Named("srv"), handlers...)
	defer srv.Close()

	// start the discovery on that connection
	Discovery.Start(srv)
	defer Discovery.Close()
	if Selection != nil {
		// start the peering on that connection
capossele's avatar
capossele committed
		Selection.Start(srv)
		defer Selection.Close()
	}
	log.Infof("Auto Peering server started: ID=%x, address=%s", local.GetInstance().ID(), srv.LocalAddr())
	<-daemon.ShutdownSignal
	log.Info("Stopping Auto Peering server ...")
}
func parseEntryNodes() (result []*peer.Peer, err error) {
	for _, entryNodeDefinition := range parameter.NodeConfig.GetStringSlice(CFG_ENTRY_NODES) {
		if entryNodeDefinition == "" {
			continue
		}

		parts := strings.Split(entryNodeDefinition, "@")
		if len(parts) != 2 {
			return nil, fmt.Errorf("parseMaster")
		}
		pubKey, err := base64.StdEncoding.DecodeString(parts[0])
		if err != nil {
			return nil, errors.Wrap(err, "parseMaster")
		}

		services := service.New()
		services.Update(service.PeeringKey, "udp", parts[1])

		result = append(result, peer.NewPeer(pubKey, services))
	}
capossele's avatar
capossele committed

	return result, nil