aergoio/aergo

View on GitHub
types/p2ptypes.go

Summary

Maintainability
A
0 mins
Test Coverage
F
58%
/*
 * @file
 * @copyright defined in aergo/LICENSE.txt
 */

package types

import (
    "github.com/mr-tron/base58"
    "net"
    "strconv"
    "strings"

    "github.com/aergoio/aergo/v2/internal/network"
    core "github.com/libp2p/go-libp2p-core"
    "github.com/libp2p/go-libp2p-core/crypto"
    "github.com/libp2p/go-libp2p-core/peer"
    "github.com/libp2p/go-libp2p-core/test"
    "github.com/multiformats/go-multiaddr"
    "github.com/pkg/errors"
)

// ProducerID is identifier of block producer. It is same format with the PeerID at version 1.x, but might be changed to other format later.
type ProducerID = core.PeerID

// PeerID is identifier of peer. It is alias of libp2p.PeerID for now
type PeerID = core.PeerID

// NOTE use only in test
func RandomPeerID() PeerID {
    id, _ := test.RandPeerID()
    return id
}

func IDB58Decode(b58 string) (PeerID, error) {
    return peer.Decode(b58)
}
func IDB58Encode(pid PeerID) string {
    return base58.Encode([]byte(pid))
}

func IDFromBytes(b []byte) (PeerID, error) {
    return peer.IDFromBytes(b)
}
func IDFromPublicKey(pubKey crypto.PubKey) (PeerID, error) {
    return peer.IDFromPublicKey(pubKey)
}
func IDFromPrivateKey(sk crypto.PrivKey) (PeerID, error) {
    return peer.IDFromPrivateKey(sk)
}
func IsSamePeerID(pid1, pid2 PeerID) bool {
    return string(pid1) == string(pid2)
}

// Stream is alias of libp2p.Stream
type Stream = core.Stream

// Multiaddr is alias of
type Multiaddr = multiaddr.Multiaddr

var InvalidArgument = errors.New("invalid argument")

const (
    protoDNS4 = "dns4"
    protoIP4  = "ip4"
    protoIP6  = "ip6"
    protoTCP  = "tcp"
    protoP2P  = "p2p"
)

func PeerToMultiAddr(address string, port uint32, pid PeerID) (Multiaddr, error) {
    idport, err := ToMultiAddr(address, port)
    if err != nil {
        return nil, err
    }
    mid, err := multiaddr.NewComponent(protoP2P, pid.Pretty())
    if err != nil {
        return nil, err
    }
    return multiaddr.Join(idport, mid), nil
}

// ToMultiAddr make libp2p compatible Multiaddr object
func ToMultiAddr(address string, port uint32) (Multiaddr, error) {
    var maddr, mport *multiaddr.Component
    var err error
    switch network.CheckAddressType(address) {
    case network.AddressTypeFQDN:
        maddr, err = multiaddr.NewComponent(protoDNS4, address)
    case network.AddressTypeIP:
        ip := net.ParseIP(address)
        if ip.To4() != nil {
            maddr, err = multiaddr.NewComponent(protoIP4, address)
        } else {
            maddr, err = multiaddr.NewComponent(protoIP6, address)
        }
    default:
        return nil, errors.New("invalid address")
    }
    if err != nil {
        return nil, err
    }
    mport, err = multiaddr.NewComponent(protoTCP, strconv.Itoa(int(port)))
    if err != nil {
        return nil, err
    }
    return multiaddr.Join(maddr, mport), nil
}

// ParseMultiaddr parse multiaddr formatted string to Multiaddr with slightly different manner; it automatically auusme that /dns is /dns4
func ParseMultiaddr(str string) (Multiaddr, error) {
    // replace /dns/ to /dns4/ for backward compatibility
    if strings.HasPrefix(str, "/dns/") {
        str = strings.Replace(str, "/dns/", "/dns4/", 1)
    }
    return multiaddr.NewMultiaddr(str)
}

const PortUndefined = uint32(0xffffffff)

var ErrInvalidIPAddress = errors.New("invalid ip address")
var ErrInvalidPort = errors.New("invalid port")

var addrProtos = []int{multiaddr.P_IP4, multiaddr.P_IP6, multiaddr.P_DNS4, multiaddr.P_DNS6}

// AddressFromMultiAddr returns address (ip4, ip6 or full qualified domain name)
func AddressFromMultiAddr(ma Multiaddr) string {
    for _, p := range addrProtos {
        val, err := ma.ValueForProtocol(p)
        if err == nil {
            return val
        }
    }
    return ""
}

func IsAddress(proto multiaddr.Protocol) bool {
    switch proto.Code {
    case multiaddr.P_IP4, multiaddr.P_IP6, multiaddr.P_DNS4, multiaddr.P_DNS6:
        return true
    default:
        return false
    }
}

func GetIPPortFromMultiaddr(ma Multiaddr) (net.IP, uint32, error) {
    ip := GetIPFromMultiaddr(ma)
    if ip == nil {
        return nil, PortUndefined, ErrInvalidIPAddress
    }
    port := GetPortFromMultiaddr(ma)
    if port == PortUndefined {
        return nil, PortUndefined, ErrInvalidPort
    }
    return ip, port, nil
}

func GetIPFromMultiaddr(ma Multiaddr) net.IP {
    val, err := ma.ValueForProtocol(multiaddr.P_IP4)
    if err != nil {
        val, err = ma.ValueForProtocol(multiaddr.P_IP6)
    }
    if err == nil {
        return net.ParseIP(val)
    } else {
        return nil
    }
}

func GetPortFromMultiaddr(ma Multiaddr) uint32 {
    val, err := ma.ValueForProtocol(multiaddr.P_TCP)
    if err != nil {
        return PortUndefined
    }
    port, err := strconv.Atoi(val)
    if err != nil {
        return PortUndefined
    }
    return uint32(port)
}