aergoio/aergo

View on GitHub
p2p/p2pcommon/peermeta.go

Summary

Maintainability
A
55 mins
Test Coverage
C
78%
/*
 * @file
 * @copyright defined in aergo/LICENSE.txt
 */

package p2pcommon

import (
    "strconv"

    "github.com/aergoio/aergo/v2/types"
    "github.com/multiformats/go-multiaddr"
)

// PeerMeta contains non changeable information of peer node during connected state
type PeerMeta struct {
    ID types.PeerID
    // AcceptedRole is the role that the remote peer claims: the local peer may not admit it, and only admits it when there is a proper proof, such as vote result in chain or AgentCertificate.
    Role types.PeerRole
    // ProducerIDs is a list of block producer IDs produced by this peer if the peer is BP, and if it is Agent, it is a list of block producer IDs that this peer acts as.
    ProducerIDs []types.PeerID
    // Address is advertised address to which other peer can connect.
    Addresses []types.Multiaddr
    // Version is build version of binary
    Version string
    Hidden  bool // Hidden means that meta info of this peer will not be sent to other peers when getting peer list

}

func (m *PeerMeta) GetVersion() string {
    if m.Version == "" {
        return ""
    } else {
        return m.Version
    }
}

// NewMetaWith1Addr make instance of PeerMeta with single address
func NewMetaWith1Addr(id types.PeerID, addr string, port uint32, version string) PeerMeta {
    ma, err := types.ToMultiAddr(addr, port)
    if err != nil {
        return PeerMeta{}
    } else {
        return PeerMeta{ID: id, Addresses: []types.Multiaddr{ma}, Version: version}
    }
}

// FromStatusToMeta create peerMeta from Status message
func NewMetaFromStatus(status *types.Status) PeerMeta {
    meta := FromPeerAddressNew(status.Sender)
    // hidden field of remote peer should be got from Status struct
    meta.Hidden = status.NoExpose
    //if len(meta.Version) == 0 {
    //    meta.Version = status.Sender.Version
    //}
    return meta
}

// FromPeerAddress convert PeerAddress to PeerMeta
func FromPeerAddress(addr *types.PeerAddress) PeerMeta {
    return FromPeerAddressNew(addr)
}

// ToPeerAddress convert PeerMeta to PeerAddress
func (m PeerMeta) ToPeerAddress() types.PeerAddress {
    addrs := make([]string, len(m.Addresses))
    for i, a := range m.Addresses {
        addrs[i] = a.String()
    }
    pds := make([][]byte, len(m.ProducerIDs))
    for i, a := range m.ProducerIDs {
        pds[i] = []byte(a)
    }

    addr := types.PeerAddress{PeerID: []byte(m.ID), Address: m.PrimaryAddress(), Port: m.PrimaryPort(), Addresses: addrs, ProducerIDs: pds, Version: m.GetVersion(), Role: m.Role}
    return addr
}

// PrimaryAddress is first advertised port of peer
func (m PeerMeta) PrimaryPort() uint32 {
    if len(m.Addresses) > 0 {
        portVal, _ := m.Addresses[0].ValueForProtocol(multiaddr.P_TCP)
        port, _ := strconv.Atoi(portVal)
        return uint32(port)
    } else {
        return 0
    }
}

// PrimaryAddress is first advertised address of peer
func (m PeerMeta) PrimaryAddress() string {
    if len(m.Addresses) > 0 {
        return types.AddressFromMultiAddr(m.Addresses[0])
    } else {
        return ""
    }

}

func (m PeerMeta) Equals(o PeerMeta) bool {
    if !types.IsSamePeerID(m.ID, o.ID) {
        return false
    }
    if m.Role != o.Role {
        return false
    }
    if len(m.ProducerIDs) != len(o.ProducerIDs) {
        return false
    }
    for i, id := range m.ProducerIDs {
        if !types.IsSamePeerID(id, o.ProducerIDs[i]) {
            return false
        }
    }
    if len(m.Addresses) != len(o.Addresses) {
        return false
    }
    for i, ad := range m.Addresses {
        if !ad.Equal(o.Addresses[i]) {
            return false
        }
    }
    if m.Version != o.Version {
        return false
    }
    if m.Hidden != o.Hidden {
        return false
    }
    return true
}

func FromPeerAddressNew(addr *types.PeerAddress) PeerMeta {
    addrs := make([]types.Multiaddr, 0, len(addr.Addresses))
    for _, a := range addr.Addresses {
        ma, err := multiaddr.NewMultiaddr(a)
        if err != nil {
            continue
        }
        addrs = append(addrs, ma)
    }
    role := types.PeerRole_LegacyVersion
    _, found := types.PeerRole_name[int32(addr.Role)]
    if found {
        role = types.PeerRole(int32(addr.Role))
    }
    producerIds := make([]types.PeerID, len(addr.ProducerIDs))
    for i, id := range addr.ProducerIDs {
        producerIds[i] = types.PeerID(id)
    }
    meta := PeerMeta{ID: types.PeerID(addr.PeerID), Addresses: addrs, Role: role, Version: addr.Version, ProducerIDs: producerIds}
    return meta
}