frostfs-node/modules/settings/address.go

110 lines
2.3 KiB
Go
Raw Permalink Normal View History

package settings
import (
"net"
"strconv"
"strings"
"github.com/multiformats/go-multiaddr"
"github.com/nspcc-dev/neofs-node/internal"
"github.com/pkg/errors"
)
const (
protoTCP = "tcp"
protoUDP = "udp"
protoQUIC = "quic"
)
const emptyAddr = "0.0.0.0"
const ip4ColonCount = 1
var (
errEmptyAddress = internal.Error("`node.address` could not be empty")
errEmptyProtocol = internal.Error("`node.protocol` could not be empty")
errUnknownProtocol = internal.Error("`node.protocol` unknown protocol")
errEmptyShutdownTTL = internal.Error("`node.shutdown_ttl` could not be empty")
)
func ipVersion(address string) string {
if strings.Count(address, ":") > ip4ColonCount {
return "ip6"
}
return "ip4"
}
func prepareAddress(address string) (string, error) {
host, port, err := net.SplitHostPort(address)
if err != nil {
return "", errors.Wrapf(err, "could not fetch host/port: %s", address)
} else if host == "" {
host = emptyAddr
}
addr, err := net.ResolveIPAddr("ip", host)
if err != nil {
return "", errors.Wrapf(err, "could not resolve address: %s:%s", host, port)
}
return net.JoinHostPort(addr.IP.String(), port), nil
}
func resolveAddress(proto, address string) (string, string, error) {
var (
ip net.IP
host, port string
)
switch proto {
case protoTCP:
addr, err := net.ResolveTCPAddr(protoTCP, address)
if err != nil {
return "", "", errors.Wrapf(err, "could not parse address: '%s'", address)
}
ip = addr.IP
port = strconv.Itoa(addr.Port)
case protoUDP, protoQUIC:
addr, err := net.ResolveUDPAddr(protoUDP, address)
if err != nil {
return "", "", errors.Wrapf(err, "could not parse address: '%s'", address)
}
ip = addr.IP
port = strconv.Itoa(addr.Port)
default:
return "", "", errors.Wrapf(errUnknownProtocol, "unknown protocol: '%s'", proto)
}
if host = ip.String(); ip == nil {
host = emptyAddr
}
return host, port, nil
}
func multiAddressFromProtoAddress(proto, addr string) (multiaddr.Multiaddr, error) {
var (
err error
host, port string
ipVer = ipVersion(addr)
)
if host, port, err = resolveAddress(proto, addr); err != nil {
return nil, errors.Wrapf(err, "could not resolve address: (%s) '%s'", proto, addr)
}
items := []string{
ipVer,
host,
proto,
port,
}
addr = "/" + strings.Join(items, "/")
return multiaddr.NewMultiaddr(addr)
}