addrinfo.go 2.6 KB
Newer Older
1 2 3 4 5
package peer

import (
	"fmt"

tavit ohanian's avatar
tavit ohanian committed
6
	ma "gitlab.dms3.io/mf/go-multiaddr"
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
)

// AddrInfo is a small struct used to pass around a peer with
// a set of addresses (and later, keys?).
type AddrInfo struct {
	ID    ID
	Addrs []ma.Multiaddr
}

var _ fmt.Stringer = AddrInfo{}

func (pi AddrInfo) String() string {
	return fmt.Sprintf("{%v: %v}", pi.ID, pi.Addrs)
}

var ErrInvalidAddr = fmt.Errorf("invalid p2p multiaddr")

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
// AddrInfosFromP2pAddrs converts a set of Multiaddrs to a set of AddrInfos.
func AddrInfosFromP2pAddrs(maddrs ...ma.Multiaddr) ([]AddrInfo, error) {
	m := make(map[ID][]ma.Multiaddr)
	for _, maddr := range maddrs {
		transport, id := SplitAddr(maddr)
		if id == "" {
			return nil, ErrInvalidAddr
		}
		if transport == nil {
			if _, ok := m[id]; !ok {
				m[id] = nil
			}
		} else {
			m[id] = append(m[id], transport)
		}
	}
	ais := make([]AddrInfo, 0, len(m))
	for id, maddrs := range m {
		ais = append(ais, AddrInfo{ID: id, Addrs: maddrs})
	}
	return ais, nil
}

// SplitAddr splits a p2p Multiaddr into a transport multiaddr and a peer ID.
//
// * Returns a nil transport if the address only contains a /p2p part.
// * Returns a empty peer ID if the address doesn't contain a /p2p part.
func SplitAddr(m ma.Multiaddr) (transport ma.Multiaddr, id ID) {
52
	if m == nil {
53
		return nil, ""
54 55
	}

Steven Allen's avatar
Steven Allen committed
56 57
	transport, p2ppart := ma.SplitLast(m)
	if p2ppart == nil || p2ppart.Protocol().Code != ma.P_P2P {
58
		return m, ""
59
	}
60 61 62 63
	id = ID(p2ppart.RawValue()) // already validated by the multiaddr library.
	return transport, id
}

64 65
// AddrInfoFromString builds an AddrInfo from the string representation of a Multiaddr
func AddrInfoFromString(s string) (*AddrInfo, error) {
Marten Seemann's avatar
Marten Seemann committed
66
	a, err := ma.NewMultiaddr(s)
67 68 69 70 71 72 73
	if err != nil {
		return nil, err
	}

	return AddrInfoFromP2pAddr(a)
}

74 75 76 77 78
// AddrInfoFromP2pAddr converts a Multiaddr to an AddrInfo.
func AddrInfoFromP2pAddr(m ma.Multiaddr) (*AddrInfo, error) {
	transport, id := SplitAddr(m)
	if id == "" {
		return nil, ErrInvalidAddr
79
	}
Steven Allen's avatar
Steven Allen committed
80 81 82
	info := &AddrInfo{ID: id}
	if transport != nil {
		info.Addrs = []ma.Multiaddr{transport}
83
	}
Steven Allen's avatar
Steven Allen committed
84
	return info, nil
85 86
}

Vasco Santos's avatar
Vasco Santos committed
87
// AddrInfoToP2pAddrs converts an AddrInfo to a list of Multiaddrs.
88 89
func AddrInfoToP2pAddrs(pi *AddrInfo) ([]ma.Multiaddr, error) {
	var addrs []ma.Multiaddr
Steven Allen's avatar
Steven Allen committed
90 91 92 93
	p2ppart, err := ma.NewComponent("p2p", IDB58Encode(pi.ID))
	if err != nil {
		return nil, err
	}
Steven Allen's avatar
Steven Allen committed
94 95 96
	if len(pi.Addrs) == 0 {
		return []ma.Multiaddr{p2ppart}, nil
	}
97
	for _, addr := range pi.Addrs {
Steven Allen's avatar
Steven Allen committed
98
		addrs = append(addrs, addr.Encapsulate(p2ppart))
99 100 101 102 103 104 105 106 107 108
	}
	return addrs, nil
}

func (pi *AddrInfo) Loggable() map[string]interface{} {
	return map[string]interface{}{
		"peerID": pi.ID.Pretty(),
		"addrs":  pi.Addrs,
	}
}